@atlaspack/core 2.31.3 → 2.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,28 @@ function _nullthrows() {
15
15
  var _ConfigRequest = require("./ConfigRequest");
16
16
  var _DevDepRequest = require("./DevDepRequest");
17
17
  var _AtlaspackConfigRequest = _interopRequireDefault(require("./AtlaspackConfigRequest"));
18
+ var _EnvironmentManager = require("../EnvironmentManager");
19
+ function _featureFlags() {
20
+ const data = require("@atlaspack/feature-flags");
21
+ _featureFlags = function () {
22
+ return data;
23
+ };
24
+ return data;
25
+ }
26
+ function _logger() {
27
+ const data = _interopRequireDefault(require("@atlaspack/logger"));
28
+ _logger = function () {
29
+ return data;
30
+ };
31
+ return data;
32
+ }
33
+ function _diagnostic() {
34
+ const data = _interopRequireDefault(require("@atlaspack/diagnostic"));
35
+ _diagnostic = function () {
36
+ return data;
37
+ };
38
+ return data;
39
+ }
18
40
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
41
  function createPackageRequest(input) {
20
42
  return {
@@ -27,7 +49,8 @@ function createPackageRequest(input) {
27
49
  async function run({
28
50
  input,
29
51
  api,
30
- farm
52
+ farm,
53
+ rustAtlaspack
31
54
  }) {
32
55
  let {
33
56
  bundleGraphReference,
@@ -44,20 +67,38 @@ async function run({
44
67
  let {
45
68
  cachePath
46
69
  } = (0, _nullthrows().default)(await api.runRequest((0, _AtlaspackConfigRequest.default)()));
70
+ let packagingResult;
71
+ if ((0, _featureFlags().getFeatureFlag)('nativePackager') && (0, _featureFlags().getFeatureFlag)('nativePackagerSSRDev') && rustAtlaspack && (0, _EnvironmentManager.fromEnvironmentId)(bundle.env).context === 'tesseract' && bundle.type === 'js') {
72
+ // Once this actually does something, the code below will be in an `else` block (i.e. we'll only run one or the other)
73
+ let result = await rustAtlaspack.package(bundle.id);
74
+ let error = null;
75
+ [packagingResult, error] = result;
76
+ if (error) {
77
+ throw new (_diagnostic().default)({
78
+ diagnostic: error
79
+ });
80
+ }
81
+ _logger().default.verbose({
82
+ message: JSON.stringify(packagingResult, null, 2),
83
+ origin: '@atlaspack/core'
84
+ });
85
+ } else {
86
+ packagingResult = await runPackage({
87
+ bundle,
88
+ bundleGraphReference,
89
+ optionsRef,
90
+ configCachePath: cachePath,
91
+ previousDevDeps: devDeps,
92
+ invalidDevDeps,
93
+ previousInvalidations: api.getInvalidations()
94
+ });
95
+ }
47
96
  let {
48
97
  devDepRequests,
49
98
  configRequests,
50
99
  bundleInfo,
51
100
  invalidations
52
- } = await runPackage({
53
- bundle,
54
- bundleGraphReference,
55
- optionsRef,
56
- configCachePath: cachePath,
57
- previousDevDeps: devDeps,
58
- invalidDevDeps,
59
- previousInvalidations: api.getInvalidations()
60
- });
101
+ } = packagingResult;
61
102
  for (let devDepRequest of devDepRequests) {
62
103
  await (0, _DevDepRequest.runDevDepRequest)(api, devDepRequest);
63
104
  }
@@ -166,7 +166,7 @@ async function resolveOptions(initialOptions) {
166
166
  if (initialOptions.cache) {
167
167
  return initialOptions.cache;
168
168
  }
169
- const needsRustLmdbCache = (0, _featureFlags().getFeatureFlag)('atlaspackV3');
169
+ const needsRustLmdbCache = (0, _featureFlags().getFeatureFlag)('atlaspackV3') || (0, _featureFlags().getFeatureFlag)('nativePackager');
170
170
  if (!(0, _featureFlags().getFeatureFlag)('cachePerformanceImprovements')) {
171
171
  if (!needsRustLmdbCache && !(outputFS instanceof _fs().NodeFS)) {
172
172
  return new (_cache().FSCache)(outputFS, cacheDir);
@@ -11,7 +11,7 @@ export declare const bundleGraphEdgeTypes: {
11
11
  readonly bundle: 3;
12
12
  readonly references: 4;
13
13
  readonly internal_async: 5;
14
- readonly conditional: 5;
14
+ readonly conditional: 6;
15
15
  };
16
16
  export type BundleGraphEdgeType = (typeof bundleGraphEdgeTypes)[keyof typeof bundleGraphEdgeTypes];
17
17
  type InternalSymbolResolution = {
@@ -77,6 +77,21 @@ export default class BundleGraph {
77
77
  static fromAssetGraph(assetGraph: AssetGraph, isProduction: boolean, publicIdByAssetId?: Map<string, string>, assetPublicIds?: Set<string>): BundleGraph;
78
78
  serialize(): SerializedBundleGraph;
79
79
  static deserialize(serialized: BundleGraphOpts): BundleGraph;
80
+ /**
81
+ * Serialize the bundle graph for efficient transfer to native Rust code.
82
+ * Returns a JSON string of nodes, an array of edges, and a map of asset IDs to public IDs.
83
+ */
84
+ serializeForNative(): {
85
+ nodesJson: string;
86
+ edges: [number, number, BundleGraphEdgeType][];
87
+ publicIdByAssetId: Record<string, string>;
88
+ environmentsJson: string;
89
+ };
90
+ /**
91
+ * Remove null and undefined values from an object to reduce JSON size.
92
+ * Preserves false, 0, empty strings, and arrays.
93
+ */
94
+ private _omitNulls;
80
95
  createBundle(opts: {
81
96
  readonly entryAsset: Asset;
82
97
  readonly bundleRoots?: Array<Asset>;
@@ -135,8 +150,36 @@ export default class BundleGraph {
135
150
  getParentBundles(bundle: Bundle): Array<Bundle>;
136
151
  isAssetReachableFromBundle(asset: Asset, bundle: Bundle): boolean;
137
152
  /**
138
- * TODO: Document why this works like this & why visitor order matters
139
- * on these use-cases.
153
+ * Performs a depth-first traversal of all assets and dependencies contained
154
+ * within a bundle. Only visits nodes that are directly contained in the bundle
155
+ * (connected via a `contains` edge).
156
+ *
157
+ * Entry Asset Ordering:
158
+ * The traversal guarantees that entry assets are visited in the exact order they
159
+ * appear in `bundle.entryAssetIds`. This ordering is critical for several reasons:
160
+ *
161
+ * 1. **Code Execution Order in Packagers**: Packagers (ScopeHoistingPackager,
162
+ * DevPackager) use this traversal to concatenate assets into the final bundle.
163
+ * The traversal order determines the execution order of code in the output.
164
+ * Entry assets must be processed in their defined order to ensure correct
165
+ * initialization sequences.
166
+ *
167
+ * 2. **Runtime Injection**: Runtime assets (HMR, bundle manifests) are prepended
168
+ * to `entryAssetIds` via `unshift()` in `applyRuntimes.ts`. By honoring the
169
+ * array order, runtimes are guaranteed to be visited (and thus output) before
170
+ * application entry points, ensuring the runtime infrastructure is available
171
+ * when application code executes.
172
+ *
173
+ * 3. **Deterministic Builds**: Consistent traversal order ensures reproducible
174
+ * bundle output, which is essential for caching and build verification.
175
+ *
176
+ * The sorting only applies at the first traversal level (direct children of the
177
+ * start node). Subsequent levels follow standard DFS order based on the graph's
178
+ * edge structure.
179
+ *
180
+ * @param bundle - The bundle to traverse
181
+ * @param visit - Visitor callback receiving asset or dependency nodes
182
+ * @param startAsset - Optional asset to start traversal from (defaults to bundle root)
140
183
  */
141
184
  traverseBundle<TContext>(bundle: Bundle, visit: GraphVisitor<AssetNode | DependencyNode, TContext>, startAsset?: Asset): TContext | null | undefined;
142
185
  traverse<TContext>(visit: GraphVisitor<AssetNode | DependencyNode, TContext>, start?: Asset): TContext | null | undefined;
@@ -1,6 +1,9 @@
1
1
  import { AtlaspackNapi, Lmdb, AtlaspackNapiOptions, CacheStats } from '@atlaspack/rust';
2
+ import { Diagnostic } from '@atlaspack/diagnostic';
2
3
  import type { Event } from '@parcel/watcher';
3
4
  import type { NapiWorkerPool as INapiWorkerPool } from '@atlaspack/types';
5
+ import type BundleGraph from '../BundleGraph';
6
+ import { RunPackagerRunnerResult } from '../PackagerRunner';
4
7
  export type AtlaspackV3Options = {
5
8
  fs?: AtlaspackNapiOptions['fs'];
6
9
  packageManager?: AtlaspackNapiOptions['packageManager'];
@@ -22,6 +25,8 @@ export declare class AtlaspackV3 {
22
25
  static create({ fs, packageManager, threads, lmdb, napiWorkerPool, ...options }: AtlaspackV3Options): Promise<AtlaspackV3>;
23
26
  end(): void;
24
27
  buildAssetGraph(): Promise<any>;
28
+ loadBundleGraph(bundleGraph: BundleGraph): Promise<void>;
29
+ package(bundleId: string): Promise<[RunPackagerRunnerResult, Diagnostic | null]>;
25
30
  respondToFsEvents(events: Array<Event>): Promise<boolean>;
26
31
  completeCacheSession(): Promise<CacheStats>;
27
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/core",
3
- "version": "2.31.3",
3
+ "version": "2.32.1",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -23,22 +23,22 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@mischnic/json-sourcemap": "^0.1.0",
26
- "@atlaspack/build-cache": "2.13.8",
27
- "@atlaspack/cache": "3.2.44",
26
+ "@atlaspack/build-cache": "2.13.9",
27
+ "@atlaspack/cache": "3.2.46",
28
28
  "@atlaspack/diagnostic": "2.14.4",
29
29
  "@atlaspack/events": "2.14.4",
30
- "@atlaspack/feature-flags": "2.27.7",
31
- "@atlaspack/fs": "2.15.44",
32
- "@atlaspack/graph": "3.6.11",
33
- "@atlaspack/logger": "2.14.41",
34
- "@atlaspack/package-manager": "2.14.49",
35
- "@atlaspack/plugin": "2.14.49",
36
- "@atlaspack/profiler": "2.15.10",
37
- "@atlaspack/rust": "3.19.0",
38
- "@atlaspack/types": "2.15.39",
39
- "@atlaspack/utils": "3.3.1",
40
- "@atlaspack/workers": "2.14.49",
41
- "@atlaspack/source-map": "3.2.4",
30
+ "@atlaspack/feature-flags": "2.28.0",
31
+ "@atlaspack/fs": "2.15.46",
32
+ "@atlaspack/graph": "3.6.13",
33
+ "@atlaspack/logger": "2.14.43",
34
+ "@atlaspack/package-manager": "2.14.51",
35
+ "@atlaspack/plugin": "2.14.51",
36
+ "@atlaspack/profiler": "2.15.12",
37
+ "@atlaspack/rust": "3.21.0",
38
+ "@atlaspack/types": "2.15.41",
39
+ "@atlaspack/utils": "3.3.3",
40
+ "@atlaspack/workers": "2.14.51",
41
+ "@atlaspack/source-map": "3.2.6",
42
42
  "base-x": "^3.0.8",
43
43
  "browserslist": "^4.6.6",
44
44
  "clone": "^2.1.1",
package/src/Atlaspack.ts CHANGED
@@ -58,7 +58,11 @@ import {
58
58
  fromProjectPathRelative,
59
59
  } from './projectPath';
60
60
  import {tracer, NativeProfiler} from '@atlaspack/profiler';
61
- import {setFeatureFlags, DEFAULT_FEATURE_FLAGS} from '@atlaspack/feature-flags';
61
+ import {
62
+ setFeatureFlags,
63
+ DEFAULT_FEATURE_FLAGS,
64
+ getFeatureFlag,
65
+ } from '@atlaspack/feature-flags';
62
66
  import {AtlaspackV3, FileSystemV3} from './atlaspack-v3';
63
67
  import createAssetGraphRequestJS from './requests/AssetGraphRequest';
64
68
  import {createAssetGraphRequestRust} from './requests/AssetGraphRequestRust';
@@ -165,7 +169,10 @@ export default class Atlaspack {
165
169
  this.#resolvedOptions = resolvedOptions;
166
170
 
167
171
  let rustAtlaspack: AtlaspackV3;
168
- if (resolvedOptions.featureFlags.atlaspackV3) {
172
+ if (
173
+ resolvedOptions.featureFlags.atlaspackV3 ||
174
+ resolvedOptions.featureFlags.nativePackager
175
+ ) {
169
176
  // eslint-disable-next-line no-unused-vars
170
177
  let {entries, inputFS, outputFS, ...options} = this.#initialOptions;
171
178
 
@@ -585,7 +592,7 @@ export default class Atlaspack {
585
592
  });
586
593
 
587
594
  let nativeInvalid = false;
588
- if (this.rustAtlaspack) {
595
+ if (getFeatureFlag('atlaspackV3') && this.rustAtlaspack) {
589
596
  nativeInvalid = await this.rustAtlaspack.respondToFsEvents(events);
590
597
  }
591
598
 
@@ -681,7 +688,7 @@ export default class Atlaspack {
681
688
 
682
689
  const start = Date.now();
683
690
  const result = await this.#requestTracker.runRequest(
684
- this.rustAtlaspack != null
691
+ getFeatureFlag('atlaspackV3') && this.rustAtlaspack != null
685
692
  ? // @ts-expect-error TS2345
686
693
  createAssetGraphRequestRust(this.rustAtlaspack)(input)
687
694
  : // @ts-expect-error TS2345
@@ -22,6 +22,7 @@ import type {
22
22
  BundleNode,
23
23
  Dependency,
24
24
  DependencyNode,
25
+ Environment,
25
26
  InternalSourceLocation,
26
27
  Target,
27
28
  Condition,
@@ -46,6 +47,7 @@ import {ISOLATED_ENVS} from './public/Environment';
46
47
  import {fromProjectPath, fromProjectPathRelative} from './projectPath';
47
48
  import {HASH_REF_PREFIX} from './constants';
48
49
  import {getFeatureFlag} from '@atlaspack/feature-flags';
50
+ import logger from '@atlaspack/logger';
49
51
  import {fromEnvironmentId} from './EnvironmentManager';
50
52
  import type {EnvironmentRef} from './EnvironmentManager';
51
53
 
@@ -74,7 +76,7 @@ export const bundleGraphEdgeTypes = {
74
76
  internal_async: 5,
75
77
  // This type is used to mark an edge between a bundle and a conditional bundle.
76
78
  // This allows efficient discovery of conditional bundles in packaging
77
- conditional: 5,
79
+ conditional: 6,
78
80
  } as const;
79
81
 
80
82
  export type BundleGraphEdgeType =
@@ -571,6 +573,122 @@ export default class BundleGraph {
571
573
  });
572
574
  }
573
575
 
576
+ /**
577
+ * Serialize the bundle graph for efficient transfer to native Rust code.
578
+ * Returns a JSON string of nodes, an array of edges, and a map of asset IDs to public IDs.
579
+ */
580
+ serializeForNative(): {
581
+ nodesJson: string;
582
+ edges: [number, number, BundleGraphEdgeType][];
583
+ publicIdByAssetId: Record<string, string>;
584
+ environmentsJson: string;
585
+ } {
586
+ const start = performance.now();
587
+
588
+ const nodes = this._graph.nodes as BundleGraphNode[];
589
+ const edges: [number, number, BundleGraphEdgeType][] = [];
590
+
591
+ const edgeIterator = this._graph.getAllEdges();
592
+ let next = edgeIterator.next();
593
+ while (!next.done) {
594
+ const edge = next.value;
595
+ edges.push([edge.from, edge.to, edge.type]);
596
+ next = edgeIterator.next();
597
+ }
598
+
599
+ // Extract and deduplicate environments
600
+ const environmentMap = new Map<string, Environment>();
601
+ const extractEnvironment = (envRef: EnvironmentRef): string => {
602
+ const env = fromEnvironmentId(envRef);
603
+ const envId = env.id;
604
+ if (!environmentMap.has(envId)) {
605
+ environmentMap.set(envId, env);
606
+ }
607
+ return envId;
608
+ };
609
+
610
+ // Replace env objects with env IDs in nodes
611
+ const processedNodes = nodes.map((node) => {
612
+ const processedNode = {...node};
613
+ if (node.type === 'asset' && node.value?.env) {
614
+ processedNode.value = {
615
+ ...node.value,
616
+ env: extractEnvironment(node.value.env),
617
+ };
618
+ } else if (node.type === 'dependency' && node.value?.env) {
619
+ processedNode.value = {
620
+ ...node.value,
621
+ env: extractEnvironment(node.value.env),
622
+ };
623
+ } else if (node.type === 'bundle' && node.value?.env) {
624
+ processedNode.value = {
625
+ ...node.value,
626
+ env: extractEnvironment(node.value.env),
627
+ };
628
+ }
629
+ return processedNode;
630
+ });
631
+
632
+ // Optimize nodes by omitting null/undefined values to reduce JSON size
633
+ const optimizedNodes = processedNodes.map((node) => this._omitNulls(node));
634
+ const nodesJson = JSON.stringify(optimizedNodes);
635
+
636
+ // Serialize environments as array
637
+ const environments = Array.from(environmentMap.values());
638
+ const environmentsJson = JSON.stringify(environments);
639
+
640
+ // Convert Map to plain object for serialization
641
+ const publicIdByAssetId: Record<string, string> = {};
642
+ for (const [assetId, publicId] of this._publicIdByAssetId) {
643
+ publicIdByAssetId[assetId] = publicId;
644
+ }
645
+
646
+ const duration = performance.now() - start;
647
+ const nodesSizeMB = (nodesJson.length / (1024 * 1024)).toFixed(2);
648
+ const envsSizeMB = (environmentsJson.length / (1024 * 1024)).toFixed(2);
649
+ logger.verbose({
650
+ origin: '@atlaspack/core',
651
+ message: `serializeForNative: ${duration.toFixed(1)}ms, ${nodesSizeMB}MB nodes, ${envsSizeMB}MB envs (${environmentMap.size} unique), ${nodes.length} nodes, ${edges.length} edges`,
652
+ });
653
+
654
+ return {nodesJson, edges, publicIdByAssetId, environmentsJson};
655
+ }
656
+
657
+ /**
658
+ * Remove null and undefined values from an object to reduce JSON size.
659
+ * Preserves false, 0, empty strings, and arrays.
660
+ */
661
+ private _omitNulls(obj: unknown): unknown {
662
+ if (obj === null || obj === undefined) return obj;
663
+ if (typeof obj !== 'object') return obj;
664
+ if (Array.isArray(obj)) {
665
+ return obj.map((item) => this._omitNulls(item));
666
+ }
667
+
668
+ const result: Record<string, unknown> = {};
669
+ for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
670
+ if (value === null || value === undefined) {
671
+ continue;
672
+ }
673
+ if (
674
+ typeof value === 'object' &&
675
+ !Array.isArray(value) &&
676
+ Object.keys(value as object).length === 0
677
+ ) {
678
+ continue;
679
+ }
680
+ if (typeof value === 'object') {
681
+ const processed = this._omitNulls(value);
682
+ if (processed !== undefined) {
683
+ result[key] = processed;
684
+ }
685
+ } else {
686
+ result[key] = value;
687
+ }
688
+ }
689
+ return result;
690
+ }
691
+
574
692
  createBundle(
575
693
  opts:
576
694
  | {
@@ -1702,8 +1820,36 @@ export default class BundleGraph {
1702
1820
  }
1703
1821
 
1704
1822
  /**
1705
- * TODO: Document why this works like this & why visitor order matters
1706
- * on these use-cases.
1823
+ * Performs a depth-first traversal of all assets and dependencies contained
1824
+ * within a bundle. Only visits nodes that are directly contained in the bundle
1825
+ * (connected via a `contains` edge).
1826
+ *
1827
+ * Entry Asset Ordering:
1828
+ * The traversal guarantees that entry assets are visited in the exact order they
1829
+ * appear in `bundle.entryAssetIds`. This ordering is critical for several reasons:
1830
+ *
1831
+ * 1. **Code Execution Order in Packagers**: Packagers (ScopeHoistingPackager,
1832
+ * DevPackager) use this traversal to concatenate assets into the final bundle.
1833
+ * The traversal order determines the execution order of code in the output.
1834
+ * Entry assets must be processed in their defined order to ensure correct
1835
+ * initialization sequences.
1836
+ *
1837
+ * 2. **Runtime Injection**: Runtime assets (HMR, bundle manifests) are prepended
1838
+ * to `entryAssetIds` via `unshift()` in `applyRuntimes.ts`. By honoring the
1839
+ * array order, runtimes are guaranteed to be visited (and thus output) before
1840
+ * application entry points, ensuring the runtime infrastructure is available
1841
+ * when application code executes.
1842
+ *
1843
+ * 3. **Deterministic Builds**: Consistent traversal order ensures reproducible
1844
+ * bundle output, which is essential for caching and build verification.
1845
+ *
1846
+ * The sorting only applies at the first traversal level (direct children of the
1847
+ * start node). Subsequent levels follow standard DFS order based on the graph's
1848
+ * edge structure.
1849
+ *
1850
+ * @param bundle - The bundle to traverse
1851
+ * @param visit - Visitor callback receiving asset or dependency nodes
1852
+ * @param startAsset - Optional asset to start traversal from (defaults to bundle root)
1707
1853
  */
1708
1854
  traverseBundle<TContext>(
1709
1855
  bundle: Bundle,
@@ -3,15 +3,19 @@ import {
3
3
  atlaspackNapiBuildAssetGraph,
4
4
  atlaspackNapiRespondToFsEvents,
5
5
  atlaspackNapiCompleteSession,
6
+ atlaspackNapiLoadBundleGraph,
7
+ atlaspackNapiPackage,
6
8
  AtlaspackNapi,
7
9
  Lmdb,
8
10
  AtlaspackNapiOptions,
9
11
  CacheStats,
10
12
  } from '@atlaspack/rust';
11
13
  import {NapiWorkerPool} from './NapiWorkerPool';
12
- import ThrowableDiagnostic from '@atlaspack/diagnostic';
14
+ import ThrowableDiagnostic, {Diagnostic} from '@atlaspack/diagnostic';
13
15
  import type {Event} from '@parcel/watcher';
14
16
  import type {NapiWorkerPool as INapiWorkerPool} from '@atlaspack/types';
17
+ import type BundleGraph from '../BundleGraph';
18
+ import {RunPackagerRunnerResult} from '../PackagerRunner';
15
19
 
16
20
  export type AtlaspackV3Options = {
17
21
  fs?: AtlaspackNapiOptions['fs'];
@@ -97,6 +101,27 @@ export class AtlaspackV3 {
97
101
  return atlaspackNapiBuildAssetGraph(this._atlaspack_napi) as Promise<any>;
98
102
  }
99
103
 
104
+ loadBundleGraph(bundleGraph: BundleGraph): Promise<void> {
105
+ const {nodesJson, edges, publicIdByAssetId, environmentsJson} =
106
+ bundleGraph.serializeForNative();
107
+
108
+ return atlaspackNapiLoadBundleGraph(
109
+ this._atlaspack_napi,
110
+ nodesJson,
111
+ edges,
112
+ publicIdByAssetId,
113
+ environmentsJson,
114
+ ) as Promise<void>;
115
+ }
116
+
117
+ package(
118
+ bundleId: string,
119
+ ): Promise<[RunPackagerRunnerResult, Diagnostic | null]> {
120
+ return atlaspackNapiPackage(this._atlaspack_napi, bundleId) as Promise<
121
+ [RunPackagerRunnerResult, Diagnostic | null]
122
+ >;
123
+ }
124
+
100
125
  async respondToFsEvents(events: Array<Event>): Promise<boolean> {
101
126
  // @ts-expect-error TS2488
102
127
  let [needsRebuild, error] = await atlaspackNapiRespondToFsEvents(
@@ -20,6 +20,9 @@ import {assetFromValue} from '../public/Asset';
20
20
 
21
21
  import {tracer} from '@atlaspack/profiler';
22
22
  import {requestTypes} from '../RequestTracker';
23
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
24
+ import {fromEnvironmentId} from '../EnvironmentManager';
25
+ import invariant from 'assert';
23
26
 
24
27
  type AtlaspackBuildRequestInput = {
25
28
  optionsRef: SharedReference;
@@ -83,6 +86,26 @@ async function run({
83
86
  (options.shouldBuildLazily && requestedAssetIds.size > 0),
84
87
  });
85
88
 
89
+ if (
90
+ getFeatureFlag('nativePackager') &&
91
+ getFeatureFlag('nativePackagerSSRDev') &&
92
+ rustAtlaspack
93
+ ) {
94
+ let hasSupportedTarget = false;
95
+ bundleGraph.traverseBundles((bundle, ctx, actions) => {
96
+ if (
97
+ fromEnvironmentId(bundle.env).context === 'tesseract' &&
98
+ bundle.type === 'js'
99
+ ) {
100
+ hasSupportedTarget = true;
101
+ actions.stop();
102
+ }
103
+ });
104
+ if (hasSupportedTarget) {
105
+ await rustAtlaspack.loadBundleGraph(bundleGraph);
106
+ }
107
+ }
108
+
86
109
  // @ts-expect-error TS2345
87
110
  dumpGraphToGraphViz(bundleGraph._graph, 'BundleGraph', bundleGraphEdgeTypes);
88
111
 
@@ -141,9 +141,10 @@ export default function createBundleGraphRequest(
141
141
  let {optionsRef, requestedAssetIds, signal} = input.input;
142
142
  let measurement = tracer.createMeasurement('building');
143
143
 
144
- let createAssetGraphRequest = input.rustAtlaspack
145
- ? createAssetGraphRequestRust(input.rustAtlaspack)
146
- : createAssetGraphRequestJS;
144
+ let createAssetGraphRequest =
145
+ getFeatureFlag('atlaspackV3') && input.rustAtlaspack
146
+ ? createAssetGraphRequestRust(input.rustAtlaspack)
147
+ : createAssetGraphRequestJS;
147
148
 
148
149
  let request = createAssetGraphRequest({
149
150
  name: 'Main',
@@ -13,6 +13,10 @@ import nullthrows from 'nullthrows';
13
13
  import {runConfigRequest} from './ConfigRequest';
14
14
  import {getDevDepRequests, runDevDepRequest} from './DevDepRequest';
15
15
  import createAtlaspackConfigRequest from './AtlaspackConfigRequest';
16
+ import {fromEnvironmentId} from '../EnvironmentManager';
17
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
18
+ import logger from '@atlaspack/logger';
19
+ import ThrowableDiagnostic, {Diagnostic} from '@atlaspack/diagnostic';
16
20
 
17
21
  type PackageRequestInput = {
18
22
  bundleGraph: BundleGraph;
@@ -46,8 +50,9 @@ export function createPackageRequest(
46
50
  };
47
51
  }
48
52
 
49
- async function run({input, api, farm}: RunInput<BundleInfo>) {
53
+ async function run({input, api, farm, rustAtlaspack}: RunInput<BundleInfo>) {
50
54
  let {bundleGraphReference, optionsRef, bundle, useMainThread} = input;
55
+
51
56
  let runPackage = farm.createHandle('runPackage', useMainThread);
52
57
 
53
58
  let start = Date.now();
@@ -58,8 +63,29 @@ async function run({input, api, farm}: RunInput<BundleInfo>) {
58
63
  ),
59
64
  );
60
65
 
61
- let {devDepRequests, configRequests, bundleInfo, invalidations} =
62
- (await runPackage({
66
+ let packagingResult: RunPackagerRunnerResult;
67
+ if (
68
+ getFeatureFlag('nativePackager') &&
69
+ getFeatureFlag('nativePackagerSSRDev') &&
70
+ rustAtlaspack &&
71
+ fromEnvironmentId(bundle.env).context === 'tesseract' &&
72
+ bundle.type === 'js'
73
+ ) {
74
+ // Once this actually does something, the code below will be in an `else` block (i.e. we'll only run one or the other)
75
+ let result = await rustAtlaspack.package(bundle.id);
76
+ let error: Diagnostic | null = null;
77
+ [packagingResult, error] = result;
78
+ if (error) {
79
+ throw new ThrowableDiagnostic({
80
+ diagnostic: error,
81
+ });
82
+ }
83
+ logger.verbose({
84
+ message: JSON.stringify(packagingResult, null, 2),
85
+ origin: '@atlaspack/core',
86
+ });
87
+ } else {
88
+ packagingResult = (await runPackage({
63
89
  bundle,
64
90
  bundleGraphReference,
65
91
  optionsRef,
@@ -68,7 +94,10 @@ async function run({input, api, farm}: RunInput<BundleInfo>) {
68
94
  invalidDevDeps,
69
95
  previousInvalidations: api.getInvalidations(),
70
96
  })) as RunPackagerRunnerResult;
97
+ }
71
98
 
99
+ let {devDepRequests, configRequests, bundleInfo, invalidations} =
100
+ packagingResult;
72
101
  for (let devDepRequest of devDepRequests) {
73
102
  await runDevDepRequest(api, devDepRequest);
74
103
  }
@@ -181,7 +181,8 @@ export default async function resolveOptions(
181
181
  return initialOptions.cache;
182
182
  }
183
183
 
184
- const needsRustLmdbCache = getFeatureFlag('atlaspackV3');
184
+ const needsRustLmdbCache =
185
+ getFeatureFlag('atlaspackV3') || getFeatureFlag('nativePackager');
185
186
 
186
187
  if (!getFeatureFlag('cachePerformanceImprovements')) {
187
188
  if (!needsRustLmdbCache && !(outputFS instanceof NodeFS)) {