@bobfrankston/importgen 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,10 @@
8
8
  "Bash(dir:*)",
9
9
  "Bash(ls:*)",
10
10
  "Bash(where extractids:*)",
11
- "Bash(cd \"y:/dev/utils/importgen\" && npx tsc --noEmit 2>&1222)"
11
+ "Bash(cd \"y:/dev/utils/importgen\" && npx tsc --noEmit 2>&1222)",
12
+ "Bash(cd y:/dev/utils/importgen && npm run release 2>&1exit)",
13
+ "Bash(cd y:/dev/utils/importgen && npx tsc --noEmit 2>&1)",
14
+ "Bash(cd:*)"
12
15
  ]
13
16
  }
14
17
  }
package/README.md CHANGED
@@ -25,7 +25,7 @@ npm install -g @bobfrankston/importgen
25
25
  Run from your project directory (containing `package.json` and your HTML file):
26
26
 
27
27
  ```bash
28
- importgen [htmlfile] [--watch|-w] [--version|-v]
28
+ importgen [htmlfile] [--watch|-w] [--freeze] [--unfreeze] [--version|-v]
29
29
  ```
30
30
 
31
31
  ```bash
@@ -42,6 +42,12 @@ importgen default.htm --watch
42
42
 
43
43
  # Show version
44
44
  importgen -v
45
+
46
+ # Freeze: replace symlinks/junctions with real copies for deployment
47
+ importgen --freeze
48
+
49
+ # Unfreeze: restore symlinks and run npm install
50
+ importgen --unfreeze
45
51
  ```
46
52
 
47
53
  `importgen` reads dependencies from `package.json` in the current directory and injects the import map into the HTML file.
@@ -129,6 +135,14 @@ Add a `.dependencies` field to `package.json` to override resolution paths for s
129
135
 
130
136
  The import map will use the `.dependencies` path instead of the `node_modules` path for that package.
131
137
 
138
+ ## Freeze / Unfreeze
139
+
140
+ `--freeze` prepares a project for deployment by replacing all symlinks and junctions in `node_modules` with real directory copies. This is useful when `file:` or `workspace:` dependencies point to local packages via symlinks that won't exist on a deployment target.
141
+
142
+ Freeze also adds a `preinstall` guard script to `package.json` that prevents accidental `npm install` from overwriting the frozen copies. If a `preinstall` script already exists, it is saved as `frozen-preinstall` so it can be restored later.
143
+
144
+ `--unfreeze` reverses the process: it removes the preinstall guard (restoring any original preinstall script), then runs `npm install` to re-establish normal symlinked dependencies.
145
+
132
146
  ## VS Code tasks.json Integration
133
147
 
134
148
  Add `importgen --watch` as a background task that starts automatically when you open the project. Combined with `tsc --watch`, your import map stays current as you develop.
package/index.js CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
8
+ import { execSync } from 'node:child_process';
8
9
  import chokidar from 'chokidar';
9
10
  import packageJson from './package.json' with { type: 'json' };
10
11
  /**
@@ -265,16 +266,53 @@ function freezeDependencies(packageJsonPath) {
265
266
  if (!pkg.scripts)
266
267
  pkg.scripts = {};
267
268
  if (pkg.scripts.preinstall) {
268
- console.warn('[importgen] Warning: preinstall script already exists, skipping guard');
269
+ // Rename existing preinstall so unfreeze can restore it
270
+ pkg.scripts['frozen-preinstall'] = pkg.scripts.preinstall;
271
+ console.log(`[importgen] Saved existing preinstall script as "frozen-preinstall"`);
272
+ }
273
+ pkg.scripts.preinstall = 'echo FROZEN: dependencies were frozen by importgen. Use importgen --unfreeze to restore. && exit 1';
274
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
275
+ console.log('[importgen] Added preinstall guard to package.json');
276
+ }
277
+ catch (e) {
278
+ console.error(`[importgen] Error updating package.json: ${e.message}`);
279
+ }
280
+ }
281
+ /**
282
+ * Unfreeze: remove preinstall guard, restore original preinstall if saved, then run npm install.
283
+ */
284
+ function unfreezeDependencies(packageJsonPath) {
285
+ try {
286
+ const pkgRaw = fs.readFileSync(packageJsonPath, 'utf-8');
287
+ const pkg = JSON.parse(pkgRaw);
288
+ if (!pkg.scripts?.preinstall) {
289
+ console.log('[importgen] No preinstall guard found — nothing to unfreeze');
290
+ return;
291
+ }
292
+ if (pkg.scripts['frozen-preinstall']) {
293
+ pkg.scripts.preinstall = pkg.scripts['frozen-preinstall'];
294
+ delete pkg.scripts['frozen-preinstall'];
295
+ console.log('[importgen] Restored original preinstall script');
269
296
  }
270
297
  else {
271
- pkg.scripts.preinstall = 'echo FROZEN: dependencies were frozen by importgen. Remove this script before running npm install. && exit 1';
272
- fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
273
- console.log('[importgen] Added preinstall guard to package.json');
298
+ delete pkg.scripts.preinstall;
299
+ console.log('[importgen] Removed preinstall guard');
274
300
  }
301
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
275
302
  }
276
303
  catch (e) {
277
304
  console.error(`[importgen] Error updating package.json: ${e.message}`);
305
+ process.exit(1);
306
+ }
307
+ // Run npm install to restore proper dependencies
308
+ console.log('[importgen] Running npm install...');
309
+ try {
310
+ execSync('npm install', { stdio: 'inherit', cwd: process.cwd() });
311
+ console.log('[importgen] Unfreeze complete');
312
+ }
313
+ catch (e) {
314
+ console.error(`[importgen] npm install failed: ${e.message}`);
315
+ process.exit(1);
278
316
  }
279
317
  }
280
318
  // Parse CLI arguments
@@ -283,9 +321,24 @@ if (args.includes('-v') || args.includes('--version')) {
283
321
  console.log(`importgen ${packageJson.version}`);
284
322
  process.exit(0);
285
323
  }
324
+ const knownFlags = new Set(['-w', '--watch', '--freeze', '-freeze', '--unfreeze', '-unfreeze', '-v', '--version']);
325
+ // Report unrecognized flags as errors
326
+ const unknownArgs = args.filter(a => a.startsWith('-') && !knownFlags.has(a));
327
+ if (unknownArgs.length > 0) {
328
+ console.error(`[importgen] Error: unrecognized argument(s): ${unknownArgs.join(', ')}`);
329
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [--unfreeze] [-v|--version]`);
330
+ process.exit(1);
331
+ }
286
332
  const watchMode = args.includes('-w') || args.includes('--watch');
287
- const freezeMode = args.includes('--freeze');
288
- const htmlArg = args.find(a => !a.startsWith('-'));
333
+ const freezeMode = args.includes('--freeze') || args.includes('-freeze');
334
+ const unfreezeMode = args.includes('--unfreeze') || args.includes('-unfreeze');
335
+ const positionalArgs = args.filter(a => !a.startsWith('-'));
336
+ if (positionalArgs.length > 1) {
337
+ console.error(`[importgen] Error: too many arguments: ${positionalArgs.join(', ')}`);
338
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [--unfreeze] [-v|--version]`);
339
+ process.exit(1);
340
+ }
341
+ const htmlArg = positionalArgs[0];
289
342
  const packageJsonPath = path.join(process.cwd(), 'package.json');
290
343
  // Resolve HTML file: explicit argument, or search for common names
291
344
  const possibleHtmlFiles = ['index.html', 'default.html', 'default.htm'];
@@ -300,6 +353,10 @@ if (freezeMode) {
300
353
  freezeDependencies(packageJsonPath);
301
354
  process.exit(0);
302
355
  }
356
+ if (unfreezeMode) {
357
+ unfreezeDependencies(packageJsonPath);
358
+ process.exit(0);
359
+ }
303
360
  if (!htmlFilePath || !fs.existsSync(htmlFilePath)) {
304
361
  if (htmlArg) {
305
362
  console.error(`[generate-importmap] Error: ${htmlArg} not found in current directory`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/importgen",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Generate ES Module import maps from package.json dependencies for native browser module loading",
5
5
  "main": "index.js",
6
6
  "bin": {