@scelar/nodepod 1.0.2 → 1.0.4

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 (94) hide show
  1. package/dist/__sw__.js +642 -642
  2. package/dist/__tests__/bench/integration.bench.d.ts +1 -0
  3. package/dist/__tests__/bench/memory-volume.bench.d.ts +1 -0
  4. package/dist/__tests__/bench/polyfills.bench.d.ts +1 -0
  5. package/dist/__tests__/bench/script-engine.bench.d.ts +1 -0
  6. package/dist/__tests__/bench/shell.bench.d.ts +1 -0
  7. package/dist/__tests__/bench/syntax-transforms.bench.d.ts +1 -0
  8. package/dist/__tests__/bench/version-resolver.bench.d.ts +1 -0
  9. package/dist/__tests__/buffer.test.d.ts +1 -0
  10. package/dist/__tests__/byte-encoding.test.d.ts +1 -0
  11. package/dist/__tests__/digest.test.d.ts +1 -0
  12. package/dist/__tests__/events.test.d.ts +1 -0
  13. package/dist/__tests__/memory-volume.test.d.ts +1 -0
  14. package/dist/__tests__/path.test.d.ts +1 -0
  15. package/dist/__tests__/process.test.d.ts +1 -0
  16. package/dist/__tests__/script-engine.test.d.ts +1 -0
  17. package/dist/__tests__/shell-builtins.test.d.ts +1 -0
  18. package/dist/__tests__/shell-interpreter.test.d.ts +1 -0
  19. package/dist/__tests__/shell-parser.test.d.ts +1 -0
  20. package/dist/__tests__/stream.test.d.ts +1 -0
  21. package/dist/__tests__/syntax-transforms.test.d.ts +1 -0
  22. package/dist/__tests__/version-resolver.test.d.ts +1 -0
  23. package/dist/{child_process-Dopvyd-E.js → child_process-53fMkug_.js} +4 -4
  24. package/dist/child_process-53fMkug_.js.map +1 -0
  25. package/dist/{child_process-B38qoN6R.cjs → child_process-lxSKECHq.cjs} +5 -5
  26. package/dist/child_process-lxSKECHq.cjs.map +1 -0
  27. package/dist/{index--Qr8LVpQ.js → index-B8lyh_ti.js} +1316 -559
  28. package/dist/index-B8lyh_ti.js.map +1 -0
  29. package/dist/{index-cnitc68U.cjs → index-C-TQIrdG.cjs} +1422 -612
  30. package/dist/index-C-TQIrdG.cjs.map +1 -0
  31. package/dist/index.cjs +1 -1
  32. package/dist/index.mjs +1 -1
  33. package/dist/memory-volume.d.ts +1 -1
  34. package/dist/polyfills/wasi.d.ts +45 -4
  35. package/dist/script-engine.d.ts +2 -0
  36. package/dist/sdk/nodepod.d.ts +4 -3
  37. package/dist/sdk/types.d.ts +6 -0
  38. package/dist/syntax-transforms.d.ts +1 -0
  39. package/dist/threading/process-manager.d.ts +1 -1
  40. package/dist/threading/worker-protocol.d.ts +1 -1
  41. package/package.json +5 -3
  42. package/src/__tests__/bench/integration.bench.ts +117 -0
  43. package/src/__tests__/bench/memory-volume.bench.ts +115 -0
  44. package/src/__tests__/bench/polyfills.bench.ts +147 -0
  45. package/src/__tests__/bench/script-engine.bench.ts +104 -0
  46. package/src/__tests__/bench/shell.bench.ts +101 -0
  47. package/src/__tests__/bench/syntax-transforms.bench.ts +82 -0
  48. package/src/__tests__/bench/version-resolver.bench.ts +95 -0
  49. package/src/__tests__/buffer.test.ts +273 -0
  50. package/src/__tests__/byte-encoding.test.ts +98 -0
  51. package/src/__tests__/digest.test.ts +44 -0
  52. package/src/__tests__/events.test.ts +245 -0
  53. package/src/__tests__/memory-volume.test.ts +443 -0
  54. package/src/__tests__/path.test.ts +181 -0
  55. package/src/__tests__/process.test.ts +129 -0
  56. package/src/__tests__/script-engine.test.ts +229 -0
  57. package/src/__tests__/shell-builtins.test.ts +357 -0
  58. package/src/__tests__/shell-interpreter.test.ts +157 -0
  59. package/src/__tests__/shell-parser.test.ts +204 -0
  60. package/src/__tests__/stream.test.ts +142 -0
  61. package/src/__tests__/syntax-transforms.test.ts +158 -0
  62. package/src/__tests__/version-resolver.test.ts +184 -0
  63. package/src/constants/cdn-urls.ts +18 -18
  64. package/src/helpers/byte-encoding.ts +51 -39
  65. package/src/index.ts +192 -192
  66. package/src/memory-volume.ts +968 -941
  67. package/src/module-transformer.ts +368 -368
  68. package/src/packages/installer.ts +396 -396
  69. package/src/packages/version-resolver.ts +12 -2
  70. package/src/polyfills/buffer.ts +633 -628
  71. package/src/polyfills/child_process.ts +2288 -2288
  72. package/src/polyfills/esbuild.ts +854 -854
  73. package/src/polyfills/events.ts +282 -276
  74. package/src/polyfills/fs.ts +2888 -2888
  75. package/src/polyfills/http.ts +1450 -1449
  76. package/src/polyfills/process.ts +721 -690
  77. package/src/polyfills/readline.ts +692 -692
  78. package/src/polyfills/stream.ts +1620 -1620
  79. package/src/polyfills/tty.ts +71 -71
  80. package/src/polyfills/wasi.ts +1284 -22
  81. package/src/request-proxy.ts +716 -716
  82. package/src/script-engine.ts +465 -146
  83. package/src/sdk/nodepod.ts +525 -509
  84. package/src/sdk/types.ts +7 -0
  85. package/src/syntax-transforms.ts +543 -561
  86. package/src/threading/offload-worker.ts +383 -383
  87. package/src/threading/offload.ts +271 -271
  88. package/src/threading/process-manager.ts +956 -956
  89. package/src/threading/process-worker-entry.ts +858 -854
  90. package/src/threading/worker-protocol.ts +1 -1
  91. package/dist/child_process-B38qoN6R.cjs.map +0 -1
  92. package/dist/child_process-Dopvyd-E.js.map +0 -1
  93. package/dist/index--Qr8LVpQ.js.map +0 -1
  94. package/dist/index-cnitc68U.cjs.map +0 -1
@@ -1,561 +1,543 @@
1
- // ESM-to-CJS conversion via acorn AST, with regex fallback
2
-
3
- import * as acorn from "acorn";
4
-
5
- export function esmToCjs(code: string): string {
6
- try {
7
- return esmToCjsViaAst(code);
8
- } catch {
9
- return esmToCjsViaRegex(code);
10
- }
11
- }
12
-
13
- function esmToCjsViaAst(code: string): string {
14
- const ast = acorn.parse(code, {
15
- ecmaVersion: "latest",
16
- sourceType: "module",
17
- });
18
- const patches: Array<[number, number, string]> = [];
19
-
20
- const hasDefaultExport = (ast as any).body.some(
21
- (n: any) => n.type === "ExportDefaultDeclaration",
22
- );
23
- const hasNamedExport = (ast as any).body.some(
24
- (n: any) => n.type === "ExportNamedDeclaration",
25
- );
26
- const mixedExports = hasDefaultExport && hasNamedExport;
27
-
28
- for (const node of (ast as any).body) {
29
- if (node.type === "ImportDeclaration") {
30
- const src = node.source.value;
31
- const specs = node.specifiers;
32
-
33
- if (specs.length === 0) {
34
- patches.push([
35
- node.start,
36
- node.end,
37
- `require(${JSON.stringify(src)});`,
38
- ]);
39
- } else {
40
- const defSpec = specs.find(
41
- (s: any) => s.type === "ImportDefaultSpecifier",
42
- );
43
- const nsSpec = specs.find(
44
- (s: any) => s.type === "ImportNamespaceSpecifier",
45
- );
46
- const namedSpecs = specs.filter(
47
- (s: any) => s.type === "ImportSpecifier",
48
- );
49
-
50
- const lines: string[] = [];
51
- const tmpVar = `__import_${node.start}`;
52
- const needsTmp = defSpec && (namedSpecs.length > 0 || nsSpec);
53
-
54
- if (needsTmp) {
55
- lines.push(`const ${tmpVar} = require(${JSON.stringify(src)})`);
56
- lines.push(
57
- `const ${defSpec.local.name} = ${tmpVar}.__esModule ? ${tmpVar}.default : ${tmpVar}`,
58
- );
59
- } else if (defSpec) {
60
- lines.push(
61
- `const ${defSpec.local.name} = (function(m) { return m.__esModule ? m.default : m; })(require(${JSON.stringify(src)}))`,
62
- );
63
- }
64
-
65
- if (nsSpec) {
66
- if (!needsTmp) {
67
- lines.push(
68
- `const ${nsSpec.local.name} = require(${JSON.stringify(src)})`,
69
- );
70
- } else {
71
- lines.push(`const ${nsSpec.local.name} = ${tmpVar}`);
72
- }
73
- }
74
-
75
- if (namedSpecs.length > 0) {
76
- const binds = namedSpecs
77
- .map((s: any) =>
78
- s.imported.name === s.local.name
79
- ? s.local.name
80
- : `${s.imported.name}: ${s.local.name}`,
81
- )
82
- .join(", ");
83
- if (needsTmp) {
84
- lines.push(`const { ${binds} } = ${tmpVar}`);
85
- } else {
86
- lines.push(`const { ${binds} } = require(${JSON.stringify(src)})`);
87
- }
88
- }
89
- patches.push([node.start, node.end, lines.join(";\n") + ";"]);
90
- }
91
- } else if (node.type === "ExportDefaultDeclaration") {
92
- const decl = node.declaration;
93
- const bodyCode = code.slice(decl.start, node.end);
94
- const exportTarget = mixedExports ? "exports.default" : "module.exports";
95
-
96
- if (
97
- (decl.type === "FunctionDeclaration" ||
98
- decl.type === "ClassDeclaration") &&
99
- decl.id?.name
100
- ) {
101
- // preserve the declaration so the name is bound in local scope
102
- patches.push([
103
- node.start,
104
- node.end,
105
- `${bodyCode};\n${exportTarget} = ${decl.id.name};`,
106
- ]);
107
- } else {
108
- patches.push([node.start, node.end, `${exportTarget} = ${bodyCode}`]);
109
- }
110
- } else if (node.type === "ExportNamedDeclaration") {
111
- if (node.declaration) {
112
- const decl = node.declaration;
113
- if (
114
- decl.type === "FunctionDeclaration" ||
115
- decl.type === "ClassDeclaration"
116
- ) {
117
- const name = decl.id.name;
118
- const bodyCode = code.slice(decl.start, node.end);
119
- // emit declaration so name is bound locally, then export it
120
- patches.push([
121
- node.start,
122
- node.end,
123
- `${bodyCode};\nexports.${name} = ${name};`,
124
- ]);
125
- } else if (decl.type === "VariableDeclaration") {
126
- const lines: string[] = [];
127
- const needsLiveBinding = decl.kind === "let" || decl.kind === "var";
128
- const hasDestructuring = decl.declarations.some(
129
- (d: any) =>
130
- d.id.type === "ObjectPattern" || d.id.type === "ArrayPattern",
131
- );
132
- if (hasDestructuring) {
133
- const declCode = code.slice(decl.start, decl.end);
134
- lines.push(declCode);
135
- for (const d of decl.declarations) {
136
- for (const name of extractBindingNames(d.id)) {
137
- if (needsLiveBinding) {
138
- lines.push(
139
- `Object.defineProperty(exports, ${JSON.stringify(name)}, { get() { return ${name}; }, enumerable: true })`,
140
- );
141
- } else {
142
- lines.push(`exports.${name} = ${name}`);
143
- }
144
- }
145
- }
146
- } else {
147
- const declCode = code.slice(decl.start, decl.end);
148
- lines.push(declCode);
149
- for (const d of decl.declarations) {
150
- if (needsLiveBinding) {
151
- // ESM live binding: getter so reassignments are visible to importers
152
- lines.push(
153
- `Object.defineProperty(exports, ${JSON.stringify(d.id.name)}, { get() { return ${d.id.name}; }, enumerable: true })`,
154
- );
155
- } else {
156
- lines.push(`exports.${d.id.name} = ${d.id.name}`);
157
- }
158
- }
159
- }
160
- patches.push([node.start, node.end, lines.join(";\n") + ";"]);
161
- }
162
- } else if (node.source) {
163
- const src = node.source.value;
164
- const tmp = `__reexport_${node.start}`;
165
- const lines = [`const ${tmp} = require(${JSON.stringify(src)})`];
166
- for (const spec of node.specifiers) {
167
- if (spec.local.name === "default") {
168
- // handle both module.exports=X and exports.default=X conventions
169
- lines.push(
170
- `exports.${spec.exported.name} = ${tmp}.__esModule ? ${tmp}.default : ${tmp}`,
171
- );
172
- } else {
173
- lines.push(
174
- `exports.${spec.exported.name} = ${tmp}.${spec.local.name}`,
175
- );
176
- }
177
- }
178
- patches.push([node.start, node.end, lines.join(";\n") + ";"]);
179
- } else {
180
- const lines = node.specifiers.map(
181
- (s: any) => `exports.${s.exported.name} = ${s.local.name}`,
182
- );
183
- patches.push([node.start, node.end, lines.join(";\n") + ";"]);
184
- }
185
- } else if (node.type === "ExportAllDeclaration") {
186
- const src = node.source.value;
187
- patches.push([
188
- node.start,
189
- node.end,
190
- `Object.assign(exports, require(${JSON.stringify(src)}))`,
191
- ]);
192
- }
193
- }
194
-
195
- let output = code;
196
- patches.sort((a, b) => b[0] - a[0]);
197
- for (const [s, e, r] of patches)
198
- output = output.slice(0, s) + r + output.slice(e);
199
- return output;
200
- }
201
-
202
- // extract all bound names from a destructuring pattern or identifier
203
- function extractBindingNames(pattern: any): string[] {
204
- if (pattern.type === "Identifier") {
205
- return [pattern.name];
206
- }
207
- if (pattern.type === "ObjectPattern") {
208
- const names: string[] = [];
209
- for (const prop of pattern.properties) {
210
- if (prop.type === "RestElement") {
211
- names.push(...extractBindingNames(prop.argument));
212
- } else {
213
- names.push(...extractBindingNames(prop.value));
214
- }
215
- }
216
- return names;
217
- }
218
- if (pattern.type === "ArrayPattern") {
219
- const names: string[] = [];
220
- for (const elem of pattern.elements) {
221
- if (elem) {
222
- if (elem.type === "RestElement") {
223
- names.push(...extractBindingNames(elem.argument));
224
- } else {
225
- names.push(...extractBindingNames(elem));
226
- }
227
- }
228
- }
229
- return names;
230
- }
231
- if (pattern.type === "AssignmentPattern") {
232
- return extractBindingNames(pattern.left);
233
- }
234
- return [];
235
- }
236
-
237
- // detect whether code contains any top-level await (outside async functions)
238
- export function hasTopLevelAwait(code: string): boolean {
239
- if (!/\bawait\b/.test(code)) return false;
240
-
241
- try {
242
- let ast: any;
243
- try {
244
- ast = acorn.parse(code, {
245
- ecmaVersion: "latest",
246
- sourceType: "script",
247
- allowAwaitOutsideFunction: true,
248
- });
249
- } catch {
250
- ast = acorn.parse(code, {
251
- ecmaVersion: "latest",
252
- sourceType: "module",
253
- });
254
- }
255
-
256
- let found = false;
257
- let insideAsync = 0;
258
-
259
- function walk(node: any): void {
260
- if (found || !node || typeof node !== "object") return;
261
- if (Array.isArray(node)) {
262
- for (const child of node) walk(child);
263
- return;
264
- }
265
- if (typeof node.type !== "string") return;
266
-
267
- const isAsyncFn =
268
- (node.type === "FunctionDeclaration" ||
269
- node.type === "FunctionExpression" ||
270
- node.type === "ArrowFunctionExpression") &&
271
- node.async;
272
-
273
- if (isAsyncFn) insideAsync++;
274
- if (node.type === "AwaitExpression" && insideAsync === 0) {
275
- found = true;
276
- }
277
- if (node.type === "ForOfStatement" && node.await && insideAsync === 0) {
278
- found = true;
279
- }
280
- if (!found) {
281
- for (const key of Object.keys(node)) {
282
- if (key === "type" || key === "start" || key === "end") continue;
283
- const val = node[key];
284
- if (val && typeof val === "object") walk(val);
285
- }
286
- }
287
- if (isAsyncFn) insideAsync--;
288
- }
289
-
290
- walk(ast);
291
- return found;
292
- } catch {
293
- // fallback: conservative regex
294
- return /(?<![.\w])await\s+(?=[\w$("'\[`!~+\-/])/.test(code);
295
- }
296
- }
297
-
298
- // strip top-level await and optionally de-async inner functions.
299
- // "topLevelOnly": only replace top-level await with __syncAwait(), leave inner async intact.
300
- // "full": strip async from all functions, replace ALL awaits with __syncAwait().
301
- // full mode is needed for synchronous require() chains where async would wrap
302
- // returns in native Promises that syncAwait() can't unwrap.
303
- export function stripTopLevelAwait(
304
- code: string,
305
- mode: "topLevelOnly" | "full" = "topLevelOnly",
306
- ): string {
307
- const full = mode === "full";
308
- if (!full && !/\bawait\b/.test(code)) return code;
309
- if (full && !/\bawait\b/.test(code) && !/\basync\b/.test(code)) return code;
310
-
311
- try {
312
- let ast: any;
313
- try {
314
- ast = acorn.parse(code, {
315
- ecmaVersion: "latest",
316
- sourceType: "script",
317
- allowAwaitOutsideFunction: true,
318
- });
319
- } catch {
320
- ast = acorn.parse(code, {
321
- ecmaVersion: "latest",
322
- sourceType: "module",
323
- });
324
- }
325
-
326
- const patches: Array<[number, number, string]> = [];
327
- let insideAsync = 0;
328
-
329
- function walk(node: any) {
330
- if (!node || typeof node !== "object") return;
331
-
332
- if (Array.isArray(node)) {
333
- for (const child of node) walk(child);
334
- return;
335
- }
336
-
337
- if (typeof node.type !== "string") return;
338
-
339
- const isAsyncFn =
340
- (node.type === "FunctionDeclaration" ||
341
- node.type === "FunctionExpression" ||
342
- node.type === "ArrowFunctionExpression") &&
343
- node.async;
344
-
345
- if (isAsyncFn) insideAsync++;
346
-
347
- // in full mode, strip async so functions return plain values (not native Promises).
348
- // skip async generators -- yield semantics can't be replaced.
349
- if (full && isAsyncFn && !node.generator) {
350
- if (code.slice(node.start, node.start + 5) === "async") {
351
- let end = node.start + 5;
352
- while (end < code.length && (code[end] === " " || code[end] === "\t")) end++;
353
- patches.push([node.start, end, ""]);
354
- } else {
355
- // method syntax: { async foo() {} }
356
- const searchStart = Math.max(0, node.start - 30);
357
- const region = code.slice(searchStart, node.start);
358
- const asyncIdx = region.lastIndexOf("async");
359
- if (asyncIdx >= 0) {
360
- const absStart = searchStart + asyncIdx;
361
- let absEnd = absStart + 5;
362
- while (absEnd < code.length && (code[absEnd] === " " || code[absEnd] === "\t")) absEnd++;
363
- patches.push([absStart, absEnd, ""]);
364
- }
365
- }
366
- }
367
-
368
- // Replace only the `await` keyword + trailing whitespace. We can't use
369
- // node.argument.start because acorn doesn't produce ParenthesizedExpression
370
- // nodes, so `await (expr)` would swallow the opening paren.
371
- if (node.type === "AwaitExpression") {
372
- if (full || insideAsync === 0) {
373
- let awaitEnd = node.start + 5; // "await" is 5 chars
374
- while (
375
- awaitEnd < node.argument.start &&
376
- (code[awaitEnd] === " " || code[awaitEnd] === "\t" || code[awaitEnd] === "\n" || code[awaitEnd] === "\r")
377
- ) {
378
- awaitEnd++;
379
- }
380
- patches.push([node.start, awaitEnd, "__syncAwait("]);
381
- patches.push([node.end, node.end, ")"]);
382
- }
383
- }
384
-
385
- // strip await from `for await (...of ...)`
386
- if (node.type === "ForOfStatement" && node.await) {
387
- if (full || insideAsync === 0) {
388
- const forEnd = node.start + 3;
389
- const snippet = code.slice(forEnd, node.left.start);
390
- const awIdx = snippet.indexOf("await");
391
- if (awIdx >= 0) {
392
- const absStart = forEnd + awIdx;
393
- let absEnd = absStart + 5;
394
- while (absEnd < code.length && code[absEnd] === " ") absEnd++;
395
- patches.push([absStart, absEnd, ""]);
396
- }
397
- }
398
- }
399
-
400
- for (const key of Object.keys(node)) {
401
- if (key === "type" || key === "start" || key === "end") continue;
402
- const val = node[key];
403
- if (val && typeof val === "object") {
404
- walk(val);
405
- }
406
- }
407
-
408
- if (isAsyncFn) insideAsync--;
409
- }
410
-
411
- walk(ast);
412
-
413
- if (patches.length === 0) return code;
414
-
415
- let output = code;
416
- patches.sort((a, b) => b[0] - a[0]);
417
- for (const [start, end, replacement] of patches) {
418
- output = output.slice(0, start) + replacement + output.slice(end);
419
- }
420
- return output;
421
- } catch {
422
- // regex fallback -- can't reliably add closing parens, best-effort strip
423
- if (full) {
424
- let out = code.replace(/(?<![.\w])await\s+(?=[\w$("'\[`!~+\-/])/g, "");
425
- out = out.replace(/(?<![.\w])async\s+(?=function[\s*(])/g, "");
426
- out = out.replace(/(?<![.\w])async\s+(?=\()/g, "");
427
- out = out.replace(/(?<![.\w])async\s+(?=\w+\s*=>)/g, "");
428
- return out;
429
- }
430
- // topLevelOnly: strip top-level await keyword
431
- return code.replace(
432
- /(?<![.\w])await\s+(?=[\w$("'\[`!~+\-/])/g,
433
- "",
434
- );
435
- }
436
- }
437
-
438
- function esmToCjsViaRegex(code: string): string {
439
- let out = code;
440
- // strip TS type-only imports
441
- out = out.replace(
442
- /import\s+type\s+\{[^}]*\}\s+from\s+['"][^'"]+['"]\s*;?/g,
443
- "",
444
- );
445
- out = out.replace(
446
- /import\s+type\s+\w+\s+from\s+['"][^'"]+['"]\s*;?/g,
447
- "",
448
- );
449
- out = out.replace(
450
- /import\s+type\s+\*\s+as\s+\w+\s+from\s+['"][^'"]+['"]\s*;?/g,
451
- "",
452
- );
453
- // remove inline type specifiers from mixed imports
454
- out = out.replace(
455
- /import\s+\{([^}]*\btype\s+\w+[^}]*)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g,
456
- (_m, specs: string, src: string) => {
457
- const kept = specs
458
- .split(",")
459
- .filter((s: string) => !/^\s*type\s+\w+/.test(s))
460
- .map((s: string) => s.trim())
461
- .filter(Boolean);
462
- if (kept.length === 0) return "";
463
- const fixed = kept.join(", ").replace(/(\w+)\s+as\s+(\w+)/g, "$1: $2");
464
- return `const {${fixed}} = require("${src}");`;
465
- },
466
- );
467
- // strip TS type-only exports
468
- out = out.replace(
469
- /export\s+type\s+\{[^}]*\}\s+from\s+['"][^'"]+['"]\s*;?/g,
470
- "",
471
- );
472
- out = out.replace(
473
- /export\s+type\s+\{[^}]*\}\s*;?/g,
474
- "",
475
- );
476
- out = out.replace(
477
- /import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g,
478
- 'const $1 = require("$2");',
479
- );
480
- out = out.replace(
481
- /import\s+(\w+)\s*,\s*\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g,
482
- (_m, def, named, src) => {
483
- const tmp = `__import_${def}`;
484
- const fixed = named.replace(/(\w+)\s+as\s+(\w+)/g, "$1: $2");
485
- return `const ${tmp} = require("${src}"); const ${def} = ${tmp}.__esModule ? ${tmp}.default : ${tmp}; const {${fixed}} = ${tmp};`;
486
- },
487
- );
488
- out = out.replace(
489
- /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g,
490
- 'const $1 = require("$2");',
491
- );
492
- out = out.replace(
493
- /import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g,
494
- (_m, specs, src) => {
495
- const fixed = specs.replace(/(\w+)\s+as\s+(\w+)/g, "$1: $2");
496
- return `const {${fixed}} = require("${src}");`;
497
- },
498
- );
499
- out = out.replace(
500
- /import\s+['"]([^'"]+)['"]\s*;?/g,
501
- 'require("$1");',
502
- );
503
- // export default
504
- out = out.replace(
505
- /export\s+default\s+class\s+(\w+)/g,
506
- "module.exports = class $1",
507
- );
508
- out = out.replace(
509
- /export\s+default\s+function\s+(\w+)/g,
510
- "module.exports = function $1",
511
- );
512
- out = out.replace(
513
- /export\s+default\s+function\s*\(/g,
514
- "module.exports = function(",
515
- );
516
- out = out.replace(/export\s+default\s+/g, "module.exports = ");
517
- // re-exports
518
- out = out.replace(
519
- /export\s+\*\s+from\s+['"]([^'"]+)['"]\s*;?/g,
520
- 'Object.assign(exports, require("$1"));',
521
- );
522
- out = out.replace(
523
- /export\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g,
524
- (_m, specs, src) => {
525
- const binds = specs
526
- .split(",")
527
- .map((s: string) => {
528
- const parts = s.trim().split(/\s+as\s+/);
529
- const local = parts[0].trim();
530
- const exported = parts.length > 1 ? parts[1].trim() : local;
531
- return `exports.${exported} = require("${src}").${local}`;
532
- })
533
- .join("; ");
534
- return binds + ";";
535
- },
536
- );
537
- out = out.replace(
538
- /export\s+\{([^}]+)\}\s*;?/g,
539
- (_m, specs) => {
540
- const binds = specs
541
- .split(",")
542
- .map((s: string) => {
543
- const parts = s.trim().split(/\s+as\s+/);
544
- const local = parts[0].trim();
545
- const exported = parts.length > 1 ? parts[1].trim() : local;
546
- return `exports.${exported} = ${local}`;
547
- })
548
- .join("; ");
549
- return binds + ";";
550
- },
551
- );
552
- // named exports
553
- out = out.replace(
554
- /export\s+async\s+function\s+(\w+)/g,
555
- "exports.$1 = async function $1",
556
- );
557
- out = out.replace(/export\s+function\s+(\w+)/g, "exports.$1 = function $1");
558
- out = out.replace(/export\s+class\s+(\w+)/g, "exports.$1 = class $1");
559
- out = out.replace(/export\s+(?:const|let|var)\s+(\w+)\s*=/g, "exports.$1 =");
560
- return out;
561
- }
1
+ // ESM-to-CJS conversion via acorn AST, with regex fallback
2
+
3
+ import * as acorn from "acorn";
4
+
5
+ // Pre-compiled regex patterns for fallback paths (avoid per-call compilation)
6
+ const RE_AWAIT_QUICK = /\bawait\b/;
7
+ const RE_ASYNC_QUICK = /\basync\b/;
8
+ const RE_AWAIT_LOOKAHEAD = /(?<![.\w])await\s+(?=[\w$("'\[`!~+\-/])/;
9
+ const RE_AWAIT_LOOKAHEAD_G = /(?<![.\w])await\s+(?=[\w$("'\[`!~+\-/])/g;
10
+ const RE_ASYNC_FN_G = /(?<![.\w])async\s+(?=function[\s*(])/g;
11
+ const RE_ASYNC_PAREN_G = /(?<![.\w])async\s+(?=\()/g;
12
+ const RE_ASYNC_ARROW_G = /(?<![.\w])async\s+(?=\w+\s*=>)/g;
13
+ const RE_TYPE_IMPORT_BRACES = /import\s+type\s+\{[^}]*\}\s+from\s+['"][^'"]+['"]\s*;?/g;
14
+ const RE_TYPE_IMPORT_DEFAULT = /import\s+type\s+\w+\s+from\s+['"][^'"]+['"]\s*;?/g;
15
+ const RE_TYPE_IMPORT_STAR = /import\s+type\s+\*\s+as\s+\w+\s+from\s+['"][^'"]+['"]\s*;?/g;
16
+ const RE_MIXED_TYPE_IMPORT = /import\s+\{([^}]*\btype\s+\w+[^}]*)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g;
17
+ const RE_TYPE_EXPORT_FROM = /export\s+type\s+\{[^}]*\}\s+from\s+['"][^'"]+['"]\s*;?/g;
18
+ const RE_TYPE_EXPORT = /export\s+type\s+\{[^}]*\}\s*;?/g;
19
+ const RE_IMPORT_STAR = /import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g;
20
+ const RE_IMPORT_DEFAULT_NAMED = /import\s+(\w+)\s*,\s*\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g;
21
+ const RE_IMPORT_DEFAULT = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]\s*;?/g;
22
+ const RE_IMPORT_NAMED = /import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g;
23
+ const RE_IMPORT_SIDE_EFFECT = /import\s+['"]([^'"]+)['"]\s*;?/g;
24
+ const RE_EXPORT_DEFAULT_CLASS = /export\s+default\s+class\s+(\w+)/g;
25
+ const RE_EXPORT_DEFAULT_FN_NAMED = /export\s+default\s+function\s+(\w+)/g;
26
+ const RE_EXPORT_DEFAULT_FN_ANON = /export\s+default\s+function\s*\(/g;
27
+ const RE_EXPORT_DEFAULT = /export\s+default\s+/g;
28
+ const RE_EXPORT_STAR = /export\s+\*\s+from\s+['"]([^'"]+)['"]\s*;?/g;
29
+ const RE_EXPORT_NAMED_FROM = /export\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?/g;
30
+ const RE_EXPORT_NAMED = /export\s+\{([^}]+)\}\s*;?/g;
31
+ const RE_EXPORT_ASYNC_FN = /export\s+async\s+function\s+(\w+)/g;
32
+ const RE_EXPORT_FN = /export\s+function\s+(\w+)/g;
33
+ const RE_EXPORT_CLASS = /export\s+class\s+(\w+)/g;
34
+ const RE_EXPORT_VAR = /export\s+(?:const|let|var)\s+(\w+)\s*=/g;
35
+ const RE_AS_RENAME = /(\w+)\s+as\s+(\w+)/g;
36
+ const RE_TYPE_SPEC = /^\s*type\s+\w+/;
37
+ const RE_AS_SPLIT = /\s+as\s+/;
38
+
39
+ export function esmToCjs(code: string): string {
40
+ try {
41
+ return esmToCjsViaAst(code);
42
+ } catch {
43
+ return esmToCjsViaRegex(code);
44
+ }
45
+ }
46
+
47
+ // collect ESM→CJS patches from a pre-parsed AST, pushes into the patches array
48
+ export function collectEsmCjsPatches(
49
+ ast: any,
50
+ code: string,
51
+ patches: Array<[number, number, string]>,
52
+ ): void {
53
+ const hasDefaultExport = ast.body.some(
54
+ (n: any) => n.type === "ExportDefaultDeclaration",
55
+ );
56
+ const hasNamedExport = ast.body.some(
57
+ (n: any) => n.type === "ExportNamedDeclaration",
58
+ );
59
+ const mixedExports = hasDefaultExport && hasNamedExport;
60
+
61
+ for (const node of ast.body) {
62
+ if (node.type === "ImportDeclaration") {
63
+ const src = node.source.value;
64
+ const specs = node.specifiers;
65
+
66
+ if (specs.length === 0) {
67
+ patches.push([
68
+ node.start,
69
+ node.end,
70
+ `require(${JSON.stringify(src)});`,
71
+ ]);
72
+ } else {
73
+ const defSpec = specs.find(
74
+ (s: any) => s.type === "ImportDefaultSpecifier",
75
+ );
76
+ const nsSpec = specs.find(
77
+ (s: any) => s.type === "ImportNamespaceSpecifier",
78
+ );
79
+ const namedSpecs = specs.filter(
80
+ (s: any) => s.type === "ImportSpecifier",
81
+ );
82
+
83
+ const lines: string[] = [];
84
+ const tmpVar = `__import_${node.start}`;
85
+ const needsTmp = defSpec && (namedSpecs.length > 0 || nsSpec);
86
+
87
+ if (needsTmp) {
88
+ lines.push(`const ${tmpVar} = require(${JSON.stringify(src)})`);
89
+ lines.push(
90
+ `const ${defSpec.local.name} = ${tmpVar}.__esModule ? ${tmpVar}.default : ${tmpVar}`,
91
+ );
92
+ } else if (defSpec) {
93
+ lines.push(
94
+ `const ${defSpec.local.name} = (function(m) { return m.__esModule ? m.default : m; })(require(${JSON.stringify(src)}))`,
95
+ );
96
+ }
97
+
98
+ if (nsSpec) {
99
+ if (!needsTmp) {
100
+ lines.push(
101
+ `const ${nsSpec.local.name} = require(${JSON.stringify(src)})`,
102
+ );
103
+ } else {
104
+ lines.push(`const ${nsSpec.local.name} = ${tmpVar}`);
105
+ }
106
+ }
107
+
108
+ if (namedSpecs.length > 0) {
109
+ const binds = namedSpecs
110
+ .map((s: any) =>
111
+ s.imported.name === s.local.name
112
+ ? s.local.name
113
+ : `${s.imported.name}: ${s.local.name}`,
114
+ )
115
+ .join(", ");
116
+ if (needsTmp) {
117
+ lines.push(`const { ${binds} } = ${tmpVar}`);
118
+ } else {
119
+ lines.push(`const { ${binds} } = require(${JSON.stringify(src)})`);
120
+ }
121
+ }
122
+ patches.push([node.start, node.end, lines.join(";\n") + ";"]);
123
+ }
124
+ } else if (node.type === "ExportDefaultDeclaration") {
125
+ const decl = node.declaration;
126
+ const exportTarget = mixedExports ? "exports.default" : "module.exports";
127
+
128
+ if (
129
+ (decl.type === "FunctionDeclaration" ||
130
+ decl.type === "ClassDeclaration") &&
131
+ decl.id?.name
132
+ ) {
133
+ // Non-overlapping: remove "export default ", append binding
134
+ patches.push([node.start, decl.start, ""]);
135
+ patches.push([
136
+ node.end,
137
+ node.end,
138
+ `;\n${exportTarget} = ${decl.id.name};`,
139
+ ]);
140
+ } else {
141
+ // Replace "export default " with assignment target
142
+ patches.push([node.start, decl.start, `${exportTarget} = `]);
143
+ }
144
+ } else if (node.type === "ExportNamedDeclaration") {
145
+ if (node.declaration) {
146
+ const decl = node.declaration;
147
+ if (
148
+ decl.type === "FunctionDeclaration" ||
149
+ decl.type === "ClassDeclaration"
150
+ ) {
151
+ const name = decl.id.name;
152
+ // Non-overlapping patches: remove "export " prefix, append binding
153
+ patches.push([node.start, decl.start, ""]);
154
+ patches.push([
155
+ node.end,
156
+ node.end,
157
+ `;\nexports.${name} = ${name};`,
158
+ ]);
159
+ } else if (decl.type === "VariableDeclaration") {
160
+ const needsLiveBinding = decl.kind === "let" || decl.kind === "var";
161
+ const hasDestructuring = decl.declarations.some(
162
+ (d: any) =>
163
+ d.id.type === "ObjectPattern" || d.id.type === "ArrayPattern",
164
+ );
165
+ // Remove "export " prefix
166
+ patches.push([node.start, decl.start, ""]);
167
+ // Append export bindings after declaration
168
+ const bindings: string[] = [];
169
+ if (hasDestructuring) {
170
+ for (const d of decl.declarations) {
171
+ for (const name of extractBindingNames(d.id)) {
172
+ if (needsLiveBinding) {
173
+ bindings.push(
174
+ `Object.defineProperty(exports, ${JSON.stringify(name)}, { get() { return ${name}; }, enumerable: true })`,
175
+ );
176
+ } else {
177
+ bindings.push(`exports.${name} = ${name}`);
178
+ }
179
+ }
180
+ }
181
+ } else {
182
+ for (const d of decl.declarations) {
183
+ if (needsLiveBinding) {
184
+ bindings.push(
185
+ `Object.defineProperty(exports, ${JSON.stringify(d.id.name)}, { get() { return ${d.id.name}; }, enumerable: true })`,
186
+ );
187
+ } else {
188
+ bindings.push(`exports.${d.id.name} = ${d.id.name}`);
189
+ }
190
+ }
191
+ }
192
+ patches.push([
193
+ node.end,
194
+ node.end,
195
+ "\n" + bindings.join(";\n") + ";",
196
+ ]);
197
+ }
198
+ } else if (node.source) {
199
+ const src = node.source.value;
200
+ const tmp = `__reexport_${node.start}`;
201
+ const lines = [`const ${tmp} = require(${JSON.stringify(src)})`];
202
+ for (const spec of node.specifiers) {
203
+ if (spec.local.name === "default") {
204
+ lines.push(
205
+ `exports.${spec.exported.name} = ${tmp}.__esModule ? ${tmp}.default : ${tmp}`,
206
+ );
207
+ } else {
208
+ lines.push(
209
+ `exports.${spec.exported.name} = ${tmp}.${spec.local.name}`,
210
+ );
211
+ }
212
+ }
213
+ patches.push([node.start, node.end, lines.join(";\n") + ";"]);
214
+ } else {
215
+ const lines = node.specifiers.map(
216
+ (s: any) => `exports.${s.exported.name} = ${s.local.name}`,
217
+ );
218
+ patches.push([node.start, node.end, lines.join(";\n") + ";"]);
219
+ }
220
+ } else if (node.type === "ExportAllDeclaration") {
221
+ const src = node.source.value;
222
+ patches.push([
223
+ node.start,
224
+ node.end,
225
+ `Object.assign(exports, require(${JSON.stringify(src)}))`,
226
+ ]);
227
+ }
228
+ }
229
+ }
230
+
231
+ function esmToCjsViaAst(code: string): string {
232
+ const ast = acorn.parse(code, {
233
+ ecmaVersion: "latest",
234
+ sourceType: "module",
235
+ });
236
+ const patches: Array<[number, number, string]> = [];
237
+ collectEsmCjsPatches(ast as any, code, patches);
238
+
239
+ let output = code;
240
+ patches.sort((a, b) => b[0] - a[0] || b[1] - a[1]);
241
+ for (const [s, e, r] of patches)
242
+ output = output.slice(0, s) + r + output.slice(e);
243
+ return output;
244
+ }
245
+
246
+ // extract all bound names from a destructuring pattern or identifier
247
+ function extractBindingNames(pattern: any): string[] {
248
+ if (pattern.type === "Identifier") {
249
+ return [pattern.name];
250
+ }
251
+ if (pattern.type === "ObjectPattern") {
252
+ const names: string[] = [];
253
+ for (const prop of pattern.properties) {
254
+ if (prop.type === "RestElement") {
255
+ names.push(...extractBindingNames(prop.argument));
256
+ } else {
257
+ names.push(...extractBindingNames(prop.value));
258
+ }
259
+ }
260
+ return names;
261
+ }
262
+ if (pattern.type === "ArrayPattern") {
263
+ const names: string[] = [];
264
+ for (const elem of pattern.elements) {
265
+ if (elem) {
266
+ if (elem.type === "RestElement") {
267
+ names.push(...extractBindingNames(elem.argument));
268
+ } else {
269
+ names.push(...extractBindingNames(elem));
270
+ }
271
+ }
272
+ }
273
+ return names;
274
+ }
275
+ if (pattern.type === "AssignmentPattern") {
276
+ return extractBindingNames(pattern.left);
277
+ }
278
+ return [];
279
+ }
280
+
281
+ export function hasTopLevelAwait(code: string): boolean {
282
+ if (!RE_AWAIT_QUICK.test(code)) return false;
283
+
284
+ try {
285
+ let ast: any;
286
+ try {
287
+ ast = acorn.parse(code, {
288
+ ecmaVersion: "latest",
289
+ sourceType: "script",
290
+ allowAwaitOutsideFunction: true,
291
+ });
292
+ } catch {
293
+ ast = acorn.parse(code, {
294
+ ecmaVersion: "latest",
295
+ sourceType: "module",
296
+ });
297
+ }
298
+
299
+ let found = false;
300
+ let insideAsync = 0;
301
+
302
+ function walk(node: any): void {
303
+ if (found || !node || typeof node !== "object") return;
304
+ if (Array.isArray(node)) {
305
+ for (const child of node) walk(child);
306
+ return;
307
+ }
308
+ if (typeof node.type !== "string") return;
309
+
310
+ const isAsyncFn =
311
+ (node.type === "FunctionDeclaration" ||
312
+ node.type === "FunctionExpression" ||
313
+ node.type === "ArrowFunctionExpression") &&
314
+ node.async;
315
+
316
+ if (isAsyncFn) insideAsync++;
317
+ if (node.type === "AwaitExpression" && insideAsync === 0) {
318
+ found = true;
319
+ }
320
+ if (node.type === "ForOfStatement" && node.await && insideAsync === 0) {
321
+ found = true;
322
+ }
323
+ if (!found) {
324
+ for (const key in node) {
325
+ if (key === "type" || key === "start" || key === "end") continue;
326
+ const val = node[key];
327
+ if (val && typeof val === "object") walk(val);
328
+ }
329
+ }
330
+ if (isAsyncFn) insideAsync--;
331
+ }
332
+
333
+ walk(ast);
334
+ return found;
335
+ } catch {
336
+ return RE_AWAIT_LOOKAHEAD.test(code);
337
+ }
338
+ }
339
+
340
+ export function stripTopLevelAwait(
341
+ code: string,
342
+ mode: "topLevelOnly" | "full" = "topLevelOnly",
343
+ ): string {
344
+ const full = mode === "full";
345
+ if (!full && !RE_AWAIT_QUICK.test(code)) return code;
346
+ if (full && !RE_AWAIT_QUICK.test(code) && !RE_ASYNC_QUICK.test(code)) return code;
347
+
348
+ try {
349
+ let ast: any;
350
+ try {
351
+ ast = acorn.parse(code, {
352
+ ecmaVersion: "latest",
353
+ sourceType: "script",
354
+ allowAwaitOutsideFunction: true,
355
+ });
356
+ } catch {
357
+ ast = acorn.parse(code, {
358
+ ecmaVersion: "latest",
359
+ sourceType: "module",
360
+ });
361
+ }
362
+
363
+ const patches: Array<[number, number, string]> = [];
364
+ let insideAsync = 0;
365
+
366
+ function walk(node: any) {
367
+ if (!node || typeof node !== "object") return;
368
+ if (Array.isArray(node)) {
369
+ for (const child of node) walk(child);
370
+ return;
371
+ }
372
+ if (typeof node.type !== "string") return;
373
+
374
+ const isAsyncFn =
375
+ (node.type === "FunctionDeclaration" ||
376
+ node.type === "FunctionExpression" ||
377
+ node.type === "ArrowFunctionExpression") &&
378
+ node.async;
379
+
380
+ if (isAsyncFn) insideAsync++;
381
+
382
+ if (full && isAsyncFn && !node.generator) {
383
+ if (code.slice(node.start, node.start + 5) === "async") {
384
+ let end = node.start + 5;
385
+ while (end < code.length && (code[end] === " " || code[end] === "\t")) end++;
386
+ patches.push([node.start, end, ""]);
387
+ } else {
388
+ const searchStart = Math.max(0, node.start - 30);
389
+ const region = code.slice(searchStart, node.start);
390
+ const asyncIdx = region.lastIndexOf("async");
391
+ if (asyncIdx >= 0) {
392
+ const absStart = searchStart + asyncIdx;
393
+ let absEnd = absStart + 5;
394
+ while (absEnd < code.length && (code[absEnd] === " " || code[absEnd] === "\t")) absEnd++;
395
+ patches.push([absStart, absEnd, ""]);
396
+ }
397
+ }
398
+ }
399
+
400
+ if (node.type === "AwaitExpression") {
401
+ if (full || insideAsync === 0) {
402
+ let awaitEnd = node.start + 5;
403
+ while (
404
+ awaitEnd < node.argument.start &&
405
+ (code[awaitEnd] === " " || code[awaitEnd] === "\t" || code[awaitEnd] === "\n" || code[awaitEnd] === "\r")
406
+ ) {
407
+ awaitEnd++;
408
+ }
409
+ patches.push([node.start, awaitEnd, "__syncAwait("]);
410
+ patches.push([node.end, node.end, ")"]);
411
+ }
412
+ }
413
+
414
+ if (node.type === "ForOfStatement" && node.await) {
415
+ if (full || insideAsync === 0) {
416
+ const forEnd = node.start + 3;
417
+ const snippet = code.slice(forEnd, node.left.start);
418
+ const awIdx = snippet.indexOf("await");
419
+ if (awIdx >= 0) {
420
+ const absStart = forEnd + awIdx;
421
+ let absEnd = absStart + 5;
422
+ while (absEnd < code.length && code[absEnd] === " ") absEnd++;
423
+ patches.push([absStart, absEnd, ""]);
424
+ }
425
+ }
426
+ }
427
+
428
+ for (const key in node) {
429
+ if (key === "type" || key === "start" || key === "end") continue;
430
+ const val = node[key];
431
+ if (val && typeof val === "object") walk(val);
432
+ }
433
+
434
+ if (isAsyncFn) insideAsync--;
435
+ }
436
+
437
+ walk(ast);
438
+
439
+ if (patches.length === 0) return code;
440
+
441
+ let output = code;
442
+ patches.sort((a, b) => b[0] - a[0] || b[1] - a[1]);
443
+ for (const [start, end, replacement] of patches) {
444
+ output = output.slice(0, start) + replacement + output.slice(end);
445
+ }
446
+ return output;
447
+ } catch {
448
+ if (full) {
449
+ let out = code.replace(RE_AWAIT_LOOKAHEAD_G, "");
450
+ out = out.replace(RE_ASYNC_FN_G, "");
451
+ out = out.replace(RE_ASYNC_PAREN_G, "");
452
+ out = out.replace(RE_ASYNC_ARROW_G, "");
453
+ return out;
454
+ }
455
+ return code.replace(RE_AWAIT_LOOKAHEAD_G, "");
456
+ }
457
+ }
458
+
459
+ function esmToCjsViaRegex(code: string): string {
460
+ let out = code;
461
+ // strip TS type-only imports
462
+ out = out.replace(RE_TYPE_IMPORT_BRACES, "");
463
+ out = out.replace(RE_TYPE_IMPORT_DEFAULT, "");
464
+ out = out.replace(RE_TYPE_IMPORT_STAR, "");
465
+ // remove inline type specifiers from mixed imports
466
+ out = out.replace(
467
+ RE_MIXED_TYPE_IMPORT,
468
+ (_m, specs: string, src: string) => {
469
+ const kept = specs
470
+ .split(",")
471
+ .filter((s: string) => !RE_TYPE_SPEC.test(s))
472
+ .map((s: string) => s.trim())
473
+ .filter(Boolean);
474
+ if (kept.length === 0) return "";
475
+ const fixed = kept.join(", ").replace(RE_AS_RENAME, "$1: $2");
476
+ return `const {${fixed}} = require("${src}");`;
477
+ },
478
+ );
479
+ // strip TS type-only exports
480
+ out = out.replace(RE_TYPE_EXPORT_FROM, "");
481
+ out = out.replace(RE_TYPE_EXPORT, "");
482
+ out = out.replace(RE_IMPORT_STAR, 'const $1 = require("$2");');
483
+ out = out.replace(
484
+ RE_IMPORT_DEFAULT_NAMED,
485
+ (_m, def, named, src) => {
486
+ const tmp = `__import_${def}`;
487
+ const fixed = named.replace(RE_AS_RENAME, "$1: $2");
488
+ return `const ${tmp} = require("${src}"); const ${def} = ${tmp}.__esModule ? ${tmp}.default : ${tmp}; const {${fixed}} = ${tmp};`;
489
+ },
490
+ );
491
+ out = out.replace(RE_IMPORT_DEFAULT, 'const $1 = require("$2");');
492
+ out = out.replace(
493
+ RE_IMPORT_NAMED,
494
+ (_m, specs, src) => {
495
+ const fixed = specs.replace(RE_AS_RENAME, "$1: $2");
496
+ return `const {${fixed}} = require("${src}");`;
497
+ },
498
+ );
499
+ out = out.replace(RE_IMPORT_SIDE_EFFECT, 'require("$1");');
500
+ // export default
501
+ out = out.replace(RE_EXPORT_DEFAULT_CLASS, "module.exports = class $1");
502
+ out = out.replace(RE_EXPORT_DEFAULT_FN_NAMED, "module.exports = function $1");
503
+ out = out.replace(RE_EXPORT_DEFAULT_FN_ANON, "module.exports = function(");
504
+ out = out.replace(RE_EXPORT_DEFAULT, "module.exports = ");
505
+ // re-exports
506
+ out = out.replace(RE_EXPORT_STAR, 'Object.assign(exports, require("$1"));');
507
+ out = out.replace(
508
+ RE_EXPORT_NAMED_FROM,
509
+ (_m, specs, src) => {
510
+ const binds = specs
511
+ .split(",")
512
+ .map((s: string) => {
513
+ const parts = s.trim().split(RE_AS_SPLIT);
514
+ const local = parts[0].trim();
515
+ const exported = parts.length > 1 ? parts[1].trim() : local;
516
+ return `exports.${exported} = require("${src}").${local}`;
517
+ })
518
+ .join("; ");
519
+ return binds + ";";
520
+ },
521
+ );
522
+ out = out.replace(
523
+ RE_EXPORT_NAMED,
524
+ (_m, specs) => {
525
+ const binds = specs
526
+ .split(",")
527
+ .map((s: string) => {
528
+ const parts = s.trim().split(RE_AS_SPLIT);
529
+ const local = parts[0].trim();
530
+ const exported = parts.length > 1 ? parts[1].trim() : local;
531
+ return `exports.${exported} = ${local}`;
532
+ })
533
+ .join("; ");
534
+ return binds + ";";
535
+ },
536
+ );
537
+ // named exports
538
+ out = out.replace(RE_EXPORT_ASYNC_FN, "exports.$1 = async function $1");
539
+ out = out.replace(RE_EXPORT_FN, "exports.$1 = function $1");
540
+ out = out.replace(RE_EXPORT_CLASS, "exports.$1 = class $1");
541
+ out = out.replace(RE_EXPORT_VAR, "exports.$1 =");
542
+ return out;
543
+ }