1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.loadConfiguration = exports.createConfiguration = exports.validatePluginLoadResult = exports.expandCliFlags = exports.DEFAULT_PACKAGES_LOCAL_CONFIG = void 0;
|
7 | const deepmerge_1 = require("deepmerge");
|
8 | const fs_1 = require("fs");
|
9 | const is_plain_object_1 = require("is-plain-object");
|
10 | const jsonschema_1 = require("jsonschema");
|
11 | const colors_1 = require("kleur/colors");
|
12 | const os_1 = __importDefault(require("os"));
|
13 | const path_1 = __importDefault(require("path"));
|
14 | const logger_1 = require("./logger");
|
15 | const plugin_esbuild_1 = require("./plugins/plugin-esbuild");
|
16 | const util_1 = require("./util");
|
17 | const CONFIG_NAME = 'snowpack';
|
18 | const ALWAYS_EXCLUDE = ['**/node_modules/**/*'];
|
19 |
|
20 | const DEFAULT_ROOT = process.cwd();
|
21 | const DEFAULT_CONFIG = {
|
22 | root: DEFAULT_ROOT,
|
23 | plugins: [],
|
24 | alias: {},
|
25 | exclude: [],
|
26 | routes: [],
|
27 | devOptions: {
|
28 | secure: false,
|
29 | hostname: 'localhost',
|
30 | port: 8080,
|
31 | open: 'default',
|
32 | output: 'dashboard',
|
33 | hmrDelay: 0,
|
34 | hmrPort: undefined,
|
35 | hmrErrorOverlay: true,
|
36 | },
|
37 | buildOptions: {
|
38 | out: 'build',
|
39 | baseUrl: '/',
|
40 | metaUrlPath: '_snowpack',
|
41 | clean: true,
|
42 | sourcemap: false,
|
43 | watch: false,
|
44 | htmlFragments: false,
|
45 | ssr: false,
|
46 | },
|
47 | testOptions: {
|
48 | files: ['__tests__/**/*', '**/*.@(spec|test).*'],
|
49 | },
|
50 | packageOptions: { source: 'local' },
|
51 | };
|
52 | exports.DEFAULT_PACKAGES_LOCAL_CONFIG = {
|
53 | source: 'local',
|
54 | external: [],
|
55 | packageLookupFields: [],
|
56 | knownEntrypoints: [],
|
57 | };
|
58 | const REMOTE_PACKAGE_ORIGIN = 'https://pkg.snowpack.dev';
|
59 | const DEFAULT_PACKAGES_REMOTE_CONFIG = {
|
60 | source: 'remote',
|
61 | origin: REMOTE_PACKAGE_ORIGIN,
|
62 | external: [],
|
63 | cache: '.snowpack',
|
64 | types: false,
|
65 | };
|
66 | const configSchema = {
|
67 | type: 'object',
|
68 | properties: {
|
69 | extends: { type: 'string' },
|
70 | exclude: { type: 'array', items: { type: 'string' } },
|
71 | plugins: { type: 'array' },
|
72 | alias: {
|
73 | type: 'object',
|
74 | additionalProperties: { type: 'string' },
|
75 | },
|
76 | mount: {
|
77 | type: 'object',
|
78 | additionalProperties: {
|
79 | oneOf: [
|
80 | { type: 'string' },
|
81 | {
|
82 | type: ['object'],
|
83 | properties: {
|
84 | url: { type: 'string' },
|
85 | static: { type: 'boolean' },
|
86 | resolve: { type: 'boolean' },
|
87 | },
|
88 | },
|
89 | ],
|
90 | },
|
91 | },
|
92 | devOptions: {
|
93 | type: 'object',
|
94 | properties: {
|
95 | secure: { type: 'boolean' },
|
96 | port: { type: 'number' },
|
97 | bundle: { type: 'boolean' },
|
98 | open: { type: 'string' },
|
99 | output: { type: 'string', enum: ['stream', 'dashboard'] },
|
100 | hmr: { type: 'boolean' },
|
101 | hmrDelay: { type: 'number' },
|
102 | hmrPort: { type: 'number' },
|
103 | hmrErrorOverlay: { type: 'boolean' },
|
104 | },
|
105 | },
|
106 | packageOptions: {
|
107 | type: 'object',
|
108 | properties: {
|
109 | dest: { type: 'string' },
|
110 | external: { type: 'array', items: { type: 'string' } },
|
111 | treeshake: { type: 'boolean' },
|
112 | installTypes: { type: 'boolean' },
|
113 | polyfillNode: { type: 'boolean' },
|
114 | env: {
|
115 | type: 'object',
|
116 | additionalProperties: {
|
117 | oneOf: [
|
118 | { id: 'EnvVarString', type: 'string' },
|
119 | { id: 'EnvVarNumber', type: 'number' },
|
120 | { id: 'EnvVarTrue', type: 'boolean', enum: [true] },
|
121 | ],
|
122 | },
|
123 | },
|
124 | rollup: {
|
125 | type: 'object',
|
126 | properties: {
|
127 | context: { type: 'string' },
|
128 | plugins: { type: 'array', items: { type: 'object' } },
|
129 | dedupe: {
|
130 | type: 'array',
|
131 | items: { type: 'string' },
|
132 | },
|
133 | },
|
134 | },
|
135 | },
|
136 | },
|
137 | buildOptions: {
|
138 | type: ['object'],
|
139 | properties: {
|
140 | out: { type: 'string' },
|
141 | baseUrl: { type: 'string' },
|
142 | clean: { type: 'boolean' },
|
143 | sourcemap: { type: 'boolean' },
|
144 | watch: { type: 'boolean' },
|
145 | ssr: { type: 'boolean' },
|
146 | htmlFragments: { type: 'boolean' },
|
147 | jsxFactory: { type: 'string' },
|
148 | jsxFragment: { type: 'string' },
|
149 | },
|
150 | },
|
151 | testOptions: {
|
152 | type: 'object',
|
153 | properties: {
|
154 | files: { type: 'array', items: { type: 'string' } },
|
155 | },
|
156 | },
|
157 | experiments: {
|
158 | type: ['object'],
|
159 | properties: {},
|
160 | },
|
161 | optimize: {
|
162 | type: ['object'],
|
163 | properties: {},
|
164 | },
|
165 | proxy: {
|
166 | type: 'object',
|
167 | },
|
168 | },
|
169 | };
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | function expandCliFlags(flags) {
|
177 | const result = {
|
178 | packageOptions: {},
|
179 | devOptions: {},
|
180 | buildOptions: {},
|
181 | experiments: {},
|
182 | };
|
183 | const { help, version, reload, config, ...relevantFlags } = flags;
|
184 | const CLI_ONLY_FLAGS = ['quiet', 'verbose'];
|
185 | for (const [flag, val] of Object.entries(relevantFlags)) {
|
186 | if (flag === '_' || flag.includes('-')) {
|
187 | continue;
|
188 | }
|
189 | if (configSchema.properties[flag]) {
|
190 | result[flag] = val;
|
191 | continue;
|
192 | }
|
193 | if (flag === 'source') {
|
194 | result.packageOptions = { source: val };
|
195 | continue;
|
196 | }
|
197 | if (configSchema.properties.experiments.properties[flag]) {
|
198 | result.experiments[flag] = val;
|
199 | continue;
|
200 | }
|
201 | if (configSchema.properties.optimize.properties[flag]) {
|
202 | result.optimize = result.optimize || {};
|
203 | result.optimize[flag] = val;
|
204 | continue;
|
205 | }
|
206 | if (configSchema.properties.packageOptions.properties[flag]) {
|
207 | result.packageOptions[flag] = val;
|
208 | continue;
|
209 | }
|
210 | if (configSchema.properties.devOptions.properties[flag]) {
|
211 | result.devOptions[flag] = val;
|
212 | continue;
|
213 | }
|
214 | if (configSchema.properties.buildOptions.properties[flag]) {
|
215 | result.buildOptions[flag] = val;
|
216 | continue;
|
217 | }
|
218 | if (CLI_ONLY_FLAGS.includes(flag)) {
|
219 | continue;
|
220 | }
|
221 | logger_1.logger.error(`Unknown CLI flag: "${flag}"`);
|
222 | process.exit(1);
|
223 | }
|
224 | if (result.packageOptions.env) {
|
225 | result.packageOptions.env = result.packageOptions.env.reduce((acc, id) => {
|
226 | const index = id.indexOf('=');
|
227 | const [key, val] = index > 0 ? [id.substr(0, index), id.substr(index + 1)] : [id, true];
|
228 | acc[key] = val;
|
229 | return acc;
|
230 | }, {});
|
231 | }
|
232 | return result;
|
233 | }
|
234 | exports.expandCliFlags = expandCliFlags;
|
235 |
|
236 | function loadPlugins(config) {
|
237 | const plugins = [];
|
238 | function execPluginFactory(pluginFactory, pluginOptions = {}) {
|
239 | let plugin = null;
|
240 | plugin = pluginFactory(config, pluginOptions);
|
241 | return plugin;
|
242 | }
|
243 | function loadPluginFromConfig(pluginLoc, options) {
|
244 | if (!path_1.default.isAbsolute(pluginLoc)) {
|
245 | throw new Error(`Snowpack Internal Error: plugin ${pluginLoc} should have been resolved to an absolute path.`);
|
246 | }
|
247 | const pluginRef = util_1.NATIVE_REQUIRE(pluginLoc);
|
248 | let plugin;
|
249 | try {
|
250 | plugin = typeof pluginRef.default === 'function' ? pluginRef.default : pluginRef;
|
251 | if (typeof plugin !== 'function')
|
252 | logger_1.logger.error(`plugin ${pluginLoc} must export a function.`);
|
253 | plugin = execPluginFactory(plugin, options);
|
254 | }
|
255 | catch (err) {
|
256 | logger_1.logger.error(err.toString());
|
257 | throw err;
|
258 | }
|
259 | if (!plugin.name) {
|
260 | plugin.name = path_1.default.relative(process.cwd(), pluginLoc);
|
261 | }
|
262 |
|
263 |
|
264 | plugin.markChanged = (file) => {
|
265 | logger_1.logger.debug(`clearCache(${file}) called, but function not yet hooked up.`, {
|
266 | name: plugin.name,
|
267 | });
|
268 | };
|
269 |
|
270 | validatePlugin(plugin);
|
271 | return plugin;
|
272 | }
|
273 |
|
274 | config.plugins.forEach((ref) => {
|
275 | const pluginName = Array.isArray(ref) ? ref[0] : ref;
|
276 | const pluginOptions = Array.isArray(ref) ? ref[1] : {};
|
277 | const plugin = loadPluginFromConfig(pluginName, pluginOptions);
|
278 | logger_1.logger.debug(`loaded plugin: ${pluginName}`);
|
279 | plugins.push(plugin);
|
280 | });
|
281 |
|
282 | plugins.push(execPluginFactory(plugin_esbuild_1.esbuildPlugin, { input: ['.mjs', '.jsx', '.ts', '.tsx'] }));
|
283 | const extensionMap = plugins.reduce((map, { resolve }) => {
|
284 | if (resolve) {
|
285 | for (const inputExt of resolve.input) {
|
286 | map[inputExt] = resolve.output;
|
287 | }
|
288 | }
|
289 | return map;
|
290 | }, {});
|
291 | return {
|
292 | plugins,
|
293 | extensionMap,
|
294 | };
|
295 | }
|
296 | function normalizeMount(config) {
|
297 | var _a, _b;
|
298 | const mountedDirs = config.mount || {};
|
299 | const normalizedMount = {};
|
300 | for (const [mountDir, rawMountEntry] of Object.entries(mountedDirs)) {
|
301 | const mountEntry = typeof rawMountEntry === 'string'
|
302 | ? { url: rawMountEntry, static: false, resolve: true }
|
303 | : rawMountEntry;
|
304 | if (!mountEntry.url) {
|
305 | handleConfigError(`mount[${mountDir}]: Object "${mountEntry.url}" missing required "url" option.`);
|
306 | return normalizedMount;
|
307 | }
|
308 | if (mountEntry.url[0] !== '/') {
|
309 | handleConfigError(`mount[${mountDir}]: Value "${mountEntry.url}" must be a URL path, and start with a "/"`);
|
310 | }
|
311 | normalizedMount[util_1.removeTrailingSlash(mountDir)] = {
|
312 | url: mountEntry.url === '/' ? '/' : util_1.removeTrailingSlash(mountEntry.url),
|
313 | static: (_a = mountEntry.static) !== null && _a !== void 0 ? _a : false,
|
314 | resolve: (_b = mountEntry.resolve) !== null && _b !== void 0 ? _b : true,
|
315 | };
|
316 | }
|
317 |
|
318 | if (!Object.keys(normalizedMount).length) {
|
319 | normalizedMount[process.cwd()] = {
|
320 | url: '/',
|
321 | static: false,
|
322 | resolve: true,
|
323 | };
|
324 | }
|
325 | return normalizedMount;
|
326 | }
|
327 | function normalizeRoutes(routes) {
|
328 | return routes.map(({ src, dest, match }, i) => {
|
329 |
|
330 | if (typeof dest === 'string') {
|
331 | dest = util_1.addLeadingSlash(dest);
|
332 | }
|
333 | if (!src.startsWith('^')) {
|
334 | src = '^' + src;
|
335 | }
|
336 | if (!src.endsWith('$')) {
|
337 | src = src + '$';
|
338 | }
|
339 |
|
340 | try {
|
341 | return { src, dest, match: match || 'all', _srcRegex: new RegExp(src) };
|
342 | }
|
343 | catch (err) {
|
344 | throw new Error(`config.routes[${i}].src: invalid regular expression syntax "${src}"`);
|
345 | }
|
346 | });
|
347 | }
|
348 |
|
349 | function normalizeConfig(_config) {
|
350 | var _a, _b, _c, _d, _e, _f, _g, _h;
|
351 |
|
352 |
|
353 |
|
354 | let config = _config;
|
355 | if (config.packageOptions.source === 'local') {
|
356 | config.packageOptions.rollup = config.packageOptions.rollup || {};
|
357 | config.packageOptions.rollup.plugins = config.packageOptions.rollup.plugins || [];
|
358 | }
|
359 | config.exclude = Array.from(new Set([...ALWAYS_EXCLUDE, `${config.buildOptions.out}/**/*`, ...config.exclude]));
|
360 |
|
361 | config.buildOptions.out = util_1.removeTrailingSlash(config.buildOptions.out);
|
362 | config.buildOptions.baseUrl = util_1.addTrailingSlash(config.buildOptions.baseUrl);
|
363 | config.buildOptions.metaUrlPath = util_1.removeTrailingSlash(util_1.addLeadingSlash(config.buildOptions.metaUrlPath));
|
364 | config.mount = normalizeMount(config);
|
365 | config.routes = normalizeRoutes(config.routes);
|
366 | if (config.optimize && JSON.stringify(config.optimize) !== '{}') {
|
367 | config.optimize = {
|
368 | entrypoints: (_a = config.optimize.entrypoints) !== null && _a !== void 0 ? _a : 'auto',
|
369 | preload: (_b = config.optimize.preload) !== null && _b !== void 0 ? _b : false,
|
370 | bundle: (_c = config.optimize.bundle) !== null && _c !== void 0 ? _c : false,
|
371 | splitting: (_d = config.optimize.splitting) !== null && _d !== void 0 ? _d : false,
|
372 | treeshake: (_e = config.optimize.treeshake) !== null && _e !== void 0 ? _e : true,
|
373 | manifest: (_f = config.optimize.manifest) !== null && _f !== void 0 ? _f : false,
|
374 | target: (_g = config.optimize.target) !== null && _g !== void 0 ? _g : 'es2020',
|
375 | minify: (_h = config.optimize.minify) !== null && _h !== void 0 ? _h : false,
|
376 | };
|
377 | }
|
378 | else {
|
379 | config.optimize = undefined;
|
380 | }
|
381 |
|
382 | const { plugins, extensionMap } = loadPlugins(config);
|
383 | config.plugins = plugins;
|
384 | config._extensionMap = extensionMap;
|
385 |
|
386 | for (const { knownEntrypoints } of config.plugins) {
|
387 | if (knownEntrypoints && config.packageOptions.source === 'local') {
|
388 | config.packageOptions.knownEntrypoints = config.packageOptions.knownEntrypoints.concat(knownEntrypoints);
|
389 | }
|
390 | }
|
391 | plugins.forEach((plugin) => {
|
392 | if (plugin.config) {
|
393 | plugin.config(config);
|
394 | }
|
395 | });
|
396 | return config;
|
397 | }
|
398 | function handleConfigError(msg) {
|
399 | logger_1.logger.error(msg);
|
400 | process.exit(1);
|
401 | }
|
402 | function handleValidationErrors(filepath, err) {
|
403 | logger_1.logger.error(`! ${filepath}\n${err.message}`);
|
404 | logger_1.logger.info(colors_1.dim(`See https://www.snowpack.dev for more info.`));
|
405 | process.exit(1);
|
406 | }
|
407 | function handleDeprecatedConfigError(mainMsg, ...msgs) {
|
408 | logger_1.logger.error(`${mainMsg}
|
409 | ${msgs.join('\n')}
|
410 | See https://www.snowpack.dev for more info.`);
|
411 | process.exit(1);
|
412 | }
|
413 | function valdiateDeprecatedConfig(rawConfig) {
|
414 | var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
415 | if (rawConfig.scripts) {
|
416 | handleDeprecatedConfigError('[v3.0] Legacy "scripts" config is deprecated in favor of "plugins". Safe to remove if empty.');
|
417 | }
|
418 | if (rawConfig.proxy) {
|
419 | handleDeprecatedConfigError('[v3.0] Legacy "proxy" config is deprecated in favor of "routes". Safe to remove if empty.');
|
420 | }
|
421 | if ((_a = rawConfig.buildOptions) === null || _a === void 0 ? void 0 : _a.metaDir) {
|
422 | handleDeprecatedConfigError('[v3.0] "config.buildOptions.metaDir" is now "config.buildOptions.metaUrlPath".');
|
423 | }
|
424 | if ((_b = rawConfig.buildOptions) === null || _b === void 0 ? void 0 : _b.webModulesUrl) {
|
425 | handleDeprecatedConfigError('[v3.0] "config.buildOptions.webModulesUrl" is now always set within the "config.buildOptions.metaUrlPath" directory.');
|
426 | }
|
427 | if ((_c = rawConfig.buildOptions) === null || _c === void 0 ? void 0 : _c.sourceMaps) {
|
428 | handleDeprecatedConfigError('[v3.0] "config.buildOptions.sourceMaps" is now "config.buildOptions.sourcemap".');
|
429 | }
|
430 | if (rawConfig.installOptions) {
|
431 | handleDeprecatedConfigError('[v3.0] "config.installOptions" is now "config.packageOptions". Safe to remove if empty.');
|
432 | }
|
433 | if ((_d = rawConfig.packageOptions) === null || _d === void 0 ? void 0 : _d.externalPackage) {
|
434 | handleDeprecatedConfigError('[v3.0] "config.installOptions.externalPackage" is now "config.packageOptions.external".');
|
435 | }
|
436 | if ((_e = rawConfig.packageOptions) === null || _e === void 0 ? void 0 : _e.treeshake) {
|
437 | handleDeprecatedConfigError('[v3.0] "config.installOptions.treeshake" is now "config.optimize.treeshake".');
|
438 | }
|
439 | if (rawConfig.install) {
|
440 | handleDeprecatedConfigError('[v3.0] "config.install" is now "config.packageOptions.knownEntrypoints". Safe to remove if empty.');
|
441 | }
|
442 | if ((_f = rawConfig.experiments) === null || _f === void 0 ? void 0 : _f.source) {
|
443 | handleDeprecatedConfigError('[v3.0] Experiment promoted! "config.experiments.source" is now "config.packageOptions.source".');
|
444 | }
|
445 | if (((_g = rawConfig.packageOptions) === null || _g === void 0 ? void 0 : _g.source) === 'skypack') {
|
446 | handleDeprecatedConfigError('[v3.0] Renamed! "config.experiments.source=skypack" is now "config.packageOptions.source=remote".');
|
447 | }
|
448 | if ((_h = rawConfig.experiments) === null || _h === void 0 ? void 0 : _h.ssr) {
|
449 | handleDeprecatedConfigError('[v3.0] Experiment promoted! "config.experiments.ssr" is now "config.buildOptions.ssr".');
|
450 | }
|
451 | if ((_j = rawConfig.experiments) === null || _j === void 0 ? void 0 : _j.optimize) {
|
452 | handleDeprecatedConfigError('[v3.0] Experiment promoted! "config.experiments.optimize" is now "config.optimize".');
|
453 | }
|
454 | if ((_k = rawConfig.experiments) === null || _k === void 0 ? void 0 : _k.routes) {
|
455 | handleDeprecatedConfigError('[v3.0] Experiment promoted! "config.experiments.routes" is now "config.routes".');
|
456 | }
|
457 | if ((_l = rawConfig.devOptions) === null || _l === void 0 ? void 0 : _l.fallback) {
|
458 | handleDeprecatedConfigError('[v3.0] Deprecated! "devOptions.fallback" is now replaced by "routes".\n' +
|
459 | 'More info: https://www.snowpack.dev/guides/routing');
|
460 | }
|
461 | }
|
462 | function validatePlugin(plugin) {
|
463 | const pluginName = plugin.name;
|
464 | if (plugin.resolve && !plugin.load) {
|
465 | handleConfigError(`[${pluginName}] "resolve" config found but "load()" method missing.`);
|
466 | }
|
467 | if (!plugin.resolve && plugin.load) {
|
468 | handleConfigError(`[${pluginName}] "load" method found but "resolve()" config missing.`);
|
469 | }
|
470 | if (plugin.resolve && !Array.isArray(plugin.resolve.input)) {
|
471 | handleConfigError(`[${pluginName}] "resolve.input" should be an array of input file extensions.`);
|
472 | }
|
473 | if (plugin.resolve && !Array.isArray(plugin.resolve.output)) {
|
474 | handleConfigError(`[${pluginName}] "resolve.output" should be an array of output file extensions.`);
|
475 | }
|
476 | }
|
477 | function validatePluginLoadResult(plugin, result) {
|
478 | const pluginName = plugin.name;
|
479 | if (!result) {
|
480 | return;
|
481 | }
|
482 | const isValidSingleResultType = typeof result === 'string' || Buffer.isBuffer(result);
|
483 | if (isValidSingleResultType && plugin.resolve.output.length !== 1) {
|
484 | handleConfigError(`[plugin=${pluginName}] "load()" returned a string, but "resolve.output" contains multiple possible outputs. If multiple outputs are expected, the object return format is required.`);
|
485 | }
|
486 | const unexpectedOutput = typeof result === 'object' &&
|
487 | Object.keys(result).find((fileExt) => !plugin.resolve.output.includes(fileExt));
|
488 | if (unexpectedOutput) {
|
489 | handleConfigError(`[plugin=${pluginName}] "load()" returned entry "${unexpectedOutput}" not found in "resolve.output": ${plugin.resolve.output}`);
|
490 | }
|
491 | }
|
492 | exports.validatePluginLoadResult = validatePluginLoadResult;
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 | function getConfigBasePath(configFileLoc, configRoot) {
|
500 | return ((configFileLoc && path_1.default.dirname(configFileLoc)) ||
|
501 | (configRoot && path_1.default.resolve(process.cwd(), configRoot)) ||
|
502 | process.cwd());
|
503 | }
|
504 | function resolveRelativeConfigAlias(aliasConfig, configBase) {
|
505 | const cleanAliasConfig = {};
|
506 | for (const [target, replacement] of Object.entries(aliasConfig)) {
|
507 | const isDirectory = target.endsWith('/');
|
508 | const isPath = replacement === '.' ||
|
509 | replacement === '..' ||
|
510 | replacement.startsWith('./') ||
|
511 | replacement.startsWith('../') ||
|
512 | replacement.startsWith('/');
|
513 | if (isPath) {
|
514 | cleanAliasConfig[target] = isDirectory
|
515 | ? util_1.addTrailingSlash(path_1.default.resolve(configBase, replacement))
|
516 | : util_1.removeTrailingSlash(path_1.default.resolve(configBase, replacement));
|
517 | }
|
518 | else {
|
519 | cleanAliasConfig[target] = replacement;
|
520 | }
|
521 | }
|
522 | return cleanAliasConfig;
|
523 | }
|
524 | function resolveRelativeConfigMount(mountConfig, configBase) {
|
525 | const cleanMountConfig = {};
|
526 | for (const [target, replacement] of Object.entries(mountConfig)) {
|
527 | cleanMountConfig[path_1.default.resolve(configBase, target)] = replacement;
|
528 | }
|
529 | return cleanMountConfig;
|
530 | }
|
531 | function resolveRelativeConfig(config, configBase) {
|
532 | var _a, _b;
|
533 | if (config.root) {
|
534 | config.root = path_1.default.resolve(configBase, config.root);
|
535 | }
|
536 | if ((_a = config.buildOptions) === null || _a === void 0 ? void 0 : _a.out) {
|
537 | config.buildOptions.out = path_1.default.resolve(configBase, config.buildOptions.out);
|
538 | }
|
539 | if (((_b = config.packageOptions) === null || _b === void 0 ? void 0 : _b.source) === 'remote' && config.packageOptions.cache) {
|
540 | config.packageOptions.cache = path_1.default.resolve(configBase, config.packageOptions.cache);
|
541 | }
|
542 | if (config.extends && /^[\.\/\\]/.test(config.extends)) {
|
543 | config.extends = path_1.default.resolve(configBase, config.extends);
|
544 | }
|
545 | if (config.plugins) {
|
546 | config.plugins = config.plugins.map((plugin) => {
|
547 | const name = Array.isArray(plugin) ? plugin[0] : plugin;
|
548 | const absName = path_1.default.isAbsolute(name) ? name : require.resolve(name, { paths: [configBase] });
|
549 | if (Array.isArray(plugin)) {
|
550 | plugin.splice(0, 1, absName);
|
551 | return plugin;
|
552 | }
|
553 | return absName;
|
554 | });
|
555 | }
|
556 | if (config.mount) {
|
557 | config.mount = resolveRelativeConfigMount(config.mount, configBase);
|
558 | }
|
559 | if (config.alias) {
|
560 | config.alias = resolveRelativeConfigAlias(config.alias, configBase);
|
561 | }
|
562 | return config;
|
563 | }
|
564 | class ConfigValidationError extends Error {
|
565 | constructor(errors) {
|
566 | super(`Configuration Error:\n${errors.map((err) => ` - ${err.toString()}`).join(os_1.default.EOL)}`);
|
567 | }
|
568 | }
|
569 | function validateConfig(config) {
|
570 | for (const mountDir of Object.keys(config.mount)) {
|
571 | if (!fs_1.existsSync(mountDir)) {
|
572 | logger_1.logger.warn(`config.mount[${mountDir}]: mounted directory does not exist.`);
|
573 | }
|
574 | }
|
575 | }
|
576 | function createConfiguration(config = {}) {
|
577 | var _a;
|
578 |
|
579 | const { errors: validationErrors } = jsonschema_1.validate(config, configSchema, {
|
580 | propertyName: CONFIG_NAME,
|
581 | allowUnknownAttributes: false,
|
582 | });
|
583 | if (validationErrors.length > 0) {
|
584 | throw new ConfigValidationError(validationErrors);
|
585 | }
|
586 |
|
587 |
|
588 |
|
589 | const mergedConfig = deepmerge_1.all([
|
590 | DEFAULT_CONFIG,
|
591 | {
|
592 | packageOptions: ((_a = config.packageOptions) === null || _a === void 0 ? void 0 : _a.source) === 'remote'
|
593 | ? DEFAULT_PACKAGES_REMOTE_CONFIG
|
594 | : exports.DEFAULT_PACKAGES_LOCAL_CONFIG,
|
595 | },
|
596 | config,
|
597 | ], {
|
598 | isMergeableObject: (val) => is_plain_object_1.isPlainObject(val) || Array.isArray(val),
|
599 | });
|
600 |
|
601 |
|
602 |
|
603 | const configBase = getConfigBasePath(undefined, config.root);
|
604 | resolveRelativeConfig(mergedConfig, configBase);
|
605 | const normalizedConfig = normalizeConfig(mergedConfig);
|
606 | validateConfig(normalizedConfig);
|
607 | return normalizedConfig;
|
608 | }
|
609 | exports.createConfiguration = createConfiguration;
|
610 | function loadConfigurationFile(filename) {
|
611 | const loc = path_1.default.resolve(process.cwd(), filename);
|
612 | if (!fs_1.existsSync(loc)) {
|
613 | return null;
|
614 | }
|
615 | return { filepath: loc, config: util_1.NATIVE_REQUIRE(loc) };
|
616 | }
|
617 | async function loadConfiguration(overrides = {}, configPath) {
|
618 | let result = null;
|
619 |
|
620 | if (configPath) {
|
621 | result = loadConfigurationFile(configPath);
|
622 | if (!result) {
|
623 | throw new Error(`Snowpack config file could not be found: ${configPath}`);
|
624 | }
|
625 | }
|
626 |
|
627 | result =
|
628 | result ||
|
629 | loadConfigurationFile('snowpack.config.mjs') ||
|
630 | loadConfigurationFile('snowpack.config.cjs') ||
|
631 | loadConfigurationFile('snowpack.config.js') ||
|
632 | loadConfigurationFile('snowpack.config.json');
|
633 |
|
634 | if (!result) {
|
635 | const potentialPackageJsonConfig = loadConfigurationFile('package.json');
|
636 | if (potentialPackageJsonConfig && potentialPackageJsonConfig.config.snowpack) {
|
637 | result = {
|
638 | filepath: potentialPackageJsonConfig.filepath,
|
639 | config: potentialPackageJsonConfig.config.snowpack,
|
640 | };
|
641 | }
|
642 | }
|
643 | if (!result) {
|
644 | logger_1.logger.warn('Hint: run "snowpack init" to create a project config file. Using defaults...');
|
645 | result = { filepath: undefined, config: {} };
|
646 | }
|
647 | const { config, filepath } = result;
|
648 | const configBase = getConfigBasePath(filepath, config.root);
|
649 | valdiateDeprecatedConfig(config);
|
650 | valdiateDeprecatedConfig(overrides);
|
651 | resolveRelativeConfig(config, configBase);
|
652 | let extendConfig = {};
|
653 | if (config.extends) {
|
654 | const extendConfigLoc = require.resolve(config.extends, { paths: [configBase] });
|
655 | const extendResult = loadConfigurationFile(extendConfigLoc);
|
656 | if (!extendResult) {
|
657 | handleConfigError(`Could not locate "extends" config at ${extendConfigLoc}`);
|
658 | process.exit(1);
|
659 | }
|
660 | extendConfig = extendResult.config;
|
661 | const extendValidation = jsonschema_1.validate(extendConfig, configSchema, {
|
662 | allowUnknownAttributes: false,
|
663 | propertyName: CONFIG_NAME,
|
664 | });
|
665 | if (extendValidation.errors && extendValidation.errors.length > 0) {
|
666 | handleValidationErrors(extendConfigLoc, new ConfigValidationError(extendValidation.errors));
|
667 | }
|
668 | valdiateDeprecatedConfig(extendConfig);
|
669 | resolveRelativeConfig(extendConfig, configBase);
|
670 | }
|
671 |
|
672 | const mergedConfig = deepmerge_1.all([extendConfig, config, overrides], {
|
673 | isMergeableObject: (val) => is_plain_object_1.isPlainObject(val) || Array.isArray(val),
|
674 | });
|
675 | try {
|
676 | return createConfiguration(mergedConfig);
|
677 | }
|
678 | catch (err) {
|
679 | if (err instanceof ConfigValidationError) {
|
680 | handleValidationErrors(filepath, err);
|
681 | }
|
682 | throw err;
|
683 | }
|
684 | }
|
685 | exports.loadConfiguration = loadConfiguration;
|