@atlaspack/core 2.35.0 → 2.38.0

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 (38) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/Atlaspack.js +41 -6
  3. package/dist/atlaspack-v3/AtlaspackV3.js +7 -4
  4. package/dist/atlaspack-v3/fs.js +1 -0
  5. package/dist/atlaspack-v3/worker/worker.js +11 -2
  6. package/dist/requests/AssetGraphRequestRust.js +5 -1
  7. package/dist/requests/AtlaspackBuildRequest.js +3 -0
  8. package/dist/requests/BundleGraphRequest.js +9 -6
  9. package/dist/requests/BundleGraphRequestRust.js +6 -1
  10. package/dist/requests/BundleGraphRequestUtils.js +133 -2
  11. package/dist/requests/WriteBundleRequest.js +168 -17
  12. package/lib/Atlaspack.js +47 -15
  13. package/lib/atlaspack-v3/AtlaspackV3.js +7 -4
  14. package/lib/atlaspack-v3/fs.js +1 -0
  15. package/lib/atlaspack-v3/worker/worker.js +13 -2
  16. package/lib/requests/AssetGraphRequestRust.js +5 -1
  17. package/lib/requests/AtlaspackBuildRequest.js +9 -0
  18. package/lib/requests/BundleGraphRequest.js +10 -7
  19. package/lib/requests/BundleGraphRequestRust.js +6 -1
  20. package/lib/requests/BundleGraphRequestUtils.js +132 -2
  21. package/lib/requests/WriteBundleRequest.js +181 -13
  22. package/lib/types/atlaspack-v3/AtlaspackV3.d.ts +3 -2
  23. package/lib/types/atlaspack-v3/fs.d.ts +1 -0
  24. package/lib/types/requests/BundleGraphRequestUtils.d.ts +7 -0
  25. package/lib/types/requests/WriteBundleRequest.d.ts +33 -0
  26. package/package.json +15 -15
  27. package/src/Atlaspack.ts +54 -12
  28. package/src/atlaspack-v3/AtlaspackV3.ts +22 -4
  29. package/src/atlaspack-v3/fs.ts +5 -0
  30. package/src/atlaspack-v3/worker/worker.ts +11 -2
  31. package/src/requests/AssetGraphRequestRust.ts +5 -1
  32. package/src/requests/AtlaspackBuildRequest.ts +4 -0
  33. package/src/requests/BundleGraphRequest.ts +11 -6
  34. package/src/requests/BundleGraphRequestRust.ts +8 -1
  35. package/src/requests/BundleGraphRequestUtils.ts +157 -1
  36. package/src/requests/WriteBundleRequest.ts +202 -22
  37. package/test/requests/WriteBundleRequest.test.ts +363 -0
  38. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,112 @@
1
1
  # @atlaspack/core
2
2
 
3
+ ## 2.38.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1054](https://github.com/atlassian-labs/atlaspack/pull/1054) [`ffa1e42`](https://github.com/atlassian-labs/atlaspack/commit/ffa1e4276c22cc48b6be45ac81df8adde85f2237) Thanks [@marcins](https://github.com/marcins)! - - Implement plumbing to ensure data flows back out of build request that JS expects
8
+ - Implement a temporary namer to get an end-to-end test working
9
+
10
+ - [#1057](https://github.com/atlassian-labs/atlaspack/pull/1057) [`939d5bd`](https://github.com/atlassian-labs/atlaspack/commit/939d5bd41b3bcb5508f58ca41165d48122762e26) Thanks [@marcins](https://github.com/marcins)! - Set `SyntaxError` as the diagnostic name for parse/syntax errors from the JS and Tokens transformers.
11
+
12
+ Parse and syntax errors from the JS Transformer and Tokens Transformer now set `diagnostic.name` to `"SyntaxError"`, so consumers can reliably detect syntax/parse failures (e.g. for reporting or error handling). The Rust diagnostic type and NAPI `JsDiagnostic` include an optional `name` field; `error_buffer_to_diagnostics` sets it to `"SyntaxError"` for SWC parse errors, and both transformers pass it through to the thrown diagnostic. Integration tests assert that the first diagnostic has `name === 'SyntaxError'` for tokens and JS parse-error cases.
13
+
14
+ - [#1053](https://github.com/atlassian-labs/atlaspack/pull/1053) [`71981ea`](https://github.com/atlassian-labs/atlaspack/commit/71981eac258f7e6dfb40ec4b202d194f71c64ff1) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add native build progress reporting.
15
+
16
+ Fires `BuildProgressEvent` from Rust requests back to JS reporters via a fire-and-forget
17
+ `ThreadsafeFunction` callback. Works in both `atlaspackV3` and `fullNative` build paths.
18
+
19
+ Events:
20
+ - `building` — per-asset progress from AssetGraphRequest (completeAssets / totalAssets)
21
+ - `bundling` — once from BuildRequest before bundle graph creation
22
+ - `packagingAndOptimizing` — ready for when native packaging is wired up
23
+
24
+ Adds `BuildingProgressEvent` type and CLI reporter handling.
25
+
26
+ ### Patch Changes
27
+
28
+ - [#1056](https://github.com/atlassian-labs/atlaspack/pull/1056) [`0bb5830`](https://github.com/atlassian-labs/atlaspack/commit/0bb5830d1a7800e673f21ab020cd86bef873df9c) Thanks [@marcins](https://github.com/marcins)! - Fix native config loader rejecting TypeScript entry points in package.json.
29
+
30
+ The Rust package.json deserializer rejected `.ts` and `.tsx` extensions in builtin target fields
31
+ (`main`, `browser`, `module`), causing builds to fail with "Unexpected file type" errors when a
32
+ package.json uses TypeScript source entry points (e.g. `"main": "index.ts"`).
33
+
34
+ Additionally fixes EntryRequest to resolve the package path using `cwd()` instead of `project_root`,
35
+ matching the JS-side behavior for correct target resolution in monorepo setups.
36
+
37
+ - Updated dependencies [[`ffa1e42`](https://github.com/atlassian-labs/atlaspack/commit/ffa1e4276c22cc48b6be45ac81df8adde85f2237), [`ea9730d`](https://github.com/atlassian-labs/atlaspack/commit/ea9730dd953d0512c2ab97cbba810e7a297a29a6), [`939d5bd`](https://github.com/atlassian-labs/atlaspack/commit/939d5bd41b3bcb5508f58ca41165d48122762e26), [`71981ea`](https://github.com/atlassian-labs/atlaspack/commit/71981eac258f7e6dfb40ec4b202d194f71c64ff1), [`0bb5830`](https://github.com/atlassian-labs/atlaspack/commit/0bb5830d1a7800e673f21ab020cd86bef873df9c), [`cba96b1`](https://github.com/atlassian-labs/atlaspack/commit/cba96b1a15c07703ee104bf2a2888cc715575cbd)]:
38
+ - @atlaspack/rust@3.26.0
39
+ - @atlaspack/utils@3.4.0
40
+ - @atlaspack/cache@3.2.53
41
+ - @atlaspack/fs@2.15.53
42
+ - @atlaspack/logger@2.14.50
43
+ - @atlaspack/source-map@3.3.2
44
+ - @atlaspack/graph@3.6.20
45
+ - @atlaspack/plugin@2.14.58
46
+ - @atlaspack/profiler@2.15.19
47
+ - @atlaspack/types@2.15.48
48
+ - @atlaspack/workers@2.14.58
49
+ - @atlaspack/package-manager@2.14.58
50
+
51
+ ## 2.37.0
52
+
53
+ ### Minor Changes
54
+
55
+ - [#1050](https://github.com/atlassian-labs/atlaspack/pull/1050) [`c80be61`](https://github.com/atlassian-labs/atlaspack/commit/c80be618e42014208fed60b7a2dccc2e47d53aed) Thanks [@marcins](https://github.com/marcins)! - Add native PackagingRequest, implement temporary JS version for testing.
56
+
57
+ ### Patch Changes
58
+
59
+ - [#1051](https://github.com/atlassian-labs/atlaspack/pull/1051) [`2d3c616`](https://github.com/atlassian-labs/atlaspack/commit/2d3c616bb2ebef55d6850e8ca9eedf13c72f5386) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add native end-to-end build pipeline via BuildRequest.
60
+
61
+ When the `fullNative` feature flag is enabled, the entire build pipeline (asset graph, bundle graph,
62
+ packaging) runs natively in Rust via a single NAPI call, bypassing the JS request tracker.
63
+
64
+ Key changes:
65
+ - Add `BuildRequest` composing `AssetGraphRequest` and `BundleGraphRequest` with a packaging stub
66
+ - Add `Atlaspack::build()` method and `atlaspack_napi_build` NAPI binding
67
+ - Add `fullNative` feature flag gating the native path in `Atlaspack.ts._build()`
68
+ - Packaging step is a no-op pending PackagingRequest implementation
69
+
70
+ - Updated dependencies [[`c80be61`](https://github.com/atlassian-labs/atlaspack/commit/c80be618e42014208fed60b7a2dccc2e47d53aed), [`2d3c616`](https://github.com/atlassian-labs/atlaspack/commit/2d3c616bb2ebef55d6850e8ca9eedf13c72f5386)]:
71
+ - @atlaspack/feature-flags@2.31.0
72
+ - @atlaspack/rust@3.25.0
73
+ - @atlaspack/build-cache@2.13.14
74
+ - @atlaspack/cache@3.2.52
75
+ - @atlaspack/fs@2.15.52
76
+ - @atlaspack/graph@3.6.19
77
+ - @atlaspack/utils@3.3.9
78
+ - @atlaspack/logger@2.14.49
79
+ - @atlaspack/source-map@3.3.1
80
+ - @atlaspack/package-manager@2.14.57
81
+ - @atlaspack/workers@2.14.57
82
+ - @atlaspack/plugin@2.14.57
83
+ - @atlaspack/profiler@2.15.18
84
+ - @atlaspack/types@2.15.47
85
+
86
+ ## 2.36.0
87
+
88
+ ### Minor Changes
89
+
90
+ - [#1047](https://github.com/atlassian-labs/atlaspack/pull/1047) [`de388ff`](https://github.com/atlassian-labs/atlaspack/commit/de388ff76d39dece97ad475fcccdb6efb6283bfc) Thanks [@marcins](https://github.com/marcins)! - Change approach to source map offset for hashRefs - use a streaming approach to avoid loading large sourcemaps into memory.
91
+
92
+ ### Patch Changes
93
+
94
+ - [#1025](https://github.com/atlassian-labs/atlaspack/pull/1025) [`f7878b2`](https://github.com/atlassian-labs/atlaspack/commit/f7878b2f19a0a3bbd0e79d0b4a4e1479646043b7) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add native ideal graph bundling algorithm behind nativeBundling feature flag
95
+
96
+ - Updated dependencies [[`f7878b2`](https://github.com/atlassian-labs/atlaspack/commit/f7878b2f19a0a3bbd0e79d0b4a4e1479646043b7), [`22bb49c`](https://github.com/atlassian-labs/atlaspack/commit/22bb49c5708798d259f98c8b5c10850b2f4f5f1b), [`bddd21a`](https://github.com/atlassian-labs/atlaspack/commit/bddd21a5313974ca333c02b2da1c6f85d1afaaea), [`de388ff`](https://github.com/atlassian-labs/atlaspack/commit/de388ff76d39dece97ad475fcccdb6efb6283bfc)]:
97
+ - @atlaspack/rust@3.24.1
98
+ - @atlaspack/source-map@3.3.0
99
+ - @atlaspack/cache@3.2.51
100
+ - @atlaspack/fs@2.15.51
101
+ - @atlaspack/logger@2.14.48
102
+ - @atlaspack/utils@3.3.8
103
+ - @atlaspack/package-manager@2.14.56
104
+ - @atlaspack/profiler@2.15.17
105
+ - @atlaspack/workers@2.14.56
106
+ - @atlaspack/graph@3.6.18
107
+ - @atlaspack/plugin@2.14.56
108
+ - @atlaspack/types@2.15.46
109
+
3
110
  ## 2.35.0
4
111
 
5
112
  ### Minor Changes
package/dist/Atlaspack.js CHANGED
@@ -85,6 +85,7 @@ const feature_flags_1 = require("@atlaspack/feature-flags");
85
85
  const atlaspack_v3_1 = require("./atlaspack-v3");
86
86
  const AssetGraphRequest_1 = __importDefault(require("./requests/AssetGraphRequest"));
87
87
  const AssetGraphRequestRust_1 = require("./requests/AssetGraphRequestRust");
88
+ const BundleGraphRequestRust_1 = require("./requests/BundleGraphRequestRust");
88
89
  const rustWorkerThreadDylibHack_1 = require("./rustWorkerThreadDylibHack");
89
90
  (0, registerCoreWithSerializer_1.registerCoreWithSerializer)();
90
91
  exports.INTERNAL_TRANSFORM = Symbol('internal_transform');
@@ -158,6 +159,7 @@ class Atlaspack {
158
159
  __classPrivateFieldSet(this, _Atlaspack_resolvedOptions, resolvedOptions, "f");
159
160
  let rustAtlaspack;
160
161
  if (resolvedOptions.featureFlags.atlaspackV3 ||
162
+ resolvedOptions.featureFlags.fullNative ||
161
163
  resolvedOptions.featureFlags.nativePackager) {
162
164
  // eslint-disable-next-line no-unused-vars
163
165
  let { entries, inputFS, outputFS, ...options } = __classPrivateFieldGet(this, _Atlaspack_initialOptions, "f");
@@ -374,12 +376,45 @@ class Atlaspack {
374
376
  type: 'buildStart',
375
377
  });
376
378
  __classPrivateFieldGet(this, _Atlaspack_requestTracker, "f").graph.invalidateOnBuildNodes();
377
- let request = (0, AtlaspackBuildRequest_1.default)({
378
- optionsRef: __classPrivateFieldGet(this, _Atlaspack_optionsRef, "f"),
379
- requestedAssetIds: __classPrivateFieldGet(this, _Atlaspack_requestedAssetIds, "f"),
380
- signal,
381
- });
382
- let { bundleGraph, bundleInfo, changedAssets, assetRequests, scopeHoistingStats, } = await __classPrivateFieldGet(this, _Atlaspack_requestTracker, "f").runRequest(request, { force: true });
379
+ let bundleGraph;
380
+ let bundleInfo;
381
+ let changedAssets;
382
+ let assetRequests;
383
+ let scopeHoistingStats;
384
+ if ((0, feature_flags_1.getFeatureFlag)('fullNative') && this.rustAtlaspack) {
385
+ let [result, error] = await this.rustAtlaspack.build((eventJson) => {
386
+ let event = JSON.parse(eventJson);
387
+ __classPrivateFieldGet(this, _Atlaspack_reporterRunner, "f").report(event);
388
+ });
389
+ if (error) {
390
+ throw new diagnostic_1.default({ diagnostic: error });
391
+ }
392
+ ({ bundleGraph, changedAssets } = (0, BundleGraphRequestRust_1.getBundleGraph)(result));
393
+ bundleInfo = new Map((result.bundleInfo ?? []).map((info) => [
394
+ info.bundleId,
395
+ {
396
+ filePath: (0, projectPath_1.toProjectPath)(options.projectRoot, info.filePath),
397
+ bundleId: info.bundleId,
398
+ type: info.type,
399
+ stats: { size: info.size, time: info.time },
400
+ },
401
+ ]));
402
+ assetRequests = result.assetRequests ?? [];
403
+ }
404
+ else {
405
+ let request = (0, AtlaspackBuildRequest_1.default)({
406
+ optionsRef: __classPrivateFieldGet(this, _Atlaspack_optionsRef, "f"),
407
+ requestedAssetIds: __classPrivateFieldGet(this, _Atlaspack_requestedAssetIds, "f"),
408
+ signal,
409
+ });
410
+ ({
411
+ bundleGraph,
412
+ bundleInfo,
413
+ changedAssets,
414
+ assetRequests,
415
+ scopeHoistingStats,
416
+ } = await __classPrivateFieldGet(this, _Atlaspack_requestTracker, "f").runRequest(request, { force: true }));
417
+ }
383
418
  __classPrivateFieldGet(this, _Atlaspack_requestedAssetIds, "f").clear();
384
419
  await (0, dumpGraphToGraphViz_1.default)(
385
420
  // @ts-expect-error TS2345
@@ -48,11 +48,14 @@ class AtlaspackV3 {
48
48
  this._napiWorkerPool.shutdown();
49
49
  }
50
50
  }
51
- buildAssetGraph() {
52
- return (0, rust_1.atlaspackNapiBuildAssetGraph)(this._atlaspack_napi);
51
+ buildAssetGraph(progressCallback) {
52
+ return (0, rust_1.atlaspackNapiBuildAssetGraph)(this._atlaspack_napi, progressCallback);
53
53
  }
54
- buildBundleGraph() {
55
- return (0, rust_1.atlaspackNapiBuildBundleGraph)(this._atlaspack_napi);
54
+ buildBundleGraph(progressCallback) {
55
+ return (0, rust_1.atlaspackNapiBuildBundleGraph)(this._atlaspack_napi, progressCallback);
56
+ }
57
+ build(progressCallback) {
58
+ return (0, rust_1.atlaspackNapiBuild)(this._atlaspack_napi, progressCallback);
56
59
  }
57
60
  loadBundleGraph(bundleGraph) {
58
61
  const { nodesJson, edges, publicIdByAssetId, environmentsJson } = bundleGraph.serializeForNative();
@@ -45,6 +45,7 @@ class FileSystemV3 {
45
45
  return __classPrivateFieldGet(this, _FileSystemV3_fs, "f").readFileSync(path, encoding);
46
46
  }
47
47
  });
48
+ this.writeFile = (0, jsCallable_1.jsCallable)((path, contents) => __classPrivateFieldGet(this, _FileSystemV3_fs, "f").writeFile(path, Buffer.from(contents)));
48
49
  __classPrivateFieldSet(this, _FileSystemV3_fs, fs, "f");
49
50
  }
50
51
  }
@@ -157,14 +157,23 @@ class AtlaspackWorker {
157
157
  resolution: { type: 'excluded' },
158
158
  };
159
159
  }
160
+ // A resolver may return a result without filePath to indicate it didn't
161
+ // resolve the dependency (equivalent to returning null). The JS-side
162
+ // PathRequest treats this as "try the next resolver".
163
+ if (!result.filePath) {
164
+ return {
165
+ invalidations: [],
166
+ resolution: { type: 'unresolved' },
167
+ };
168
+ }
160
169
  return {
161
170
  invalidations: [],
162
171
  resolution: {
163
172
  type: 'resolved',
164
- filePath: result.filePath || '',
173
+ filePath: result.filePath,
165
174
  canDefer: result.canDefer || false,
166
175
  sideEffects: result.sideEffects ?? true,
167
- code: result.code || undefined,
176
+ code: result.code ?? undefined,
168
177
  meta: result.meta || undefined,
169
178
  pipeline: result.pipeline || undefined,
170
179
  priority: compat_1.dependencyPriorityMap.intoNullable(result.priority),
@@ -43,6 +43,7 @@ const diagnostic_1 = __importDefault(require("@atlaspack/diagnostic"));
43
43
  const logger_1 = __importStar(require("@atlaspack/logger"));
44
44
  const feature_flags_1 = require("@atlaspack/feature-flags");
45
45
  const AssetGraph_1 = __importDefault(require("../AssetGraph"));
46
+ const ReporterRunner_1 = require("../ReporterRunner");
46
47
  const RequestTracker_1 = require("../RequestTracker");
47
48
  const SymbolPropagation_1 = require("../SymbolPropagation");
48
49
  const EnvironmentManager_1 = require("../EnvironmentManager");
@@ -55,7 +56,10 @@ function createAssetGraphRequestRust(rustAtlaspack) {
55
56
  id: input.name,
56
57
  run: async (runInput) => {
57
58
  let options = runInput.options;
58
- let { assetGraphPromise, commitPromise } = await rustAtlaspack.buildAssetGraph();
59
+ let { assetGraphPromise, commitPromise } = await rustAtlaspack.buildAssetGraph((eventJson) => {
60
+ let event = JSON.parse(eventJson);
61
+ (0, ReporterRunner_1.report)(event);
62
+ });
59
63
  let [serializedAssetGraph, assetGraphError] = (await assetGraphPromise);
60
64
  if (assetGraphError) {
61
65
  throw new diagnostic_1.default({
@@ -18,6 +18,7 @@ const profiler_1 = require("@atlaspack/profiler");
18
18
  const RequestTracker_1 = require("../RequestTracker");
19
19
  const feature_flags_1 = require("@atlaspack/feature-flags");
20
20
  const EnvironmentManager_1 = require("../EnvironmentManager");
21
+ const logger_1 = require("@atlaspack/logger");
21
22
  function createAtlaspackBuildRequest(input) {
22
23
  return {
23
24
  type: RequestTracker_1.requestTypes.atlaspack_build_request,
@@ -78,12 +79,14 @@ async function run({ input, api, options, rustAtlaspack, }) {
78
79
  ])),
79
80
  });
80
81
  let packagingMeasurement = profiler_1.tracer.createMeasurement('packaging');
82
+ const span = logger_1.tracer.enter('writeBundles');
81
83
  let writeBundlesRequest = (0, WriteBundlesRequest_1.default)({
82
84
  bundleGraph,
83
85
  optionsRef,
84
86
  });
85
87
  let { bundleInfo, scopeHoistingStats } = await api.runRequest(writeBundlesRequest);
86
88
  packagingMeasurement && packagingMeasurement.end();
89
+ logger_1.tracer.exit(span);
87
90
  (0, utils_1.assertSignalNotAborted)(signal);
88
91
  return {
89
92
  bundleGraph,
@@ -263,14 +263,17 @@ class BundlerRunner {
263
263
  measurement = tracer.createMeasurement(plugin.name, 'bundling:bundle', measurementFilename);
264
264
  }
265
265
  // this the normal bundle workflow (bundle, optimizing, run-times, naming)
266
- await bundler.bundle({
267
- bundleGraph: mutableBundleGraph,
268
- config: this.configs.get(plugin.name)?.result,
269
- options: this.pluginOptions,
270
- logger,
271
- tracer,
266
+ await (0, logger_1.instrumentAsync)('bundle (V2)', async () => {
267
+ await bundler.bundle({
268
+ bundleGraph: mutableBundleGraph,
269
+ config: this.configs.get(plugin.name)?.result,
270
+ options: this.pluginOptions,
271
+ logger,
272
+ tracer,
273
+ });
272
274
  });
273
275
  measurement && measurement.end();
276
+ (0, BundleGraphRequestUtils_1.dumpBundleGraphSnapshot)(internalBundleGraph, 'js');
274
277
  if (this.pluginOptions.mode === 'production') {
275
278
  let optimizeMeasurement;
276
279
  try {
@@ -44,6 +44,7 @@ const graph_1 = require("@atlaspack/graph");
44
44
  const logger_1 = require("@atlaspack/logger");
45
45
  const feature_flags_1 = require("@atlaspack/feature-flags");
46
46
  const BundleGraph_1 = __importStar(require("../BundleGraph"));
47
+ const ReporterRunner_1 = require("../ReporterRunner");
47
48
  const dumpGraphToGraphViz_1 = __importDefault(require("../dumpGraphToGraphViz"));
48
49
  const nullthrows_1 = __importDefault(require("nullthrows"));
49
50
  const rust_1 = require("@atlaspack/rust");
@@ -64,13 +65,17 @@ function createBundleGraphRequestRust(input) {
64
65
  run: async (runInput) => {
65
66
  const { api, options, rustAtlaspack } = runInput;
66
67
  (0, assert_1.default)(rustAtlaspack, 'BundleGraphRequestRust requires rustAtlaspack');
67
- let { bundleGraphPromise, commitPromise } = await rustAtlaspack.buildBundleGraph();
68
+ let { bundleGraphPromise, commitPromise } = await rustAtlaspack.buildBundleGraph((eventJson) => {
69
+ let event = JSON.parse(eventJson);
70
+ (0, ReporterRunner_1.report)(event);
71
+ });
68
72
  let [serializedBundleGraph, bundleGraphError] = (await bundleGraphPromise);
69
73
  if (bundleGraphError) {
70
74
  throw new diagnostic_1.default({ diagnostic: bundleGraphError });
71
75
  }
72
76
  // Don’t reuse previous JS result yet; we just rebuild from scratch.
73
77
  let { bundleGraph, changedAssets } = (0, logger_1.instrument)('atlaspack_v3_getBundleGraph', () => getBundleGraph(serializedBundleGraph));
78
+ (0, BundleGraphRequestUtils_1.dumpBundleGraphSnapshot)(bundleGraph, 'rust');
74
79
  const runner = new NativeBundlerRunner({ api, options }, input.optionsRef);
75
80
  await runner.loadConfigs();
76
81
  // Name all bundles
@@ -37,15 +37,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.validateBundles = validateBundles;
40
+ exports.dumpBundleGraphSnapshot = dumpBundleGraphSnapshot;
40
41
  exports.nameBundle = nameBundle;
41
42
  exports.loadPluginConfigWithDevDeps = loadPluginConfigWithDevDeps;
42
43
  exports.runDevDepRequest = runDevDepRequest;
43
44
  const assert_1 = __importDefault(require("assert"));
45
+ const fs_1 = __importDefault(require("fs"));
44
46
  const nullthrows_1 = __importDefault(require("nullthrows"));
47
+ const path_1 = __importDefault(require("path"));
45
48
  const logger_1 = require("@atlaspack/logger");
46
49
  const diagnostic_1 = __importStar(require("@atlaspack/diagnostic"));
47
50
  const utils_1 = require("@atlaspack/utils");
48
- const BundleGraph_1 = __importDefault(require("../public/BundleGraph"));
51
+ const BundleGraph_1 = require("../BundleGraph");
52
+ const BundleGraph_2 = __importDefault(require("../public/BundleGraph"));
49
53
  const Bundle_1 = require("../public/Bundle");
50
54
  const InternalConfig_1 = require("../InternalConfig");
51
55
  const DevDepRequest_1 = require("./DevDepRequest");
@@ -64,12 +68,139 @@ function validateBundles(bundleGraph) {
64
68
  ...(0, utils_1.setSymmetricDifference)(new Set(bundleNames), new Set((0, utils_1.unique)(bundleNames))),
65
69
  ].join());
66
70
  }
71
+ /**
72
+ * Dump a canonical JSON snapshot of the bundle graph for parity comparison.
73
+ * Gated by ATLASPACK_DUMP_BUNDLE_GRAPH environment variable which specifies the output directory.
74
+ * The snapshot captures bundle identity, type, contained assets, and bundle group structure
75
+ * in a deterministic, sorted format suitable for diffing.
76
+ */
77
+ function dumpBundleGraphSnapshot(bundleGraph, variant) {
78
+ let outDir = process.env.ATLASPACK_DUMP_BUNDLE_GRAPH;
79
+ if (!outDir)
80
+ return;
81
+ let filename = variant === 'js' ? 'bundle-graph-js.json' : 'bundle-graph-rust.json';
82
+ let outPath = path_1.default.join(outDir, filename);
83
+ fs_1.default.mkdirSync(outDir, { recursive: true });
84
+ let bundles = bundleGraph.getBundles();
85
+ let bundlesSnapshot = bundles
86
+ .map((bundle) => {
87
+ let bundleNodeId = bundleGraph._graph.getNodeIdByContentKey(bundle.id);
88
+ let containedAssetNodeIds = bundleGraph._graph.getNodeIdsConnectedFrom(bundleNodeId, BundleGraph_1.bundleGraphEdgeTypes.contains);
89
+ let containedAssets = containedAssetNodeIds
90
+ .map((nodeId) => bundleGraph._graph.getNode(nodeId))
91
+ .flatMap((node) => {
92
+ if (node?.type !== 'asset')
93
+ return [];
94
+ return [
95
+ {
96
+ id: node.value.id,
97
+ filePath: (0, projectPath_1.fromProjectPathRelative)(node.value.filePath),
98
+ },
99
+ ];
100
+ })
101
+ .sort((a, b) => a.filePath.localeCompare(b.filePath));
102
+ // Resolve mainEntry and entry asset file paths
103
+ let mainEntryPath = null;
104
+ let entryAssetPaths = [];
105
+ if (bundle.mainEntryId) {
106
+ let mainEntryNodeId = bundleGraph._graph.getNodeIdByContentKey(bundle.mainEntryId);
107
+ let mainEntryNode = bundleGraph._graph.getNode(mainEntryNodeId);
108
+ if (mainEntryNode?.type === 'asset') {
109
+ mainEntryPath = (0, projectPath_1.fromProjectPathRelative)(mainEntryNode.value.filePath);
110
+ }
111
+ }
112
+ for (let entryId of bundle.entryAssetIds) {
113
+ let entryNodeId = bundleGraph._graph.getNodeIdByContentKey(entryId);
114
+ let entryNode = bundleGraph._graph.getNode(entryNodeId);
115
+ if (entryNode?.type === 'asset') {
116
+ entryAssetPaths.push((0, projectPath_1.fromProjectPathRelative)(entryNode.value.filePath));
117
+ }
118
+ }
119
+ entryAssetPaths.sort();
120
+ return {
121
+ id: bundle.id,
122
+ type: bundle.type,
123
+ bundleBehavior: bundle.bundleBehavior ?? null,
124
+ needsStableName: bundle.needsStableName,
125
+ isSplittable: bundle.isSplittable,
126
+ isPlaceholder: bundle.isPlaceholder,
127
+ mainEntryPath,
128
+ entryAssetPaths,
129
+ assets: containedAssets.map((a) => a.filePath),
130
+ };
131
+ })
132
+ .sort((a, b) => {
133
+ // Sort by mainEntryPath first, then by sorted assets as tiebreaker
134
+ let aKey = a.mainEntryPath || a.assets.join(',');
135
+ let bKey = b.mainEntryPath || b.assets.join(',');
136
+ return aKey.localeCompare(bKey);
137
+ });
138
+ let bundleGroupsSnapshot = bundleGraph._graph.nodes
139
+ .flatMap((node) => {
140
+ if (node?.type !== 'bundle_group')
141
+ return [];
142
+ let bundleGroup = node.value;
143
+ // Resolve entry asset file path
144
+ let entryAssetPath = null;
145
+ try {
146
+ let entryNodeId = bundleGraph._graph.getNodeIdByContentKey(bundleGroup.entryAssetId);
147
+ let entryNode = bundleGraph._graph.getNode(entryNodeId);
148
+ if (entryNode?.type === 'asset') {
149
+ entryAssetPath = (0, projectPath_1.fromProjectPathRelative)(entryNode.value.filePath);
150
+ }
151
+ }
152
+ catch {
153
+ // Content key not found
154
+ }
155
+ let bundlesInGroup = bundleGraph.getBundlesInBundleGroup(bundleGroup);
156
+ let bundlePaths = bundlesInGroup
157
+ .map((b) => {
158
+ // Use mainEntry file path if available, otherwise bundle id as fallback
159
+ if (b.mainEntryId) {
160
+ try {
161
+ let nodeId = bundleGraph._graph.getNodeIdByContentKey(b.mainEntryId);
162
+ let node = bundleGraph._graph.getNode(nodeId);
163
+ if (node?.type === 'asset') {
164
+ return (0, projectPath_1.fromProjectPathRelative)(node.value.filePath);
165
+ }
166
+ }
167
+ catch {
168
+ // fallback
169
+ }
170
+ }
171
+ return `[bundle:${b.id}]`;
172
+ })
173
+ .sort();
174
+ return [
175
+ {
176
+ entryAssetPath: entryAssetPath ?? `[unknown:${bundleGroup.entryAssetId}]`,
177
+ bundlePaths,
178
+ },
179
+ ];
180
+ })
181
+ .sort((a, b) => a.entryAssetPath.localeCompare(b.entryAssetPath));
182
+ let totalAssets = bundleGraph._graph.nodes.filter((node) => node?.type === 'asset').length;
183
+ let snapshot = {
184
+ version: 1,
185
+ variant,
186
+ stats: {
187
+ totalBundles: bundlesSnapshot.length,
188
+ totalBundleGroups: bundleGroupsSnapshot.length,
189
+ totalAssets,
190
+ },
191
+ bundles: bundlesSnapshot,
192
+ bundleGroups: bundleGroupsSnapshot,
193
+ };
194
+ fs_1.default.writeFileSync(outPath, JSON.stringify(snapshot, null, 2), 'utf8');
195
+ // eslint-disable-next-line no-console
196
+ console.log(`[BundleGraphSnapshot] Wrote ${variant} snapshot to ${outPath}`);
197
+ }
67
198
  /**
68
199
  * Names a bundle by running through the configured namers until one returns a name.
69
200
  */
70
201
  async function nameBundle(namers, internalBundle, internalBundleGraph, options, pluginOptions, configs) {
71
202
  const bundle = Bundle_1.Bundle.get(internalBundle, internalBundleGraph, options);
72
- const bundleGraph = new BundleGraph_1.default(internalBundleGraph, Bundle_1.NamedBundle.get.bind(Bundle_1.NamedBundle), options);
203
+ const bundleGraph = new BundleGraph_2.default(internalBundleGraph, Bundle_1.NamedBundle.get.bind(Bundle_1.NamedBundle), options);
73
204
  for (const namer of namers) {
74
205
  let measurement;
75
206
  try {