@knighted/module 1.0.0-beta.0 → 1.0.0-beta.2

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.
Files changed (55) hide show
  1. package/README.md +34 -4
  2. package/dist/cjs/exports.d.cts +6 -0
  3. package/dist/cjs/format.cjs +315 -12
  4. package/dist/cjs/format.d.cts +3 -2
  5. package/dist/cjs/formatters/assignmentExpression.cjs +1 -1
  6. package/dist/cjs/formatters/identifier.cjs +4 -4
  7. package/dist/cjs/formatters/memberExpression.cjs +2 -2
  8. package/dist/cjs/formatters/metaProperty.cjs +19 -1
  9. package/dist/cjs/identifiers.d.cts +19 -0
  10. package/dist/cjs/lang.d.cts +4 -0
  11. package/dist/cjs/module.cjs +5 -4
  12. package/dist/cjs/types.d.cts +9 -0
  13. package/dist/cjs/url.d.cts +2 -0
  14. package/dist/cjs/utils/exports.cjs +227 -0
  15. package/dist/cjs/utils/identifiers.cjs +190 -0
  16. package/dist/cjs/utils/lang.cjs +25 -0
  17. package/dist/cjs/utils/url.cjs +16 -0
  18. package/dist/cjs/utils.cjs +71 -1
  19. package/dist/cjs/utils.d.cts +3 -2
  20. package/dist/exports.d.ts +6 -0
  21. package/dist/format.d.ts +3 -2
  22. package/dist/format.js +311 -9
  23. package/dist/formatters/assignmentExpression.js +1 -1
  24. package/dist/formatters/identifier.js +2 -2
  25. package/dist/formatters/memberExpression.js +1 -1
  26. package/dist/formatters/metaProperty.js +19 -1
  27. package/dist/identifiers.d.ts +19 -0
  28. package/dist/lang.d.ts +4 -0
  29. package/dist/module.js +4 -3
  30. package/dist/src/format.d.ts +9 -0
  31. package/dist/src/module.d.ts +3 -0
  32. package/dist/src/parse.d.ts +2 -0
  33. package/dist/src/types.d.ts +44 -0
  34. package/dist/src/utils/exports.d.ts +6 -0
  35. package/dist/src/utils/identifiers.d.ts +19 -0
  36. package/dist/src/utils/lang.d.ts +4 -0
  37. package/dist/src/utils/url.d.ts +2 -0
  38. package/dist/src/utils.d.ts +26 -0
  39. package/dist/src/walk.d.ts +20 -0
  40. package/dist/types.d.ts +9 -0
  41. package/dist/url.d.ts +2 -0
  42. package/dist/utils/exports.js +221 -0
  43. package/dist/utils/identifiers.js +183 -0
  44. package/dist/utils/lang.js +20 -0
  45. package/dist/utils/url.js +10 -0
  46. package/dist/utils.d.ts +3 -2
  47. package/dist/utils.js +70 -1
  48. package/package.json +4 -4
  49. /package/dist/{formatters → src/formatters}/assignmentExpression.d.ts +0 -0
  50. /package/dist/{formatters → src/formatters}/expressionStatement.d.ts +0 -0
  51. /package/dist/{formatters → src/formatters}/identifier.d.ts +0 -0
  52. /package/dist/{formatters → src/formatters}/memberExpression.d.ts +0 -0
  53. /package/dist/{formatters → src/formatters}/metaProperty.d.ts +0 -0
  54. /package/dist/{helpers → src/helpers}/identifier.d.ts +0 -0
  55. /package/dist/{helpers → src/helpers}/scope.d.ts +0 -0
package/dist/format.js CHANGED
@@ -1,15 +1,251 @@
1
1
  import MagicString from 'magic-string';
2
- import { identifier } from './formatters/identifier.js';
3
- import { metaProperty } from './formatters/metaProperty.js';
4
- import { memberExpression } from './formatters/memberExpression.js';
5
- import { assignmentExpression } from './formatters/assignmentExpression.js';
6
- import { isValidUrl, exportsRename, collectModuleIdentifiers } from './utils.js';
7
- import { isIdentifierName } from './helpers/identifier.js';
8
- import { ancestorWalk } from './walk.js';
2
+ import { identifier } from '#formatters/identifier.js';
3
+ import { metaProperty } from '#formatters/metaProperty.js';
4
+ import { memberExpression } from '#formatters/memberExpression.js';
5
+ import { assignmentExpression } from '#formatters/assignmentExpression.js';
6
+ import { isValidUrl } from '#utils/url.js';
7
+ import { exportsRename, collectCjsExports } from '#utils/exports.js';
8
+ import { collectModuleIdentifiers } from '#utils/identifiers.js';
9
+ import { isIdentifierName } from '#helpers/identifier.js';
10
+ import { ancestorWalk } from '#walk';
11
+ const isValidIdent = name => /^[$A-Z_a-z][$\w]*$/.test(name);
12
+ const exportAssignment = (name, expr, live) => {
13
+ const prop = isValidIdent(name) ? `.${name}` : `[${JSON.stringify(name)}]`;
14
+ if (live === 'strict') {
15
+ const key = JSON.stringify(name);
16
+ return `Object.defineProperty(exports, ${key}, { enumerable: true, get: () => ${expr} });`;
17
+ }
18
+ return `exports${prop} = ${expr};`;
19
+ };
20
+ const defaultInteropName = '__interopDefault';
21
+ const interopHelper = `const ${defaultInteropName} = mod => (mod && mod.__esModule ? mod.default : mod);\n`;
22
+ const hasTopLevelAwait = program => {
23
+ let found = false;
24
+ const walkNode = (node, inFunction) => {
25
+ if (found) return;
26
+ switch (node.type) {
27
+ case 'FunctionDeclaration':
28
+ case 'FunctionExpression':
29
+ case 'ArrowFunctionExpression':
30
+ case 'ClassDeclaration':
31
+ case 'ClassExpression':
32
+ inFunction = true;
33
+ break;
34
+ }
35
+ if (!inFunction && node.type === 'AwaitExpression') {
36
+ found = true;
37
+ return;
38
+ }
39
+ const keys = Object.keys(node);
40
+ for (const key of keys) {
41
+ const value = node[key];
42
+ if (!value) continue;
43
+ if (Array.isArray(value)) {
44
+ for (const item of value) {
45
+ if (item && typeof item === 'object') {
46
+ walkNode(item, inFunction);
47
+ if (found) return;
48
+ }
49
+ }
50
+ } else if (value && typeof value === 'object') {
51
+ walkNode(value, inFunction);
52
+ if (found) return;
53
+ }
54
+ }
55
+ };
56
+ walkNode(program, false);
57
+ return found;
58
+ };
59
+ const lowerEsmToCjs = (program, code, opts, containsTopLevelAwait) => {
60
+ const live = opts.liveBindings ?? 'strict';
61
+ const importTransforms = [];
62
+ const exportTransforms = [];
63
+ let needsInterop = false;
64
+ let importIndex = 0;
65
+ for (const node of program.body) {
66
+ if (node.type === 'ImportDeclaration') {
67
+ const srcLiteral = code.slice(node.source.start, node.source.end);
68
+ const specifiers = node.specifiers ?? [];
69
+ const defaultSpec = specifiers.find(s => s.type === 'ImportDefaultSpecifier');
70
+ const namespaceSpec = specifiers.find(s => s.type === 'ImportNamespaceSpecifier');
71
+ const namedSpecs = specifiers.filter(s => s.type === 'ImportSpecifier');
72
+
73
+ // Side-effect import
74
+ if (!specifiers.length) {
75
+ importTransforms.push({
76
+ start: node.start,
77
+ end: node.end,
78
+ code: `require(${srcLiteral});\n`,
79
+ needsInterop: false
80
+ });
81
+ continue;
82
+ }
83
+ const modIdent = `__mod${importIndex++}`;
84
+ const lines = [];
85
+ lines.push(`const ${modIdent} = require(${srcLiteral});`);
86
+ if (namespaceSpec) {
87
+ lines.push(`const ${namespaceSpec.local.name} = ${modIdent};`);
88
+ }
89
+ if (defaultSpec) {
90
+ let init = modIdent;
91
+ switch (opts.cjsDefault) {
92
+ case 'module-exports':
93
+ init = modIdent;
94
+ break;
95
+ case 'none':
96
+ init = `${modIdent}.default`;
97
+ break;
98
+ case 'auto':
99
+ default:
100
+ init = `${defaultInteropName}(${modIdent})`;
101
+ needsInterop = true;
102
+ break;
103
+ }
104
+ lines.push(`const ${defaultSpec.local.name} = ${init};`);
105
+ }
106
+ if (namedSpecs.length) {
107
+ const pairs = namedSpecs.map(s => {
108
+ const imported = s.imported.name;
109
+ const local = s.local.name;
110
+ return imported === local ? imported : `${imported}: ${local}`;
111
+ });
112
+ lines.push(`const { ${pairs.join(', ')} } = ${modIdent};`);
113
+ }
114
+ importTransforms.push({
115
+ start: node.start,
116
+ end: node.end,
117
+ code: `${lines.join('\n')}\n`,
118
+ needsInterop
119
+ });
120
+ }
121
+ if (node.type === 'ExportNamedDeclaration') {
122
+ // Handle declaration exports
123
+ if (node.declaration) {
124
+ const decl = node.declaration;
125
+ const declSrc = code.slice(decl.start, decl.end);
126
+ const exportedNames = [];
127
+ if (decl.type === 'VariableDeclaration') {
128
+ for (const d of decl.declarations) {
129
+ if (d.id.type === 'Identifier') {
130
+ exportedNames.push(d.id.name);
131
+ }
132
+ }
133
+ } else if (decl.id?.type === 'Identifier') {
134
+ exportedNames.push(decl.id.name);
135
+ }
136
+ const exportLines = exportedNames.map(name => exportAssignment(name, name, live));
137
+ exportTransforms.push({
138
+ start: node.start,
139
+ end: node.end,
140
+ code: `${declSrc}\n${exportLines.join('\n')}\n`
141
+ });
142
+ continue;
143
+ }
9
144
 
145
+ // Handle re-export or local specifiers
146
+ if (node.specifiers?.length) {
147
+ if (node.source) {
148
+ const srcLiteral = code.slice(node.source.start, node.source.end);
149
+ const modIdent = `__mod${importIndex++}`;
150
+ const lines = [`const ${modIdent} = require(${srcLiteral});`];
151
+ for (const spec of node.specifiers) {
152
+ if (spec.type !== 'ExportSpecifier') continue;
153
+ const exported = spec.exported.name;
154
+ const imported = spec.local.name;
155
+ let rhs = `${modIdent}.${imported}`;
156
+ if (imported === 'default') {
157
+ rhs = `${defaultInteropName}(${modIdent})`;
158
+ needsInterop = true;
159
+ }
160
+ lines.push(exportAssignment(exported, rhs, live));
161
+ }
162
+ exportTransforms.push({
163
+ start: node.start,
164
+ end: node.end,
165
+ code: `${lines.join('\n')}\n`,
166
+ needsInterop
167
+ });
168
+ } else {
169
+ const lines = [];
170
+ for (const spec of node.specifiers) {
171
+ if (spec.type !== 'ExportSpecifier') continue;
172
+ const exported = spec.exported.name;
173
+ const local = spec.local.name;
174
+ lines.push(exportAssignment(exported, local, live));
175
+ }
176
+ exportTransforms.push({
177
+ start: node.start,
178
+ end: node.end,
179
+ code: `${lines.join('\n')}\n`
180
+ });
181
+ }
182
+ }
183
+ }
184
+ if (node.type === 'ExportDefaultDeclaration') {
185
+ const decl = node.declaration;
186
+ const useExportsObject = containsTopLevelAwait && opts.topLevelAwait !== 'error';
187
+ if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {
188
+ if (decl.id?.name) {
189
+ const declSrc = code.slice(decl.start, decl.end);
190
+ const assign = useExportsObject ? `exports.default = ${decl.id.name};` : `module.exports = ${decl.id.name};`;
191
+ exportTransforms.push({
192
+ start: node.start,
193
+ end: node.end,
194
+ code: `${declSrc}\n${assign}\n`
195
+ });
196
+ } else {
197
+ const declSrc = code.slice(decl.start, decl.end);
198
+ const assign = useExportsObject ? `exports.default = ${declSrc};` : `module.exports = ${declSrc};`;
199
+ exportTransforms.push({
200
+ start: node.start,
201
+ end: node.end,
202
+ code: `${assign}\n`
203
+ });
204
+ }
205
+ } else {
206
+ const exprSrc = code.slice(decl.start, decl.end);
207
+ const assign = useExportsObject ? `exports.default = ${exprSrc};` : `module.exports = ${exprSrc};`;
208
+ exportTransforms.push({
209
+ start: node.start,
210
+ end: node.end,
211
+ code: `${assign}\n`
212
+ });
213
+ }
214
+ }
215
+ if (node.type === 'ExportAllDeclaration') {
216
+ const srcLiteral = code.slice(node.source.start, node.source.end);
217
+ if (node.exported) {
218
+ const exported = node.exported.name;
219
+ const modIdent = `__mod${importIndex++}`;
220
+ const lines = [`const ${modIdent} = require(${srcLiteral});`, exportAssignment(exported, modIdent, live)];
221
+ exportTransforms.push({
222
+ start: node.start,
223
+ end: node.end,
224
+ code: `${lines.join('\n')}\n`
225
+ });
226
+ } else {
227
+ const modIdent = `__mod${importIndex++}`;
228
+ const lines = [`const ${modIdent} = require(${srcLiteral});`];
229
+ const loop = `for (const k in ${modIdent}) {\n if (k === 'default') continue;\n if (!Object.prototype.hasOwnProperty.call(${modIdent}, k)) continue;\n Object.defineProperty(exports, k, { enumerable: true, get: () => ${modIdent}[k] });\n}`;
230
+ lines.push(loop);
231
+ exportTransforms.push({
232
+ start: node.start,
233
+ end: node.end,
234
+ code: `${lines.join('\n')}\n`
235
+ });
236
+ }
237
+ }
238
+ }
239
+ return {
240
+ importTransforms,
241
+ exportTransforms,
242
+ needsInterop
243
+ };
244
+ };
10
245
  /**
11
- * Note, there is no specific conversion for `import.meta.main` as it does not exist.
12
- * @see https://github.com/nodejs/node/issues/49440
246
+ * Node added support for import.meta.main.
247
+ * Added in: v24.2.0, v22.18.0
248
+ * @see https://nodejs.org/api/esm.html#importmetamain
13
249
  */
14
250
  const format = async (src, ast, opts) => {
15
251
  const code = new MagicString(src);
@@ -19,7 +255,15 @@ const format = async (src, ast, opts) => {
19
255
  hasDefaultExportBeenReassigned: false,
20
256
  hasDefaultExportBeenAssigned: false
21
257
  };
258
+ const exportTable = opts.target === 'module' ? await collectCjsExports(ast.program) : null;
22
259
  await collectModuleIdentifiers(ast.program);
260
+ const shouldCheckTopLevelAwait = opts.target === 'commonjs' && opts.transformSyntax;
261
+ const containsTopLevelAwait = shouldCheckTopLevelAwait ? hasTopLevelAwait(ast.program) : false;
262
+ const shouldLowerCjs = opts.target === 'commonjs' && opts.transformSyntax;
263
+ let pendingCjsTransforms = null;
264
+ if (shouldLowerCjs && opts.topLevelAwait === 'error' && containsTopLevelAwait) {
265
+ throw new Error('Top-level await is not supported when targeting CommonJS (set topLevelAwait to "wrap" or "preserve" to override).');
266
+ }
23
267
  if (opts.target === 'module' && opts.transformSyntax) {
24
268
  /**
25
269
  * Prepare ESM output by renaming `exports` to `__exports` and seeding an
@@ -104,6 +348,64 @@ void import.meta.filename;
104
348
  }
105
349
  }
106
350
  });
351
+ if (shouldLowerCjs) {
352
+ const {
353
+ importTransforms,
354
+ exportTransforms,
355
+ needsInterop
356
+ } = lowerEsmToCjs(ast.program, code, opts, containsTopLevelAwait);
357
+ pendingCjsTransforms = {
358
+ transforms: [...importTransforms, ...exportTransforms].sort((a, b) => a.start - b.start),
359
+ needsInterop
360
+ };
361
+ }
362
+ if (pendingCjsTransforms) {
363
+ for (const t of pendingCjsTransforms.transforms) {
364
+ code.overwrite(t.start, t.end, t.code);
365
+ }
366
+ if (pendingCjsTransforms.needsInterop) {
367
+ code.prepend(`${interopHelper}exports.__esModule = true;\n`);
368
+ }
369
+ }
370
+ if (opts.target === 'module' && opts.transformSyntax && exportTable) {
371
+ const isValidExportName = name => /^[$A-Z_a-z][$\w]*$/.test(name);
372
+ const asExportName = name => isValidExportName(name) ? name : JSON.stringify(name);
373
+ const accessProp = name => isValidExportName(name) ? `${exportsRename}.${name}` : `${exportsRename}[${JSON.stringify(name)}]`;
374
+ const tempNameFor = name => {
375
+ const sanitized = name.replace(/[^$\w]/g, '_') || 'value';
376
+ const safe = /^[0-9]/.test(sanitized) ? `_${sanitized}` : sanitized;
377
+ return `__export_${safe}`;
378
+ };
379
+ const lines = [];
380
+ const defaultEntry = exportTable.get('default');
381
+ if (defaultEntry) {
382
+ const def = defaultEntry.fromIdentifier ?? exportsRename;
383
+ lines.push(`export default ${def};`);
384
+ }
385
+ for (const [key, entry] of exportTable) {
386
+ if (key === 'default') continue;
387
+ if (entry.fromIdentifier) {
388
+ lines.push(`export { ${entry.fromIdentifier} as ${asExportName(key)} };`);
389
+ } else {
390
+ const temp = tempNameFor(key);
391
+ lines.push(`const ${temp} = ${accessProp(key)};`);
392
+ lines.push(`export { ${temp} as ${asExportName(key)} };`);
393
+ }
394
+ }
395
+ if (lines.length) {
396
+ code.append(`\n${lines.join('\n')}\n`);
397
+ }
398
+ }
399
+ if (opts.target === 'commonjs' && opts.transformSyntax && containsTopLevelAwait) {
400
+ const body = code.toString();
401
+ if (opts.topLevelAwait === 'wrap') {
402
+ const tlaPromise = `const __tla = (async () => {\n${body}\nreturn module.exports;\n})();\n`;
403
+ const setPromise = `const __setTla = target => {\n if (!target) return;\n const type = typeof target;\n if (type !== 'object' && type !== 'function') return;\n target.__tla = __tla;\n};\n`;
404
+ const attach = `__setTla(module.exports);\n__tla.then(resolved => __setTla(resolved), err => { throw err; });\n`;
405
+ return `${tlaPromise}${setPromise}${attach}`;
406
+ }
407
+ return `;(async () => {\n${body}\n})();\n`;
408
+ }
107
409
  return code.toString();
108
410
  };
109
411
  export { format };
@@ -1,4 +1,4 @@
1
- import { walk } from '../walk.js';
1
+ import { walk } from '#walk';
2
2
  export const assignmentExpression = async ({
3
3
  node,
4
4
  parent: _parent,
@@ -1,5 +1,5 @@
1
- import { exportsRename } from '../utils.js';
2
- import { identifier as ident } from '../helpers/identifier.js';
1
+ import { exportsRename } from '#utils/exports.js';
2
+ import { identifier as ident } from '#helpers/identifier.js';
3
3
  export const identifier = ({
4
4
  node,
5
5
  ancestors,
@@ -1,4 +1,4 @@
1
- import { exportsRename } from '../utils.js';
1
+ import { exportsRename } from '#utils/exports.js';
2
2
  export const memberExpression = (node, parent, src, options) => {
3
3
  if (options.target === 'module') {
4
4
  if (node.object.type === 'Identifier' && node.property.type === 'Identifier' && node.object.name === 'module' && node.property.name === 'exports') {
@@ -1,3 +1,16 @@
1
+ const importMetaMainSupport = '(() => { const [__nmaj, __nmin] = process.versions.node.split(".").map(n => parseInt(n, 10) || 0); return (__nmaj > 24 || (__nmaj === 24 && __nmin >= 2) || (__nmaj === 22 && __nmin >= 18)); })()';
2
+ const importMetaMainShim = 'process.argv[1] === __filename';
3
+ const importMetaMainExpr = mode => {
4
+ switch (mode) {
5
+ case 'warn':
6
+ return `(${importMetaMainSupport} ? ${importMetaMainShim} : (console.warn("import.meta.main is not supported before Node 22.18/24.2; falling back to shim."), ${importMetaMainShim}))`;
7
+ case 'error':
8
+ return `(${importMetaMainSupport} ? ${importMetaMainShim} : (() => { throw new Error("import.meta.main is not supported before Node 22.18/24.2"); })())`;
9
+ case 'shim':
10
+ default:
11
+ return importMetaMainShim;
12
+ }
13
+ };
1
14
  export const metaProperty = (node, parent, src, options) => {
2
15
  if (options.target === 'commonjs') {
3
16
  if (parent?.type !== 'MemberExpression') {
@@ -21,10 +34,15 @@ export const metaProperty = (node, parent, src, options) => {
21
34
  break;
22
35
  case 'resolve':
23
36
  /**
24
- * Should this be `require('node:url').pathToFileURL(require.resolve(<parsed specifier>)).href`?
37
+ * Map to require.resolve intentionally: matches CJS resolution semantics.
38
+ * Wrapping in pathToFileURL(...) would change the return shape (URL string)
39
+ * without truly emulating ESM import.meta.resolve rules.
25
40
  */
26
41
  src.update(parent.start, parent.end, 'require.resolve');
27
42
  break;
43
+ case 'main':
44
+ src.update(parent.start, parent.end, importMetaMainExpr(options.importMetaMain));
45
+ break;
28
46
  }
29
47
  }
30
48
  }
@@ -0,0 +1,19 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { IdentMeta, Scope } from '../types.js';
3
+ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
4
+ /**
5
+ * Collects all module scope identifiers in the AST.
6
+ *
7
+ * Ignores identifiers that are in functions or classes.
8
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
9
+ *
10
+ * Special case handling for these which create their own scopes,
11
+ * but are also valid module scope identifiers:
12
+ * - ClassDeclaration
13
+ * - FunctionDeclaration
14
+ *
15
+ * Special case handling for var inside BlockStatement
16
+ * which are also valid module scope identifiers.
17
+ */
18
+ declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
19
+ export { collectScopeIdentifiers, collectModuleIdentifiers };
package/dist/lang.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Specifier } from '@knighted/specifier';
2
+ type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
3
+ declare const getLangFromExt: (filename: string) => UpdateSrcLang;
4
+ export { getLangFromExt };
package/dist/module.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { readFile, writeFile } from 'node:fs/promises';
3
3
  import { specifier } from '@knighted/specifier';
4
- import { parse } from './parse.js';
5
- import { format } from './format.js';
6
- import { getLangFromExt } from './utils.js';
4
+ import { parse } from '#parse';
5
+ import { format } from '#format';
6
+ import { getLangFromExt } from '#utils/lang.js';
7
7
  const defaultOptions = {
8
8
  target: 'commonjs',
9
9
  sourceType: 'auto',
@@ -12,6 +12,7 @@ const defaultOptions = {
12
12
  rewriteSpecifier: undefined,
13
13
  dirFilename: 'inject',
14
14
  importMeta: 'shim',
15
+ importMetaMain: 'shim',
15
16
  requireSource: 'builtin',
16
17
  cjsDefault: 'auto',
17
18
  topLevelAwait: 'error',
@@ -0,0 +1,9 @@
1
+ import type { ParseResult } from 'oxc-parser';
2
+ import type { FormatterOptions } from './types.js';
3
+ /**
4
+ * Node added support for import.meta.main.
5
+ * Added in: v24.2.0, v22.18.0
6
+ * @see https://nodejs.org/api/esm.html#importmetamain
7
+ */
8
+ declare const format: (src: string, ast: ParseResult, opts: FormatterOptions) => Promise<string>;
9
+ export { format };
@@ -0,0 +1,3 @@
1
+ import type { ModuleOptions } from './types.js';
2
+ declare const transform: (filename: string, options?: ModuleOptions) => Promise<string>;
3
+ export { transform };
@@ -0,0 +1,2 @@
1
+ declare const parse: (filename: string, code: string) => import("oxc-parser").ParseResult;
2
+ export { parse };
@@ -0,0 +1,44 @@
1
+ import type { Node, Span, IdentifierName, IdentifierReference, BindingIdentifier, LabelIdentifier, TSIndexSignatureName } from 'oxc-parser';
2
+ export type RewriteSpecifier = '.js' | '.mjs' | '.cjs' | '.ts' | '.mts' | '.cts' | ((value: string) => string | null | undefined);
3
+ export type ModuleOptions = {
4
+ target: 'module' | 'commonjs';
5
+ sourceType?: 'auto' | 'module' | 'commonjs';
6
+ transformSyntax?: boolean;
7
+ liveBindings?: 'strict' | 'loose' | 'off';
8
+ rewriteSpecifier?: RewriteSpecifier;
9
+ dirFilename?: 'inject' | 'preserve' | 'error';
10
+ importMeta?: 'preserve' | 'shim' | 'error';
11
+ importMetaMain?: 'shim' | 'warn' | 'error';
12
+ requireSource?: 'builtin' | 'create-require';
13
+ cjsDefault?: 'module-exports' | 'auto' | 'none';
14
+ topLevelAwait?: 'error' | 'wrap' | 'preserve';
15
+ out?: string;
16
+ inPlace?: boolean;
17
+ };
18
+ export type SpannedNode = Node & Span;
19
+ export type ExportsMeta = {
20
+ hasExportsBeenReassigned: boolean;
21
+ hasDefaultExportBeenReassigned: boolean;
22
+ hasDefaultExportBeenAssigned: boolean;
23
+ defaultExportValue: unknown;
24
+ };
25
+ export type CjsExport = {
26
+ key: string;
27
+ writes: SpannedNode[];
28
+ fromIdentifier?: string;
29
+ via: Set<'exports' | 'module.exports'>;
30
+ reassignments: SpannedNode[];
31
+ hasGetter?: boolean;
32
+ };
33
+ export type IdentMeta = {
34
+ declare: SpannedNode[];
35
+ read: SpannedNode[];
36
+ };
37
+ export type Scope = {
38
+ type: string;
39
+ name: string;
40
+ node: Node;
41
+ idents: Set<string>;
42
+ };
43
+ export type FormatterOptions = Omit<ModuleOptions, 'out' | 'inPlace'>;
44
+ export type Identifier = IdentifierName | IdentifierReference | BindingIdentifier | LabelIdentifier | TSIndexSignatureName;
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { CjsExport } from '../types.js';
3
+ declare const exportsRename = "__exports";
4
+ declare const requireMainRgx: RegExp;
5
+ declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
6
+ export { exportsRename, requireMainRgx, collectCjsExports };
@@ -0,0 +1,19 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { IdentMeta, Scope } from '../types.js';
3
+ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
4
+ /**
5
+ * Collects all module scope identifiers in the AST.
6
+ *
7
+ * Ignores identifiers that are in functions or classes.
8
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
9
+ *
10
+ * Special case handling for these which create their own scopes,
11
+ * but are also valid module scope identifiers:
12
+ * - ClassDeclaration
13
+ * - FunctionDeclaration
14
+ *
15
+ * Special case handling for var inside BlockStatement
16
+ * which are also valid module scope identifiers.
17
+ */
18
+ declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
19
+ export { collectScopeIdentifiers, collectModuleIdentifiers };
@@ -0,0 +1,4 @@
1
+ import type { Specifier } from '@knighted/specifier';
2
+ type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
3
+ declare const getLangFromExt: (filename: string) => UpdateSrcLang;
4
+ export { getLangFromExt };
@@ -0,0 +1,2 @@
1
+ declare const isValidUrl: (url: string) => boolean;
2
+ export { isValidUrl };
@@ -0,0 +1,26 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { Specifier } from '@knighted/specifier';
3
+ import type { IdentMeta, Scope, CjsExport } from './types.js';
4
+ type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
5
+ declare const getLangFromExt: (filename: string) => UpdateSrcLang;
6
+ declare const isValidUrl: (url: string) => boolean;
7
+ declare const exportsRename = "__exports";
8
+ declare const requireMainRgx: RegExp;
9
+ declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
10
+ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
11
+ /**
12
+ * Collects all module scope identifiers in the AST.
13
+ *
14
+ * Ignores identifiers that are in functions or classes.
15
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
16
+ *
17
+ * Special case handling for these which create their own scopes,
18
+ * but are also valid module scope identifiers:
19
+ * - ClassDeclaration
20
+ * - FunctionDeclaration
21
+ *
22
+ * Special case handling for var inside BlockStatement
23
+ * which are also valid module scope identifiers.
24
+ */
25
+ declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
26
+ export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
@@ -0,0 +1,20 @@
1
+ import type { Node } from 'oxc-parser';
2
+ /**
3
+ * Using visitorKeys instead of oxc Visitor to keep
4
+ * an ancestor-aware enter/leave API with this.skip()
5
+ * without per-node method boilerplate.
6
+ */
7
+ type AncestorContext = {
8
+ skip: () => void;
9
+ };
10
+ type AncestorVisitor = {
11
+ enter?: (this: AncestorContext, node: Node, ancestors: Node[]) => void | Promise<void>;
12
+ leave?: (this: AncestorContext, node: Node, ancestors: Node[]) => void | Promise<void>;
13
+ };
14
+ type WalkVisitor = {
15
+ enter?: (this: AncestorContext, node: Node, parent: Node | null) => void | Promise<void>;
16
+ leave?: (this: AncestorContext, node: Node, parent: Node | null) => void | Promise<void>;
17
+ };
18
+ declare const ancestorWalk: (node: Node, visitors: AncestorVisitor) => Promise<void>;
19
+ declare const walk: (node: Node, visitors: WalkVisitor) => Promise<void>;
20
+ export { ancestorWalk, walk };
package/dist/types.d.ts CHANGED
@@ -8,6 +8,7 @@ export type ModuleOptions = {
8
8
  rewriteSpecifier?: RewriteSpecifier;
9
9
  dirFilename?: 'inject' | 'preserve' | 'error';
10
10
  importMeta?: 'preserve' | 'shim' | 'error';
11
+ importMetaMain?: 'shim' | 'warn' | 'error';
11
12
  requireSource?: 'builtin' | 'create-require';
12
13
  cjsDefault?: 'module-exports' | 'auto' | 'none';
13
14
  topLevelAwait?: 'error' | 'wrap' | 'preserve';
@@ -21,6 +22,14 @@ export type ExportsMeta = {
21
22
  hasDefaultExportBeenAssigned: boolean;
22
23
  defaultExportValue: unknown;
23
24
  };
25
+ export type CjsExport = {
26
+ key: string;
27
+ writes: SpannedNode[];
28
+ fromIdentifier?: string;
29
+ via: Set<'exports' | 'module.exports'>;
30
+ reassignments: SpannedNode[];
31
+ hasGetter?: boolean;
32
+ };
24
33
  export type IdentMeta = {
25
34
  declare: SpannedNode[];
26
35
  read: SpannedNode[];
package/dist/url.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const isValidUrl: (url: string) => boolean;
2
+ export { isValidUrl };