@knighted/module 1.0.0-beta.5 → 1.0.0-rc.1

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 (49) hide show
  1. package/README.md +0 -1
  2. package/dist/assignmentExpression.d.cts +12 -0
  3. package/dist/cjs/helpers/scope.cjs +12 -0
  4. package/dist/cjs/lang.d.cts +2 -3
  5. package/dist/cjs/module.cjs +1 -1
  6. package/dist/cjs/scope.d.cts +6 -0
  7. package/dist/cjs/specifier.cjs +265 -0
  8. package/dist/cjs/specifier.d.cts +16 -0
  9. package/dist/cjs/utils/lang.cjs +0 -1
  10. package/dist/cjs/utils.cjs +1 -18
  11. package/dist/cjs/utils.d.cts +1 -4
  12. package/dist/exports.d.cts +6 -0
  13. package/dist/expressionStatement.d.cts +4 -0
  14. package/dist/format.d.cts +9 -0
  15. package/dist/formatters/assignmentExpression.d.ts +12 -0
  16. package/dist/formatters/expressionStatement.d.ts +4 -0
  17. package/dist/formatters/identifier.d.ts +12 -0
  18. package/dist/formatters/memberExpression.d.ts +4 -0
  19. package/dist/formatters/metaProperty.d.ts +4 -0
  20. package/dist/helpers/identifier.d.ts +31 -0
  21. package/dist/helpers/scope.d.ts +6 -0
  22. package/dist/helpers/scope.js +7 -0
  23. package/dist/identifier.d.cts +31 -0
  24. package/dist/identifiers.d.cts +19 -0
  25. package/dist/lang.d.cts +3 -0
  26. package/dist/lang.d.ts +2 -3
  27. package/dist/memberExpression.d.cts +4 -0
  28. package/dist/metaProperty.d.cts +4 -0
  29. package/dist/module.d.cts +3 -0
  30. package/dist/module.js +1 -1
  31. package/dist/parse.d.cts +2 -0
  32. package/dist/scope.d.cts +6 -0
  33. package/dist/scope.d.ts +6 -0
  34. package/dist/scopeNodes.d.cts +2 -0
  35. package/dist/specifier.d.cts +16 -0
  36. package/dist/specifier.d.ts +16 -0
  37. package/dist/specifier.js +259 -0
  38. package/dist/src/helpers/scope.d.ts +6 -0
  39. package/dist/src/specifier.d.ts +16 -0
  40. package/dist/src/utils/lang.d.ts +2 -3
  41. package/dist/src/utils.d.ts +1 -4
  42. package/dist/types.d.cts +44 -0
  43. package/dist/url.d.cts +2 -0
  44. package/dist/utils/lang.js +0 -2
  45. package/dist/utils.d.cts +23 -0
  46. package/dist/utils.d.ts +1 -4
  47. package/dist/utils.js +1 -17
  48. package/dist/walk.d.cts +20 -0
  49. package/package.json +1 -2
package/README.md CHANGED
@@ -139,7 +139,6 @@ See [docs/esm-to-cjs.md](docs/esm-to-cjs.md) for deeper notes on live bindings,
139
139
 
140
140
  ## Roadmap
141
141
 
142
- - Remove `@knighted/specifier` and avoid double parsing.
143
142
  - Emit source maps and clearer diagnostics for transform choices.
144
143
  - Broaden fixtures covering live-binding and top-level await edge cases across Node versions.
145
144
  - Benchmark scope analysis choices: compare `periscopic`, `scope-analyzer`, and `eslint-scope` on fixtures and pick the final adapter.
@@ -0,0 +1,12 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, AssignmentExpression } from 'oxc-parser';
3
+ import type { FormatterOptions, ExportsMeta } from '../types.cjs';
4
+ type AssignmentExpressionArg = {
5
+ node: AssignmentExpression;
6
+ parent: Node | null;
7
+ code: MagicString;
8
+ opts: FormatterOptions;
9
+ meta: ExportsMeta;
10
+ };
11
+ export declare const assignmentExpression: ({ node, parent: _parent, code: _code, opts, meta: _meta, }: AssignmentExpressionArg) => Promise<void>;
12
+ export {};
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.scopes = exports.scope = void 0;
7
+ const scopes = exports.scopes = ['BlockStatement', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression', 'ClassDeclaration', 'ClassExpression', 'ClassBody', 'StaticBlock'];
8
+ const scope = exports.scope = {
9
+ isScope(node) {
10
+ return scopes.includes(node.type);
11
+ }
12
+ };
@@ -1,4 +1,3 @@
1
- import type { Specifier } from '@knighted/specifier';
2
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
3
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
1
+ import type { ParserOptions } from 'oxc-parser';
2
+ declare const getLangFromExt: (filename: string) => ParserOptions["lang"] | undefined;
4
3
  export { getLangFromExt };
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.transform = void 0;
7
7
  var _nodePath = require("node:path");
8
8
  var _promises = require("node:fs/promises");
9
- var _specifier = require("@knighted/specifier");
9
+ var _specifier = require("./specifier.cjs");
10
10
  var _parse = require("#parse");
11
11
  var _format = require("#format");
12
12
  var _lang = require("#utils/lang.js");
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ declare const scopes: string[];
3
+ declare const scope: {
4
+ isScope(node: Node): boolean;
5
+ };
6
+ export { scopes, scope };
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.specifier = void 0;
7
+ var _nodePath = require("node:path");
8
+ var _promises = require("node:fs/promises");
9
+ var _magicString = _interopRequireDefault(require("magic-string"));
10
+ var _oxcParser = require("oxc-parser");
11
+ var _walk = require("#walk");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ const isStringLiteral = node => {
14
+ return node.type === 'Literal' && typeof node.value === 'string';
15
+ };
16
+ const isBinaryExpression = node => {
17
+ // Distinguish between BinaryExpression and PrivateInExpression
18
+ return node.type === 'BinaryExpression' && node.operator !== 'in';
19
+ };
20
+ const isCallExpression = node => {
21
+ return node.type === 'CallExpression' && node.callee !== undefined;
22
+ };
23
+ const formatSpecifiers = async (src, ast, cb) => {
24
+ const code = new _magicString.default(src);
25
+ const formatExpression = expression => {
26
+ const node = isCallExpression(expression) ? expression.arguments[0] : expression.source;
27
+ const {
28
+ type
29
+ } = node;
30
+ switch (type) {
31
+ case 'Literal':
32
+ {
33
+ if (isStringLiteral(node)) {
34
+ const {
35
+ start,
36
+ end,
37
+ value
38
+ } = node;
39
+ const updated = cb({
40
+ type: 'StringLiteral',
41
+ parent: expression,
42
+ node,
43
+ start,
44
+ end,
45
+ value
46
+ });
47
+ if (typeof updated === 'string') {
48
+ code.update(start + 1, end - 1, updated);
49
+ }
50
+ }
51
+ break;
52
+ }
53
+ case 'TemplateLiteral':
54
+ {
55
+ const {
56
+ start,
57
+ end
58
+ } = node;
59
+ const value = src.slice(start + 1, end - 1);
60
+ const updated = cb({
61
+ type: 'TemplateLiteral',
62
+ parent: expression,
63
+ node,
64
+ start,
65
+ end,
66
+ value
67
+ });
68
+ if (typeof updated === 'string') {
69
+ code.update(start + 1, end - 1, updated);
70
+ }
71
+ break;
72
+ }
73
+ case 'BinaryExpression':
74
+ {
75
+ if (isBinaryExpression(node)) {
76
+ const {
77
+ start,
78
+ end
79
+ } = node;
80
+ const value = src.slice(start, end);
81
+ const updated = cb({
82
+ type: 'BinaryExpression',
83
+ parent: expression,
84
+ node,
85
+ start,
86
+ end,
87
+ value
88
+ });
89
+ if (typeof updated === 'string') {
90
+ code.update(start, end, updated);
91
+ }
92
+ }
93
+ break;
94
+ }
95
+ case 'NewExpression':
96
+ {
97
+ if (node.callee.type === 'Identifier' && node.callee.name === 'String') {
98
+ const {
99
+ start,
100
+ end
101
+ } = node;
102
+ const value = src.slice(start, end);
103
+ const updated = cb({
104
+ type: 'NewExpression',
105
+ parent: expression,
106
+ node,
107
+ start,
108
+ end,
109
+ value
110
+ });
111
+ if (typeof updated === 'string') {
112
+ code.update(start, end, updated);
113
+ }
114
+ }
115
+ break;
116
+ }
117
+ }
118
+ };
119
+ await (0, _walk.walk)(ast.program, {
120
+ enter(node) {
121
+ if (node.type === 'ExpressionStatement') {
122
+ const {
123
+ expression
124
+ } = node;
125
+ if (expression.type === 'ImportExpression') {
126
+ formatExpression(expression);
127
+ }
128
+ }
129
+ if (node.type === 'CallExpression') {
130
+ // Handle require(), require.resolve(), import.meta.resolve()
131
+ if (node.callee.type === 'Identifier' && node.callee.name === 'require' || node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name === 'require' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve' || node.callee.type === 'MemberExpression' && node.callee.object.type === 'MetaProperty' && node.callee.object.meta.name === 'import' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve') {
132
+ formatExpression(node);
133
+ }
134
+ }
135
+ if (node.type === 'ArrowFunctionExpression') {
136
+ const {
137
+ body
138
+ } = node;
139
+ if (body.type === 'ImportExpression') {
140
+ formatExpression(body);
141
+ }
142
+ if (body.type === 'CallExpression' && body.callee.type === 'Identifier' && body.callee.name === 'require') {
143
+ formatExpression(body);
144
+ }
145
+ }
146
+ if (node.type === 'MemberExpression' && node.object.type === 'ImportExpression' && node.property.type === 'Identifier' && node.property.name === 'then') {
147
+ formatExpression(node.object);
148
+ }
149
+ if (node.type === 'TSImportType') {
150
+ const source = node.source;
151
+ if (source && isStringLiteral(source)) {
152
+ const {
153
+ start,
154
+ end,
155
+ value
156
+ } = source;
157
+ const updated = cb({
158
+ type: 'StringLiteral',
159
+ node: source,
160
+ parent: node,
161
+ start,
162
+ end,
163
+ value
164
+ });
165
+ if (typeof updated === 'string') {
166
+ code.update(start + 1, end - 1, updated);
167
+ }
168
+ }
169
+ }
170
+ if (node.type === 'ImportDeclaration') {
171
+ const {
172
+ source
173
+ } = node;
174
+ const {
175
+ start,
176
+ end,
177
+ value
178
+ } = source;
179
+ const updated = cb({
180
+ type: 'StringLiteral',
181
+ node: source,
182
+ parent: node,
183
+ start,
184
+ end,
185
+ value
186
+ });
187
+ if (typeof updated === 'string') {
188
+ code.update(start + 1, end - 1, updated);
189
+ }
190
+ }
191
+ if (node.type === 'ExportNamedDeclaration' && node.source) {
192
+ const {
193
+ source
194
+ } = node;
195
+ const {
196
+ start,
197
+ end,
198
+ value
199
+ } = source;
200
+ const updated = cb({
201
+ type: 'StringLiteral',
202
+ node: source,
203
+ parent: node,
204
+ start,
205
+ end,
206
+ value
207
+ });
208
+ if (typeof updated === 'string') {
209
+ code.update(start + 1, end - 1, updated);
210
+ }
211
+ }
212
+ if (node.type === 'ExportAllDeclaration') {
213
+ const {
214
+ source
215
+ } = node;
216
+ const {
217
+ start,
218
+ end,
219
+ value
220
+ } = source;
221
+ const updated = cb({
222
+ type: 'StringLiteral',
223
+ node: source,
224
+ parent: node,
225
+ start,
226
+ end,
227
+ value
228
+ });
229
+ if (typeof updated === 'string') {
230
+ code.update(start + 1, end - 1, updated);
231
+ }
232
+ }
233
+ }
234
+ });
235
+ return code.toString();
236
+ };
237
+ const isValidFilename = async filename => {
238
+ let stats;
239
+ try {
240
+ stats = await (0, _promises.stat)(filename);
241
+ } catch {
242
+ return false;
243
+ }
244
+ if (!stats.isFile()) {
245
+ return false;
246
+ }
247
+ return true;
248
+ };
249
+ const specifier = exports.specifier = {
250
+ async update(path, callback) {
251
+ const filename = (0, _nodePath.resolve)(path);
252
+ const validated = await isValidFilename(filename);
253
+ if (!validated) {
254
+ throw new Error(`The provided path ${path} does not resolve to a file on disk.`);
255
+ }
256
+ const src = (await (0, _promises.readFile)(filename)).toString();
257
+ const ast = (0, _oxcParser.parseSync)(filename, src);
258
+ return await formatSpecifiers(src, ast, callback);
259
+ },
260
+ async updateSrc(src, lang, callback) {
261
+ const filename = lang === 'ts' ? 'file.ts' : lang === 'tsx' ? 'file.tsx' : lang === 'js' ? 'file.js' : 'file.jsx';
262
+ const ast = (0, _oxcParser.parseSync)(filename, src);
263
+ return await formatSpecifiers(src, ast, callback);
264
+ }
265
+ };
@@ -0,0 +1,16 @@
1
+ import type { ParserOptions, StringLiteral, TemplateLiteral, BinaryExpression, NewExpression, ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration, TSImportType, ImportExpression, CallExpression } from 'oxc-parser';
2
+ type Spec = {
3
+ type: 'StringLiteral' | 'TemplateLiteral' | 'BinaryExpression' | 'NewExpression';
4
+ node: StringLiteral | TemplateLiteral | BinaryExpression | NewExpression;
5
+ parent: CallExpression | ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression | TSImportType;
6
+ start: number;
7
+ end: number;
8
+ value: string;
9
+ };
10
+ type Callback = (spec: Spec) => string | void;
11
+ declare const specifier: {
12
+ update(path: string, callback: Callback): Promise<string>;
13
+ updateSrc(src: string, lang: ParserOptions["lang"], callback: Callback): Promise<string>;
14
+ };
15
+ export { specifier };
16
+ export type { Spec, Callback };
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.getLangFromExt = void 0;
7
7
  var _nodePath = require("node:path");
8
8
  // Determine language from filename extension for specifier rewrite.
9
-
10
9
  const getLangFromExt = filename => {
11
10
  const ext = (0, _nodePath.extname)(filename).toLowerCase();
12
11
  if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
@@ -3,27 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.requireMainRgx = exports.isValidUrl = exports.getLangFromExt = exports.exportsRename = exports.collectScopeIdentifiers = exports.collectModuleIdentifiers = exports.collectCjsExports = void 0;
7
- var _nodePath = require("node:path");
6
+ exports.requireMainRgx = exports.isValidUrl = exports.exportsRename = exports.collectScopeIdentifiers = exports.collectModuleIdentifiers = exports.collectCjsExports = void 0;
8
7
  var _walk = require("./walk.cjs");
9
8
  var _identifier = require("./helpers/identifier.cjs");
10
9
  var _scopeNodes = require("./utils/scopeNodes.cjs");
11
- const getLangFromExt = filename => {
12
- const ext = (0, _nodePath.extname)(filename).toLowerCase();
13
- if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
14
- return 'js';
15
- }
16
- if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
17
- return 'ts';
18
- }
19
- if (ext === '.tsx') {
20
- return 'tsx';
21
- }
22
- if (ext === '.jsx') {
23
- return 'jsx';
24
- }
25
- };
26
- exports.getLangFromExt = getLangFromExt;
27
10
  const isValidUrl = url => {
28
11
  try {
29
12
  new URL(url);
@@ -1,8 +1,5 @@
1
1
  import type { Node } from 'oxc-parser';
2
- import type { Specifier } from '@knighted/specifier';
3
2
  import type { IdentMeta, Scope, CjsExport } from './types.cjs';
4
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
5
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
6
3
  declare const isValidUrl: (url: string) => boolean;
7
4
  declare const exportsRename = "__exports";
8
5
  declare const requireMainRgx: RegExp;
@@ -23,4 +20,4 @@ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
23
20
  * which are also valid module scope identifiers.
24
21
  */
25
22
  declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
26
- export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
23
+ export { isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { CjsExport } from '../types.cjs';
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,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, ExpressionStatement } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.cjs';
4
+ export declare const expressionStatement: (node: ExpressionStatement, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
@@ -0,0 +1,9 @@
1
+ import type { ParseResult } from 'oxc-parser';
2
+ import type { FormatterOptions } from './types.cjs';
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,12 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, AssignmentExpression } from 'oxc-parser';
3
+ import type { FormatterOptions, ExportsMeta } from '../types.js';
4
+ type AssignmentExpressionArg = {
5
+ node: AssignmentExpression;
6
+ parent: Node | null;
7
+ code: MagicString;
8
+ opts: FormatterOptions;
9
+ meta: ExportsMeta;
10
+ };
11
+ export declare const assignmentExpression: ({ node, parent: _parent, code: _code, opts, meta: _meta, }: AssignmentExpressionArg) => Promise<void>;
12
+ export {};
@@ -0,0 +1,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, ExpressionStatement } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.js';
4
+ export declare const expressionStatement: (node: ExpressionStatement, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
@@ -0,0 +1,12 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, IdentifierName } from 'oxc-parser';
3
+ import type { FormatterOptions, ExportsMeta } from '../types.js';
4
+ type IdentifierArg = {
5
+ node: IdentifierName;
6
+ ancestors: Node[];
7
+ code: MagicString;
8
+ opts: FormatterOptions;
9
+ meta: ExportsMeta;
10
+ };
11
+ export declare const identifier: ({ node, ancestors, code, opts, meta }: IdentifierArg) => void;
12
+ export {};
@@ -0,0 +1,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { MemberExpression, Node } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.js';
4
+ export declare const memberExpression: (node: MemberExpression, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
@@ -0,0 +1,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, MetaProperty } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.js';
4
+ export declare const metaProperty: (node: MetaProperty, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
@@ -0,0 +1,31 @@
1
+ import type { Node, IdentifierName } from 'oxc-parser';
2
+ /**
3
+ * Focus exclusively on IdentifierName type as it has the name property,
4
+ * which is what the identifer utilities are interested in.
5
+ *
6
+ * Explicitly ignore the TSThisParameter type as it is not a valid identifier name.
7
+ */
8
+ declare const isIdentifierName: (node: Node) => node is IdentifierName;
9
+ /**
10
+ * All methods receive the full set of ancestors, which
11
+ * specifically includes the node itself as the last element.
12
+ * The second to last element is the parent node, and so on.
13
+ * The first element is the root node.
14
+ */
15
+ declare const identifier: {
16
+ isNamed: (node: Node) => node is IdentifierName;
17
+ isMetaProperty(ancestors: Node[]): boolean;
18
+ isModuleScope(ancestors: Node[], includeImports?: boolean): boolean;
19
+ isMemberExpressionRoot(ancestors: Node[]): boolean;
20
+ isDeclaration(ancestors: Node[]): boolean;
21
+ isClassOrFuncDeclarationId(ancestors: Node[]): boolean;
22
+ isVarDeclarationInGlobalScope(ancestors: Node[]): boolean;
23
+ isIife(ancestors: Node[]): boolean;
24
+ isFunctionExpressionId(ancestors: Node[]): boolean;
25
+ isExportSpecifierAlias(ancestors: Node[]): boolean;
26
+ isClassPropertyKey(ancestors: Node[]): boolean;
27
+ isMethodDefinitionKey(ancestors: Node[]): boolean;
28
+ isMemberKey(ancestors: Node[]): boolean;
29
+ isPropertyKey(ancestors: Node[]): boolean;
30
+ };
31
+ export { identifier, isIdentifierName };
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ declare const scopes: string[];
3
+ declare const scope: {
4
+ isScope(node: Node): boolean;
5
+ };
6
+ export { scopes, scope };
@@ -0,0 +1,7 @@
1
+ const scopes = ['BlockStatement', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression', 'ClassDeclaration', 'ClassExpression', 'ClassBody', 'StaticBlock'];
2
+ const scope = {
3
+ isScope(node) {
4
+ return scopes.includes(node.type);
5
+ }
6
+ };
7
+ export { scopes, scope };
@@ -0,0 +1,31 @@
1
+ import type { Node, IdentifierName } from 'oxc-parser';
2
+ /**
3
+ * Focus exclusively on IdentifierName type as it has the name property,
4
+ * which is what the identifer utilities are interested in.
5
+ *
6
+ * Explicitly ignore the TSThisParameter type as it is not a valid identifier name.
7
+ */
8
+ declare const isIdentifierName: (node: Node) => node is IdentifierName;
9
+ /**
10
+ * All methods receive the full set of ancestors, which
11
+ * specifically includes the node itself as the last element.
12
+ * The second to last element is the parent node, and so on.
13
+ * The first element is the root node.
14
+ */
15
+ declare const identifier: {
16
+ isNamed: (node: Node) => node is IdentifierName;
17
+ isMetaProperty(ancestors: Node[]): boolean;
18
+ isModuleScope(ancestors: Node[], includeImports?: boolean): boolean;
19
+ isMemberExpressionRoot(ancestors: Node[]): boolean;
20
+ isDeclaration(ancestors: Node[]): boolean;
21
+ isClassOrFuncDeclarationId(ancestors: Node[]): boolean;
22
+ isVarDeclarationInGlobalScope(ancestors: Node[]): boolean;
23
+ isIife(ancestors: Node[]): boolean;
24
+ isFunctionExpressionId(ancestors: Node[]): boolean;
25
+ isExportSpecifierAlias(ancestors: Node[]): boolean;
26
+ isClassPropertyKey(ancestors: Node[]): boolean;
27
+ isMethodDefinitionKey(ancestors: Node[]): boolean;
28
+ isMemberKey(ancestors: Node[]): boolean;
29
+ isPropertyKey(ancestors: Node[]): boolean;
30
+ };
31
+ export { identifier, isIdentifierName };
@@ -0,0 +1,19 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { IdentMeta, Scope } from '../types.cjs';
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,3 @@
1
+ import type { ParserOptions } from 'oxc-parser';
2
+ declare const getLangFromExt: (filename: string) => ParserOptions["lang"] | undefined;
3
+ export { getLangFromExt };
package/dist/lang.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { Specifier } from '@knighted/specifier';
2
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
3
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
1
+ import type { ParserOptions } from 'oxc-parser';
2
+ declare const getLangFromExt: (filename: string) => ParserOptions["lang"] | undefined;
4
3
  export { getLangFromExt };
@@ -0,0 +1,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { MemberExpression, Node } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.cjs';
4
+ export declare const memberExpression: (node: MemberExpression, parent: Node | null, src: MagicString, options: FormatterOptions, shadowed?: Set<string>) => void;
@@ -0,0 +1,4 @@
1
+ import MagicString from 'magic-string';
2
+ import type { Node, MetaProperty } from 'oxc-parser';
3
+ import type { FormatterOptions } from '../types.cjs';
4
+ export declare const metaProperty: (node: MetaProperty, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
@@ -0,0 +1,3 @@
1
+ import type { ModuleOptions } from './types.cjs';
2
+ declare const transform: (filename: string, options?: ModuleOptions) => Promise<string>;
3
+ export { transform };
package/dist/module.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { resolve } from 'node:path';
2
2
  import { readFile, writeFile } from 'node:fs/promises';
3
- import { specifier } from '@knighted/specifier';
3
+ import { specifier } from './specifier.js';
4
4
  import { parse } from '#parse';
5
5
  import { format } from '#format';
6
6
  import { getLangFromExt } from '#utils/lang.js';
@@ -0,0 +1,2 @@
1
+ declare const parse: (filename: string, code: string) => import("oxc-parser").ParseResult;
2
+ export { parse };
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ declare const scopes: string[];
3
+ declare const scope: {
4
+ isScope(node: Node): boolean;
5
+ };
6
+ export { scopes, scope };
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ declare const scopes: string[];
3
+ declare const scope: {
4
+ isScope(node: Node): boolean;
5
+ };
6
+ export { scopes, scope };
@@ -0,0 +1,2 @@
1
+ declare const scopeNodes: string[];
2
+ export { scopeNodes };
@@ -0,0 +1,16 @@
1
+ import type { ParserOptions, StringLiteral, TemplateLiteral, BinaryExpression, NewExpression, ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration, TSImportType, ImportExpression, CallExpression } from 'oxc-parser';
2
+ type Spec = {
3
+ type: 'StringLiteral' | 'TemplateLiteral' | 'BinaryExpression' | 'NewExpression';
4
+ node: StringLiteral | TemplateLiteral | BinaryExpression | NewExpression;
5
+ parent: CallExpression | ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression | TSImportType;
6
+ start: number;
7
+ end: number;
8
+ value: string;
9
+ };
10
+ type Callback = (spec: Spec) => string | void;
11
+ declare const specifier: {
12
+ update(path: string, callback: Callback): Promise<string>;
13
+ updateSrc(src: string, lang: ParserOptions["lang"], callback: Callback): Promise<string>;
14
+ };
15
+ export { specifier };
16
+ export type { Spec, Callback };
@@ -0,0 +1,16 @@
1
+ import type { ParserOptions, StringLiteral, TemplateLiteral, BinaryExpression, NewExpression, ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration, TSImportType, ImportExpression, CallExpression } from 'oxc-parser';
2
+ type Spec = {
3
+ type: 'StringLiteral' | 'TemplateLiteral' | 'BinaryExpression' | 'NewExpression';
4
+ node: StringLiteral | TemplateLiteral | BinaryExpression | NewExpression;
5
+ parent: CallExpression | ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression | TSImportType;
6
+ start: number;
7
+ end: number;
8
+ value: string;
9
+ };
10
+ type Callback = (spec: Spec) => string | void;
11
+ declare const specifier: {
12
+ update(path: string, callback: Callback): Promise<string>;
13
+ updateSrc(src: string, lang: ParserOptions["lang"], callback: Callback): Promise<string>;
14
+ };
15
+ export { specifier };
16
+ export type { Spec, Callback };
@@ -0,0 +1,259 @@
1
+ import { resolve } from 'node:path';
2
+ import { stat, readFile } from 'node:fs/promises';
3
+ import MagicString from 'magic-string';
4
+ import { parseSync } from 'oxc-parser';
5
+ import { walk } from '#walk';
6
+ const isStringLiteral = node => {
7
+ return node.type === 'Literal' && typeof node.value === 'string';
8
+ };
9
+ const isBinaryExpression = node => {
10
+ // Distinguish between BinaryExpression and PrivateInExpression
11
+ return node.type === 'BinaryExpression' && node.operator !== 'in';
12
+ };
13
+ const isCallExpression = node => {
14
+ return node.type === 'CallExpression' && node.callee !== undefined;
15
+ };
16
+ const formatSpecifiers = async (src, ast, cb) => {
17
+ const code = new MagicString(src);
18
+ const formatExpression = expression => {
19
+ const node = isCallExpression(expression) ? expression.arguments[0] : expression.source;
20
+ const {
21
+ type
22
+ } = node;
23
+ switch (type) {
24
+ case 'Literal':
25
+ {
26
+ if (isStringLiteral(node)) {
27
+ const {
28
+ start,
29
+ end,
30
+ value
31
+ } = node;
32
+ const updated = cb({
33
+ type: 'StringLiteral',
34
+ parent: expression,
35
+ node,
36
+ start,
37
+ end,
38
+ value
39
+ });
40
+ if (typeof updated === 'string') {
41
+ code.update(start + 1, end - 1, updated);
42
+ }
43
+ }
44
+ break;
45
+ }
46
+ case 'TemplateLiteral':
47
+ {
48
+ const {
49
+ start,
50
+ end
51
+ } = node;
52
+ const value = src.slice(start + 1, end - 1);
53
+ const updated = cb({
54
+ type: 'TemplateLiteral',
55
+ parent: expression,
56
+ node,
57
+ start,
58
+ end,
59
+ value
60
+ });
61
+ if (typeof updated === 'string') {
62
+ code.update(start + 1, end - 1, updated);
63
+ }
64
+ break;
65
+ }
66
+ case 'BinaryExpression':
67
+ {
68
+ if (isBinaryExpression(node)) {
69
+ const {
70
+ start,
71
+ end
72
+ } = node;
73
+ const value = src.slice(start, end);
74
+ const updated = cb({
75
+ type: 'BinaryExpression',
76
+ parent: expression,
77
+ node,
78
+ start,
79
+ end,
80
+ value
81
+ });
82
+ if (typeof updated === 'string') {
83
+ code.update(start, end, updated);
84
+ }
85
+ }
86
+ break;
87
+ }
88
+ case 'NewExpression':
89
+ {
90
+ if (node.callee.type === 'Identifier' && node.callee.name === 'String') {
91
+ const {
92
+ start,
93
+ end
94
+ } = node;
95
+ const value = src.slice(start, end);
96
+ const updated = cb({
97
+ type: 'NewExpression',
98
+ parent: expression,
99
+ node,
100
+ start,
101
+ end,
102
+ value
103
+ });
104
+ if (typeof updated === 'string') {
105
+ code.update(start, end, updated);
106
+ }
107
+ }
108
+ break;
109
+ }
110
+ }
111
+ };
112
+ await walk(ast.program, {
113
+ enter(node) {
114
+ if (node.type === 'ExpressionStatement') {
115
+ const {
116
+ expression
117
+ } = node;
118
+ if (expression.type === 'ImportExpression') {
119
+ formatExpression(expression);
120
+ }
121
+ }
122
+ if (node.type === 'CallExpression') {
123
+ // Handle require(), require.resolve(), import.meta.resolve()
124
+ if (node.callee.type === 'Identifier' && node.callee.name === 'require' || node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name === 'require' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve' || node.callee.type === 'MemberExpression' && node.callee.object.type === 'MetaProperty' && node.callee.object.meta.name === 'import' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve') {
125
+ formatExpression(node);
126
+ }
127
+ }
128
+ if (node.type === 'ArrowFunctionExpression') {
129
+ const {
130
+ body
131
+ } = node;
132
+ if (body.type === 'ImportExpression') {
133
+ formatExpression(body);
134
+ }
135
+ if (body.type === 'CallExpression' && body.callee.type === 'Identifier' && body.callee.name === 'require') {
136
+ formatExpression(body);
137
+ }
138
+ }
139
+ if (node.type === 'MemberExpression' && node.object.type === 'ImportExpression' && node.property.type === 'Identifier' && node.property.name === 'then') {
140
+ formatExpression(node.object);
141
+ }
142
+ if (node.type === 'TSImportType') {
143
+ const source = node.source;
144
+ if (source && isStringLiteral(source)) {
145
+ const {
146
+ start,
147
+ end,
148
+ value
149
+ } = source;
150
+ const updated = cb({
151
+ type: 'StringLiteral',
152
+ node: source,
153
+ parent: node,
154
+ start,
155
+ end,
156
+ value
157
+ });
158
+ if (typeof updated === 'string') {
159
+ code.update(start + 1, end - 1, updated);
160
+ }
161
+ }
162
+ }
163
+ if (node.type === 'ImportDeclaration') {
164
+ const {
165
+ source
166
+ } = node;
167
+ const {
168
+ start,
169
+ end,
170
+ value
171
+ } = source;
172
+ const updated = cb({
173
+ type: 'StringLiteral',
174
+ node: source,
175
+ parent: node,
176
+ start,
177
+ end,
178
+ value
179
+ });
180
+ if (typeof updated === 'string') {
181
+ code.update(start + 1, end - 1, updated);
182
+ }
183
+ }
184
+ if (node.type === 'ExportNamedDeclaration' && node.source) {
185
+ const {
186
+ source
187
+ } = node;
188
+ const {
189
+ start,
190
+ end,
191
+ value
192
+ } = source;
193
+ const updated = cb({
194
+ type: 'StringLiteral',
195
+ node: source,
196
+ parent: node,
197
+ start,
198
+ end,
199
+ value
200
+ });
201
+ if (typeof updated === 'string') {
202
+ code.update(start + 1, end - 1, updated);
203
+ }
204
+ }
205
+ if (node.type === 'ExportAllDeclaration') {
206
+ const {
207
+ source
208
+ } = node;
209
+ const {
210
+ start,
211
+ end,
212
+ value
213
+ } = source;
214
+ const updated = cb({
215
+ type: 'StringLiteral',
216
+ node: source,
217
+ parent: node,
218
+ start,
219
+ end,
220
+ value
221
+ });
222
+ if (typeof updated === 'string') {
223
+ code.update(start + 1, end - 1, updated);
224
+ }
225
+ }
226
+ }
227
+ });
228
+ return code.toString();
229
+ };
230
+ const isValidFilename = async filename => {
231
+ let stats;
232
+ try {
233
+ stats = await stat(filename);
234
+ } catch {
235
+ return false;
236
+ }
237
+ if (!stats.isFile()) {
238
+ return false;
239
+ }
240
+ return true;
241
+ };
242
+ const specifier = {
243
+ async update(path, callback) {
244
+ const filename = resolve(path);
245
+ const validated = await isValidFilename(filename);
246
+ if (!validated) {
247
+ throw new Error(`The provided path ${path} does not resolve to a file on disk.`);
248
+ }
249
+ const src = (await readFile(filename)).toString();
250
+ const ast = parseSync(filename, src);
251
+ return await formatSpecifiers(src, ast, callback);
252
+ },
253
+ async updateSrc(src, lang, callback) {
254
+ const filename = lang === 'ts' ? 'file.ts' : lang === 'tsx' ? 'file.tsx' : lang === 'js' ? 'file.js' : 'file.jsx';
255
+ const ast = parseSync(filename, src);
256
+ return await formatSpecifiers(src, ast, callback);
257
+ }
258
+ };
259
+ export { specifier };
@@ -0,0 +1,6 @@
1
+ import type { Node } from 'oxc-parser';
2
+ declare const scopes: string[];
3
+ declare const scope: {
4
+ isScope(node: Node): boolean;
5
+ };
6
+ export { scopes, scope };
@@ -0,0 +1,16 @@
1
+ import type { ParserOptions, StringLiteral, TemplateLiteral, BinaryExpression, NewExpression, ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration, TSImportType, ImportExpression, CallExpression } from 'oxc-parser';
2
+ type Spec = {
3
+ type: 'StringLiteral' | 'TemplateLiteral' | 'BinaryExpression' | 'NewExpression';
4
+ node: StringLiteral | TemplateLiteral | BinaryExpression | NewExpression;
5
+ parent: CallExpression | ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression | TSImportType;
6
+ start: number;
7
+ end: number;
8
+ value: string;
9
+ };
10
+ type Callback = (spec: Spec) => string | void;
11
+ declare const specifier: {
12
+ update(path: string, callback: Callback): Promise<string>;
13
+ updateSrc(src: string, lang: ParserOptions["lang"], callback: Callback): Promise<string>;
14
+ };
15
+ export { specifier };
16
+ export type { Spec, Callback };
@@ -1,4 +1,3 @@
1
- import type { Specifier } from '@knighted/specifier';
2
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
3
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
1
+ import type { ParserOptions } from 'oxc-parser';
2
+ declare const getLangFromExt: (filename: string) => ParserOptions["lang"] | undefined;
4
3
  export { getLangFromExt };
@@ -1,8 +1,5 @@
1
1
  import type { Node } from 'oxc-parser';
2
- import type { Specifier } from '@knighted/specifier';
3
2
  import type { IdentMeta, Scope, CjsExport } from './types.js';
4
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
5
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
6
3
  declare const isValidUrl: (url: string) => boolean;
7
4
  declare const exportsRename = "__exports";
8
5
  declare const requireMainRgx: RegExp;
@@ -23,4 +20,4 @@ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
23
20
  * which are also valid module scope identifiers.
24
21
  */
25
22
  declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
26
- export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
23
+ export { isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
@@ -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;
package/dist/url.d.cts ADDED
@@ -0,0 +1,2 @@
1
+ declare const isValidUrl: (url: string) => boolean;
2
+ export { isValidUrl };
@@ -1,7 +1,5 @@
1
1
  import { extname } from 'node:path';
2
-
3
2
  // Determine language from filename extension for specifier rewrite.
4
-
5
3
  const getLangFromExt = filename => {
6
4
  const ext = extname(filename).toLowerCase();
7
5
  if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
@@ -0,0 +1,23 @@
1
+ import type { Node } from 'oxc-parser';
2
+ import type { IdentMeta, Scope, CjsExport } from './types.cjs';
3
+ declare const isValidUrl: (url: string) => boolean;
4
+ declare const exportsRename = "__exports";
5
+ declare const requireMainRgx: RegExp;
6
+ declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
7
+ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
8
+ /**
9
+ * Collects all module scope identifiers in the AST.
10
+ *
11
+ * Ignores identifiers that are in functions or classes.
12
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
13
+ *
14
+ * Special case handling for these which create their own scopes,
15
+ * but are also valid module scope identifiers:
16
+ * - ClassDeclaration
17
+ * - FunctionDeclaration
18
+ *
19
+ * Special case handling for var inside BlockStatement
20
+ * which are also valid module scope identifiers.
21
+ */
22
+ declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
23
+ export { isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
package/dist/utils.d.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  import type { Node } from 'oxc-parser';
2
- import type { Specifier } from '@knighted/specifier';
3
2
  import type { IdentMeta, Scope, CjsExport } from './types.js';
4
- type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
5
- declare const getLangFromExt: (filename: string) => UpdateSrcLang;
6
3
  declare const isValidUrl: (url: string) => boolean;
7
4
  declare const exportsRename = "__exports";
8
5
  declare const requireMainRgx: RegExp;
@@ -23,4 +20,4 @@ declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
23
20
  * which are also valid module scope identifiers.
24
21
  */
25
22
  declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
26
- export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
23
+ export { isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
package/dist/utils.js CHANGED
@@ -1,22 +1,6 @@
1
- import { extname } from 'node:path';
2
1
  import { ancestorWalk } from './walk.js';
3
2
  import { identifier } from './helpers/identifier.js';
4
3
  import { scopeNodes } from './utils/scopeNodes.js';
5
- const getLangFromExt = filename => {
6
- const ext = extname(filename).toLowerCase();
7
- if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
8
- return 'js';
9
- }
10
- if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
11
- return 'ts';
12
- }
13
- if (ext === '.tsx') {
14
- return 'tsx';
15
- }
16
- if (ext === '.jsx') {
17
- return 'jsx';
18
- }
19
- };
20
4
  const isValidUrl = url => {
21
5
  try {
22
6
  new URL(url);
@@ -278,4 +262,4 @@ const collectModuleIdentifiers = async (ast, hoisting = true) => {
278
262
  });
279
263
  return identifiers;
280
264
  };
281
- export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx };
265
+ export { 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/module",
3
- "version": "1.0.0-beta.5",
3
+ "version": "1.0.0-rc.1",
4
4
  "description": "Transforms differences between ES modules and CommonJS.",
5
5
  "type": "module",
6
6
  "main": "dist/module.js",
@@ -78,7 +78,6 @@
78
78
  "typescript": "^5.9.3"
79
79
  },
80
80
  "dependencies": {
81
- "@knighted/specifier": "^2.0.9",
82
81
  "magic-string": "^0.30.21",
83
82
  "node-module-type": "^1.0.4",
84
83
  "oxc-parser": "^0.105.0",