@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 +19 -0
- package/index.d.ts +11 -1
- package/index.js +102 -84
- package/package.json +5 -1
- package/.claude/settings.local.json +0 -17
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
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
212
|
-
|
|
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
|
-
|
|
239
|
-
|
|
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
|
-
|
|
222
|
+
return generateImportMap(pkgPath, htmlPath);
|
|
242
223
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
260
|
-
|
|
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
|
-
|
|
261
|
+
process.exit(1);
|
|
266
262
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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.
|
|
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
|
-
}
|