@vmz/vmz 0.2.7 → 0.3.0

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,6 @@
9
9
  import crypto from 'node:crypto';
10
10
  import fs from 'node:fs';
11
11
  import path from 'node:path';
12
- import { requireNativeAddon } from './native-addon.js';
13
12
  import { canonicalJson, sha256Hex } from './release-pack.js';
14
13
  import { writePrettyJsonFile } from './pretty-json.js';
15
14
  export const CONTENT_ADDRESSED_ASSETS_SCHEMA = 'vmz.content_addressed_assets.v0';
@@ -62,18 +61,14 @@ export function rewriteCssImports(cssText, rewrites) {
62
61
  * @param {Record<string, string>} [_rewrites]
63
62
  */
64
63
  export function rewriteJsEntryRelativeImports(jsText, _rewrites = {}) {
65
- const native = requireNativeAddon();
66
- if (typeof native.rewriteModuleSpecifiers !== 'function') {
67
- throw new Error('native missing rewriteModuleSpecifiers — run `pnpm napi:build`');
68
- }
69
- // Static import/export specs via oxc AST (`./x` → `../x`). Dynamic
70
- // `import("./"+id)` is not a literal specifier — rewrite that codegen form only.
71
- let out = String(native.rewriteModuleSpecifiers(String(jsText ?? ''), JSON.stringify({
72
- tsExtToJs: false,
73
- dotSlashToParent: true,
74
- })));
75
- out = out.replace(/import\(\s*"\.\/"\s*\+/g, 'import("../"+');
76
- out = out.replace(/import\(\s*'\.\/'\s*\+/g, "import('../'+");
64
+ // These files are already generated JavaScript. Re-parsing them through
65
+ // the native module parser here creates a second parser boundary during
66
+ // static assembly and can re-enter the generated graph indefinitely.
67
+ // Restrict the rewrite to import/export module-specifier positions and
68
+ // keep it bounded to the source text.
69
+ let out = String(jsText ?? '').replace(/(\b(?:from|import)\s*)(["'])\.\/([^"'\\]+)\2/g, (_match, prefix, quote, specifier) => `${prefix}${quote}../${specifier}${quote}`);
70
+ out = out.replace(/import\(\s*(["'])\.\/([^"'\\]+)\1\s*\)/g, (_match, quote, specifier) => `import(${quote}../${specifier}${quote})`);
71
+ out = out.replace(/import\(\s*(["'])\.\/\1\s*\+/g, (_match, quote) => `import(${quote}../${quote}+`);
77
72
  return out;
78
73
  }
79
74
  /**
@@ -4,7 +4,8 @@
4
4
  * Bare npm/workspace imports are legal on the author surface (01/04).
5
5
  * Browser ESM cannot resolve them. Pack materializes reachable package
6
6
  * modules under `dist/vendor/<pkg>/…` and rewrites importers to relative paths
7
- * via oxc AST (N-API `rewriteModuleSpecifiers`) — no import-text regex.
7
+ * via a bounded rewrite of generated module syntax. Pack must not re-enter the
8
+ * parser pipeline for every emitted JavaScript file.
8
9
  *
9
10
  * Not full oxc chunk-split/minify (`oxc-pending` remains for release minify).
10
11
  */
@@ -4,7 +4,8 @@
4
4
  * Bare npm/workspace imports are legal on the author surface (01/04).
5
5
  * Browser ESM cannot resolve them. Pack materializes reachable package
6
6
  * modules under `dist/vendor/<pkg>/…` and rewrites importers to relative paths
7
- * via oxc AST (N-API `rewriteModuleSpecifiers`) — no import-text regex.
7
+ * via a bounded rewrite of generated module syntax. Pack must not re-enter the
8
+ * parser pipeline for every emitted JavaScript file.
8
9
  *
9
10
  * Not full oxc chunk-split/minify (`oxc-pending` remains for release minify).
10
11
  */
@@ -60,7 +61,7 @@ export function packClientBareImports(outDir, opts = {}) {
60
61
  const before = readFileSync(file, 'utf8');
61
62
  let after = rewriteBareImports(before, file, bareToVendor);
62
63
  try {
63
- after = rewriteRelativeTsSpecs(after);
64
+ after = rewritePackModuleSpecifiers(after);
64
65
  }
65
66
  catch (error) {
66
67
  throw new Error(`pack module ${file}: ${error instanceof Error ? error.message : String(error)}`);
@@ -184,14 +185,14 @@ export function collectBareSpecs(js) {
184
185
  };
185
186
  // `from 'x'` covers import/export … from
186
187
  let m;
187
- const fromRe = /\bfrom\s+['"]([^'"]+)['"]/g;
188
+ const fromRe = /\bfrom\s*['"]([^'"]+)['"]/g;
188
189
  while ((m = fromRe.exec(js)))
189
190
  add(m[1]);
190
191
  const dynRe = /\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
191
192
  while ((m = dynRe.exec(js)))
192
193
  add(m[1]);
193
194
  // side-effect: import 'x' (not import( and not import … from)
194
- const sideRe = /\bimport\s+['"]([^'"]+)['"]/g;
195
+ const sideRe = /\bimport\s*['"]([^'"]+)['"]/g;
195
196
  while ((m = sideRe.exec(js)))
196
197
  add(m[1]);
197
198
  return [...specs];
@@ -199,7 +200,7 @@ export function collectBareSpecs(js) {
199
200
  function collectRelativeSpecs(js) {
200
201
  /** @type {Set<string>} */
201
202
  const specs = new Set();
202
- const re = /(?:from\s+|import\s*\(\s*)['"](\.[^'"]+)['"]/g;
203
+ const re = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s*)['"](\.[^'"]+)['"]/g;
203
204
  let m;
204
205
  while ((m = re.exec(js)))
205
206
  specs.add(m[1]);
@@ -327,7 +328,7 @@ function materializeModule(sourceFile) {
327
328
  if (ext === '.ts' || ext === '.tsx')
328
329
  return transpileTs(raw, sourceFile);
329
330
  try {
330
- return rewriteRelativeTsSpecs(raw);
331
+ return rewritePackModuleSpecifiers(raw);
331
332
  }
332
333
  catch (error) {
333
334
  throw new Error(`pack source ${sourceFile}: ${error instanceof Error ? error.message : String(error)}`);
@@ -347,11 +348,11 @@ function transpileTs(source, filename) {
347
348
  skipLibCheck: true,
348
349
  },
349
350
  });
350
- return rewriteRelativeTsSpecs(out.outputText || '');
351
+ return rewritePackModuleSpecifiers(out.outputText || '');
351
352
  }
352
353
  catch (err) {
353
354
  const msg = err instanceof Error ? err.message : String(err);
354
- return `/* vmz-pack: typescript transpile failed (${msg}) */\n${rewriteRelativeTsSpecs(source)}`;
355
+ return `/* vmz-pack: typescript transpile failed (${msg}) */\n${rewritePackModuleSpecifiers(source)}`;
355
356
  }
356
357
  }
357
358
  function rewriteTsExt(p) {
@@ -362,6 +363,13 @@ function rewriteTsExt(p) {
362
363
  }
363
364
  /** oxc AST module specifier rewrite (`.ts`→`.js` + optional exact map). */
364
365
  export function rewriteRelativeTsSpecs(js, exactMap = null) {
366
+ const source = String(js ?? '');
367
+ const hasModuleTsSpecifier = /(?:import\s*(?:[^'"()]*?\s*from\s*)?|export\s+[^'"()]*?\s*from\s*|import\s*\()(['"])[^'"\r\n]+\.tsx?\1/i.test(source);
368
+ const exactKeys = Object.keys(exactMap ?? {});
369
+ const hasExactSpecifier = exactKeys.some((spec) => source.includes(`'${spec}'`) || source.includes(`"${spec}"`));
370
+ if (!hasModuleTsSpecifier && !hasExactSpecifier) {
371
+ return source;
372
+ }
365
373
  const native = requireNativeAddon();
366
374
  if (typeof native.rewriteModuleSpecifiers !== 'function') {
367
375
  throw new Error('native missing rewriteModuleSpecifiers — run `pnpm napi:build`');
@@ -405,5 +413,21 @@ function rewriteBareImports(js, fromFile, bareToVendor) {
405
413
  rel = `./${rel}`;
406
414
  exact[spec] = rel;
407
415
  }
408
- return rewriteRelativeTsSpecs(js, exact);
416
+ return rewritePackModuleSpecifiers(js, exact);
417
+ }
418
+ function rewritePackModuleSpecifiers(source, exactMap = null) {
419
+ const rewrite = (spec) => {
420
+ const exact = exactMap && exactMap[spec];
421
+ if (typeof exact === 'string')
422
+ return exact;
423
+ return /\.tsx?$/i.test(spec) ? spec.replace(/\.tsx?$/i, '.js') : spec;
424
+ };
425
+ const replace = (match, quote, spec) => {
426
+ const next = rewrite(spec);
427
+ return next === spec ? match : match.replace(`${quote}${spec}${quote}`, `${quote}${next}${quote}`);
428
+ };
429
+ let out = source.replace(/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g, replace);
430
+ out = out.replace(/\bimport\s+[^;\n]*?\sfrom\s+(['"])([^'"]+)\1/g, replace);
431
+ out = out.replace(/\bimport\s*(['"])([^'"]+)\1/g, replace);
432
+ return out.replace(/\bfrom\s*(['"])([^'"]+)\1/g, replace);
409
433
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
6
6
  "license": "MIT",
@@ -48,16 +48,16 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@vmz/commander": "0.2.7",
52
- "@vmz/core": "0.2.7",
53
- "@vmz/diagnostic": "0.2.7",
54
- "@vmz/plugin": "0.2.7",
55
- "@vmz/protocol": "0.2.7",
51
+ "@vmz/commander": "0.3.0",
52
+ "@vmz/core": "0.3.0",
53
+ "@vmz/diagnostic": "0.3.0",
54
+ "@vmz/plugin": "0.3.0",
55
+ "@vmz/protocol": "0.3.0",
56
56
  "jiti": "^2.6.1"
57
57
  },
58
58
  "peerDependencies": {
59
- "@vmz/plugin-markdown-it": "0.2.7",
60
- "@vmz/test": "0.2.7",
59
+ "@vmz/plugin-markdown-it": "0.3.0",
60
+ "@vmz/test": "0.3.0",
61
61
  "typescript": "^5.8.3"
62
62
  },
63
63
  "peerDependenciesMeta": {
@@ -96,12 +96,12 @@
96
96
  "cli"
97
97
  ],
98
98
  "optionalDependencies": {
99
- "@vmz/vmz-win32-x64": "0.2.7",
100
- "@vmz/vmz-win32-arm64": "0.2.7",
101
- "@vmz/vmz-darwin-x64": "0.2.7",
102
- "@vmz/vmz-darwin-arm64": "0.2.7",
103
- "@vmz/vmz-linux-x64": "0.2.7",
104
- "@vmz/vmz-linux-arm64": "0.2.7"
99
+ "@vmz/vmz-win32-x64": "0.3.0",
100
+ "@vmz/vmz-win32-arm64": "0.3.0",
101
+ "@vmz/vmz-darwin-x64": "0.3.0",
102
+ "@vmz/vmz-darwin-arm64": "0.3.0",
103
+ "@vmz/vmz-linux-x64": "0.3.0",
104
+ "@vmz/vmz-linux-arm64": "0.3.0"
105
105
  },
106
106
  "repository": {
107
107
  "type": "git",