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