@atlaspack/core 2.17.3 → 2.18.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 (67) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/lib/AssetGraph.js +17 -6
  3. package/lib/Atlaspack.js +3 -1
  4. package/lib/BundleGraph.js +6 -5
  5. package/lib/Dependency.js +6 -2
  6. package/lib/Environment.js +4 -3
  7. package/lib/EnvironmentManager.js +137 -0
  8. package/lib/InternalConfig.js +3 -2
  9. package/lib/PackagerRunner.js +52 -15
  10. package/lib/RequestTracker.js +191 -89
  11. package/lib/UncommittedAsset.js +20 -2
  12. package/lib/applyRuntimes.js +2 -1
  13. package/lib/assetUtils.js +2 -1
  14. package/lib/atlaspack-v3/worker/worker.js +8 -0
  15. package/lib/public/Asset.js +3 -2
  16. package/lib/public/Bundle.js +2 -1
  17. package/lib/public/BundleGraph.js +21 -5
  18. package/lib/public/Config.js +98 -3
  19. package/lib/public/Dependency.js +2 -1
  20. package/lib/public/MutableBundleGraph.js +2 -1
  21. package/lib/public/Target.js +2 -1
  22. package/lib/requests/AssetGraphRequest.js +13 -1
  23. package/lib/requests/AssetRequest.js +2 -1
  24. package/lib/requests/BundleGraphRequest.js +13 -1
  25. package/lib/requests/ConfigRequest.js +27 -4
  26. package/lib/requests/TargetRequest.js +18 -16
  27. package/lib/requests/WriteBundleRequest.js +15 -3
  28. package/lib/requests/WriteBundlesRequest.js +1 -0
  29. package/lib/resolveOptions.js +4 -2
  30. package/package.json +13 -13
  31. package/src/AssetGraph.js +12 -6
  32. package/src/Atlaspack.js +5 -4
  33. package/src/BundleGraph.js +13 -8
  34. package/src/Dependency.js +13 -5
  35. package/src/Environment.js +8 -5
  36. package/src/EnvironmentManager.js +145 -0
  37. package/src/InternalConfig.js +6 -5
  38. package/src/PackagerRunner.js +72 -20
  39. package/src/RequestTracker.js +330 -146
  40. package/src/UncommittedAsset.js +23 -3
  41. package/src/applyRuntimes.js +6 -1
  42. package/src/assetUtils.js +4 -3
  43. package/src/atlaspack-v3/worker/compat/plugin-config.js +9 -5
  44. package/src/atlaspack-v3/worker/worker.js +7 -0
  45. package/src/public/Asset.js +9 -2
  46. package/src/public/Bundle.js +2 -1
  47. package/src/public/BundleGraph.js +22 -5
  48. package/src/public/Config.js +129 -14
  49. package/src/public/Dependency.js +2 -1
  50. package/src/public/MutableBundleGraph.js +2 -1
  51. package/src/public/Target.js +2 -1
  52. package/src/requests/AssetGraphRequest.js +13 -3
  53. package/src/requests/AssetRequest.js +2 -1
  54. package/src/requests/BundleGraphRequest.js +13 -3
  55. package/src/requests/ConfigRequest.js +33 -9
  56. package/src/requests/TargetRequest.js +19 -25
  57. package/src/requests/WriteBundleRequest.js +14 -8
  58. package/src/requests/WriteBundlesRequest.js +1 -0
  59. package/src/resolveOptions.js +4 -2
  60. package/src/types.js +9 -7
  61. package/test/Environment.test.js +43 -34
  62. package/test/EnvironmentManager.test.js +192 -0
  63. package/test/PublicEnvironment.test.js +10 -7
  64. package/test/RequestTracker.test.js +115 -3
  65. package/test/public/Config.test.js +108 -0
  66. package/test/requests/ConfigRequest.test.js +187 -3
  67. package/test/test-utils.js +4 -9
@@ -49,6 +49,7 @@ import {BROWSER_ENVS} from '../public/Environment';
49
49
  import {optionsProxy, toInternalSourceLocation} from '../utils';
50
50
  import {fromProjectPath, toProjectPath, joinProjectPath} from '../projectPath';
51
51
  import {requestTypes} from '../RequestTracker';
52
+ import {fromEnvironmentId} from '../EnvironmentManager';
52
53
 
53
54
  type RunOpts<TResult> = {|
54
55
  input: Entry,
@@ -345,7 +346,7 @@ export class TargetResolver {
345
346
  },
346
347
  });
347
348
  }
348
- if (!BROWSER_ENVS.has(targets[0].env.context)) {
349
+ if (!BROWSER_ENVS.has(fromEnvironmentId(targets[0].env).context)) {
349
350
  throw new ThrowableDiagnostic({
350
351
  diagnostic: {
351
352
  message: `Only browser targets are supported in serve mode`,
@@ -1491,21 +1492,22 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1491
1492
 
1492
1493
  // Resolve relevant engines for context.
1493
1494
  let engines;
1494
- switch (target.env.context) {
1495
+ const env = fromEnvironmentId(target.env);
1496
+ switch (env.context) {
1495
1497
  case 'browser':
1496
1498
  case 'web-worker':
1497
1499
  case 'service-worker':
1498
1500
  case 'worklet': {
1499
- let browsers = target.env.engines.browsers;
1501
+ let browsers = env.engines.browsers;
1500
1502
  engines = Array.isArray(browsers) ? browsers.join(', ') : browsers;
1501
1503
  break;
1502
1504
  }
1503
1505
  case 'node':
1504
- engines = target.env.engines.node;
1506
+ engines = env.engines.node;
1505
1507
  break;
1506
1508
  case 'electron-main':
1507
1509
  case 'electron-renderer':
1508
- engines = target.env.engines.electron;
1510
+ engines = env.engines.electron;
1509
1511
  break;
1510
1512
  }
1511
1513
 
@@ -1547,9 +1549,7 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1547
1549
  }
1548
1550
 
1549
1551
  if (keyInfo.inferred) {
1550
- highlight.inferred.push(
1551
- md`${key} to be ${JSON.stringify(target.env[key])}`,
1552
- );
1552
+ highlight.inferred.push(md`${key} to be ${JSON.stringify(env[key])}`);
1553
1553
  }
1554
1554
  }
1555
1555
 
@@ -1578,22 +1578,20 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1578
1578
 
1579
1579
  // Format includeNodeModules to be human readable.
1580
1580
  let includeNodeModules;
1581
- if (typeof target.env.includeNodeModules === 'boolean') {
1582
- includeNodeModules = String(target.env.includeNodeModules);
1583
- } else if (Array.isArray(target.env.includeNodeModules)) {
1581
+ if (typeof env.includeNodeModules === 'boolean') {
1582
+ includeNodeModules = String(env.includeNodeModules);
1583
+ } else if (Array.isArray(env.includeNodeModules)) {
1584
1584
  includeNodeModules =
1585
1585
  'only ' +
1586
- listFormat.format(
1587
- target.env.includeNodeModules.map((m) => JSON.stringify(m)),
1588
- );
1586
+ listFormat.format(env.includeNodeModules.map((m) => JSON.stringify(m)));
1589
1587
  } else if (
1590
- target.env.includeNodeModules &&
1591
- typeof target.env.includeNodeModules === 'object'
1588
+ env.includeNodeModules &&
1589
+ typeof env.includeNodeModules === 'object'
1592
1590
  ) {
1593
1591
  includeNodeModules =
1594
1592
  'all except ' +
1595
1593
  listFormat.format(
1596
- Object.entries(target.env.includeNodeModules)
1594
+ Object.entries(env.includeNodeModules)
1597
1595
  .filter(([, v]) => v === false)
1598
1596
  .map(([k]) => JSON.stringify(k)),
1599
1597
  );
@@ -1609,18 +1607,14 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1609
1607
  fromProjectPath(options.projectRoot, input.filePath),
1610
1608
  )}
1611
1609
  **Output**: ${path.relative(process.cwd(), output)}
1612
- **Format**: ${target.env.outputFormat} ${format(
1613
- info.outputFormat,
1614
- )}
1615
- **Context**: ${target.env.context} ${format(info.context)}
1610
+ **Format**: ${env.outputFormat} ${format(info.outputFormat)}
1611
+ **Context**: ${env.context} ${format(info.context)}
1616
1612
  **Engines**: ${engines || ''} ${format(info.engines)}
1617
- **Library Mode**: ${String(target.env.isLibrary)} ${format(
1618
- info.isLibrary,
1619
- )}
1613
+ **Library Mode**: ${String(env.isLibrary)} ${format(info.isLibrary)}
1620
1614
  **Include Node Modules**: ${includeNodeModules} ${format(
1621
1615
  info.includeNodeModules,
1622
1616
  )}
1623
- **Optimize**: ${String(target.env.shouldOptimize)} ${format(
1617
+ **Optimize**: ${String(env.shouldOptimize)} ${format(
1624
1618
  info.shouldOptimize,
1625
1619
  )}`,
1626
1620
  codeFrames: target.loc
@@ -40,6 +40,8 @@ import {AtlaspackConfig} from '../AtlaspackConfig';
40
40
  import ThrowableDiagnostic, {errorToDiagnostic} from '@atlaspack/diagnostic';
41
41
  import {PluginTracer, tracer} from '@atlaspack/profiler';
42
42
  import {requestTypes} from '../RequestTracker';
43
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
44
+ import {fromEnvironmentId} from '../EnvironmentManager';
43
45
 
44
46
  const HASH_REF_PREFIX_LEN = HASH_REF_PREFIX.length;
45
47
  const BOUNDARY_LENGTH = HASH_REF_PREFIX.length + 32 - 1;
@@ -110,7 +112,9 @@ async function run({input, options, api}) {
110
112
  let cacheKeys = info.cacheKeys;
111
113
  let mapKey = cacheKeys.map;
112
114
  let fullPath = fromProjectPath(options.projectRoot, filePath);
113
- if (mapKey && bundle.env.sourceMap && !bundle.env.sourceMap.inline) {
115
+ const env = fromEnvironmentId(bundle.env);
116
+
117
+ if (mapKey && env.sourceMap && !env.sourceMap.inline) {
114
118
  api.invalidateOnFileDelete(
115
119
  toProjectPath(options.projectRoot, fullPath + '.map'),
116
120
  );
@@ -167,14 +171,15 @@ async function run({input, options, api}) {
167
171
  api,
168
172
  );
169
173
 
170
- if (
171
- mapKey &&
172
- bundle.env.sourceMap &&
173
- !bundle.env.sourceMap.inline &&
174
- (await options.cache.has(mapKey))
175
- ) {
174
+ const hasSourceMap = getFeatureFlag('cachePerformanceImprovements')
175
+ ? await options.cache.hasLargeBlob(mapKey)
176
+ : await options.cache.has(mapKey);
177
+ if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
178
+ const mapEntry = getFeatureFlag('cachePerformanceImprovements')
179
+ ? await options.cache.getLargeBlob(mapKey)
180
+ : await options.cache.getBlob(mapKey);
176
181
  await writeFiles(
177
- blobToStream(await options.cache.getBlob(mapKey)),
182
+ blobToStream(mapEntry),
178
183
  info,
179
184
  hashRefToNameHash,
180
185
  options,
@@ -189,6 +194,7 @@ async function run({input, options, api}) {
189
194
 
190
195
  let res = {
191
196
  filePath,
197
+ bundleId: bundle.id,
192
198
  type: info.type,
193
199
  stats: {
194
200
  size,
@@ -84,6 +84,7 @@ async function run({input, api, farm, options}) {
84
84
  ).replace(bundle.hashReference, hash);
85
85
  res.set(bundle.id, {
86
86
  filePath: joinProjectPath(bundle.target.distDir, name),
87
+ bundleId: bundle.id,
87
88
  type: bundle.type, // FIXME: this is wrong if the packager changes the type...
88
89
  stats: {
89
90
  time: 0,
@@ -153,8 +153,10 @@ export default async function resolveOptions(
153
153
 
154
154
  const needsRustLmdbCache = getFeatureFlag('atlaspackV3');
155
155
 
156
- if (!needsRustLmdbCache && !(outputFS instanceof NodeFS)) {
157
- return new FSCache(outputFS, cacheDir);
156
+ if (!getFeatureFlag('cachePerformanceImprovements')) {
157
+ if (!needsRustLmdbCache && !(outputFS instanceof NodeFS)) {
158
+ return new FSCache(outputFS, cacheDir);
159
+ }
158
160
  }
159
161
 
160
162
  return new LMDBLiteCache(cacheDir);
package/src/types.js CHANGED
@@ -34,6 +34,7 @@ import type {ProjectPath} from './projectPath';
34
34
  import type {Event} from '@parcel/watcher';
35
35
  import type {FeatureFlags} from '@atlaspack/feature-flags';
36
36
  import type {BackendType} from '@parcel/watcher';
37
+ import type {EnvironmentRef} from './EnvironmentManager';
37
38
 
38
39
  export type AtlaspackPluginNode = {|
39
40
  packageName: PackageName,
@@ -97,7 +98,7 @@ export type InternalSourceLocation = {|
97
98
  export type Target = {|
98
99
  distEntry?: ?FilePath,
99
100
  distDir: ProjectPath,
100
- env: Environment,
101
+ env: EnvironmentRef,
101
102
  name: string,
102
103
  publicUrl: string,
103
104
  loc?: ?InternalSourceLocation,
@@ -139,7 +140,7 @@ export type Dependency = {|
139
140
  isEntry: boolean,
140
141
  isOptional: boolean,
141
142
  loc: ?InternalSourceLocation,
142
- env: Environment,
143
+ env: EnvironmentRef,
143
144
  packageConditions?: number,
144
145
  customPackageConditions?: Array<string>,
145
146
  meta: Meta,
@@ -180,7 +181,7 @@ export type Asset = {|
180
181
  bundleBehavior: ?$Values<typeof BundleBehavior>,
181
182
  isBundleSplittable: boolean,
182
183
  isSource: boolean,
183
- env: Environment,
184
+ env: EnvironmentRef,
184
185
  meta: Meta,
185
186
  stats: Stats,
186
187
  contentKey: ?string,
@@ -388,7 +389,7 @@ export type RootNode = {|id: ContentKey, +type: 'root', value: string | null|};
388
389
  export type AssetRequestInput = {|
389
390
  name?: string, // AssetGraph name, needed so that different graphs can isolated requests since the results are not stored
390
391
  filePath: ProjectPath,
391
- env: Environment,
392
+ env: EnvironmentRef,
392
393
  isSource?: boolean,
393
394
  canDefer?: boolean,
394
395
  sideEffects?: boolean,
@@ -492,13 +493,13 @@ export type Config = {|
492
493
  id: string,
493
494
  isSource: boolean,
494
495
  searchPath: ProjectPath,
495
- env: Environment,
496
+ env: EnvironmentRef,
496
497
  cacheKey: ?string,
497
498
  result: ConfigResult,
498
499
  invalidateOnFileChange: Set<ProjectPath>,
499
500
  invalidateOnConfigKeyChange: Array<{|
500
501
  filePath: ProjectPath,
501
- configKey: string,
502
+ configKey: string[],
502
503
  |}>,
503
504
  invalidateOnFileCreate: Array<InternalFileCreateInvalidation>,
504
505
  invalidateOnEnvChange: Set<string>,
@@ -539,7 +540,7 @@ export type Bundle = {|
539
540
  publicId: ?string,
540
541
  hashReference: string,
541
542
  type: string,
542
- env: Environment,
543
+ env: EnvironmentRef,
543
544
  entryAssetIds: Array<ContentKey>,
544
545
  mainEntryId: ?ContentKey,
545
546
  needsStableName: ?boolean,
@@ -573,6 +574,7 @@ export type BundleGroupNode = {|
573
574
 
574
575
  export type PackagedBundleInfo = {|
575
576
  filePath: ProjectPath,
577
+ bundleId: ContentKey,
576
578
  type: string,
577
579
  stats: Stats,
578
580
  |};
@@ -5,10 +5,11 @@ import assert from 'assert';
5
5
  import expect from 'expect';
6
6
  import {createEnvironment} from '../src/Environment';
7
7
  import {initializeMonitoring} from '../../rust';
8
+ import {fromEnvironmentId} from '../src/EnvironmentManager';
8
9
 
9
10
  describe('Environment', () => {
10
11
  it('assigns a default environment with nothing passed', () => {
11
- assert.deepEqual(createEnvironment(), {
12
+ assert.deepEqual(fromEnvironmentId(createEnvironment()), {
12
13
  id: 'd821e85f6b50315e',
13
14
  context: 'browser',
14
15
  engines: {
@@ -27,27 +28,32 @@ describe('Environment', () => {
27
28
  });
28
29
 
29
30
  it('assigns a node context if a node engine is given', () => {
30
- assert.deepEqual(createEnvironment({engines: {node: '>= 10.0.0'}}), {
31
- id: '2320af923a717577',
32
- context: 'node',
33
- engines: {
34
- node: '>= 10.0.0',
31
+ assert.deepEqual(
32
+ fromEnvironmentId(createEnvironment({engines: {node: '>= 10.0.0'}})),
33
+ {
34
+ id: '2320af923a717577',
35
+ context: 'node',
36
+ engines: {
37
+ node: '>= 10.0.0',
38
+ },
39
+ includeNodeModules: false,
40
+ outputFormat: 'commonjs',
41
+ isLibrary: false,
42
+ shouldOptimize: false,
43
+ shouldScopeHoist: false,
44
+ sourceMap: undefined,
45
+ loc: undefined,
46
+ sourceType: 'module',
47
+ unstableSingleFileOutput: false,
35
48
  },
36
- includeNodeModules: false,
37
- outputFormat: 'commonjs',
38
- isLibrary: false,
39
- shouldOptimize: false,
40
- shouldScopeHoist: false,
41
- sourceMap: undefined,
42
- loc: undefined,
43
- sourceType: 'module',
44
- unstableSingleFileOutput: false,
45
- });
49
+ );
46
50
  });
47
51
 
48
52
  it('assigns a browser context if browser engines are given', () => {
49
53
  assert.deepEqual(
50
- createEnvironment({engines: {browsers: ['last 1 version']}}),
54
+ fromEnvironmentId(
55
+ createEnvironment({engines: {browsers: ['last 1 version']}}),
56
+ ),
51
57
  {
52
58
  id: '75603271034eff15',
53
59
  context: 'browser',
@@ -68,7 +74,7 @@ describe('Environment', () => {
68
74
  });
69
75
 
70
76
  it('assigns default engines for node', () => {
71
- assert.deepEqual(createEnvironment({context: 'node'}), {
77
+ assert.deepEqual(fromEnvironmentId(createEnvironment({context: 'node'})), {
72
78
  id: 'e45cc12216f7857d',
73
79
  context: 'node',
74
80
  engines: {
@@ -87,22 +93,25 @@ describe('Environment', () => {
87
93
  });
88
94
 
89
95
  it('assigns default engines for browsers', () => {
90
- assert.deepEqual(createEnvironment({context: 'browser'}), {
91
- id: 'd821e85f6b50315e',
92
- context: 'browser',
93
- engines: {
94
- browsers: ['> 0.25%'],
96
+ assert.deepEqual(
97
+ fromEnvironmentId(createEnvironment({context: 'browser'})),
98
+ {
99
+ id: 'd821e85f6b50315e',
100
+ context: 'browser',
101
+ engines: {
102
+ browsers: ['> 0.25%'],
103
+ },
104
+ includeNodeModules: true,
105
+ outputFormat: 'global',
106
+ isLibrary: false,
107
+ shouldOptimize: false,
108
+ shouldScopeHoist: false,
109
+ sourceMap: undefined,
110
+ loc: undefined,
111
+ sourceType: 'module',
112
+ unstableSingleFileOutput: false,
95
113
  },
96
- includeNodeModules: true,
97
- outputFormat: 'global',
98
- isLibrary: false,
99
- shouldOptimize: false,
100
- shouldScopeHoist: false,
101
- sourceMap: undefined,
102
- loc: undefined,
103
- sourceType: 'module',
104
- unstableSingleFileOutput: false,
105
- });
114
+ );
106
115
  });
107
116
  });
108
117
 
@@ -114,6 +123,6 @@ describe('createEnvironment', function () {
114
123
  /* ignore */
115
124
  }
116
125
  const environment = createEnvironment({});
117
- expect(environment.id).toEqual('d821e85f6b50315e');
126
+ expect(fromEnvironmentId(environment).id).toEqual('d821e85f6b50315e');
118
127
  });
119
128
  });
@@ -0,0 +1,192 @@
1
+ // @flow strict-local
2
+
3
+ import assert from 'assert';
4
+ import nullthrows from 'nullthrows';
5
+ import sinon from 'sinon';
6
+ import {ATLASPACK_VERSION} from '../src/constants';
7
+ import {DEFAULT_FEATURE_FLAGS, setFeatureFlags} from '@atlaspack/feature-flags';
8
+ import {setAllEnvironments, getAllEnvironments} from '@atlaspack/rust';
9
+ import {
10
+ loadEnvironmentsFromCache,
11
+ writeEnvironmentsToCache,
12
+ } from '../src/EnvironmentManager';
13
+ import {DEFAULT_OPTIONS} from './test-utils';
14
+ import {LMDBLiteCache} from '@atlaspack/cache';
15
+
16
+ const options = {
17
+ ...DEFAULT_OPTIONS,
18
+ cache: new LMDBLiteCache(DEFAULT_OPTIONS.cacheDir),
19
+ };
20
+
21
+ describe('EnvironmentManager', () => {
22
+ const env1 = {
23
+ id: 'd821e85f6b50315e',
24
+ context: 'browser',
25
+ engines: {browsers: ['> 0.25%']},
26
+ includeNodeModules: true,
27
+ outputFormat: 'global',
28
+ isLibrary: false,
29
+ shouldOptimize: false,
30
+ shouldScopeHoist: false,
31
+ loc: undefined,
32
+ sourceMap: undefined,
33
+ sourceType: 'module',
34
+ unstableSingleFileOutput: false,
35
+ };
36
+ const env2 = {
37
+ id: 'de92f48baa8448d2',
38
+ context: 'node',
39
+ engines: {
40
+ browsers: [],
41
+ node: '>= 8',
42
+ },
43
+ includeNodeModules: false,
44
+ outputFormat: 'commonjs',
45
+ isLibrary: true,
46
+ shouldOptimize: true,
47
+ shouldScopeHoist: true,
48
+ loc: null,
49
+ sourceMap: null,
50
+ sourceType: 'module',
51
+ unstableSingleFileOutput: false,
52
+ };
53
+
54
+ beforeEach(async () => {
55
+ await options.cache.ensure();
56
+
57
+ for (const key of options.cache.keys()) {
58
+ await options.cache.getNativeRef().delete(key);
59
+ }
60
+ setAllEnvironments([]);
61
+
62
+ setFeatureFlags({
63
+ ...DEFAULT_FEATURE_FLAGS,
64
+ environmentDeduplication: true,
65
+ });
66
+ });
67
+
68
+ it('should store environments by ID in the cache', async () => {
69
+ setAllEnvironments([env1]);
70
+ await writeEnvironmentsToCache(options.cache);
71
+
72
+ const cachedEnv1 = await options.cache.get(
73
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
74
+ );
75
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
76
+ });
77
+
78
+ it('should list all environment IDs in the environment manager', async () => {
79
+ const environmentIds = [env1.id, env2.id];
80
+ setAllEnvironments([env1, env2]);
81
+ await writeEnvironmentsToCache(options.cache);
82
+
83
+ const cachedEnvIds = await options.cache.get(
84
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
85
+ );
86
+ const cachedIdsArray = nullthrows(cachedEnvIds);
87
+ assert.equal(
88
+ cachedIdsArray.length,
89
+ environmentIds.length,
90
+ 'Should have same number of IDs',
91
+ );
92
+ assert(
93
+ environmentIds.every((id) => cachedIdsArray.includes(id)),
94
+ 'All environment IDs should be present in cache',
95
+ );
96
+ });
97
+
98
+ it('should write all environments to cache using writeEnvironmentsToCache', async () => {
99
+ setAllEnvironments([env1, env2]);
100
+ await writeEnvironmentsToCache(options.cache);
101
+
102
+ // Verify each environment was stored individually
103
+ const cachedEnv1 = await options.cache.get(
104
+ `Environment/${ATLASPACK_VERSION}/${env1.id}`,
105
+ );
106
+ const cachedEnv2 = await options.cache.get(
107
+ `Environment/${ATLASPACK_VERSION}/${env2.id}`,
108
+ );
109
+ assert.deepEqual(cachedEnv1, env1, 'Environment 1 should be cached');
110
+ assert.deepEqual(cachedEnv2, env2, 'Environment 2 should be cached');
111
+
112
+ // Verify environment IDs were stored in manager
113
+ const cachedEnvIds = await options.cache.get(
114
+ `EnvironmentManager/${ATLASPACK_VERSION}`,
115
+ );
116
+ const cachedIdsArray = nullthrows(cachedEnvIds);
117
+ assert(
118
+ cachedIdsArray.length === 2 &&
119
+ [env1.id, env2.id].every((id) => cachedIdsArray.includes(id)),
120
+ 'Environment IDs should be stored in manager',
121
+ );
122
+ });
123
+
124
+ it('should load environments from cache on loadRequestGraph on a subsequent build', async () => {
125
+ // Simulate cache written on a first build
126
+ setAllEnvironments([env1, env2]);
127
+ await writeEnvironmentsToCache(options.cache);
128
+
129
+ await loadEnvironmentsFromCache(options.cache);
130
+
131
+ const loadedEnvironments = getAllEnvironments();
132
+ assert.equal(
133
+ loadedEnvironments.length,
134
+ 2,
135
+ 'Should load 2 environments from cache',
136
+ );
137
+
138
+ const env1Loaded = loadedEnvironments.find((e) => e.id === env1.id);
139
+ const env2Loaded = loadedEnvironments.find((e) => e.id === env2.id);
140
+
141
+ assert.deepEqual(
142
+ env1Loaded,
143
+ env1,
144
+ 'First environment should match cached environment',
145
+ );
146
+ assert.deepEqual(
147
+ env2Loaded,
148
+ env2,
149
+ 'Second environment should match cached environment',
150
+ );
151
+ });
152
+
153
+ it('should handle empty cache gracefully without calling setAllEnvironments', async () => {
154
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
155
+
156
+ await assert.doesNotReject(
157
+ loadEnvironmentsFromCache(options.cache),
158
+ 'loadEnvironmentsFromCache should not throw when cache is empty',
159
+ );
160
+
161
+ assert.equal(
162
+ setAllEnvironmentsSpy.callCount,
163
+ 0,
164
+ 'setAllEnvironments should not be called when loading from empty cache',
165
+ );
166
+ });
167
+
168
+ it('should not load environments from a different version', async () => {
169
+ const setAllEnvironmentsSpy = sinon.spy(setAllEnvironments);
170
+ const differentVersion = '2.17.2'; // A different version than ATLASPACK_VERSION
171
+
172
+ // Store an environment with a different version
173
+ await options.cache.set(`Environment/${differentVersion}/${env1.id}`, env1);
174
+ await options.cache.set(`EnvironmentManager/${differentVersion}`, [
175
+ env1.id,
176
+ ]);
177
+
178
+ await loadEnvironmentsFromCache(options.cache);
179
+
180
+ assert.equal(
181
+ setAllEnvironmentsSpy.callCount,
182
+ 0,
183
+ 'setAllEnvironments should not be called when loading from different version',
184
+ );
185
+ const loadedEnvironments = getAllEnvironments();
186
+ assert.equal(
187
+ loadedEnvironments.length,
188
+ 0,
189
+ 'Should not load any environments from different version',
190
+ );
191
+ });
192
+ });
@@ -2,19 +2,22 @@
2
2
 
3
3
  import assert from 'assert';
4
4
  import {createEnvironment} from '../src/Environment';
5
+ import {fromEnvironmentId} from '../src/EnvironmentManager';
5
6
  import PublicEnvironment from '../src/public/Environment';
6
7
  import {DEFAULT_OPTIONS} from './test-utils';
7
8
 
8
9
  describe('Public Environment', () => {
9
10
  it('has correct support data for ChromeAndroid', () => {
10
11
  let env = new PublicEnvironment(
11
- createEnvironment({
12
- context: 'browser',
13
- engines: {
14
- browsers: ['last 1 Chrome version', 'last 1 ChromeAndroid version'],
15
- },
16
- outputFormat: 'esmodule',
17
- }),
12
+ fromEnvironmentId(
13
+ createEnvironment({
14
+ context: 'browser',
15
+ engines: {
16
+ browsers: ['last 1 Chrome version', 'last 1 ChromeAndroid version'],
17
+ },
18
+ outputFormat: 'esmodule',
19
+ }),
20
+ ),
18
21
  DEFAULT_OPTIONS,
19
22
  );
20
23