@knighted/module 1.0.0-alpha.9 → 1.0.0-beta.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 (85) hide show
  1. package/README.md +28 -16
  2. package/dist/assignmentExpression.d.ts +12 -0
  3. package/dist/cjs/assignmentExpression.d.cts +12 -0
  4. package/dist/cjs/exports.d.cts +6 -0
  5. package/dist/cjs/expressionStatement.d.cts +2 -3
  6. package/dist/cjs/format.cjs +133 -26
  7. package/dist/cjs/format.d.cts +6 -6
  8. package/dist/cjs/formatters/assignmentExpression.cjs +37 -0
  9. package/dist/cjs/formatters/expressionStatement.cjs +36 -55
  10. package/dist/cjs/formatters/identifier.cjs +31 -31
  11. package/dist/cjs/formatters/memberExpression.cjs +24 -11
  12. package/dist/cjs/formatters/metaProperty.cjs +23 -35
  13. package/dist/cjs/helpers/identifier.cjs +132 -0
  14. package/dist/cjs/helpers/scope.cjs +12 -0
  15. package/dist/cjs/identifier.d.cts +31 -5
  16. package/dist/cjs/identifiers.d.cts +19 -0
  17. package/dist/cjs/lang.d.cts +4 -0
  18. package/dist/cjs/memberExpression.d.cts +2 -3
  19. package/dist/cjs/metaProperty.d.cts +2 -3
  20. package/dist/cjs/module.cjs +26 -27
  21. package/dist/cjs/parse.cjs +3 -14
  22. package/dist/cjs/parse.d.cts +1 -1
  23. package/dist/cjs/scope.d.cts +6 -0
  24. package/dist/cjs/types.d.cts +40 -4
  25. package/dist/cjs/url.d.cts +2 -0
  26. package/dist/cjs/utils/exports.cjs +227 -0
  27. package/dist/cjs/utils/identifiers.cjs +190 -0
  28. package/dist/cjs/utils/lang.cjs +25 -0
  29. package/dist/cjs/utils/url.cjs +16 -0
  30. package/dist/cjs/utils.cjs +288 -0
  31. package/dist/cjs/utils.d.cts +26 -0
  32. package/dist/cjs/walk.cjs +75 -0
  33. package/dist/cjs/walk.d.cts +20 -0
  34. package/dist/exports.d.ts +6 -0
  35. package/dist/expressionStatement.d.ts +2 -3
  36. package/dist/format.d.ts +6 -6
  37. package/dist/format.js +135 -27
  38. package/dist/formatters/assignmentExpression.js +30 -0
  39. package/dist/formatters/expressionStatement.js +36 -55
  40. package/dist/formatters/identifier.js +31 -31
  41. package/dist/formatters/memberExpression.js +24 -11
  42. package/dist/formatters/metaProperty.js +23 -35
  43. package/dist/helpers/identifier.js +127 -0
  44. package/dist/helpers/scope.js +7 -0
  45. package/dist/identifier.d.ts +31 -5
  46. package/dist/identifiers.d.ts +19 -0
  47. package/dist/lang.d.ts +4 -0
  48. package/dist/memberExpression.d.ts +2 -3
  49. package/dist/metaProperty.d.ts +2 -3
  50. package/dist/module.js +26 -27
  51. package/dist/parse.d.ts +1 -1
  52. package/dist/parse.js +3 -14
  53. package/dist/scope.d.ts +6 -0
  54. package/dist/src/format.d.ts +9 -0
  55. package/dist/src/formatters/assignmentExpression.d.ts +12 -0
  56. package/dist/src/formatters/expressionStatement.d.ts +4 -0
  57. package/dist/src/formatters/identifier.d.ts +12 -0
  58. package/dist/src/formatters/memberExpression.d.ts +4 -0
  59. package/dist/src/formatters/metaProperty.d.ts +4 -0
  60. package/dist/src/helpers/identifier.d.ts +31 -0
  61. package/dist/src/helpers/scope.d.ts +6 -0
  62. package/dist/src/module.d.ts +3 -0
  63. package/dist/src/parse.d.ts +2 -0
  64. package/dist/src/types.d.ts +43 -0
  65. package/dist/src/utils/exports.d.ts +6 -0
  66. package/dist/src/utils/identifiers.d.ts +19 -0
  67. package/dist/src/utils/lang.d.ts +4 -0
  68. package/dist/src/utils/url.d.ts +2 -0
  69. package/dist/src/utils.d.ts +26 -0
  70. package/dist/src/walk.d.ts +20 -0
  71. package/dist/types.d.ts +40 -4
  72. package/dist/url.d.ts +2 -0
  73. package/dist/utils/exports.js +221 -0
  74. package/dist/utils/identifiers.js +183 -0
  75. package/dist/utils/lang.js +20 -0
  76. package/dist/utils/url.js +10 -0
  77. package/dist/utils.d.ts +26 -0
  78. package/dist/utils.js +278 -0
  79. package/dist/walk.d.ts +20 -0
  80. package/dist/walk.js +69 -0
  81. package/package.json +43 -25
  82. package/dist/formatters/expressionStatement.d.ts +0 -5
  83. package/dist/formatters/identifier.d.ts +0 -5
  84. package/dist/formatters/memberExpression.d.ts +0 -5
  85. package/dist/formatters/metaProperty.d.ts +0 -5
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.collectScopeIdentifiers = exports.collectModuleIdentifiers = void 0;
7
+ var _walk = require("#walk");
8
+ var _scope = require("#helpers/scope.js");
9
+ var _identifier = require("#helpers/identifier.js");
10
+ const collectScopeIdentifiers = (node, scopes) => {
11
+ const {
12
+ type
13
+ } = node;
14
+ switch (type) {
15
+ case 'BlockStatement':
16
+ case 'ClassBody':
17
+ scopes.push({
18
+ node,
19
+ type: 'Block',
20
+ name: type,
21
+ idents: new Set()
22
+ });
23
+ break;
24
+ case 'FunctionDeclaration':
25
+ case 'FunctionExpression':
26
+ case 'ArrowFunctionExpression':
27
+ {
28
+ const name = node.id ? node.id.name : 'anonymous';
29
+ const scope = {
30
+ node,
31
+ name,
32
+ type: 'Function',
33
+ idents: new Set()
34
+ };
35
+ node.params.map(param => {
36
+ if (param.type === 'TSParameterProperty') {
37
+ return param.parameter;
38
+ }
39
+ if (param.type === 'RestElement') {
40
+ return param.argument;
41
+ }
42
+ if (param.type === 'AssignmentPattern') {
43
+ return param.left;
44
+ }
45
+ return param;
46
+ }).filter(_identifier.identifier.isNamed).forEach(param => {
47
+ scope.idents.add(param.name);
48
+ });
49
+
50
+ /**
51
+ * If a FunctionExpression has an id, it is a named function expression.
52
+ * The function expression name shadows the module scope identifier, so
53
+ * we don't want to count reads of module identifers that have the same name.
54
+ * They also do not cause a SyntaxError if the function expression name is
55
+ * the same as a module scope identifier.
56
+ *
57
+ * TODO: Is this necessary for FunctionDeclaration?
58
+ */
59
+ if (node.type === 'FunctionExpression' && node.id) {
60
+ scope.idents.add(node.id.name);
61
+ }
62
+
63
+ // First add the function to any previous scopes
64
+ if (scopes.length > 0) {
65
+ scopes[scopes.length - 1].idents.add(name);
66
+ }
67
+
68
+ // Then add the function scope to the scopes stack
69
+ scopes.push(scope);
70
+ }
71
+ break;
72
+ case 'ClassDeclaration':
73
+ {
74
+ const className = node.id ? node.id.name : 'anonymous';
75
+
76
+ // First add the class to any previous scopes
77
+ if (scopes.length > 0) {
78
+ scopes[scopes.length - 1].idents.add(className);
79
+ }
80
+
81
+ // Then add the class to the scopes stack
82
+ scopes.push({
83
+ node,
84
+ name: className,
85
+ type: 'Class',
86
+ idents: new Set()
87
+ });
88
+ }
89
+ break;
90
+ case 'ClassExpression':
91
+ {}
92
+ break;
93
+ case 'VariableDeclaration':
94
+ if (scopes.length > 0) {
95
+ const scope = scopes[scopes.length - 1];
96
+ node.declarations.forEach(decl => {
97
+ if (decl.type === 'VariableDeclarator' && decl.id.type === 'Identifier') {
98
+ scope.idents.add(decl.id.name);
99
+ }
100
+ });
101
+ }
102
+ break;
103
+ }
104
+ };
105
+
106
+ /**
107
+ * Collects all module scope identifiers in the AST.
108
+ *
109
+ * Ignores identifiers that are in functions or classes.
110
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
111
+ *
112
+ * Special case handling for these which create their own scopes,
113
+ * but are also valid module scope identifiers:
114
+ * - ClassDeclaration
115
+ * - FunctionDeclaration
116
+ *
117
+ * Special case handling for var inside BlockStatement
118
+ * which are also valid module scope identifiers.
119
+ */
120
+ exports.collectScopeIdentifiers = collectScopeIdentifiers;
121
+ const collectModuleIdentifiers = async (ast, hoisting = true) => {
122
+ const identifiers = new Map();
123
+ const globalReads = new Map();
124
+ const scopes = [];
125
+ await (0, _walk.ancestorWalk)(ast, {
126
+ enter(node, ancestors) {
127
+ const {
128
+ type
129
+ } = node;
130
+ collectScopeIdentifiers(node, scopes);
131
+
132
+ // Add module scope identifiers to the registry map
133
+
134
+ if (type === 'Identifier') {
135
+ const {
136
+ name
137
+ } = node;
138
+ const meta = identifiers.get(name) ?? {
139
+ declare: [],
140
+ read: []
141
+ };
142
+ const isDeclaration = _identifier.identifier.isDeclaration(ancestors);
143
+ const inScope = scopes.some(scope => scope.idents.has(name) || scope.name === name);
144
+ if (hoisting && !_identifier.identifier.isDeclaration(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors) && !_identifier.identifier.isIife(ancestors) && !inScope) {
145
+ if (globalReads.has(name)) {
146
+ globalReads.get(name)?.push(node);
147
+ } else {
148
+ globalReads.set(name, [node]);
149
+ }
150
+ }
151
+ if (isDeclaration) {
152
+ const isModuleScope = _identifier.identifier.isModuleScope(ancestors);
153
+ const isClassOrFuncDeclaration = _identifier.identifier.isClassOrFuncDeclarationId(ancestors);
154
+ const isVarDeclarationInGlobalScope = _identifier.identifier.isVarDeclarationInGlobalScope(ancestors);
155
+ if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
156
+ meta.declare.push(node);
157
+
158
+ // Check for hoisted reads
159
+ if (hoisting && globalReads.has(name)) {
160
+ const reads = globalReads.get(name);
161
+ if (reads) {
162
+ reads.forEach(read => {
163
+ if (!meta.read.includes(read)) {
164
+ meta.read.push(read);
165
+ }
166
+ });
167
+ }
168
+ }
169
+ identifiers.set(name, meta);
170
+ }
171
+ } else {
172
+ if (identifiers.has(name) && !inScope && !_identifier.identifier.isIife(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors)) {
173
+ // Closure is referencing module scope identifier
174
+ meta.read.push(node);
175
+ }
176
+ }
177
+ }
178
+ },
179
+ leave(node) {
180
+ const {
181
+ type
182
+ } = node;
183
+ if (_scope.scopes.includes(type)) {
184
+ scopes.pop();
185
+ }
186
+ }
187
+ });
188
+ return identifiers;
189
+ };
190
+ exports.collectModuleIdentifiers = collectModuleIdentifiers;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLangFromExt = void 0;
7
+ var _nodePath = require("node:path");
8
+ // Determine language from filename extension for specifier rewrite.
9
+
10
+ const getLangFromExt = filename => {
11
+ const ext = (0, _nodePath.extname)(filename);
12
+ if (ext.endsWith('.js')) {
13
+ return 'js';
14
+ }
15
+ if (ext.endsWith('.ts')) {
16
+ return 'ts';
17
+ }
18
+ if (ext === '.tsx') {
19
+ return 'tsx';
20
+ }
21
+ if (ext === '.jsx') {
22
+ return 'jsx';
23
+ }
24
+ };
25
+ exports.getLangFromExt = getLangFromExt;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isValidUrl = void 0;
7
+ // URL validation used when rewriting import.meta.url assignments.
8
+ const isValidUrl = url => {
9
+ try {
10
+ new URL(url);
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ };
16
+ exports.isValidUrl = isValidUrl;
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.requireMainRgx = exports.isValidUrl = exports.getLangFromExt = exports.exportsRename = exports.collectScopeIdentifiers = exports.collectModuleIdentifiers = exports.collectCjsExports = void 0;
7
+ var _nodePath = require("node:path");
8
+ var _walk = require("./walk.cjs");
9
+ var _scope = require("./helpers/scope.cjs");
10
+ var _identifier = require("./helpers/identifier.cjs");
11
+ const getLangFromExt = filename => {
12
+ const ext = (0, _nodePath.extname)(filename);
13
+ if (ext.endsWith('.js')) {
14
+ return 'js';
15
+ }
16
+ if (ext.endsWith('.ts')) {
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
+ const isValidUrl = url => {
28
+ try {
29
+ new URL(url);
30
+ return true;
31
+ } catch {
32
+ return false;
33
+ }
34
+ };
35
+ exports.isValidUrl = isValidUrl;
36
+ const exportsRename = exports.exportsRename = '__exports';
37
+ const requireMainRgx = exports.requireMainRgx = /(require\.main\s*===\s*module|module\s*===\s*require\.main)/g;
38
+ const resolveExportTarget = node => {
39
+ if (node.type !== 'MemberExpression') return null;
40
+ const base = node.object;
41
+ const prop = node.property;
42
+ if (prop.type !== 'Identifier') return null;
43
+ if (base.type === 'Identifier' && base.name === 'exports') {
44
+ return {
45
+ key: prop.name,
46
+ via: 'exports'
47
+ };
48
+ }
49
+ if (base.type === 'MemberExpression' && base.object.type === 'Identifier' && base.object.name === 'module' && base.property.type === 'Identifier' && base.property.name === 'exports') {
50
+ return {
51
+ key: prop.name,
52
+ via: 'module.exports'
53
+ };
54
+ }
55
+ if (base.type === 'Identifier' && base.name === 'module' && prop.type === 'Identifier' && prop.name === 'exports') {
56
+ return {
57
+ key: 'default',
58
+ via: 'module.exports'
59
+ };
60
+ }
61
+ return null;
62
+ };
63
+ const collectCjsExports = async ast => {
64
+ const exportsMap = new Map();
65
+ const localToExport = new Map();
66
+ await (0, _walk.ancestorWalk)(ast, {
67
+ enter(node) {
68
+ if (node.type === 'AssignmentExpression') {
69
+ const target = resolveExportTarget(node.left);
70
+ if (target) {
71
+ const entry = exportsMap.get(target.key) ?? {
72
+ key: target.key,
73
+ writes: [],
74
+ via: new Set(),
75
+ reassignments: []
76
+ };
77
+ entry.via.add(target.via);
78
+ entry.writes.push(node);
79
+ if (node.right.type === 'Identifier') {
80
+ entry.fromIdentifier ??= node.right.name;
81
+ if (entry.fromIdentifier) {
82
+ const set = localToExport.get(entry.fromIdentifier) ?? new Set();
83
+ set.add(target.key);
84
+ localToExport.set(entry.fromIdentifier, set);
85
+ }
86
+ }
87
+ exportsMap.set(target.key, entry);
88
+ return;
89
+ }
90
+ if (node.left.type === 'Identifier') {
91
+ const keys = localToExport.get(node.left.name);
92
+ if (keys) {
93
+ keys.forEach(key => {
94
+ const entry = exportsMap.get(key);
95
+ if (entry) {
96
+ entry.reassignments.push(node);
97
+ exportsMap.set(key, entry);
98
+ }
99
+ });
100
+ }
101
+ }
102
+ }
103
+ }
104
+ });
105
+ return exportsMap;
106
+ };
107
+ exports.collectCjsExports = collectCjsExports;
108
+ const collectScopeIdentifiers = (node, scopes) => {
109
+ const {
110
+ type
111
+ } = node;
112
+ switch (type) {
113
+ case 'BlockStatement':
114
+ case 'ClassBody':
115
+ scopes.push({
116
+ node,
117
+ type: 'Block',
118
+ name: type,
119
+ idents: new Set()
120
+ });
121
+ break;
122
+ case 'FunctionDeclaration':
123
+ case 'FunctionExpression':
124
+ case 'ArrowFunctionExpression':
125
+ {
126
+ const name = node.id ? node.id.name : 'anonymous';
127
+ const scope = {
128
+ node,
129
+ name,
130
+ type: 'Function',
131
+ idents: new Set()
132
+ };
133
+ node.params.map(param => {
134
+ if (param.type === 'TSParameterProperty') {
135
+ return param.parameter;
136
+ }
137
+ if (param.type === 'RestElement') {
138
+ return param.argument;
139
+ }
140
+ if (param.type === 'AssignmentPattern') {
141
+ return param.left;
142
+ }
143
+ return param;
144
+ }).filter(_identifier.identifier.isNamed).forEach(param => {
145
+ scope.idents.add(param.name);
146
+ });
147
+
148
+ /**
149
+ * If a FunctionExpression has an id, it is a named function expression.
150
+ * The function expression name shadows the module scope identifier, so
151
+ * we don't want to count reads of module identifers that have the same name.
152
+ * They also do not cause a SyntaxError if the function expression name is
153
+ * the same as a module scope identifier.
154
+ *
155
+ * TODO: Is this necessary for FunctionDeclaration?
156
+ */
157
+ if (node.type === 'FunctionExpression' && node.id) {
158
+ scope.idents.add(node.id.name);
159
+ }
160
+
161
+ // First add the function to any previous scopes
162
+ if (scopes.length > 0) {
163
+ scopes[scopes.length - 1].idents.add(name);
164
+ }
165
+
166
+ // Then add the function scope to the scopes stack
167
+ scopes.push(scope);
168
+ }
169
+ break;
170
+ case 'ClassDeclaration':
171
+ {
172
+ const className = node.id ? node.id.name : 'anonymous';
173
+
174
+ // First add the class to any previous scopes
175
+ if (scopes.length > 0) {
176
+ scopes[scopes.length - 1].idents.add(className);
177
+ }
178
+
179
+ // Then add the class to the scopes stack
180
+ scopes.push({
181
+ node,
182
+ name: className,
183
+ type: 'Class',
184
+ idents: new Set()
185
+ });
186
+ }
187
+ break;
188
+ case 'ClassExpression':
189
+ {}
190
+ break;
191
+ case 'VariableDeclaration':
192
+ if (scopes.length > 0) {
193
+ const scope = scopes[scopes.length - 1];
194
+ node.declarations.forEach(decl => {
195
+ if (decl.type === 'VariableDeclarator' && decl.id.type === 'Identifier') {
196
+ scope.idents.add(decl.id.name);
197
+ }
198
+ });
199
+ }
200
+ break;
201
+ }
202
+ };
203
+
204
+ /**
205
+ * Collects all module scope identifiers in the AST.
206
+ *
207
+ * Ignores identifiers that are in functions or classes.
208
+ * Ignores new scopes for StaticBlock nodes (can only reference static class members).
209
+ *
210
+ * Special case handling for these which create their own scopes,
211
+ * but are also valid module scope identifiers:
212
+ * - ClassDeclaration
213
+ * - FunctionDeclaration
214
+ *
215
+ * Special case handling for var inside BlockStatement
216
+ * which are also valid module scope identifiers.
217
+ */
218
+ exports.collectScopeIdentifiers = collectScopeIdentifiers;
219
+ const collectModuleIdentifiers = async (ast, hoisting = true) => {
220
+ const identifiers = new Map();
221
+ const globalReads = new Map();
222
+ const scopes = [];
223
+ await (0, _walk.ancestorWalk)(ast, {
224
+ enter(node, ancestors) {
225
+ const {
226
+ type
227
+ } = node;
228
+ collectScopeIdentifiers(node, scopes);
229
+
230
+ // Add module scope identifiers to the registry map
231
+
232
+ if (type === 'Identifier') {
233
+ const {
234
+ name
235
+ } = node;
236
+ const meta = identifiers.get(name) ?? {
237
+ declare: [],
238
+ read: []
239
+ };
240
+ const isDeclaration = _identifier.identifier.isDeclaration(ancestors);
241
+ const inScope = scopes.some(scope => scope.idents.has(name) || scope.name === name);
242
+ if (hoisting && !_identifier.identifier.isDeclaration(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors) && !_identifier.identifier.isIife(ancestors) && !inScope) {
243
+ if (globalReads.has(name)) {
244
+ globalReads.get(name)?.push(node);
245
+ } else {
246
+ globalReads.set(name, [node]);
247
+ }
248
+ }
249
+ if (isDeclaration) {
250
+ const isModuleScope = _identifier.identifier.isModuleScope(ancestors);
251
+ const isClassOrFuncDeclaration = _identifier.identifier.isClassOrFuncDeclarationId(ancestors);
252
+ const isVarDeclarationInGlobalScope = _identifier.identifier.isVarDeclarationInGlobalScope(ancestors);
253
+ if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
254
+ meta.declare.push(node);
255
+
256
+ // Check for hoisted reads
257
+ if (hoisting && globalReads.has(name)) {
258
+ const reads = globalReads.get(name);
259
+ if (reads) {
260
+ reads.forEach(read => {
261
+ if (!meta.read.includes(read)) {
262
+ meta.read.push(read);
263
+ }
264
+ });
265
+ }
266
+ }
267
+ identifiers.set(name, meta);
268
+ }
269
+ } else {
270
+ if (identifiers.has(name) && !inScope && !_identifier.identifier.isIife(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors)) {
271
+ // Closure is referencing module scope identifier
272
+ meta.read.push(node);
273
+ }
274
+ }
275
+ }
276
+ },
277
+ leave(node) {
278
+ const {
279
+ type
280
+ } = node;
281
+ if (_scope.scopes.includes(type)) {
282
+ scopes.pop();
283
+ }
284
+ }
285
+ });
286
+ return identifiers;
287
+ };
288
+ exports.collectModuleIdentifiers = collectModuleIdentifiers;
@@ -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.cjs';
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,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.walk = exports.ancestorWalk = void 0;
7
+ var _oxcParser = require("oxc-parser");
8
+ /**
9
+ * Using visitorKeys instead of oxc Visitor to keep
10
+ * an ancestor-aware enter/leave API with this.skip()
11
+ * without per-node method boilerplate.
12
+ */
13
+
14
+ let skipDepth = -1;
15
+ const isNodeLike = value => {
16
+ return Boolean(value && typeof value === 'object' && 'type' in value);
17
+ };
18
+ const traverse = async (node, visitors, ancestors, depth) => {
19
+ if (!node) return;
20
+ const keys = _oxcParser.visitorKeys[node.type] ?? [];
21
+ const ctx = {
22
+ skip: () => {
23
+ skipDepth = depth;
24
+ }
25
+ };
26
+ ancestors.push(node);
27
+ if (visitors.enter) {
28
+ await visitors.enter.call(ctx, node, ancestors);
29
+ }
30
+ if (skipDepth === -1 || depth < skipDepth) {
31
+ const fields = node;
32
+ for (const key of keys) {
33
+ const child = fields[key];
34
+ if (Array.isArray(child)) {
35
+ for (const nested of child) {
36
+ if (isNodeLike(nested)) {
37
+ await traverse(nested, visitors, ancestors, depth + 1);
38
+ }
39
+ }
40
+ } else if (isNodeLike(child)) {
41
+ await traverse(child, visitors, ancestors, depth + 1);
42
+ }
43
+ }
44
+ }
45
+ if (visitors.leave) {
46
+ await visitors.leave.call(ctx, node, ancestors);
47
+ }
48
+ ancestors.pop();
49
+ if (skipDepth === depth) {
50
+ skipDepth = -1;
51
+ }
52
+ };
53
+ const ancestorWalk = async (node, visitors) => {
54
+ skipDepth = -1;
55
+ await traverse(node, visitors, [], 0);
56
+ };
57
+ exports.ancestorWalk = ancestorWalk;
58
+ const walk = async (node, visitors) => {
59
+ const wrap = {
60
+ enter(current, ancestors) {
61
+ const parent = ancestors[ancestors.length - 2] ?? null;
62
+ if (visitors.enter) {
63
+ return visitors.enter.call(this, current, parent);
64
+ }
65
+ },
66
+ leave(current, ancestors) {
67
+ const parent = ancestors[ancestors.length - 2] ?? null;
68
+ if (visitors.leave) {
69
+ return visitors.leave.call(this, current, parent);
70
+ }
71
+ }
72
+ };
73
+ await ancestorWalk(node, wrap);
74
+ };
75
+ exports.walk = walk;
@@ -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 };
@@ -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 };
@@ -1,5 +1,4 @@
1
1
  import MagicString from 'magic-string';
2
- import type { NodePath } from '@babel/traverse';
3
- import type { ExpressionStatement } from '@babel/types';
2
+ import type { Node, ExpressionStatement } from 'oxc-parser';
4
3
  import type { FormatterOptions } from '../types.js';
5
- export declare const expressionStatement: (nodePath: NodePath<ExpressionStatement>, src: MagicString, options: FormatterOptions) => void;
4
+ export declare const expressionStatement: (node: ExpressionStatement, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
package/dist/format.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import MagicString from 'magic-string';
2
- import type { ParseResult } from '@babel/parser';
3
- import type { File } from '@babel/types';
1
+ import type { ParseResult } from 'oxc-parser';
4
2
  import type { FormatterOptions } from './types.js';
5
3
  /**
6
- * Note, there is no specific conversion for `import.meta.main` as it does not exist.
7
- * @see https://github.com/nodejs/node/issues/49440
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
8
7
  */
9
- export declare const format: (code: string, ast: ParseResult<File>, options: FormatterOptions) => MagicString;
8
+ declare const format: (src: string, ast: ParseResult, opts: FormatterOptions) => Promise<string>;
9
+ export { format };