@bobfrankston/importgen 0.1.28 → 0.1.29

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.
package/README.md CHANGED
@@ -103,6 +103,25 @@ The browser sees `date-utils`, looks it up in the import map, and loads `./node_
103
103
 
104
104
  The key point: your TypeScript source files are the same whether they run in Node or the browser. `importgen` just provides the mapping the browser needs to find the packages.
105
105
 
106
+ ## Programmatic API
107
+
108
+ `importgen` can be called from another application (e.g., `npmglobalize`) instead of the CLI:
109
+
110
+ ```typescript
111
+ import { importgen } from "@bobfrankston/importgen";
112
+
113
+ // Generate import map for a specific directory
114
+ importgen("/path/to/my/app");
115
+
116
+ // With explicit HTML filename
117
+ importgen("/path/to/my/app", "default.htm");
118
+
119
+ // Uses process.cwd() if no directory given
120
+ importgen();
121
+ ```
122
+
123
+ The function throws on missing `package.json` or HTML file (instead of calling `process.exit`), so callers can handle errors. Returns a `GenerateResult` with resolved dependency directories.
124
+
106
125
  ## How Entry Points Are Resolved
107
126
 
108
127
  For each dependency, `importgen` reads that package's `package.json` and picks the entry point in this order:
package/index.d.ts CHANGED
@@ -3,5 +3,15 @@
3
3
  * Generate ES Module import map from package.json dependencies
4
4
  * Injects into HTML files for native browser module loading
5
5
  */
6
- export {};
6
+ /** Result from generateImportMap including paths for watch mode */
7
+ export interface GenerateResult {
8
+ depDirs: string[]; /** Resolved dependency directories */
9
+ }
10
+ /**
11
+ * API: run importgen on a directory.
12
+ * @param appDir - directory containing package.json and HTML file (defaults to cwd)
13
+ * @param htmlFile - HTML filename to update (auto-detected if omitted)
14
+ * @returns GenerateResult with resolved dependency directories
15
+ */
16
+ export declare function importgen(appDir?: string, htmlFile?: string): GenerateResult;
7
17
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -199,98 +199,116 @@ function generateImportMap(packageJsonPath, htmlFilePath) {
199
199
  }
200
200
  return result;
201
201
  }
202
- // Parse CLI arguments
203
- const args = process.argv.slice(2);
204
- if (args.includes('-v') || args.includes('--version')) {
205
- console.log(`importgen ${packageJson.version}`);
206
- process.exit(0);
207
- }
208
- const knownFlags = new Set(['-w', '--watch', '-v', '--version']);
209
- // Report unrecognized flags as errors
210
- const unknownArgs = args.filter(a => a.startsWith('-') && !knownFlags.has(a));
211
- if (unknownArgs.length > 0) {
212
- console.error(`${ts()} [importgen] Error: unrecognized argument(s): ${unknownArgs.join(', ')}`);
213
- console.error(` Usage: importgen [htmlfile] [-w|--watch] [-v|--version]`);
214
- process.exit(1);
215
- }
216
- const watchMode = args.includes('-w') || args.includes('--watch');
217
- const positionalArgs = args.filter(a => !a.startsWith('-'));
218
- if (positionalArgs.length > 1) {
219
- console.error(`${ts()} [importgen] Error: too many arguments: ${positionalArgs.join(', ')}`);
220
- console.error(` Usage: importgen [htmlfile] [-w|--watch] [-v|--version]`);
221
- process.exit(1);
222
- }
223
- const htmlArg = positionalArgs[0];
224
- const packageJsonPath = path.join(process.cwd(), 'package.json');
225
- // Resolve HTML file: explicit argument, or search for common names
226
- const possibleHtmlFiles = ['index.html', 'default.html', 'default.htm'];
227
- const htmlFileName = htmlArg || possibleHtmlFiles.find(f => fs.existsSync(path.join(process.cwd(), f)));
228
- const htmlFilePath = htmlFileName ? path.join(process.cwd(), htmlFileName) : null;
229
- // Check if files exist
230
- if (!fs.existsSync(packageJsonPath)) {
231
- console.error(`${ts()} [generate-importmap] Error: package.json not found in current directory`);
232
- process.exit(1);
233
- }
234
- if (!htmlFilePath || !fs.existsSync(htmlFilePath)) {
235
- if (htmlArg) {
236
- console.error(`${ts()} [generate-importmap] Error: ${htmlArg} not found in current directory`);
202
+ /**
203
+ * API: run importgen on a directory.
204
+ * @param appDir - directory containing package.json and HTML file (defaults to cwd)
205
+ * @param htmlFile - HTML filename to update (auto-detected if omitted)
206
+ * @returns GenerateResult with resolved dependency directories
207
+ */
208
+ export function importgen(appDir, htmlFile) {
209
+ const dir = appDir || process.cwd();
210
+ const pkgPath = path.join(dir, 'package.json');
211
+ if (!fs.existsSync(pkgPath)) {
212
+ throw new Error(`package.json not found in ${dir}`);
237
213
  }
238
- else {
239
- console.error(`${ts()} [generate-importmap] Error: No HTML file found. Looking for: ${possibleHtmlFiles.join(', ')}`);
214
+ const possibleHtmlFiles = ['index.html', 'default.html', 'default.htm'];
215
+ const htmlName = htmlFile || possibleHtmlFiles.find(f => fs.existsSync(path.join(dir, f)));
216
+ const htmlPath = htmlName ? path.join(dir, htmlName) : null;
217
+ if (!htmlPath || !fs.existsSync(htmlPath)) {
218
+ throw new Error(htmlFile
219
+ ? `${htmlFile} not found in ${dir}`
220
+ : `No HTML file found in ${dir}. Looking for: ${possibleHtmlFiles.join(', ')}`);
240
221
  }
241
- process.exit(1);
222
+ return generateImportMap(pkgPath, htmlPath);
242
223
  }
243
- if (watchMode) {
244
- let result = generateImportMap(packageJsonPath, htmlFilePath);
245
- let watchedDepDirs = new Set();
246
- const watcher = chokidar.watch([packageJsonPath], {
247
- persistent: true,
248
- ignoreInitial: true
249
- });
250
- /** Update watcher to include/remove dependency directories */
251
- function syncWatchedDeps(depDirs) {
252
- const newDirs = new Set(depDirs);
253
- // Remove dirs no longer in dependency list
254
- for (const dir of watchedDepDirs) {
255
- if (!newDirs.has(dir)) {
256
- watcher.unwatch(dir);
257
- }
224
+ // CLI entry point
225
+ if (import.meta.main) {
226
+ const args = process.argv.slice(2);
227
+ if (args.includes('-v') || args.includes('--version')) {
228
+ console.log(`importgen ${packageJson.version}`);
229
+ process.exit(0);
230
+ }
231
+ const knownFlags = new Set(['-w', '--watch', '-v', '--version']);
232
+ const unknownArgs = args.filter(a => a.startsWith('-') && !knownFlags.has(a));
233
+ if (unknownArgs.length > 0) {
234
+ console.error(`${ts()} [importgen] Error: unrecognized argument(s): ${unknownArgs.join(', ')}`);
235
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [-v|--version]`);
236
+ process.exit(1);
237
+ }
238
+ const watchMode = args.includes('-w') || args.includes('--watch');
239
+ const positionalArgs = args.filter(a => !a.startsWith('-'));
240
+ if (positionalArgs.length > 1) {
241
+ console.error(`${ts()} [importgen] Error: too many arguments: ${positionalArgs.join(', ')}`);
242
+ console.error(` Usage: importgen [htmlfile] [-w|--watch] [-v|--version]`);
243
+ process.exit(1);
244
+ }
245
+ const htmlArg = positionalArgs[0];
246
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
247
+ const possibleHtmlFiles = ['index.html', 'default.html', 'default.htm'];
248
+ const htmlFileName = htmlArg || possibleHtmlFiles.find(f => fs.existsSync(path.join(process.cwd(), f)));
249
+ const htmlFilePath = htmlFileName ? path.join(process.cwd(), htmlFileName) : null;
250
+ if (!fs.existsSync(packageJsonPath)) {
251
+ console.error(`${ts()} [generate-importmap] Error: package.json not found in current directory`);
252
+ process.exit(1);
253
+ }
254
+ if (!htmlFilePath || !fs.existsSync(htmlFilePath)) {
255
+ if (htmlArg) {
256
+ console.error(`${ts()} [generate-importmap] Error: ${htmlArg} not found in current directory`);
258
257
  }
259
- // Add new dirs
260
- for (const dir of newDirs) {
261
- if (!watchedDepDirs.has(dir)) {
262
- watcher.add(dir);
263
- }
258
+ else {
259
+ console.error(`${ts()} [generate-importmap] Error: No HTML file found. Looking for: ${possibleHtmlFiles.join(', ')}`);
264
260
  }
265
- watchedDepDirs = newDirs;
261
+ process.exit(1);
266
262
  }
267
- syncWatchedDeps(result.depDirs);
268
- let debounceTimer = null;
269
- const onChange = () => {
270
- if (debounceTimer)
271
- clearTimeout(debounceTimer);
272
- debounceTimer = setTimeout(() => {
273
- result = generateImportMap(packageJsonPath, htmlFilePath);
274
- syncWatchedDeps(result.depDirs);
275
- }, 100);
276
- };
277
- watcher.on('change', onChange);
278
- watcher.on('add', onChange);
279
- watcher.on('unlink', onChange);
280
- watcher.on('ready', () => {
281
- const total = 1 + watchedDepDirs.size;
282
- console.log(`${ts()} [generate-importmap] Watching ${total} directories for changes...`);
283
- if (watchedDepDirs.size > 0) {
263
+ if (watchMode) {
264
+ let result = generateImportMap(packageJsonPath, htmlFilePath);
265
+ let watchedDepDirs = new Set();
266
+ const watcher = chokidar.watch([packageJsonPath], {
267
+ persistent: true,
268
+ ignoreInitial: true
269
+ });
270
+ function syncWatchedDeps(depDirs) {
271
+ const newDirs = new Set(depDirs);
284
272
  for (const dir of watchedDepDirs) {
285
- console.log(` ${dir}`);
273
+ if (!newDirs.has(dir)) {
274
+ watcher.unwatch(dir);
275
+ }
286
276
  }
277
+ for (const dir of newDirs) {
278
+ if (!watchedDepDirs.has(dir)) {
279
+ watcher.add(dir);
280
+ }
281
+ }
282
+ watchedDepDirs = newDirs;
287
283
  }
288
- });
289
- watcher.on('error', (error) => {
290
- console.error(`${ts()} [generate-importmap] Watcher error:`, error.message);
291
- });
292
- }
293
- else {
294
- generateImportMap(packageJsonPath, htmlFilePath);
284
+ syncWatchedDeps(result.depDirs);
285
+ let debounceTimer = null;
286
+ const onChange = () => {
287
+ if (debounceTimer)
288
+ clearTimeout(debounceTimer);
289
+ debounceTimer = setTimeout(() => {
290
+ result = generateImportMap(packageJsonPath, htmlFilePath);
291
+ syncWatchedDeps(result.depDirs);
292
+ }, 100);
293
+ };
294
+ watcher.on('change', onChange);
295
+ watcher.on('add', onChange);
296
+ watcher.on('unlink', onChange);
297
+ watcher.on('ready', () => {
298
+ const total = 1 + watchedDepDirs.size;
299
+ console.log(`${ts()} [generate-importmap] Watching ${total} directories for changes...`);
300
+ if (watchedDepDirs.size > 0) {
301
+ for (const dir of watchedDepDirs) {
302
+ console.log(` ${dir}`);
303
+ }
304
+ }
305
+ });
306
+ watcher.on('error', (error) => {
307
+ console.error(`${ts()} [generate-importmap] Watcher error:`, error.message);
308
+ });
309
+ }
310
+ else {
311
+ generateImportMap(packageJsonPath, htmlFilePath);
312
+ }
295
313
  }
296
314
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "@bobfrankston/importgen",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "Generate ES Module import maps from package.json dependencies for native browser module loading",
5
5
  "main": "index.js",
6
+ "exports": {
7
+ ".": "./index.js"
8
+ },
6
9
  "bin": {
7
10
  "importgen": "index.js"
8
11
  },
9
12
  "type": "module",
10
13
  "scripts": {
14
+ "start": "node index.js --watch",
11
15
  "build": "tsc",
12
16
  "watch": "tsc -w",
13
17
  "preversion": "npm run build",
@@ -1,17 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npm run build:*)",
5
- "Bash(npmglobalize)",
6
- "Bash(npx tsc)",
7
- "Bash(node index.js:*)",
8
- "Bash(dir:*)",
9
- "Bash(ls:*)",
10
- "Bash(where extractids:*)",
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:*)"
15
- ]
16
- }
17
- }