@knighted/module 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -130,7 +130,9 @@ type ModuleOptions = {
130
130
  requireMainStrategy?: 'import-meta-main' | 'realpath'
131
131
  detectCircularRequires?: 'off' | 'warn' | 'error'
132
132
  requireSource?: 'builtin' | 'create-require'
133
+ importMetaPrelude?: 'off' | 'auto' | 'on'
133
134
  cjsDefault?: 'module-exports' | 'auto' | 'none'
135
+ idiomaticExports?: 'off' | 'safe' | 'aggressive'
134
136
  topLevelAwait?: 'error' | 'wrap' | 'preserve'
135
137
  out?: string
136
138
  inPlace?: boolean
@@ -149,11 +151,13 @@ type ModuleOptions = {
149
151
  - `importMeta` (`shim`): rewrite `import.meta.*` to CommonJS equivalents.
150
152
  - `importMetaMain` (`shim`): gate `import.meta.main` with shimming/warning/error when Node support is too old.
151
153
  - `requireMainStrategy` (`import-meta-main`): use `import.meta.main` or the realpath-based `pathToFileURL(realpathSync(process.argv[1])).href` check.
154
+ - `importMetaPrelude` (`auto`): emit a no-op `void import.meta.filename;` touch. `on` always emits; `off` never emits; `auto` emits only when helpers that reference `import.meta.*` are synthesized (e.g., `__dirname`/`__filename` in CJS→ESM, require-main shims, createRequire helpers). Useful for bundlers/transpilers that do usage-based `import.meta` polyfilling.
152
155
  - `detectCircularRequires` (`off`): optionally detect relative static require cycles and warn/throw.
153
156
  - `topLevelAwait` (`error`): throw, wrap, or preserve when TLA appears in CommonJS output.
154
157
  - `rewriteSpecifier` (off): rewrite relative specifiers to a chosen extension or via a callback. Precedence: the callback (if provided) runs first; if it returns a string, that wins. If it returns `undefined` or `null`, the appenders still apply.
155
158
  - `requireSource` (`builtin`): whether `require` comes from Node or `createRequire`.
156
159
  - `cjsDefault` (`auto`): bundler-style default interop vs direct `module.exports`.
160
+ - `idiomaticExports` (`safe`): when raising CJS to ESM, attempt to synthesize `export` statements directly when it is safe. `off` always uses the helper bag; `aggressive` currently matches `safe` heuristics.
157
161
  - `out`/`inPlace`: write the transformed code to a file; otherwise the function returns the transformed string only.
158
162
  - CommonJS → ESM lowering will throw on `with` statements and unshadowed `eval` calls to avoid unsound rewrites.
159
163
 
@@ -607,6 +607,8 @@ const format = async (src, ast, opts) => {
607
607
  let requireMainNeedsRealpath = false;
608
608
  let needsRequireResolveHelper = false;
609
609
  const nestedRequireStrategy = opts.nestedRequireStrategy ?? 'create-require';
610
+ const importMetaPreludeMode = opts.importMetaPrelude ?? 'auto';
611
+ let importMetaRef = false;
610
612
  const shouldLowerCjs = opts.target === 'commonjs' && fullTransform;
611
613
  const shouldRaiseEsm = opts.target === 'module' && fullTransform;
612
614
  let hoistedImports = [];
@@ -654,6 +656,10 @@ const format = async (src, ast, opts) => {
654
656
  const mainExpr = requireMainStrategy === 'import-meta-main' ? 'import.meta.main' : 'import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href';
655
657
  if (requireMainStrategy === 'realpath') {
656
658
  requireMainNeedsRealpath = true;
659
+ importMetaRef = true;
660
+ }
661
+ if (requireMainStrategy === 'import-meta-main') {
662
+ importMetaRef = true;
657
663
  }
658
664
  code.update(node.start, node.end, negate ? `!(${mainExpr})` : mainExpr);
659
665
  return;
@@ -772,6 +778,9 @@ const format = async (src, ast, opts) => {
772
778
  }
773
779
  }
774
780
  if ((0, _identifier2.isIdentifierName)(node)) {
781
+ if (shouldRaiseEsm && node.type === 'Identifier' && (node.name === '__dirname' || node.name === '__filename')) {
782
+ importMetaRef = true;
783
+ }
775
784
  (0, _identifier.identifier)({
776
785
  node,
777
786
  ancestors,
@@ -827,8 +836,14 @@ const format = async (src, ast, opts) => {
827
836
  const asExportName = name => isValidExportName(name) ? name : JSON.stringify(name);
828
837
  const accessProp = name => isValidExportName(name) ? `${_exports.exportsRename}.${name}` : `${_exports.exportsRename}[${JSON.stringify(name)}]`;
829
838
  const exportValueFor = name => {
830
- if (name === '__dirname') return 'import.meta.dirname';
831
- if (name === '__filename') return 'import.meta.filename';
839
+ if (name === '__dirname') {
840
+ importMetaRef = true;
841
+ return 'import.meta.dirname';
842
+ }
843
+ if (name === '__filename') {
844
+ importMetaRef = true;
845
+ return 'import.meta.filename';
846
+ }
832
847
  return name;
833
848
  };
834
849
  const tempNameFor = name => {
@@ -884,6 +899,9 @@ const format = async (src, ast, opts) => {
884
899
  }
885
900
  if (shouldRaiseEsm && fullTransform) {
886
901
  const importPrelude = [];
902
+ if (needsCreateRequire || needsRequireResolveHelper) {
903
+ importMetaRef = true;
904
+ }
887
905
  if (needsCreateRequire || needsRequireResolveHelper) {
888
906
  importPrelude.push('import { createRequire } from "node:module";\n');
889
907
  }
@@ -916,9 +934,13 @@ const format = async (src, ast, opts) => {
916
934
  const exportsBagInit = useExportsBag ? `let ${_exports.exportsRename} = {};
917
935
  ` : '';
918
936
  const modulePrelude = '';
919
- const prelude = `${importPrelude.join('')}${importPrelude.length ? '\n' : ''}${setupPrelude.join('')}${setupPrelude.length ? '\n' : ''}${requireInit}${requireResolveInit}${exportsBagInit}${modulePrelude}void import.meta.filename;
920
- `;
921
- code.prepend(prelude);
937
+ const prelude = `${importPrelude.join('')}${importPrelude.length ? '\n' : ''}${setupPrelude.join('')}${setupPrelude.length ? '\n' : ''}${requireInit}${requireResolveInit}${exportsBagInit}${modulePrelude}`;
938
+ const importMetaTouch = (() => {
939
+ if (importMetaPreludeMode === 'on') return 'void import.meta.filename;\n';
940
+ if (importMetaPreludeMode === 'off') return '';
941
+ return importMetaRef ? 'void import.meta.filename;\n' : '';
942
+ })();
943
+ code.prepend(`${prelude}${importMetaTouch}`);
922
944
  }
923
945
  if (opts.target === 'commonjs' && fullTransform && containsTopLevelAwait) {
924
946
  const body = code.toString();
@@ -161,6 +161,7 @@ const defaultOptions = {
161
161
  nestedRequireStrategy: 'create-require',
162
162
  cjsDefault: 'auto',
163
163
  idiomaticExports: 'safe',
164
+ importMetaPrelude: 'auto',
164
165
  topLevelAwait: 'error',
165
166
  out: undefined,
166
167
  inPlace: false
@@ -40,6 +40,8 @@ export type ModuleOptions = {
40
40
  cjsDefault?: 'module-exports' | 'auto' | 'none';
41
41
  /** Emit idiomatic exports when raising CJS to ESM. */
42
42
  idiomaticExports?: 'off' | 'safe' | 'aggressive';
43
+ /** Control whether a no-op import.meta prelude is emitted. */
44
+ importMetaPrelude?: 'off' | 'auto' | 'on';
43
45
  /** Handling for top-level await constructs. */
44
46
  topLevelAwait?: 'error' | 'wrap' | 'preserve';
45
47
  /** Optional diagnostics sink for warnings/errors emitted during transform. */
package/dist/format.js CHANGED
@@ -600,6 +600,8 @@ const format = async (src, ast, opts) => {
600
600
  let requireMainNeedsRealpath = false;
601
601
  let needsRequireResolveHelper = false;
602
602
  const nestedRequireStrategy = opts.nestedRequireStrategy ?? 'create-require';
603
+ const importMetaPreludeMode = opts.importMetaPrelude ?? 'auto';
604
+ let importMetaRef = false;
603
605
  const shouldLowerCjs = opts.target === 'commonjs' && fullTransform;
604
606
  const shouldRaiseEsm = opts.target === 'module' && fullTransform;
605
607
  let hoistedImports = [];
@@ -647,6 +649,10 @@ const format = async (src, ast, opts) => {
647
649
  const mainExpr = requireMainStrategy === 'import-meta-main' ? 'import.meta.main' : 'import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href';
648
650
  if (requireMainStrategy === 'realpath') {
649
651
  requireMainNeedsRealpath = true;
652
+ importMetaRef = true;
653
+ }
654
+ if (requireMainStrategy === 'import-meta-main') {
655
+ importMetaRef = true;
650
656
  }
651
657
  code.update(node.start, node.end, negate ? `!(${mainExpr})` : mainExpr);
652
658
  return;
@@ -765,6 +771,9 @@ const format = async (src, ast, opts) => {
765
771
  }
766
772
  }
767
773
  if (isIdentifierName(node)) {
774
+ if (shouldRaiseEsm && node.type === 'Identifier' && (node.name === '__dirname' || node.name === '__filename')) {
775
+ importMetaRef = true;
776
+ }
768
777
  identifier({
769
778
  node,
770
779
  ancestors,
@@ -820,8 +829,14 @@ const format = async (src, ast, opts) => {
820
829
  const asExportName = name => isValidExportName(name) ? name : JSON.stringify(name);
821
830
  const accessProp = name => isValidExportName(name) ? `${exportsRename}.${name}` : `${exportsRename}[${JSON.stringify(name)}]`;
822
831
  const exportValueFor = name => {
823
- if (name === '__dirname') return 'import.meta.dirname';
824
- if (name === '__filename') return 'import.meta.filename';
832
+ if (name === '__dirname') {
833
+ importMetaRef = true;
834
+ return 'import.meta.dirname';
835
+ }
836
+ if (name === '__filename') {
837
+ importMetaRef = true;
838
+ return 'import.meta.filename';
839
+ }
825
840
  return name;
826
841
  };
827
842
  const tempNameFor = name => {
@@ -877,6 +892,9 @@ const format = async (src, ast, opts) => {
877
892
  }
878
893
  if (shouldRaiseEsm && fullTransform) {
879
894
  const importPrelude = [];
895
+ if (needsCreateRequire || needsRequireResolveHelper) {
896
+ importMetaRef = true;
897
+ }
880
898
  if (needsCreateRequire || needsRequireResolveHelper) {
881
899
  importPrelude.push('import { createRequire } from "node:module";\n');
882
900
  }
@@ -909,9 +927,13 @@ const format = async (src, ast, opts) => {
909
927
  const exportsBagInit = useExportsBag ? `let ${exportsRename} = {};
910
928
  ` : '';
911
929
  const modulePrelude = '';
912
- const prelude = `${importPrelude.join('')}${importPrelude.length ? '\n' : ''}${setupPrelude.join('')}${setupPrelude.length ? '\n' : ''}${requireInit}${requireResolveInit}${exportsBagInit}${modulePrelude}void import.meta.filename;
913
- `;
914
- code.prepend(prelude);
930
+ const prelude = `${importPrelude.join('')}${importPrelude.length ? '\n' : ''}${setupPrelude.join('')}${setupPrelude.length ? '\n' : ''}${requireInit}${requireResolveInit}${exportsBagInit}${modulePrelude}`;
931
+ const importMetaTouch = (() => {
932
+ if (importMetaPreludeMode === 'on') return 'void import.meta.filename;\n';
933
+ if (importMetaPreludeMode === 'off') return '';
934
+ return importMetaRef ? 'void import.meta.filename;\n' : '';
935
+ })();
936
+ code.prepend(`${prelude}${importMetaTouch}`);
915
937
  }
916
938
  if (opts.target === 'commonjs' && fullTransform && containsTopLevelAwait) {
917
939
  const body = code.toString();
package/dist/module.js CHANGED
@@ -158,6 +158,7 @@ const defaultOptions = {
158
158
  nestedRequireStrategy: 'create-require',
159
159
  cjsDefault: 'auto',
160
160
  idiomaticExports: 'safe',
161
+ importMetaPrelude: 'auto',
161
162
  topLevelAwait: 'error',
162
163
  out: undefined,
163
164
  inPlace: false
@@ -40,6 +40,8 @@ export type ModuleOptions = {
40
40
  cjsDefault?: 'module-exports' | 'auto' | 'none';
41
41
  /** Emit idiomatic exports when raising CJS to ESM. */
42
42
  idiomaticExports?: 'off' | 'safe' | 'aggressive';
43
+ /** Control whether a no-op import.meta prelude is emitted. */
44
+ importMetaPrelude?: 'off' | 'auto' | 'on';
43
45
  /** Handling for top-level await constructs. */
44
46
  topLevelAwait?: 'error' | 'wrap' | 'preserve';
45
47
  /** Optional diagnostics sink for warnings/errors emitted during transform. */
package/dist/types.d.ts CHANGED
@@ -40,6 +40,8 @@ export type ModuleOptions = {
40
40
  cjsDefault?: 'module-exports' | 'auto' | 'none';
41
41
  /** Emit idiomatic exports when raising CJS to ESM. */
42
42
  idiomaticExports?: 'off' | 'safe' | 'aggressive';
43
+ /** Control whether a no-op import.meta prelude is emitted. */
44
+ importMetaPrelude?: 'off' | 'auto' | 'on';
43
45
  /** Handling for top-level await constructs. */
44
46
  topLevelAwait?: 'error' | 'wrap' | 'preserve';
45
47
  /** Optional diagnostics sink for warnings/errors emitted during transform. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/module",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Bidirectional transform for ES modules and CommonJS.",
5
5
  "type": "module",
6
6
  "main": "dist/module.js",