@bobfrankston/importgen 0.1.25 → 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.
@@ -9,7 +9,9 @@
9
9
  "Bash(ls:*)",
10
10
  "Bash(where extractids:*)",
11
11
  "Bash(cd \"y:/dev/utils/importgen\" && npx tsc --noEmit 2>&1222)",
12
- "Bash(cd y:/dev/utils/importgen && npm run release 2>&1exit)"
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:*)"
13
15
  ]
14
16
  }
15
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,20 +321,21 @@ if (args.includes('-v') || args.includes('--version')) {
283
321
  console.log(`importgen ${packageJson.version}`);
284
322
  process.exit(0);
285
323
  }
286
- const knownFlags = new Set(['-w', '--watch', '--freeze', '-freeze', '-v', '--version']);
324
+ const knownFlags = new Set(['-w', '--watch', '--freeze', '-freeze', '--unfreeze', '-unfreeze', '-v', '--version']);
287
325
  // Report unrecognized flags as errors
288
326
  const unknownArgs = args.filter(a => a.startsWith('-') && !knownFlags.has(a));
289
327
  if (unknownArgs.length > 0) {
290
328
  console.error(`[importgen] Error: unrecognized argument(s): ${unknownArgs.join(', ')}`);
291
- console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [-v|--version]`);
329
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [--unfreeze] [-v|--version]`);
292
330
  process.exit(1);
293
331
  }
294
332
  const watchMode = args.includes('-w') || args.includes('--watch');
295
333
  const freezeMode = args.includes('--freeze') || args.includes('-freeze');
334
+ const unfreezeMode = args.includes('--unfreeze') || args.includes('-unfreeze');
296
335
  const positionalArgs = args.filter(a => !a.startsWith('-'));
297
336
  if (positionalArgs.length > 1) {
298
337
  console.error(`[importgen] Error: too many arguments: ${positionalArgs.join(', ')}`);
299
- console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [-v|--version]`);
338
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [--freeze] [--unfreeze] [-v|--version]`);
300
339
  process.exit(1);
301
340
  }
302
341
  const htmlArg = positionalArgs[0];
@@ -314,6 +353,10 @@ if (freezeMode) {
314
353
  freezeDependencies(packageJsonPath);
315
354
  process.exit(0);
316
355
  }
356
+ if (unfreezeMode) {
357
+ unfreezeDependencies(packageJsonPath);
358
+ process.exit(0);
359
+ }
317
360
  if (!htmlFilePath || !fs.existsSync(htmlFilePath)) {
318
361
  if (htmlArg) {
319
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.25",
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": {