@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,490 @@
1
+ // @flow
2
+ import type {
3
+ Glob,
4
+ Transformer,
5
+ Resolver,
6
+ Bundler,
7
+ Namer,
8
+ Runtime,
9
+ PackageName,
10
+ Optimizer,
11
+ Compressor,
12
+ Packager,
13
+ Reporter,
14
+ Semver,
15
+ SemverRange,
16
+ Validator,
17
+ FilePath,
18
+ } from '@atlaspack/types';
19
+ import type {
20
+ ProcessedAtlaspackConfig,
21
+ AtlaspackPluginNode,
22
+ PureAtlaspackConfigPipeline,
23
+ ExtendableAtlaspackConfigPipeline,
24
+ AtlaspackOptions,
25
+ } from './types';
26
+ import ThrowableDiagnostic, {
27
+ md,
28
+ generateJSONCodeHighlights,
29
+ } from '@atlaspack/diagnostic';
30
+ import json5 from 'json5';
31
+
32
+ import {globToRegex} from '@atlaspack/utils';
33
+ import {basename} from 'path';
34
+ import loadPlugin from './loadAtlaspackPlugin';
35
+ import {
36
+ type ProjectPath,
37
+ fromProjectPath,
38
+ fromProjectPathRelative,
39
+ toProjectPathUnsafe,
40
+ } from './projectPath';
41
+
42
+ type GlobMap<T> = {[Glob]: T, ...};
43
+ type SerializedAtlaspackConfig = {|
44
+ $$raw: boolean,
45
+ config: ProcessedAtlaspackConfig,
46
+ options: AtlaspackOptions,
47
+ |};
48
+
49
+ export type LoadedPlugin<T> = {|
50
+ name: string,
51
+ version: Semver,
52
+ plugin: T,
53
+ resolveFrom: ProjectPath,
54
+ keyPath?: string,
55
+ range?: ?SemverRange,
56
+ |};
57
+
58
+ export default class AtlaspackConfig {
59
+ options: AtlaspackOptions;
60
+ filePath: ProjectPath;
61
+ resolvers: PureAtlaspackConfigPipeline;
62
+ transformers: GlobMap<ExtendableAtlaspackConfigPipeline>;
63
+ bundler: ?AtlaspackPluginNode;
64
+ namers: PureAtlaspackConfigPipeline;
65
+ runtimes: PureAtlaspackConfigPipeline;
66
+ packagers: GlobMap<AtlaspackPluginNode>;
67
+ validators: GlobMap<ExtendableAtlaspackConfigPipeline>;
68
+ optimizers: GlobMap<ExtendableAtlaspackConfigPipeline>;
69
+ compressors: GlobMap<ExtendableAtlaspackConfigPipeline>;
70
+ reporters: PureAtlaspackConfigPipeline;
71
+ pluginCache: Map<PackageName, any>;
72
+ regexCache: Map<string, RegExp>;
73
+
74
+ constructor(config: ProcessedAtlaspackConfig, options: AtlaspackOptions) {
75
+ this.options = options;
76
+ this.filePath = config.filePath;
77
+ this.resolvers = config.resolvers || [];
78
+ this.transformers = config.transformers || {};
79
+ this.runtimes = config.runtimes || [];
80
+ this.bundler = config.bundler;
81
+ this.namers = config.namers || [];
82
+ this.packagers = config.packagers || {};
83
+ this.optimizers = config.optimizers || {};
84
+ this.compressors = config.compressors || {};
85
+ this.reporters = config.reporters || [];
86
+ this.validators = config.validators || {};
87
+ this.pluginCache = new Map();
88
+ this.regexCache = new Map();
89
+ }
90
+
91
+ static deserialize(serialized: SerializedAtlaspackConfig): AtlaspackConfig {
92
+ return new AtlaspackConfig(serialized.config, serialized.options);
93
+ }
94
+
95
+ getConfig(): ProcessedAtlaspackConfig {
96
+ return {
97
+ filePath: this.filePath,
98
+ resolvers: this.resolvers,
99
+ transformers: this.transformers,
100
+ validators: this.validators,
101
+ runtimes: this.runtimes,
102
+ bundler: this.bundler,
103
+ namers: this.namers,
104
+ packagers: this.packagers,
105
+ optimizers: this.optimizers,
106
+ compressors: this.compressors,
107
+ reporters: this.reporters,
108
+ };
109
+ }
110
+
111
+ serialize(): SerializedAtlaspackConfig {
112
+ return {
113
+ $$raw: false,
114
+ config: this.getConfig(),
115
+ options: this.options,
116
+ };
117
+ }
118
+
119
+ _loadPlugin<T>(node: AtlaspackPluginNode): Promise<{|
120
+ plugin: T,
121
+ version: Semver,
122
+ resolveFrom: ProjectPath,
123
+ range: ?SemverRange,
124
+ |}> {
125
+ let plugin = this.pluginCache.get(node.packageName);
126
+ if (plugin) {
127
+ return plugin;
128
+ }
129
+
130
+ plugin = loadPlugin<T>(
131
+ node.packageName,
132
+ fromProjectPath(this.options.projectRoot, node.resolveFrom),
133
+ node.keyPath,
134
+ this.options,
135
+ );
136
+
137
+ this.pluginCache.set(node.packageName, plugin);
138
+ return plugin;
139
+ }
140
+
141
+ async loadPlugin<T>(node: AtlaspackPluginNode): Promise<LoadedPlugin<T>> {
142
+ let plugin = await this._loadPlugin(node);
143
+ return {
144
+ ...plugin,
145
+ name: node.packageName,
146
+ keyPath: node.keyPath,
147
+ };
148
+ }
149
+
150
+ invalidatePlugin(packageName: PackageName) {
151
+ this.pluginCache.delete(packageName);
152
+ }
153
+
154
+ loadPlugins<T>(
155
+ plugins: PureAtlaspackConfigPipeline,
156
+ ): Promise<Array<LoadedPlugin<T>>> {
157
+ return Promise.all(plugins.map(p => this.loadPlugin<T>(p)));
158
+ }
159
+
160
+ async getResolvers(): Promise<Array<LoadedPlugin<Resolver<mixed>>>> {
161
+ if (this.resolvers.length === 0) {
162
+ throw await this.missingPluginError(
163
+ this.resolvers,
164
+ 'No resolver plugins specified in .atlaspackrc config',
165
+ '/resolvers',
166
+ );
167
+ }
168
+
169
+ return this.loadPlugins<Resolver<mixed>>(this.resolvers);
170
+ }
171
+
172
+ _getValidatorNodes(
173
+ filePath: ProjectPath,
174
+ ): $ReadOnlyArray<AtlaspackPluginNode> {
175
+ let validators: PureAtlaspackConfigPipeline =
176
+ this.matchGlobMapPipelines(filePath, this.validators) || [];
177
+
178
+ return validators;
179
+ }
180
+
181
+ getValidatorNames(filePath: ProjectPath): Array<string> {
182
+ let validators: PureAtlaspackConfigPipeline =
183
+ this._getValidatorNodes(filePath);
184
+ return validators.map(v => v.packageName);
185
+ }
186
+
187
+ getValidators(
188
+ filePath: ProjectPath,
189
+ ): Promise<Array<LoadedPlugin<Validator>>> {
190
+ let validators = this._getValidatorNodes(filePath);
191
+ return this.loadPlugins<Validator>(validators);
192
+ }
193
+
194
+ getNamedPipelines(): $ReadOnlyArray<string> {
195
+ return Object.keys(this.transformers)
196
+ .filter(glob => glob.includes(':'))
197
+ .map(glob => glob.split(':')[0]);
198
+ }
199
+
200
+ async getTransformers(
201
+ filePath: ProjectPath,
202
+ pipeline?: ?string,
203
+ allowEmpty?: boolean,
204
+ ): Promise<Array<LoadedPlugin<Transformer<mixed>>>> {
205
+ let transformers: PureAtlaspackConfigPipeline | null =
206
+ this.matchGlobMapPipelines(filePath, this.transformers, pipeline);
207
+ if (!transformers || transformers.length === 0) {
208
+ if (allowEmpty) {
209
+ return [];
210
+ }
211
+
212
+ throw await this.missingPluginError(
213
+ this.transformers,
214
+ md`No transformers found for __${fromProjectPathRelative(filePath)}__` +
215
+ (pipeline != null ? ` with pipeline: '${pipeline}'` : '') +
216
+ '.',
217
+ '/transformers',
218
+ );
219
+ }
220
+
221
+ return this.loadPlugins<Transformer<mixed>>(transformers);
222
+ }
223
+
224
+ async getBundler(): Promise<LoadedPlugin<Bundler<mixed>>> {
225
+ if (!this.bundler) {
226
+ throw await this.missingPluginError(
227
+ [],
228
+ 'No bundler specified in .atlaspackrc config',
229
+ '/bundler',
230
+ );
231
+ }
232
+
233
+ return this.loadPlugin<Bundler<mixed>>(this.bundler);
234
+ }
235
+
236
+ async getNamers(): Promise<Array<LoadedPlugin<Namer<mixed>>>> {
237
+ if (this.namers.length === 0) {
238
+ throw await this.missingPluginError(
239
+ this.namers,
240
+ 'No namer plugins specified in .atlaspackrc config',
241
+ '/namers',
242
+ );
243
+ }
244
+
245
+ return this.loadPlugins<Namer<mixed>>(this.namers);
246
+ }
247
+
248
+ getRuntimes(): Promise<Array<LoadedPlugin<Runtime<mixed>>>> {
249
+ if (!this.runtimes) {
250
+ return Promise.resolve([]);
251
+ }
252
+
253
+ return this.loadPlugins<Runtime<mixed>>(this.runtimes);
254
+ }
255
+
256
+ async getPackager(
257
+ filePath: FilePath,
258
+ ): Promise<LoadedPlugin<Packager<mixed, mixed>>> {
259
+ let packager = this.matchGlobMap(
260
+ toProjectPathUnsafe(filePath),
261
+ this.packagers,
262
+ );
263
+ if (!packager) {
264
+ throw await this.missingPluginError(
265
+ this.packagers,
266
+ md`No packager found for __${filePath}__.`,
267
+ '/packagers',
268
+ );
269
+ }
270
+ return this.loadPlugin<Packager<mixed, mixed>>(packager);
271
+ }
272
+
273
+ _getOptimizerNodes(
274
+ filePath: FilePath,
275
+ pipeline: ?string,
276
+ ): PureAtlaspackConfigPipeline {
277
+ // If a pipeline is specified, but it doesn't exist in the optimizers config, ignore it.
278
+ // Pipelines for bundles come from their entry assets, so the pipeline likely exists in transformers.
279
+ if (pipeline) {
280
+ let prefix = pipeline + ':';
281
+ if (!Object.keys(this.optimizers).some(glob => glob.startsWith(prefix))) {
282
+ pipeline = null;
283
+ }
284
+ }
285
+
286
+ return (
287
+ this.matchGlobMapPipelines(
288
+ toProjectPathUnsafe(filePath),
289
+ this.optimizers,
290
+ pipeline,
291
+ ) ?? []
292
+ );
293
+ }
294
+
295
+ getOptimizerNames(filePath: FilePath, pipeline: ?string): Array<string> {
296
+ let optimizers = this._getOptimizerNodes(filePath, pipeline);
297
+ return optimizers.map(o => o.packageName);
298
+ }
299
+
300
+ getOptimizers(
301
+ filePath: FilePath,
302
+ pipeline: ?string,
303
+ ): Promise<Array<LoadedPlugin<Optimizer<mixed, mixed>>>> {
304
+ let optimizers = this._getOptimizerNodes(filePath, pipeline);
305
+ if (optimizers.length === 0) {
306
+ return Promise.resolve([]);
307
+ }
308
+
309
+ return this.loadPlugins<Optimizer<mixed, mixed>>(optimizers);
310
+ }
311
+
312
+ async getCompressors(
313
+ filePath: FilePath,
314
+ ): Promise<Array<LoadedPlugin<Compressor>>> {
315
+ let compressors =
316
+ this.matchGlobMapPipelines(
317
+ toProjectPathUnsafe(filePath),
318
+ this.compressors,
319
+ ) ?? [];
320
+
321
+ if (compressors.length === 0) {
322
+ throw await this.missingPluginError(
323
+ this.compressors,
324
+ md`No compressors found for __${filePath}__.`,
325
+ '/compressors',
326
+ );
327
+ }
328
+
329
+ return this.loadPlugins<Compressor>(compressors);
330
+ }
331
+
332
+ getReporters(): Promise<Array<LoadedPlugin<Reporter>>> {
333
+ return this.loadPlugins<Reporter>(this.reporters);
334
+ }
335
+
336
+ isGlobMatch(
337
+ projectPath: ProjectPath,
338
+ pattern: Glob,
339
+ pipeline?: ?string,
340
+ ): boolean {
341
+ // glob's shouldn't be dependant on absolute paths anyway
342
+ let filePath = fromProjectPathRelative(projectPath);
343
+
344
+ let [patternPipeline, patternGlob] = pattern.split(':');
345
+ if (!patternGlob) {
346
+ patternGlob = patternPipeline;
347
+ patternPipeline = null;
348
+ }
349
+
350
+ let re = this.regexCache.get(patternGlob);
351
+ if (!re) {
352
+ re = globToRegex(patternGlob, {dot: true, nocase: true});
353
+ this.regexCache.set(patternGlob, re);
354
+ }
355
+
356
+ return (
357
+ (pipeline === patternPipeline || (!pipeline && !patternPipeline)) &&
358
+ (re.test(filePath) || re.test(basename(filePath)))
359
+ );
360
+ }
361
+
362
+ matchGlobMap<T>(filePath: ProjectPath, globMap: {|[Glob]: T|}): ?T {
363
+ for (let pattern in globMap) {
364
+ if (this.isGlobMatch(filePath, pattern)) {
365
+ return globMap[pattern];
366
+ }
367
+ }
368
+
369
+ return null;
370
+ }
371
+
372
+ matchGlobMapPipelines(
373
+ filePath: ProjectPath,
374
+ globMap: {|[Glob]: ExtendableAtlaspackConfigPipeline|},
375
+ pipeline?: ?string,
376
+ ): PureAtlaspackConfigPipeline {
377
+ let matches = [];
378
+ if (pipeline) {
379
+ // If a pipeline is requested, a the glob needs to match exactly
380
+ let exactMatch;
381
+ for (let pattern in globMap) {
382
+ if (this.isGlobMatch(filePath, pattern, pipeline)) {
383
+ exactMatch = globMap[pattern];
384
+ break;
385
+ }
386
+ }
387
+ if (!exactMatch) {
388
+ return [];
389
+ } else {
390
+ matches.push(exactMatch);
391
+ }
392
+ }
393
+
394
+ for (let pattern in globMap) {
395
+ if (this.isGlobMatch(filePath, pattern)) {
396
+ matches.push(globMap[pattern]);
397
+ }
398
+ }
399
+
400
+ let flatten = () => {
401
+ let pipeline = matches.shift() || [];
402
+ let spreadIndex = pipeline.indexOf('...');
403
+ if (spreadIndex >= 0) {
404
+ pipeline = [
405
+ ...pipeline.slice(0, spreadIndex),
406
+ ...flatten(),
407
+ ...pipeline.slice(spreadIndex + 1),
408
+ ];
409
+ }
410
+
411
+ if (pipeline.includes('...')) {
412
+ throw new Error(
413
+ 'Only one spread parameter can be included in a config pipeline',
414
+ );
415
+ }
416
+
417
+ return pipeline;
418
+ };
419
+
420
+ let res = flatten();
421
+ // $FlowFixMe afaik this should work
422
+ return res;
423
+ }
424
+
425
+ async missingPluginError(
426
+ plugins:
427
+ | GlobMap<ExtendableAtlaspackConfigPipeline>
428
+ | GlobMap<AtlaspackPluginNode>
429
+ | PureAtlaspackConfigPipeline,
430
+ message: string,
431
+ key: string,
432
+ ): Promise<ThrowableDiagnostic> {
433
+ let configsWithPlugin;
434
+ if (Array.isArray(plugins)) {
435
+ configsWithPlugin = new Set(getConfigPaths(this.options, plugins));
436
+ } else {
437
+ configsWithPlugin = new Set(
438
+ Object.keys(plugins).flatMap(k =>
439
+ Array.isArray(plugins[k])
440
+ ? getConfigPaths(this.options, plugins[k])
441
+ : [getConfigPath(this.options, plugins[k])],
442
+ ),
443
+ );
444
+ }
445
+
446
+ if (configsWithPlugin.size === 0) {
447
+ configsWithPlugin.add(
448
+ fromProjectPath(this.options.projectRoot, this.filePath),
449
+ );
450
+ }
451
+
452
+ let seenKey = false;
453
+ let codeFrames = await Promise.all(
454
+ [...configsWithPlugin].map(async filePath => {
455
+ let configContents = await this.options.inputFS.readFile(
456
+ filePath,
457
+ 'utf8',
458
+ );
459
+ if (!json5.parse(configContents)[key.slice(1)]) {
460
+ key = '';
461
+ } else {
462
+ seenKey = true;
463
+ }
464
+ return {
465
+ filePath,
466
+ code: configContents,
467
+ codeHighlights: generateJSONCodeHighlights(configContents, [{key}]),
468
+ };
469
+ }),
470
+ );
471
+ return new ThrowableDiagnostic({
472
+ diagnostic: {
473
+ message,
474
+ origin: '@atlaspack/core',
475
+ codeFrames,
476
+ hints: !seenKey ? ['Try extending __@atlaspack/config-default__'] : [],
477
+ },
478
+ });
479
+ }
480
+ }
481
+
482
+ function getConfigPaths(options, nodes) {
483
+ return nodes
484
+ .map(node => (node !== '...' ? getConfigPath(options, node) : null))
485
+ .filter(Boolean);
486
+ }
487
+
488
+ function getConfigPath(options, node) {
489
+ return fromProjectPath(options.projectRoot, node.resolveFrom);
490
+ }
@@ -0,0 +1,141 @@
1
+ // @flow strict-local
2
+ import type {PackageName} from '@atlaspack/types';
3
+ import type {SchemaEntity} from '@atlaspack/utils';
4
+ import assert from 'assert';
5
+
6
+ // Reasoning behind this validation:
7
+ // https://github.com/parcel-bundler/parcel/issues/3397#issuecomment-521353931
8
+ export function validatePackageName(
9
+ pkg: ?PackageName,
10
+ pluginType: string,
11
+ key: string,
12
+ ) {
13
+ // $FlowFixMe
14
+ if (!pkg) {
15
+ return;
16
+ }
17
+
18
+ assert(typeof pkg === 'string', `"${key}" must be a string`);
19
+
20
+ if (pkg.startsWith('@atlaspack')) {
21
+ assert(
22
+ pkg.replace(/^@atlaspack\//, '').startsWith(`${pluginType}-`),
23
+ `Official atlaspack ${pluginType} packages must be named according to "@atlaspack/${pluginType}-{name}"`,
24
+ );
25
+ } else if (pkg.startsWith('@')) {
26
+ // Disabling this validation to allow for migration to atlaspack
27
+ // let [scope, name] = pkg.split('/');
28
+ // assert(
29
+ // name.startsWith(`atlaspack-${pluginType}-`) ||
30
+ // name === `atlaspack-${pluginType}` ||
31
+ // name.startsWith(`parcel-${pluginType}-`) ||
32
+ // name === `parcel-${pluginType}`,
33
+ // `Scoped atlaspack ${pluginType} packages must be named according to "${scope}/atlaspack-${pluginType}[-{name}]"`,
34
+ // );
35
+ } else if (!pkg.startsWith('.')) {
36
+ assert(
37
+ pkg.startsWith(`atlaspack-${pluginType}-`),
38
+ `Atlaspack ${pluginType} packages must be named according to "atlaspack-${pluginType}-{name}"`,
39
+ );
40
+ }
41
+ }
42
+
43
+ const validatePluginName = (pluginType: string, key: string) => {
44
+ return (val: string) => {
45
+ // allow plugin spread...
46
+ if (val === '...') return;
47
+
48
+ try {
49
+ validatePackageName(val, pluginType, key);
50
+ } catch (e) {
51
+ return e.message;
52
+ }
53
+ };
54
+ };
55
+
56
+ const validateExtends = (val: string): void => {
57
+ // allow relative paths...
58
+ if (val.startsWith('.')) return;
59
+
60
+ try {
61
+ validatePackageName(val, 'config', 'extends');
62
+ } catch (e) {
63
+ return e.message;
64
+ }
65
+ };
66
+
67
+ const pipelineSchema = (pluginType: string, key: string): SchemaEntity => {
68
+ return {
69
+ type: 'array',
70
+ items: {
71
+ type: 'string',
72
+ __validate: validatePluginName(pluginType, key),
73
+ },
74
+ };
75
+ };
76
+
77
+ const mapPipelineSchema = (pluginType: string, key: string): SchemaEntity => {
78
+ return {
79
+ type: 'object',
80
+ properties: {},
81
+ additionalProperties: pipelineSchema(pluginType, key),
82
+ };
83
+ };
84
+
85
+ const mapStringSchema = (pluginType: string, key: string): SchemaEntity => {
86
+ return {
87
+ type: 'object',
88
+ properties: {},
89
+ additionalProperties: {
90
+ type: 'string',
91
+ __validate: validatePluginName(pluginType, key),
92
+ },
93
+ };
94
+ };
95
+
96
+ export default {
97
+ type: 'object',
98
+ properties: {
99
+ $schema: {
100
+ type: 'string',
101
+ },
102
+ extends: {
103
+ oneOf: [
104
+ {
105
+ type: 'string',
106
+ __validate: validateExtends,
107
+ },
108
+ {
109
+ type: 'array',
110
+ items: {
111
+ type: 'string',
112
+ __validate: validateExtends,
113
+ },
114
+ },
115
+ ],
116
+ },
117
+ bundler: {
118
+ type: 'string',
119
+ __validate: (validatePluginName('bundler', 'bundler'): string => void),
120
+ },
121
+ resolvers: (pipelineSchema('resolver', 'resolvers'): SchemaEntity),
122
+ transformers: (mapPipelineSchema(
123
+ 'transformer',
124
+ 'transformers',
125
+ ): SchemaEntity),
126
+ validators: (mapPipelineSchema('validator', 'validators'): SchemaEntity),
127
+ namers: (pipelineSchema('namer', 'namers'): SchemaEntity),
128
+ packagers: (mapStringSchema('packager', 'packagers'): SchemaEntity),
129
+ optimizers: (mapPipelineSchema('optimizer', 'optimizers'): SchemaEntity),
130
+ compressors: (mapPipelineSchema('compressor', 'compressors'): SchemaEntity),
131
+ reporters: (pipelineSchema('reporter', 'reporters'): SchemaEntity),
132
+ runtimes: (pipelineSchema('runtime', 'runtimes'): SchemaEntity),
133
+ filePath: {
134
+ type: 'string',
135
+ },
136
+ resolveFrom: {
137
+ type: 'string',
138
+ },
139
+ },
140
+ additionalProperties: false,
141
+ };