@atlaspack/core 2.12.1-canary.3354

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 (215) hide show
  1. package/LICENSE +201 -0
  2. package/index.d.ts +22 -0
  3. package/lib/AssetGraph.js +518 -0
  4. package/lib/Atlaspack.js +587 -0
  5. package/lib/AtlaspackConfig.js +298 -0
  6. package/lib/AtlaspackConfig.schema.js +125 -0
  7. package/lib/BundleGraph.js +1445 -0
  8. package/lib/CommittedAsset.js +133 -0
  9. package/lib/Dependency.js +88 -0
  10. package/lib/Environment.js +128 -0
  11. package/lib/InternalConfig.js +48 -0
  12. package/lib/PackagerRunner.js +519 -0
  13. package/lib/ReporterRunner.js +151 -0
  14. package/lib/RequestTracker.js +1089 -0
  15. package/lib/SymbolPropagation.js +625 -0
  16. package/lib/TargetDescriptor.schema.js +115 -0
  17. package/lib/Transformation.js +536 -0
  18. package/lib/UncommittedAsset.js +342 -0
  19. package/lib/Validation.js +215 -0
  20. package/lib/applyRuntimes.js +279 -0
  21. package/lib/assetUtils.js +189 -0
  22. package/lib/atlaspack-v3/AtlaspackV3.js +74 -0
  23. package/lib/atlaspack-v3/fs.js +30 -0
  24. package/lib/atlaspack-v3/index.js +19 -0
  25. package/lib/atlaspack-v3/jsCallable.js +15 -0
  26. package/lib/atlaspack-v3/plugins/Resolver.js +12 -0
  27. package/lib/atlaspack-v3/plugins/index.js +16 -0
  28. package/lib/atlaspack-v3/worker/index.js +3 -0
  29. package/lib/atlaspack-v3/worker/worker.js +30 -0
  30. package/lib/buildCache.js +18 -0
  31. package/lib/constants.js +21 -0
  32. package/lib/dumpGraphToGraphViz.js +206 -0
  33. package/lib/index.js +106 -0
  34. package/lib/loadAtlaspackPlugin.js +148 -0
  35. package/lib/loadDotEnv.js +54 -0
  36. package/lib/projectPath.js +86 -0
  37. package/lib/public/Asset.js +259 -0
  38. package/lib/public/Bundle.js +231 -0
  39. package/lib/public/BundleGraph.js +193 -0
  40. package/lib/public/BundleGroup.js +44 -0
  41. package/lib/public/Config.js +202 -0
  42. package/lib/public/Dependency.js +131 -0
  43. package/lib/public/Environment.js +244 -0
  44. package/lib/public/MutableBundleGraph.js +184 -0
  45. package/lib/public/PluginOptions.js +71 -0
  46. package/lib/public/Symbols.js +247 -0
  47. package/lib/public/Target.js +64 -0
  48. package/lib/registerCoreWithSerializer.js +45 -0
  49. package/lib/requests/AssetGraphRequest.js +427 -0
  50. package/lib/requests/AssetGraphRequestRust.js +187 -0
  51. package/lib/requests/AssetRequest.js +137 -0
  52. package/lib/requests/AtlaspackBuildRequest.js +78 -0
  53. package/lib/requests/AtlaspackConfigRequest.js +473 -0
  54. package/lib/requests/BundleGraphRequest.js +419 -0
  55. package/lib/requests/ConfigRequest.js +198 -0
  56. package/lib/requests/DevDepRequest.js +166 -0
  57. package/lib/requests/EntryRequest.js +295 -0
  58. package/lib/requests/PackageRequest.js +88 -0
  59. package/lib/requests/PathRequest.js +349 -0
  60. package/lib/requests/TargetRequest.js +1177 -0
  61. package/lib/requests/ValidationRequest.js +66 -0
  62. package/lib/requests/WriteBundleRequest.js +252 -0
  63. package/lib/requests/WriteBundlesRequest.js +153 -0
  64. package/lib/resolveOptions.js +234 -0
  65. package/lib/serializer.js +216 -0
  66. package/lib/serializerCore.browser.js +29 -0
  67. package/lib/serializerCore.js +16 -0
  68. package/lib/summarizeRequest.js +55 -0
  69. package/lib/types.js +35 -0
  70. package/lib/utils.js +160 -0
  71. package/lib/worker.js +170 -0
  72. package/package.json +59 -0
  73. package/src/AssetGraph.js +646 -0
  74. package/src/Atlaspack.js +632 -0
  75. package/src/AtlaspackConfig.js +490 -0
  76. package/src/AtlaspackConfig.schema.js +141 -0
  77. package/src/BundleGraph.js +2193 -0
  78. package/src/CommittedAsset.js +143 -0
  79. package/src/Dependency.js +142 -0
  80. package/src/Environment.js +151 -0
  81. package/src/InternalConfig.js +72 -0
  82. package/src/PackagerRunner.js +790 -0
  83. package/src/ReporterRunner.js +158 -0
  84. package/src/RequestTracker.js +1697 -0
  85. package/src/SymbolPropagation.js +794 -0
  86. package/src/TargetDescriptor.schema.js +136 -0
  87. package/src/Transformation.js +752 -0
  88. package/src/UncommittedAsset.js +426 -0
  89. package/src/Validation.js +223 -0
  90. package/src/applyRuntimes.js +341 -0
  91. package/src/assetUtils.js +254 -0
  92. package/src/atlaspack-v3/AtlaspackV3.js +73 -0
  93. package/src/atlaspack-v3/fs.js +36 -0
  94. package/src/atlaspack-v3/index.js +5 -0
  95. package/src/atlaspack-v3/jsCallable.js +13 -0
  96. package/src/atlaspack-v3/plugins/Resolver.js +9 -0
  97. package/src/atlaspack-v3/plugins/index.js +3 -0
  98. package/src/atlaspack-v3/worker/index.js +8 -0
  99. package/src/atlaspack-v3/worker/worker.js +14 -0
  100. package/src/buildCache.js +15 -0
  101. package/src/constants.js +22 -0
  102. package/src/dumpGraphToGraphViz.js +244 -0
  103. package/src/index.js +22 -0
  104. package/src/loadAtlaspackPlugin.js +239 -0
  105. package/src/loadDotEnv.js +56 -0
  106. package/src/projectPath.js +87 -0
  107. package/src/public/Asset.js +359 -0
  108. package/src/public/Bundle.js +337 -0
  109. package/src/public/BundleGraph.js +335 -0
  110. package/src/public/BundleGroup.js +55 -0
  111. package/src/public/Config.js +261 -0
  112. package/src/public/Dependency.js +176 -0
  113. package/src/public/Environment.js +316 -0
  114. package/src/public/MutableBundleGraph.js +320 -0
  115. package/src/public/PluginOptions.js +99 -0
  116. package/src/public/Symbols.js +315 -0
  117. package/src/public/Target.js +71 -0
  118. package/src/registerCoreWithSerializer.js +34 -0
  119. package/src/requests/AssetGraphRequest.js +577 -0
  120. package/src/requests/AssetGraphRequestRust.js +222 -0
  121. package/src/requests/AssetRequest.js +179 -0
  122. package/src/requests/AtlaspackBuildRequest.js +109 -0
  123. package/src/requests/AtlaspackConfigRequest.js +709 -0
  124. package/src/requests/BundleGraphRequest.js +547 -0
  125. package/src/requests/ConfigRequest.js +287 -0
  126. package/src/requests/DevDepRequest.js +246 -0
  127. package/src/requests/EntryRequest.js +385 -0
  128. package/src/requests/PackageRequest.js +105 -0
  129. package/src/requests/PathRequest.js +454 -0
  130. package/src/requests/TargetRequest.js +1632 -0
  131. package/src/requests/ValidationRequest.js +79 -0
  132. package/src/requests/WriteBundleRequest.js +362 -0
  133. package/src/requests/WriteBundlesRequest.js +209 -0
  134. package/src/resolveOptions.js +278 -0
  135. package/src/serializer.js +255 -0
  136. package/src/serializerCore.browser.js +8 -0
  137. package/src/serializerCore.js +5 -0
  138. package/src/summarizeRequest.js +47 -0
  139. package/src/types.js +581 -0
  140. package/src/utils.js +211 -0
  141. package/src/worker.js +189 -0
  142. package/test/AssetGraph.test.js +679 -0
  143. package/test/Atlaspack.test.js +142 -0
  144. package/test/AtlaspackConfig.test.js +405 -0
  145. package/test/AtlaspackConfigRequest.test.js +993 -0
  146. package/test/BundleGraph.test.js +121 -0
  147. package/test/EntryRequest.test.js +215 -0
  148. package/test/Environment.test.js +99 -0
  149. package/test/InternalAsset.test.js +76 -0
  150. package/test/PackagerRunner.test.js +27 -0
  151. package/test/PublicAsset.test.js +40 -0
  152. package/test/PublicBundle.test.js +68 -0
  153. package/test/PublicDependency.test.js +22 -0
  154. package/test/PublicEnvironment.test.js +27 -0
  155. package/test/PublicMutableBundleGraph.test.js +192 -0
  156. package/test/RequestTracker.test.js +448 -0
  157. package/test/SymbolPropagation.test.js +716 -0
  158. package/test/TargetRequest.test.js +1715 -0
  159. package/test/fixtures/application-targets/package.json +3 -0
  160. package/test/fixtures/atlaspack/index.js +1 -0
  161. package/test/fixtures/atlaspack/other.js +3 -0
  162. package/test/fixtures/atlaspack/package.json +1 -0
  163. package/test/fixtures/atlaspack/yarn.lock +0 -0
  164. package/test/fixtures/bundle.js +10 -0
  165. package/test/fixtures/common-targets/package.json +24 -0
  166. package/test/fixtures/common-targets-ignore/package.json +13 -0
  167. package/test/fixtures/config/.atlaspackrc +6 -0
  168. package/test/fixtures/config/subfolder/.atlaspackrc +6 -0
  169. package/test/fixtures/config-extends-not-found/.atlaspackrc +3 -0
  170. package/test/fixtures/config-extends-not-found/.atlaspackrc-json5 +3 -0
  171. package/test/fixtures/config-extends-not-found/.atlaspackrc-multiple +3 -0
  172. package/test/fixtures/config-extends-not-found/.atlaspackrc-node-modules +3 -0
  173. package/test/fixtures/config-malformed/.atlaspackrc +3 -0
  174. package/test/fixtures/config-node-pipeline/.atlaspackrc +6 -0
  175. package/test/fixtures/config-plugin-not-found/.atlaspackrc +6 -0
  176. package/test/fixtures/context/package.json +8 -0
  177. package/test/fixtures/custom-format-infer-ext/package.json +6 -0
  178. package/test/fixtures/custom-format-infer-type/package.json +7 -0
  179. package/test/fixtures/custom-format-mismatch/package.json +8 -0
  180. package/test/fixtures/custom-targets/package.json +20 -0
  181. package/test/fixtures/custom-targets-distdir/package.json +11 -0
  182. package/test/fixtures/duplicate-targets/package.json +4 -0
  183. package/test/fixtures/glob-like/[entry].js +0 -0
  184. package/test/fixtures/invalid-distpath/package.json +11 -0
  185. package/test/fixtures/invalid-engines/package.json +12 -0
  186. package/test/fixtures/invalid-source-missing/package.json +5 -0
  187. package/test/fixtures/invalid-source-not-file/package.json +5 -0
  188. package/test/fixtures/invalid-source-not-file/src/index.js +1 -0
  189. package/test/fixtures/invalid-target-source-missing/package.json +9 -0
  190. package/test/fixtures/invalid-target-source-not-file/package.json +9 -0
  191. package/test/fixtures/invalid-target-source-not-file/src/index.js +1 -0
  192. package/test/fixtures/invalid-targets/package.json +19 -0
  193. package/test/fixtures/library-custom-scopehoist/package.json +9 -0
  194. package/test/fixtures/library-scopehoist/package.json +8 -0
  195. package/test/fixtures/local-plugin-config-pkg/.atlaspackrc +3 -0
  196. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/index.json +8 -0
  197. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/local-plugin.js +7 -0
  198. package/test/fixtures/local-plugin-config-pkg/node_modules/atlaspack-config-local/package.json +7 -0
  199. package/test/fixtures/main-format-mismatch/package.json +8 -0
  200. package/test/fixtures/main-global/package.json +8 -0
  201. package/test/fixtures/main-mjs/package.json +8 -0
  202. package/test/fixtures/module-a.js +1 -0
  203. package/test/fixtures/module-b.js +1 -0
  204. package/test/fixtures/plugins/local-plugin.js +7 -0
  205. package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/index.js +7 -0
  206. package/test/fixtures/plugins/node_modules/atlaspack-transformer-bad-engines/package.json +7 -0
  207. package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/index.js +7 -0
  208. package/test/fixtures/plugins/node_modules/atlaspack-transformer-no-engines/package.json +4 -0
  209. package/test/fixtures/targets-default-distdir-none/package.json +5 -0
  210. package/test/fixtures/targets-default-distdir-one/package.json +8 -0
  211. package/test/fixtures/targets-default-distdir-two/package.json +18 -0
  212. package/test/requests/ConfigRequest.test.js +254 -0
  213. package/test/serializer.test.js +302 -0
  214. package/test/test-utils.js +80 -0
  215. package/test/utils.test.js +43 -0
@@ -0,0 +1,709 @@
1
+ // @flow strict-local
2
+ import type {
3
+ Async,
4
+ FilePath,
5
+ PackageName,
6
+ RawAtlaspackConfig,
7
+ ResolvedAtlaspackConfigFile,
8
+ } from '@atlaspack/types';
9
+ import type {FileSystem} from '@atlaspack/fs';
10
+ import type {StaticRunOpts} from '../RequestTracker';
11
+ import type {
12
+ ExtendableAtlaspackConfigPipeline,
13
+ PureAtlaspackConfigPipeline,
14
+ AtlaspackOptions,
15
+ ProcessedAtlaspackConfig,
16
+ } from '../types';
17
+
18
+ import {
19
+ isDirectoryInside,
20
+ hashObject,
21
+ resolveConfig,
22
+ validateSchema,
23
+ findAlternativeNodeModules,
24
+ findAlternativeFiles,
25
+ } from '@atlaspack/utils';
26
+ import ThrowableDiagnostic, {
27
+ generateJSONCodeHighlights,
28
+ escapeMarkdown,
29
+ md,
30
+ errorToDiagnostic,
31
+ } from '@atlaspack/diagnostic';
32
+ import {parse} from 'json5';
33
+ import path from 'path';
34
+ import invariant from 'assert';
35
+
36
+ import AtlaspackConfigSchema from '../AtlaspackConfig.schema';
37
+ import {optionsProxy} from '../utils';
38
+ import AtlaspackConfig from '../AtlaspackConfig';
39
+ import {createBuildCache} from '../buildCache';
40
+ import {toProjectPath} from '../projectPath';
41
+ import {requestTypes} from '../RequestTracker';
42
+
43
+ type ConfigMap<K, V> = {[K]: V, ...};
44
+
45
+ export type ConfigAndCachePath = {|
46
+ config: ProcessedAtlaspackConfig,
47
+ cachePath: string,
48
+ |};
49
+
50
+ type RunOpts<TResult> = {|
51
+ input: null,
52
+ ...StaticRunOpts<TResult>,
53
+ |};
54
+
55
+ export type AtlaspackConfigRequest = {|
56
+ id: string,
57
+ type: typeof requestTypes.atlaspack_config_request,
58
+ input: null,
59
+ run: (
60
+ RunOpts<AtlaspackConfigRequestResult>,
61
+ ) => Async<AtlaspackConfigRequestResult>,
62
+ |};
63
+
64
+ export type AtlaspackConfigRequestResult = ConfigAndCachePath;
65
+
66
+ type AtlaspackConfigChain = {|
67
+ config: ProcessedAtlaspackConfig,
68
+ extendedFiles: Array<FilePath>,
69
+ |};
70
+
71
+ const type = 'atlaspack_config_request';
72
+
73
+ export default function createAtlaspackConfigRequest(): AtlaspackConfigRequest {
74
+ return {
75
+ id: type,
76
+ type: requestTypes[type],
77
+ async run({api, options}) {
78
+ let {
79
+ config,
80
+ extendedFiles,
81
+ usedDefault,
82
+ }: {|
83
+ ...AtlaspackConfigChain,
84
+ usedDefault: boolean,
85
+ |} = await loadAtlaspackConfig(
86
+ optionsProxy(options, api.invalidateOnOptionChange),
87
+ );
88
+
89
+ api.invalidateOnFileUpdate(config.filePath);
90
+ api.invalidateOnFileDelete(config.filePath);
91
+
92
+ for (let filePath of extendedFiles) {
93
+ let pp = toProjectPath(options.projectRoot, filePath);
94
+ api.invalidateOnFileUpdate(pp);
95
+ api.invalidateOnFileDelete(pp);
96
+ }
97
+
98
+ if (usedDefault) {
99
+ let resolveFrom = getResolveFrom(options.inputFS, options.projectRoot);
100
+ api.invalidateOnFileCreate({
101
+ fileName: '.atlaspackrc',
102
+ aboveFilePath: toProjectPath(options.projectRoot, resolveFrom),
103
+ });
104
+ }
105
+
106
+ let cachePath = hashObject(config);
107
+ await options.cache.set(cachePath, config);
108
+ let result = {config, cachePath};
109
+ // TODO: don't store config twice (once in the graph and once in a separate cache entry)
110
+ api.storeResult(result);
111
+ return result;
112
+ },
113
+ input: null,
114
+ };
115
+ }
116
+
117
+ const atlaspackConfigCache = createBuildCache();
118
+ export function getCachedAtlaspackConfig(
119
+ result: ConfigAndCachePath,
120
+ options: AtlaspackOptions,
121
+ ): AtlaspackConfig {
122
+ let {config: processedConfig, cachePath} = result;
123
+ let config = atlaspackConfigCache.get(cachePath);
124
+ if (config) {
125
+ return config;
126
+ }
127
+
128
+ config = new AtlaspackConfig(processedConfig, options);
129
+
130
+ atlaspackConfigCache.set(cachePath, config);
131
+ return config;
132
+ }
133
+
134
+ export async function loadAtlaspackConfig(
135
+ options: AtlaspackOptions,
136
+ ): Promise<{|...AtlaspackConfigChain, usedDefault: boolean|}> {
137
+ let atlaspackConfig = await resolveAtlaspackConfig(options);
138
+
139
+ if (!atlaspackConfig) {
140
+ throw new Error('Could not find a .atlaspackrc');
141
+ }
142
+
143
+ return atlaspackConfig;
144
+ }
145
+
146
+ export async function resolveAtlaspackConfig(
147
+ options: AtlaspackOptions,
148
+ ): Promise<?{|...AtlaspackConfigChain, usedDefault: boolean|}> {
149
+ let resolveFrom = getResolveFrom(options.inputFS, options.projectRoot);
150
+ let configPath =
151
+ options.config != null
152
+ ? (await options.packageManager.resolve(options.config, resolveFrom))
153
+ .resolved
154
+ : await resolveConfig(
155
+ options.inputFS,
156
+ resolveFrom,
157
+ ['.atlaspackrc'],
158
+ options.projectRoot,
159
+ );
160
+
161
+ let usedDefault = false;
162
+ if (configPath == null && options.defaultConfig != null) {
163
+ usedDefault = true;
164
+ configPath = (
165
+ await options.packageManager.resolve(options.defaultConfig, resolveFrom)
166
+ ).resolved;
167
+ }
168
+
169
+ if (configPath == null) {
170
+ return null;
171
+ }
172
+
173
+ let contents;
174
+ try {
175
+ contents = await options.inputFS.readFile(configPath, 'utf8');
176
+ } catch (e) {
177
+ throw new ThrowableDiagnostic({
178
+ diagnostic: {
179
+ message: md`Could not find atlaspack config at ${path.relative(
180
+ options.projectRoot,
181
+ configPath,
182
+ )}`,
183
+ origin: '@atlaspack/core',
184
+ },
185
+ });
186
+ }
187
+
188
+ let {config, extendedFiles}: AtlaspackConfigChain =
189
+ await parseAndProcessConfig(configPath, contents, options);
190
+
191
+ if (options.additionalReporters.length > 0) {
192
+ config.reporters = [
193
+ ...options.additionalReporters.map(({packageName, resolveFrom}) => ({
194
+ packageName,
195
+ resolveFrom,
196
+ })),
197
+ ...(config.reporters ?? []),
198
+ ];
199
+ }
200
+
201
+ return {config, extendedFiles, usedDefault};
202
+ }
203
+
204
+ export function create(
205
+ config: ResolvedAtlaspackConfigFile,
206
+ options: AtlaspackOptions,
207
+ ): Promise<AtlaspackConfigChain> {
208
+ return processConfigChain(config, config.filePath, options);
209
+ }
210
+
211
+ // eslint-disable-next-line require-await
212
+ export async function parseAndProcessConfig(
213
+ configPath: FilePath,
214
+ contents: string,
215
+ options: AtlaspackOptions,
216
+ ): Promise<AtlaspackConfigChain> {
217
+ let config: RawAtlaspackConfig;
218
+ try {
219
+ config = parse(contents);
220
+ } catch (e) {
221
+ let pos = {
222
+ line: e.lineNumber,
223
+ column: e.columnNumber,
224
+ };
225
+ throw new ThrowableDiagnostic({
226
+ diagnostic: {
227
+ message: `Failed to parse .atlaspackrc`,
228
+ origin: '@atlaspack/core',
229
+
230
+ codeFrames: [
231
+ {
232
+ filePath: configPath,
233
+ language: 'json5',
234
+ code: contents,
235
+ codeHighlights: [
236
+ {
237
+ start: pos,
238
+ end: pos,
239
+ message: escapeMarkdown(e.message),
240
+ },
241
+ ],
242
+ },
243
+ ],
244
+ },
245
+ });
246
+ }
247
+ return processConfigChain(config, configPath, options);
248
+ }
249
+
250
+ function processPipeline(
251
+ options: AtlaspackOptions,
252
+ pipeline: ?Array<PackageName>,
253
+ keyPath: string,
254
+ filePath: FilePath,
255
+ ) {
256
+ if (pipeline) {
257
+ return pipeline.map((pkg, i) => {
258
+ // $FlowFixMe
259
+ if (pkg === '...') return pkg;
260
+
261
+ return {
262
+ packageName: pkg,
263
+ resolveFrom: toProjectPath(options.projectRoot, filePath),
264
+ keyPath: `${keyPath}/${i}`,
265
+ };
266
+ });
267
+ }
268
+ }
269
+
270
+ const RESERVED_PIPELINES = new Set([
271
+ 'node:',
272
+ 'npm:',
273
+ 'http:',
274
+ 'https:',
275
+ 'data:',
276
+ 'tel:',
277
+ 'mailto:',
278
+ ]);
279
+
280
+ async function processMap(
281
+ // $FlowFixMe
282
+ map: ?ConfigMap<any, any>,
283
+ keyPath: string,
284
+ filePath: FilePath,
285
+ options: AtlaspackOptions,
286
+ // $FlowFixMe
287
+ ): Promise<ConfigMap<any, any> | typeof undefined> {
288
+ if (!map) return undefined;
289
+
290
+ // $FlowFixMe
291
+ let res: ConfigMap<any, any> = {};
292
+ for (let k in map) {
293
+ let i = k.indexOf(':');
294
+ if (i > 0 && RESERVED_PIPELINES.has(k.slice(0, i + 1))) {
295
+ let code = await options.inputFS.readFile(filePath, 'utf8');
296
+ throw new ThrowableDiagnostic({
297
+ diagnostic: {
298
+ message: `Named pipeline '${k.slice(0, i + 1)}' is reserved.`,
299
+ origin: '@atlaspack/core',
300
+ codeFrames: [
301
+ {
302
+ filePath: filePath,
303
+ language: 'json5',
304
+ code,
305
+ codeHighlights: generateJSONCodeHighlights(code, [
306
+ {
307
+ key: `${keyPath}/${k}`,
308
+ type: 'key',
309
+ },
310
+ ]),
311
+ },
312
+ ],
313
+ documentationURL:
314
+ 'https://parceljs.org/features/dependency-resolution/#url-schemes',
315
+ },
316
+ });
317
+ }
318
+
319
+ if (typeof map[k] === 'string') {
320
+ res[k] = {
321
+ packageName: map[k],
322
+ resolveFrom: toProjectPath(options.projectRoot, filePath),
323
+ keyPath: `${keyPath}/${k}`,
324
+ };
325
+ } else {
326
+ res[k] = processPipeline(options, map[k], `${keyPath}/${k}`, filePath);
327
+ }
328
+ }
329
+
330
+ return res;
331
+ }
332
+
333
+ export async function processConfig(
334
+ configFile: ResolvedAtlaspackConfigFile,
335
+ options: AtlaspackOptions,
336
+ ): Promise<ProcessedAtlaspackConfig> {
337
+ return {
338
+ filePath: toProjectPath(options.projectRoot, configFile.filePath),
339
+ ...(configFile.resolveFrom != null
340
+ ? {
341
+ resolveFrom: toProjectPath(
342
+ options.projectRoot,
343
+ configFile.resolveFrom,
344
+ ),
345
+ }
346
+ : {
347
+ /*::...null*/
348
+ }),
349
+ resolvers: processPipeline(
350
+ options,
351
+ configFile.resolvers,
352
+ '/resolvers',
353
+ configFile.filePath,
354
+ ),
355
+ transformers: await processMap(
356
+ configFile.transformers,
357
+ '/transformers',
358
+ configFile.filePath,
359
+ options,
360
+ ),
361
+ bundler:
362
+ configFile.bundler != null
363
+ ? {
364
+ packageName: configFile.bundler,
365
+ resolveFrom: toProjectPath(
366
+ options.projectRoot,
367
+ configFile.filePath,
368
+ ),
369
+ keyPath: '/bundler',
370
+ }
371
+ : undefined,
372
+ namers: processPipeline(
373
+ options,
374
+ configFile.namers,
375
+ '/namers',
376
+ configFile.filePath,
377
+ ),
378
+ runtimes: processPipeline(
379
+ options,
380
+ configFile.runtimes,
381
+ '/runtimes',
382
+ configFile.filePath,
383
+ ),
384
+ packagers: await processMap(
385
+ configFile.packagers,
386
+ '/packagers',
387
+ configFile.filePath,
388
+ options,
389
+ ),
390
+ optimizers: await processMap(
391
+ configFile.optimizers,
392
+ '/optimizers',
393
+ configFile.filePath,
394
+ options,
395
+ ),
396
+ compressors: await processMap(
397
+ configFile.compressors,
398
+ '/compressors',
399
+ configFile.filePath,
400
+ options,
401
+ ),
402
+ reporters: processPipeline(
403
+ options,
404
+ configFile.reporters,
405
+ '/reporters',
406
+ configFile.filePath,
407
+ ),
408
+ validators: await processMap(
409
+ configFile.validators,
410
+ '/validators',
411
+ configFile.filePath,
412
+ options,
413
+ ),
414
+ };
415
+ }
416
+
417
+ export async function processConfigChain(
418
+ configFile: RawAtlaspackConfig | ResolvedAtlaspackConfigFile,
419
+ filePath: FilePath,
420
+ options: AtlaspackOptions,
421
+ ): Promise<AtlaspackConfigChain> {
422
+ // Validate config...
423
+ let relativePath = path.relative(options.inputFS.cwd(), filePath);
424
+ validateConfigFile(configFile, relativePath);
425
+
426
+ // Process config...
427
+ let config: ProcessedAtlaspackConfig = await processConfig(
428
+ {
429
+ filePath,
430
+ ...configFile,
431
+ },
432
+ options,
433
+ );
434
+
435
+ let extendedFiles: Array<FilePath> = [];
436
+ if (configFile.extends != null) {
437
+ let exts = Array.isArray(configFile.extends)
438
+ ? configFile.extends
439
+ : [configFile.extends];
440
+ let errors = [];
441
+ if (exts.length !== 0) {
442
+ let extStartConfig;
443
+ let i = 0;
444
+ for (let ext of exts) {
445
+ try {
446
+ let key = Array.isArray(configFile.extends)
447
+ ? `/extends/${i}`
448
+ : '/extends';
449
+ let resolved = await resolveExtends(ext, filePath, key, options);
450
+ extendedFiles.push(resolved);
451
+ let {extendedFiles: moreExtendedFiles, config: nextConfig} =
452
+ await processExtendedConfig(filePath, key, ext, resolved, options);
453
+ extendedFiles = extendedFiles.concat(moreExtendedFiles);
454
+ extStartConfig = extStartConfig
455
+ ? mergeConfigs(extStartConfig, nextConfig)
456
+ : nextConfig;
457
+ } catch (err) {
458
+ errors.push(err);
459
+ }
460
+
461
+ i++;
462
+ }
463
+
464
+ // Merge with the inline config last
465
+ if (extStartConfig) {
466
+ config = mergeConfigs(extStartConfig, config);
467
+ }
468
+ }
469
+
470
+ if (errors.length > 0) {
471
+ throw new ThrowableDiagnostic({
472
+ diagnostic: errors.flatMap(e => e.diagnostics ?? errorToDiagnostic(e)),
473
+ });
474
+ }
475
+ }
476
+
477
+ return {config, extendedFiles};
478
+ }
479
+
480
+ export async function resolveExtends(
481
+ ext: string,
482
+ configPath: FilePath,
483
+ extendsKey: string,
484
+ options: AtlaspackOptions,
485
+ ): Promise<FilePath> {
486
+ if (ext.startsWith('.')) {
487
+ return path.resolve(path.dirname(configPath), ext);
488
+ } else {
489
+ try {
490
+ let {resolved} = await options.packageManager.resolve(ext, configPath);
491
+ return options.inputFS.realpath(resolved);
492
+ } catch (err) {
493
+ let parentContents = await options.inputFS.readFile(configPath, 'utf8');
494
+ let alternatives = await findAlternativeNodeModules(
495
+ options.inputFS,
496
+ ext,
497
+ path.dirname(configPath),
498
+ );
499
+ throw new ThrowableDiagnostic({
500
+ diagnostic: {
501
+ message: `Cannot find extended atlaspack config`,
502
+ origin: '@atlaspack/core',
503
+ codeFrames: [
504
+ {
505
+ filePath: configPath,
506
+ language: 'json5',
507
+ code: parentContents,
508
+ codeHighlights: generateJSONCodeHighlights(parentContents, [
509
+ {
510
+ key: extendsKey,
511
+ type: 'value',
512
+ message: md`Cannot find module "${ext}"${
513
+ alternatives[0]
514
+ ? `, did you mean "${alternatives[0]}"?`
515
+ : ''
516
+ }`,
517
+ },
518
+ ]),
519
+ },
520
+ ],
521
+ },
522
+ });
523
+ }
524
+ }
525
+ }
526
+
527
+ async function processExtendedConfig(
528
+ configPath: FilePath,
529
+ extendsKey: string,
530
+ extendsSpecifier: string,
531
+ resolvedExtendedConfigPath: FilePath,
532
+ options: AtlaspackOptions,
533
+ ): Promise<AtlaspackConfigChain> {
534
+ let contents;
535
+ try {
536
+ contents = await options.inputFS.readFile(
537
+ resolvedExtendedConfigPath,
538
+ 'utf8',
539
+ );
540
+ } catch (e) {
541
+ let parentContents = await options.inputFS.readFile(configPath, 'utf8');
542
+ let alternatives = await findAlternativeFiles(
543
+ options.inputFS,
544
+ extendsSpecifier,
545
+ path.dirname(resolvedExtendedConfigPath),
546
+ options.projectRoot,
547
+ );
548
+ throw new ThrowableDiagnostic({
549
+ diagnostic: {
550
+ message: 'Cannot find extended atlaspack config',
551
+ origin: '@atlaspack/core',
552
+ codeFrames: [
553
+ {
554
+ filePath: configPath,
555
+ language: 'json5',
556
+ code: parentContents,
557
+ codeHighlights: generateJSONCodeHighlights(parentContents, [
558
+ {
559
+ key: extendsKey,
560
+ type: 'value',
561
+ message: md`"${extendsSpecifier}" does not exist${
562
+ alternatives[0] ? `, did you mean "${alternatives[0]}"?` : ''
563
+ }`,
564
+ },
565
+ ]),
566
+ },
567
+ ],
568
+ },
569
+ });
570
+ }
571
+
572
+ return parseAndProcessConfig(resolvedExtendedConfigPath, contents, options);
573
+ }
574
+
575
+ export function validateConfigFile(
576
+ config: RawAtlaspackConfig | ResolvedAtlaspackConfigFile,
577
+ relativePath: FilePath,
578
+ ) {
579
+ try {
580
+ validateNotEmpty(config, relativePath);
581
+ } catch (e) {
582
+ throw new ThrowableDiagnostic({
583
+ diagnostic: {
584
+ message: e.message,
585
+ origin: '@atlaspack/core',
586
+ },
587
+ });
588
+ }
589
+
590
+ validateSchema.diagnostic(
591
+ AtlaspackConfigSchema,
592
+ {data: config, filePath: relativePath},
593
+ '@atlaspack/core',
594
+ 'Invalid Atlaspack Config',
595
+ );
596
+ }
597
+
598
+ export function validateNotEmpty(
599
+ config: RawAtlaspackConfig | ResolvedAtlaspackConfigFile,
600
+ relativePath: FilePath,
601
+ ) {
602
+ invariant.notDeepStrictEqual(config, {}, `${relativePath} can't be empty`);
603
+ }
604
+
605
+ export function mergeConfigs(
606
+ base: ProcessedAtlaspackConfig,
607
+ ext: ProcessedAtlaspackConfig,
608
+ ): ProcessedAtlaspackConfig {
609
+ return {
610
+ filePath: ext.filePath,
611
+ resolvers: assertPurePipeline(
612
+ mergePipelines(base.resolvers, ext.resolvers),
613
+ ),
614
+ transformers: mergeMaps(
615
+ base.transformers,
616
+ ext.transformers,
617
+ mergePipelines,
618
+ ),
619
+ validators: mergeMaps(base.validators, ext.validators, mergePipelines),
620
+ bundler: ext.bundler || base.bundler,
621
+ namers: assertPurePipeline(mergePipelines(base.namers, ext.namers)),
622
+ runtimes: assertPurePipeline(mergePipelines(base.runtimes, ext.runtimes)),
623
+ packagers: mergeMaps(base.packagers, ext.packagers),
624
+ optimizers: mergeMaps(base.optimizers, ext.optimizers, mergePipelines),
625
+ compressors: mergeMaps(base.compressors, ext.compressors, mergePipelines),
626
+ reporters: assertPurePipeline(
627
+ mergePipelines(base.reporters, ext.reporters),
628
+ ),
629
+ };
630
+ }
631
+
632
+ export function getResolveFrom(
633
+ fs: FileSystem,
634
+ projectRoot: FilePath,
635
+ ): FilePath {
636
+ let cwd = fs.cwd();
637
+ let dir = isDirectoryInside(cwd, projectRoot) ? cwd : projectRoot;
638
+ return path.join(dir, 'index');
639
+ }
640
+
641
+ function assertPurePipeline(
642
+ pipeline: ExtendableAtlaspackConfigPipeline,
643
+ ): PureAtlaspackConfigPipeline {
644
+ return pipeline.map(s => {
645
+ invariant(typeof s !== 'string');
646
+ return s;
647
+ });
648
+ }
649
+
650
+ export function mergePipelines(
651
+ base: ?ExtendableAtlaspackConfigPipeline,
652
+ ext: ?ExtendableAtlaspackConfigPipeline,
653
+ ): ExtendableAtlaspackConfigPipeline {
654
+ if (ext == null) {
655
+ return base ?? [];
656
+ }
657
+
658
+ if (ext.filter(v => v === '...').length > 1) {
659
+ throw new Error(
660
+ 'Only one spread element can be included in a config pipeline',
661
+ );
662
+ }
663
+
664
+ // Merge the base pipeline if a rest element is defined
665
+ let spreadIndex = ext.indexOf('...');
666
+ if (spreadIndex >= 0) {
667
+ return [
668
+ ...ext.slice(0, spreadIndex),
669
+ ...(base ?? []),
670
+ ...ext.slice(spreadIndex + 1),
671
+ ];
672
+ } else {
673
+ return ext;
674
+ }
675
+ }
676
+
677
+ export function mergeMaps<K: string, V>(
678
+ base: ?ConfigMap<K, V>,
679
+ ext: ?ConfigMap<K, V>,
680
+ merger?: (a: V, b: V) => V,
681
+ ): ConfigMap<K, V> {
682
+ if (!ext || Object.keys(ext).length === 0) {
683
+ return base || {};
684
+ }
685
+
686
+ if (!base) {
687
+ return ext;
688
+ }
689
+
690
+ let res: ConfigMap<K, V> = {};
691
+ // Add the extension options first so they have higher precedence in the output glob map
692
+ for (let k in ext) {
693
+ //$FlowFixMe Flow doesn't correctly infer the type. See https://github.com/facebook/flow/issues/1736.
694
+ let key: K = (k: any);
695
+ res[key] =
696
+ merger && base[key] != null ? merger(base[key], ext[key]) : ext[key];
697
+ }
698
+
699
+ // Add base options that aren't defined in the extension
700
+ for (let k in base) {
701
+ // $FlowFixMe
702
+ let key: K = (k: any);
703
+ if (res[key] == null) {
704
+ res[key] = base[key];
705
+ }
706
+ }
707
+
708
+ return res;
709
+ }