@wyw-in-js/transform 1.0.6 → 1.0.7

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 (77) hide show
  1. package/esm/cache.js +100 -7
  2. package/esm/cache.js.map +1 -1
  3. package/esm/debug/fileReporter.js.map +1 -1
  4. package/esm/module.js +51 -2
  5. package/esm/module.js.map +1 -1
  6. package/esm/plugins/shaker.js +152 -13
  7. package/esm/plugins/shaker.js.map +1 -1
  8. package/esm/shaker.js +51 -23
  9. package/esm/shaker.js.map +1 -1
  10. package/esm/transform/BaseEntrypoint.js +3 -1
  11. package/esm/transform/BaseEntrypoint.js.map +1 -1
  12. package/esm/transform/Entrypoint.js +60 -17
  13. package/esm/transform/Entrypoint.js.map +1 -1
  14. package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
  15. package/esm/transform/barrelManifest.js +291 -0
  16. package/esm/transform/barrelManifest.js.map +1 -0
  17. package/esm/transform/generators/getExports.js +5 -0
  18. package/esm/transform/generators/getExports.js.map +1 -1
  19. package/esm/transform/generators/processEntrypoint.js +27 -1
  20. package/esm/transform/generators/processEntrypoint.js.map +1 -1
  21. package/esm/transform/generators/resolveImports.js +29 -5
  22. package/esm/transform/generators/resolveImports.js.map +1 -1
  23. package/esm/transform/generators/rewriteBarrelImports.js +733 -0
  24. package/esm/transform/generators/rewriteBarrelImports.js.map +1 -0
  25. package/esm/transform/generators/transform.js +154 -21
  26. package/esm/transform/generators/transform.js.map +1 -1
  27. package/esm/transform/types.js.map +1 -1
  28. package/lib/cache.js +103 -7
  29. package/lib/cache.js.map +1 -1
  30. package/lib/debug/fileReporter.js.map +1 -1
  31. package/lib/module.js +51 -2
  32. package/lib/module.js.map +1 -1
  33. package/lib/plugins/shaker.js +152 -13
  34. package/lib/plugins/shaker.js.map +1 -1
  35. package/lib/shaker.js +58 -26
  36. package/lib/shaker.js.map +1 -1
  37. package/lib/transform/BaseEntrypoint.js +3 -1
  38. package/lib/transform/BaseEntrypoint.js.map +1 -1
  39. package/lib/transform/Entrypoint.js +61 -17
  40. package/lib/transform/Entrypoint.js.map +1 -1
  41. package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
  42. package/lib/transform/barrelManifest.js +300 -0
  43. package/lib/transform/barrelManifest.js.map +1 -0
  44. package/lib/transform/generators/getExports.js +5 -0
  45. package/lib/transform/generators/getExports.js.map +1 -1
  46. package/lib/transform/generators/processEntrypoint.js +27 -1
  47. package/lib/transform/generators/processEntrypoint.js.map +1 -1
  48. package/lib/transform/generators/resolveImports.js +29 -5
  49. package/lib/transform/generators/resolveImports.js.map +1 -1
  50. package/lib/transform/generators/rewriteBarrelImports.js +743 -0
  51. package/lib/transform/generators/rewriteBarrelImports.js.map +1 -0
  52. package/lib/transform/generators/transform.js +158 -22
  53. package/lib/transform/generators/transform.js.map +1 -1
  54. package/lib/transform/types.js.map +1 -1
  55. package/package.json +8 -4
  56. package/types/cache.d.ts +16 -2
  57. package/types/cache.js +111 -7
  58. package/types/debug/fileReporter.d.ts +1 -0
  59. package/types/module.d.ts +3 -0
  60. package/types/module.js +57 -2
  61. package/types/plugins/shaker.js +161 -16
  62. package/types/shaker.d.ts +10 -1
  63. package/types/shaker.js +56 -28
  64. package/types/transform/BaseEntrypoint.d.ts +3 -1
  65. package/types/transform/BaseEntrypoint.js +5 -1
  66. package/types/transform/Entrypoint.d.ts +9 -0
  67. package/types/transform/Entrypoint.js +73 -20
  68. package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
  69. package/types/transform/barrelManifest.d.ts +42 -0
  70. package/types/transform/barrelManifest.js +300 -0
  71. package/types/transform/generators/getExports.js +5 -0
  72. package/types/transform/generators/processEntrypoint.js +26 -1
  73. package/types/transform/generators/resolveImports.js +29 -5
  74. package/types/transform/generators/rewriteBarrelImports.d.ts +15 -0
  75. package/types/transform/generators/rewriteBarrelImports.js +815 -0
  76. package/types/transform/generators/transform.js +148 -19
  77. package/types/transform/types.d.ts +2 -0
@@ -0,0 +1,815 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.rewriteOptimizedBarrelImports = rewriteOptimizedBarrelImports;
40
+ /* eslint-disable no-continue, @typescript-eslint/no-use-before-define, @typescript-eslint/no-explicit-any, no-param-reassign, prefer-destructuring */
41
+ const generator_1 = __importDefault(require("@babel/generator"));
42
+ const t = __importStar(require("@babel/types"));
43
+ const EventEmitter_1 = require("../../utils/EventEmitter");
44
+ const shaker_1 = require("../../shaker");
45
+ const cache_1 = require("../../cache");
46
+ const Entrypoint_1 = require("../Entrypoint");
47
+ const barrelManifest_1 = require("../barrelManifest");
48
+ const createAnalysisServices = (services) => ({
49
+ ...services,
50
+ cache: new cache_1.TransformCacheCollection({
51
+ barrelManifests: services.cache.barrelManifests,
52
+ exports: services.cache.exports,
53
+ }),
54
+ eventEmitter: EventEmitter_1.EventEmitter.dummy,
55
+ });
56
+ const addBinding = (manifest, exported, binding, explicitExports) => {
57
+ const existing = manifest[exported];
58
+ if (explicitExports.has(exported)) {
59
+ return;
60
+ }
61
+ if (!existing) {
62
+ manifest[exported] = binding;
63
+ return;
64
+ }
65
+ if (existing.kind === 'blocked') {
66
+ return;
67
+ }
68
+ if (!isSameBinding(existing, binding)) {
69
+ manifest[exported] = {
70
+ kind: 'blocked',
71
+ reason: 'ambiguous',
72
+ };
73
+ }
74
+ };
75
+ const addBlockedExport = (manifest, exported, reason) => {
76
+ manifest[exported] = {
77
+ kind: 'blocked',
78
+ reason,
79
+ };
80
+ };
81
+ const buildResolvedDependencyMap = (resolvedImports) => new Map(resolvedImports.map((dependency) => [dependency.source, dependency]));
82
+ const cloneExportedName = (name) => t.isValidIdentifier(name) ? t.identifier(name) : t.stringLiteral(name);
83
+ const cloneImportedName = (name) => name === 'default' || t.isValidIdentifier(name)
84
+ ? t.identifier(name)
85
+ : t.stringLiteral(name);
86
+ const isSameBinding = (left, right) => {
87
+ if (left.kind !== right.kind) {
88
+ return false;
89
+ }
90
+ if (left.source !== right.source) {
91
+ return false;
92
+ }
93
+ if (left.kind === 'named' && right.kind === 'named') {
94
+ return left.imported === right.imported;
95
+ }
96
+ return true;
97
+ };
98
+ function createAnalysisEntrypoint(services, filename, loadedCode) {
99
+ return Entrypoint_1.Entrypoint.createRoot(services, filename, ['*'], loadedCode);
100
+ }
101
+ function getUniqueSources(raw) {
102
+ return Array.from(new Set([
103
+ ...raw.reexports.map((reexport) => reexport.source),
104
+ ...raw.exportAll,
105
+ ]));
106
+ }
107
+ function buildImportsForResolve(raw) {
108
+ return new Map(getUniqueSources(raw).map((source) => [source, []]));
109
+ }
110
+ function getReexportResolutionMap(resolvedImports) {
111
+ return new Map(resolvedImports.map((dependency) => [
112
+ dependency.source,
113
+ dependency.resolved,
114
+ ]));
115
+ }
116
+ function isBarrelEntry(entry) {
117
+ return entry.kind === 'barrel';
118
+ }
119
+ function isRawBarrelManifest(entry) {
120
+ return 'reexports' in entry;
121
+ }
122
+ function shouldUseDirectExports(reason) {
123
+ return reason === 'impure';
124
+ }
125
+ const getModuleName = (node) => t.isIdentifier(node) ? node.name : node.value;
126
+ const canEmitNamedReexport = (imported) => imported === 'default' || t.isValidIdentifier(imported);
127
+ function collectOptimizedImports(ast) {
128
+ const imports = new Map();
129
+ const addImport = (source, imported) => {
130
+ if (!imports.has(source)) {
131
+ imports.set(source, []);
132
+ }
133
+ if (!imports.get(source).includes(imported)) {
134
+ imports.get(source).push(imported);
135
+ }
136
+ };
137
+ const program = ast.program;
138
+ for (const statement of program.body) {
139
+ if (t.isImportDeclaration(statement) &&
140
+ t.isStringLiteral(statement.source)) {
141
+ if (statement.specifiers.length === 0) {
142
+ addImport(statement.source.value, 'side-effect');
143
+ continue;
144
+ }
145
+ for (const specifier of statement.specifiers) {
146
+ if (t.isImportDefaultSpecifier(specifier)) {
147
+ addImport(statement.source.value, 'default');
148
+ continue;
149
+ }
150
+ if (t.isImportNamespaceSpecifier(specifier)) {
151
+ addImport(statement.source.value, '*');
152
+ continue;
153
+ }
154
+ if (t.isImportSpecifier(specifier)) {
155
+ addImport(statement.source.value, t.isIdentifier(specifier.imported)
156
+ ? specifier.imported.name
157
+ : specifier.imported.value);
158
+ }
159
+ }
160
+ continue;
161
+ }
162
+ if (t.isExportNamedDeclaration(statement) &&
163
+ statement.source &&
164
+ t.isStringLiteral(statement.source)) {
165
+ for (const specifier of statement.specifiers) {
166
+ if (t.isExportNamespaceSpecifier(specifier)) {
167
+ addImport(statement.source.value, '*');
168
+ continue;
169
+ }
170
+ if (t.isExportDefaultSpecifier(specifier)) {
171
+ addImport(statement.source.value, 'default');
172
+ continue;
173
+ }
174
+ if (t.isExportSpecifier(specifier)) {
175
+ addImport(statement.source.value, getModuleName(specifier.local));
176
+ }
177
+ }
178
+ continue;
179
+ }
180
+ if (t.isExportAllDeclaration(statement) &&
181
+ statement.source &&
182
+ t.isStringLiteral(statement.source)) {
183
+ addImport(statement.source.value, '*');
184
+ }
185
+ }
186
+ return imports;
187
+ }
188
+ function groupImportSpecifiers(optimized) {
189
+ const grouped = new Map();
190
+ for (const specifier of optimized) {
191
+ if (!grouped.has(specifier.source)) {
192
+ grouped.set(specifier.source, {
193
+ defaults: [],
194
+ named: [],
195
+ });
196
+ }
197
+ const bucket = grouped.get(specifier.source);
198
+ if (specifier.kind === 'default') {
199
+ bucket.defaults.push(t.importDefaultSpecifier(specifier.local));
200
+ continue;
201
+ }
202
+ bucket.named.push(t.importSpecifier(specifier.local, cloneImportedName(specifier.imported)));
203
+ }
204
+ const declarations = [];
205
+ for (const [source, bucket] of grouped) {
206
+ if (bucket.defaults.length === 0) {
207
+ declarations.push(t.importDeclaration(bucket.named, t.stringLiteral(source)));
208
+ continue;
209
+ }
210
+ declarations.push(t.importDeclaration([bucket.defaults[0], ...bucket.named], t.stringLiteral(source)));
211
+ for (const defaultSpecifier of bucket.defaults.slice(1)) {
212
+ declarations.push(t.importDeclaration([defaultSpecifier], t.stringLiteral(source)));
213
+ }
214
+ }
215
+ return declarations;
216
+ }
217
+ function groupExportSpecifiers(optimized) {
218
+ const grouped = new Map();
219
+ for (const specifier of optimized) {
220
+ if (!grouped.has(specifier.source)) {
221
+ grouped.set(specifier.source, []);
222
+ }
223
+ if (specifier.kind === 'namespace') {
224
+ grouped
225
+ .get(specifier.source)
226
+ .push(t.exportNamespaceSpecifier(t.identifier(specifier.exported)));
227
+ continue;
228
+ }
229
+ grouped
230
+ .get(specifier.source)
231
+ .push(t.exportSpecifier(t.identifier(specifier.imported), cloneExportedName(specifier.exported)));
232
+ }
233
+ return Array.from(grouped.entries()).map(([source, specifiers]) => t.exportNamedDeclaration(null, specifiers, t.stringLiteral(source)));
234
+ }
235
+ function createImportFallback(statement, fallbackSpecifiers) {
236
+ if (fallbackSpecifiers.length === 0) {
237
+ return null;
238
+ }
239
+ return t.importDeclaration(fallbackSpecifiers, t.stringLiteral(statement.source.value));
240
+ }
241
+ function createExportFallback(statement, fallbackSpecifiers) {
242
+ if (!statement.source || fallbackSpecifiers.length === 0) {
243
+ return null;
244
+ }
245
+ return t.exportNamedDeclaration(null, fallbackSpecifiers, t.stringLiteral(statement.source.value));
246
+ }
247
+ function emitRewriteSkipped(action, source, reason) {
248
+ action.services.eventEmitter.single({
249
+ file: action.entrypoint.name,
250
+ kind: 'barrelRewriteSkipped',
251
+ reason,
252
+ source,
253
+ });
254
+ }
255
+ function getManifestExport(manifest, exported) {
256
+ return manifest.exports[exported] ?? null;
257
+ }
258
+ function* getNamedBinding(analysisServices, targetResolved, imported, stack) {
259
+ if (stack.has(targetResolved)) {
260
+ return {
261
+ kind: 'blocked',
262
+ reason: 'cycle',
263
+ };
264
+ }
265
+ const targetManifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, targetResolved, stack);
266
+ if (isBarrelEntry(targetManifest)) {
267
+ const resolved = getManifestExport(targetManifest, imported);
268
+ if (resolved) {
269
+ return resolved;
270
+ }
271
+ return {
272
+ kind: 'blocked',
273
+ reason: targetManifest.complete ? 'unresolved' : 'unknown-star',
274
+ };
275
+ }
276
+ return {
277
+ kind: 'named',
278
+ imported,
279
+ source: targetResolved,
280
+ };
281
+ }
282
+ function* getStarCandidates(analysisServices, targetResolved, stack) {
283
+ if (stack.has(targetResolved)) {
284
+ return {
285
+ candidates: [],
286
+ complete: false,
287
+ };
288
+ }
289
+ const targetManifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, targetResolved, stack);
290
+ if (isBarrelEntry(targetManifest)) {
291
+ if (!targetManifest.complete) {
292
+ return {
293
+ candidates: [],
294
+ complete: false,
295
+ };
296
+ }
297
+ return {
298
+ candidates: Object.entries(targetManifest.exports)
299
+ .filter(([exported, binding]) => exported !== 'default' && binding.kind !== 'blocked')
300
+ .map(([exported, binding]) => ({
301
+ binding: binding,
302
+ exported,
303
+ })),
304
+ complete: true,
305
+ };
306
+ }
307
+ if (!shouldUseDirectExports(targetManifest.reason)) {
308
+ return {
309
+ candidates: [],
310
+ complete: false,
311
+ };
312
+ }
313
+ const exports = yield* getExportsForFile.call(this, analysisServices, targetResolved);
314
+ return {
315
+ candidates: exports
316
+ .filter((exported) => exported !== 'default')
317
+ .map((exported) => ({
318
+ binding: {
319
+ kind: 'named',
320
+ imported: exported,
321
+ source: targetResolved,
322
+ },
323
+ exported,
324
+ })),
325
+ complete: true,
326
+ };
327
+ }
328
+ function* getExportsForFile(services, filename) {
329
+ const entrypoint = createAnalysisEntrypoint(services, filename);
330
+ return yield* this.getNext('getExports', entrypoint, undefined, null);
331
+ }
332
+ function* getOrBuildBarrelManifest(analysisServices, filename, stack = new Set()) {
333
+ const cached = this.services.cache.get('barrelManifests', filename);
334
+ if (cached) {
335
+ this.services.eventEmitter.single({
336
+ file: filename,
337
+ kind: 'barrelManifest',
338
+ status: 'hit',
339
+ });
340
+ return cached;
341
+ }
342
+ const loadedAndParsed = analysisServices.loadAndParseFn(analysisServices, filename, undefined, analysisServices.log);
343
+ if (loadedAndParsed.evaluator === 'ignored') {
344
+ const ignoredEntry = {
345
+ kind: 'ineligible',
346
+ reason: 'ignored',
347
+ };
348
+ this.services.cache.add('barrelManifests', filename, ignoredEntry);
349
+ return ignoredEntry;
350
+ }
351
+ if (loadedAndParsed.evaluator !== shaker_1.shaker) {
352
+ const customEntry = {
353
+ kind: 'ineligible',
354
+ reason: 'custom-evaluator',
355
+ };
356
+ this.services.cache.add('barrelManifests', filename, customEntry);
357
+ return customEntry;
358
+ }
359
+ const analyzed = (0, barrelManifest_1.analyzeBarrelFile)(loadedAndParsed.ast);
360
+ if (!isRawBarrelManifest(analyzed)) {
361
+ this.services.cache.add('barrelManifests', filename, analyzed);
362
+ return analyzed;
363
+ }
364
+ const resolveEntrypoint = createAnalysisEntrypoint(analysisServices, filename, loadedAndParsed.code);
365
+ const resolvedImports = yield* this.getNext('resolveImports', resolveEntrypoint, {
366
+ imports: buildImportsForResolve(analyzed),
367
+ }, null);
368
+ const manifestDependencies = resolvedImports.flatMap((dependency) => dependency.resolved ? [dependency.resolved] : []);
369
+ const resolutionMap = getReexportResolutionMap(resolvedImports);
370
+ const manifest = {
371
+ complete: analyzed.complete,
372
+ exports: {},
373
+ kind: 'barrel',
374
+ };
375
+ const explicitExports = new Set(analyzed.explicitExports);
376
+ const nextStack = new Set(stack);
377
+ nextStack.add(filename);
378
+ for (const reexport of analyzed.reexports) {
379
+ explicitExports.add(reexport.exported);
380
+ const targetResolved = resolutionMap.get(reexport.source);
381
+ if (!targetResolved) {
382
+ manifest.complete = false;
383
+ addBlockedExport(manifest.exports, reexport.exported, 'unresolved');
384
+ continue;
385
+ }
386
+ if (reexport.kind === 'namespace') {
387
+ const namespaceBinding = yield* getNamespaceBinding.call(this, analysisServices, targetResolved, nextStack);
388
+ manifest.exports[reexport.exported] = namespaceBinding;
389
+ if (namespaceBinding.kind === 'blocked') {
390
+ manifest.complete = false;
391
+ }
392
+ continue;
393
+ }
394
+ const binding = yield* getNamedBinding.call(this, analysisServices, targetResolved, reexport.imported, nextStack);
395
+ manifest.exports[reexport.exported] = binding;
396
+ if (binding.kind === 'blocked') {
397
+ manifest.complete = false;
398
+ }
399
+ }
400
+ for (const exportAllSource of analyzed.exportAll) {
401
+ const targetResolved = resolutionMap.get(exportAllSource);
402
+ if (!targetResolved) {
403
+ manifest.complete = false;
404
+ continue;
405
+ }
406
+ const { candidates, complete } = yield* getStarCandidates.call(this, analysisServices, targetResolved, nextStack);
407
+ if (!complete) {
408
+ manifest.complete = false;
409
+ continue;
410
+ }
411
+ for (const candidate of candidates) {
412
+ addBinding(manifest.exports, candidate.exported, candidate.binding, explicitExports);
413
+ }
414
+ }
415
+ this.services.cache.add('barrelManifests', filename, manifest);
416
+ this.services.cache.setCacheDependencies('barrelManifests', filename, manifestDependencies);
417
+ this.services.eventEmitter.single({
418
+ complete: manifest.complete,
419
+ file: filename,
420
+ kind: 'barrelManifest',
421
+ status: 'built',
422
+ });
423
+ return manifest;
424
+ }
425
+ function* getNamespaceBinding(analysisServices, targetResolved, stack) {
426
+ if (stack.has(targetResolved)) {
427
+ return {
428
+ kind: 'blocked',
429
+ reason: 'cycle',
430
+ };
431
+ }
432
+ const targetManifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, targetResolved, stack);
433
+ if (isBarrelEntry(targetManifest)) {
434
+ return {
435
+ kind: 'blocked',
436
+ reason: 'namespace-barrel',
437
+ };
438
+ }
439
+ return {
440
+ kind: 'namespace',
441
+ source: targetResolved,
442
+ };
443
+ }
444
+ function getResolvedDependency(dependencies, source) {
445
+ return dependencies.get(source);
446
+ }
447
+ function* rewriteImportDeclaration(analysisServices, statement, dependencies) {
448
+ const dependency = getResolvedDependency(dependencies, statement.source.value);
449
+ if (!dependency?.resolved) {
450
+ return {
451
+ generatedSources: [],
452
+ mode: 'unchanged',
453
+ statements: [statement],
454
+ };
455
+ }
456
+ const manifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, dependency.resolved);
457
+ if (!isBarrelEntry(manifest)) {
458
+ return {
459
+ generatedSources: [],
460
+ mode: 'unchanged',
461
+ statements: [statement],
462
+ };
463
+ }
464
+ const optimized = [];
465
+ const fallback = [];
466
+ for (const specifier of statement.specifiers) {
467
+ if (t.isImportNamespaceSpecifier(specifier)) {
468
+ fallback.push(specifier);
469
+ continue;
470
+ }
471
+ if (t.isImportDefaultSpecifier(specifier)) {
472
+ const binding = getManifestExport(manifest, 'default');
473
+ if (binding?.kind === 'named' && binding.imported === 'default') {
474
+ optimized.push({
475
+ kind: 'default',
476
+ local: specifier.local,
477
+ source: binding.source,
478
+ });
479
+ continue;
480
+ }
481
+ if (binding?.kind === 'blocked') {
482
+ emitRewriteSkipped(this, statement.source.value, binding.reason);
483
+ }
484
+ fallback.push(specifier);
485
+ continue;
486
+ }
487
+ const imported = t.isIdentifier(specifier.imported)
488
+ ? specifier.imported.name
489
+ : specifier.imported.value;
490
+ const binding = getManifestExport(manifest, imported);
491
+ if (binding?.kind === 'named') {
492
+ optimized.push({
493
+ imported: binding.imported,
494
+ kind: 'named',
495
+ local: specifier.local,
496
+ source: binding.source,
497
+ });
498
+ continue;
499
+ }
500
+ if (binding?.kind === 'blocked') {
501
+ emitRewriteSkipped(this, statement.source.value, binding.reason);
502
+ }
503
+ fallback.push(specifier);
504
+ }
505
+ if (optimized.length === 0) {
506
+ return {
507
+ generatedSources: [],
508
+ mode: 'unchanged',
509
+ statements: [statement],
510
+ };
511
+ }
512
+ const rewritten = groupImportSpecifiers(optimized);
513
+ const fallbackDeclaration = createImportFallback(statement, fallback);
514
+ const mode = fallbackDeclaration ? 'partial' : 'full';
515
+ this.services.eventEmitter.single({
516
+ file: this.entrypoint.name,
517
+ kind: 'barrelRewrite',
518
+ mode,
519
+ optimized: optimized.length,
520
+ source: statement.source.value,
521
+ });
522
+ return {
523
+ generatedSources: Array.from(new Set(optimized.map((specifier) => specifier.source))),
524
+ mode,
525
+ statements: fallbackDeclaration
526
+ ? [fallbackDeclaration, ...rewritten]
527
+ : rewritten,
528
+ };
529
+ }
530
+ function* rewriteExportNamedDeclaration(analysisServices, statement, dependencies) {
531
+ if (!statement.source || !t.isStringLiteral(statement.source)) {
532
+ return {
533
+ generatedSources: [],
534
+ mode: 'unchanged',
535
+ statements: [statement],
536
+ };
537
+ }
538
+ const dependency = getResolvedDependency(dependencies, statement.source.value);
539
+ if (!dependency?.resolved) {
540
+ return {
541
+ generatedSources: [],
542
+ mode: 'unchanged',
543
+ statements: [statement],
544
+ };
545
+ }
546
+ const manifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, dependency.resolved);
547
+ if (!isBarrelEntry(manifest)) {
548
+ return {
549
+ generatedSources: [],
550
+ mode: 'unchanged',
551
+ statements: [statement],
552
+ };
553
+ }
554
+ const optimized = [];
555
+ const fallback = [];
556
+ for (const specifier of statement.specifiers) {
557
+ if (t.isExportNamespaceSpecifier(specifier)) {
558
+ fallback.push(specifier);
559
+ continue;
560
+ }
561
+ if (t.isExportDefaultSpecifier(specifier)) {
562
+ const binding = getManifestExport(manifest, 'default');
563
+ if (binding?.kind === 'named' && binding.imported === 'default') {
564
+ optimized.push({
565
+ exported: getModuleName(specifier.exported),
566
+ imported: 'default',
567
+ kind: 'named',
568
+ source: binding.source,
569
+ });
570
+ continue;
571
+ }
572
+ if (binding?.kind === 'blocked') {
573
+ emitRewriteSkipped(this, statement.source.value, binding.reason);
574
+ }
575
+ fallback.push(specifier);
576
+ continue;
577
+ }
578
+ const imported = getModuleName(specifier.local);
579
+ const exported = getModuleName(specifier.exported);
580
+ const binding = getManifestExport(manifest, imported);
581
+ if (binding?.kind === 'named' && canEmitNamedReexport(binding.imported)) {
582
+ optimized.push({
583
+ exported,
584
+ imported: binding.imported,
585
+ kind: 'named',
586
+ source: binding.source,
587
+ });
588
+ continue;
589
+ }
590
+ if (binding?.kind === 'namespace' && t.isValidIdentifier(exported)) {
591
+ optimized.push({
592
+ exported,
593
+ kind: 'namespace',
594
+ source: binding.source,
595
+ });
596
+ continue;
597
+ }
598
+ if (binding?.kind === 'blocked') {
599
+ emitRewriteSkipped(this, statement.source.value, binding.reason);
600
+ }
601
+ fallback.push(specifier);
602
+ }
603
+ if (optimized.length === 0) {
604
+ return {
605
+ generatedSources: [],
606
+ mode: 'unchanged',
607
+ statements: [statement],
608
+ };
609
+ }
610
+ const rewritten = groupExportSpecifiers(optimized);
611
+ const fallbackDeclaration = createExportFallback(statement, fallback);
612
+ const mode = fallbackDeclaration ? 'partial' : 'full';
613
+ this.services.eventEmitter.single({
614
+ file: this.entrypoint.name,
615
+ kind: 'barrelRewrite',
616
+ mode,
617
+ optimized: optimized.length,
618
+ source: statement.source.value,
619
+ });
620
+ return {
621
+ generatedSources: Array.from(new Set(optimized.map((specifier) => specifier.source))),
622
+ mode,
623
+ statements: fallbackDeclaration
624
+ ? [fallbackDeclaration, ...rewritten]
625
+ : rewritten,
626
+ };
627
+ }
628
+ function* rewriteExportAllDeclaration(analysisServices, statement, dependencies) {
629
+ const dependency = getResolvedDependency(dependencies, statement.source.value);
630
+ if (!dependency?.resolved) {
631
+ return {
632
+ generatedSources: [],
633
+ mode: 'unchanged',
634
+ statements: [statement],
635
+ };
636
+ }
637
+ const manifest = yield* getOrBuildBarrelManifest.call(this, analysisServices, dependency.resolved);
638
+ if (!isBarrelEntry(manifest) || !manifest.complete) {
639
+ return {
640
+ generatedSources: [],
641
+ mode: 'unchanged',
642
+ statements: [statement],
643
+ };
644
+ }
645
+ const optimized = [];
646
+ let hasUnrewritableExport = false;
647
+ for (const [exported, binding] of Object.entries(manifest.exports)) {
648
+ if (exported === 'default' || binding.kind === 'blocked') {
649
+ continue;
650
+ }
651
+ if (binding.kind === 'namespace') {
652
+ if (!t.isValidIdentifier(exported)) {
653
+ emitRewriteSkipped(this, statement.source.value, 'namespace-barrel');
654
+ hasUnrewritableExport = true;
655
+ continue;
656
+ }
657
+ optimized.push({
658
+ exported,
659
+ kind: 'namespace',
660
+ source: binding.source,
661
+ });
662
+ continue;
663
+ }
664
+ if (!canEmitNamedReexport(binding.imported)) {
665
+ emitRewriteSkipped(this, statement.source.value, 'unknown-star');
666
+ hasUnrewritableExport = true;
667
+ continue;
668
+ }
669
+ optimized.push({
670
+ exported,
671
+ imported: binding.imported,
672
+ kind: 'named',
673
+ source: binding.source,
674
+ });
675
+ }
676
+ if (hasUnrewritableExport) {
677
+ return {
678
+ generatedSources: [],
679
+ mode: 'unchanged',
680
+ statements: [statement],
681
+ };
682
+ }
683
+ if (optimized.length === 0) {
684
+ this.services.eventEmitter.single({
685
+ file: this.entrypoint.name,
686
+ kind: 'barrelRewrite',
687
+ mode: 'full',
688
+ optimized: 0,
689
+ source: statement.source.value,
690
+ });
691
+ return {
692
+ generatedSources: [],
693
+ mode: 'full',
694
+ statements: [],
695
+ };
696
+ }
697
+ this.services.eventEmitter.single({
698
+ complete: true,
699
+ file: this.entrypoint.name,
700
+ kind: 'barrelRewrite',
701
+ mode: 'full',
702
+ optimized: optimized.length,
703
+ source: statement.source.value,
704
+ });
705
+ return {
706
+ generatedSources: Array.from(new Set(optimized.map((specifier) => specifier.source))),
707
+ mode: 'full',
708
+ statements: groupExportSpecifiers(optimized),
709
+ };
710
+ }
711
+ function* rewriteOptimizedBarrelImports(ast, code, resolvedImports) {
712
+ const dependencies = buildResolvedDependencyMap(resolvedImports);
713
+ const analysisServices = createAnalysisServices(this.services);
714
+ const nextBody = [];
715
+ const generatedSources = new Set();
716
+ let optimizedCount = 0;
717
+ const sourceModes = new Map();
718
+ let skippedCount = 0;
719
+ const recordSourceMode = (source, mode, statementChanged) => {
720
+ if (mode === 'unchanged') {
721
+ return;
722
+ }
723
+ if (statementChanged) {
724
+ optimizedCount += 1;
725
+ }
726
+ if (mode === 'partial') {
727
+ sourceModes.set(source, 'partial');
728
+ return;
729
+ }
730
+ if (!sourceModes.has(source)) {
731
+ sourceModes.set(source, 'full');
732
+ }
733
+ };
734
+ for (const statement of ast.program.body) {
735
+ if (t.isImportDeclaration(statement) &&
736
+ t.isStringLiteral(statement.source)) {
737
+ const rewritten = yield* rewriteImportDeclaration.call(this, analysisServices, statement, dependencies);
738
+ recordSourceMode(statement.source.value, rewritten.mode, !(rewritten.statements.length === 1 &&
739
+ rewritten.statements[0] === statement));
740
+ for (const source of rewritten.generatedSources) {
741
+ generatedSources.add(source);
742
+ }
743
+ nextBody.push(...rewritten.statements);
744
+ continue;
745
+ }
746
+ if (t.isExportNamedDeclaration(statement) &&
747
+ statement.source &&
748
+ t.isStringLiteral(statement.source)) {
749
+ const rewritten = yield* rewriteExportNamedDeclaration.call(this, analysisServices, statement, dependencies);
750
+ recordSourceMode(statement.source.value, rewritten.mode, !(rewritten.statements.length === 1 &&
751
+ rewritten.statements[0] === statement));
752
+ for (const source of rewritten.generatedSources) {
753
+ generatedSources.add(source);
754
+ }
755
+ nextBody.push(...rewritten.statements);
756
+ continue;
757
+ }
758
+ if (t.isExportAllDeclaration(statement) &&
759
+ statement.source &&
760
+ t.isStringLiteral(statement.source)) {
761
+ const rewritten = yield* rewriteExportAllDeclaration.call(this, analysisServices, statement, dependencies);
762
+ if (rewritten.mode === 'unchanged' &&
763
+ rewritten.statements.length === 1 &&
764
+ rewritten.statements[0] === statement) {
765
+ skippedCount += 1;
766
+ }
767
+ recordSourceMode(statement.source.value, rewritten.mode, !(rewritten.statements.length === 1 &&
768
+ rewritten.statements[0] === statement));
769
+ for (const source of rewritten.generatedSources) {
770
+ generatedSources.add(source);
771
+ }
772
+ nextBody.push(...rewritten.statements);
773
+ continue;
774
+ }
775
+ nextBody.push(statement);
776
+ }
777
+ ast.program.body = nextBody;
778
+ const rewrittenCode = (0, generator_1.default)(ast).code;
779
+ const imports = collectOptimizedImports(ast);
780
+ const preResolvedImports = Array.from(imports.entries()).flatMap(([source, only]) => {
781
+ const dependency = dependencies.get(source);
782
+ if (dependency) {
783
+ return [
784
+ {
785
+ ...dependency,
786
+ only,
787
+ },
788
+ ];
789
+ }
790
+ if (generatedSources.has(source)) {
791
+ return [
792
+ {
793
+ only,
794
+ resolved: source,
795
+ source,
796
+ },
797
+ ];
798
+ }
799
+ return [];
800
+ });
801
+ return {
802
+ ast,
803
+ code: rewrittenCode,
804
+ fullyRewrittenSources: Array.from(sourceModes.entries())
805
+ .filter(([, mode]) => mode === 'full')
806
+ .map(([source]) => source),
807
+ imports,
808
+ optimizedCount,
809
+ partialFallbackSources: Array.from(sourceModes.entries())
810
+ .filter(([, mode]) => mode === 'partial')
811
+ .map(([source]) => source),
812
+ preResolvedImports,
813
+ skippedCount,
814
+ };
815
+ }