1 | import { existsSync } from 'fs';
|
2 | import sade from 'sade';
|
3 | import { pathToFileURL, resolve as resolve$1 } from 'url';
|
4 | import path from 'path';
|
5 |
|
6 | let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;
|
7 | if (typeof process !== 'undefined') {
|
8 | ({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env);
|
9 | isTTY = process.stdout && process.stdout.isTTY;
|
10 | }
|
11 |
|
12 | const $ = {
|
13 | enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (
|
14 | FORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY
|
15 | ),
|
16 |
|
17 |
|
18 | reset: init(0, 0),
|
19 | bold: init(1, 22),
|
20 | dim: init(2, 22),
|
21 | italic: init(3, 23),
|
22 | underline: init(4, 24),
|
23 | inverse: init(7, 27),
|
24 | hidden: init(8, 28),
|
25 | strikethrough: init(9, 29),
|
26 |
|
27 |
|
28 | black: init(30, 39),
|
29 | red: init(31, 39),
|
30 | green: init(32, 39),
|
31 | yellow: init(33, 39),
|
32 | blue: init(34, 39),
|
33 | magenta: init(35, 39),
|
34 | cyan: init(36, 39),
|
35 | white: init(37, 39),
|
36 | gray: init(90, 39),
|
37 | grey: init(90, 39),
|
38 |
|
39 |
|
40 | bgBlack: init(40, 49),
|
41 | bgRed: init(41, 49),
|
42 | bgGreen: init(42, 49),
|
43 | bgYellow: init(43, 49),
|
44 | bgBlue: init(44, 49),
|
45 | bgMagenta: init(45, 49),
|
46 | bgCyan: init(46, 49),
|
47 | bgWhite: init(47, 49)
|
48 | };
|
49 |
|
50 | function run(arr, str) {
|
51 | let i=0, tmp, beg='', end='';
|
52 | for (; i < arr.length; i++) {
|
53 | tmp = arr[i];
|
54 | beg += tmp.open;
|
55 | end += tmp.close;
|
56 | if (!!~str.indexOf(tmp.close)) {
|
57 | str = str.replace(tmp.rgx, tmp.close + tmp.open);
|
58 | }
|
59 | }
|
60 | return beg + str + end;
|
61 | }
|
62 |
|
63 | function chain(has, keys) {
|
64 | let ctx = { has, keys };
|
65 |
|
66 | ctx.reset = $.reset.bind(ctx);
|
67 | ctx.bold = $.bold.bind(ctx);
|
68 | ctx.dim = $.dim.bind(ctx);
|
69 | ctx.italic = $.italic.bind(ctx);
|
70 | ctx.underline = $.underline.bind(ctx);
|
71 | ctx.inverse = $.inverse.bind(ctx);
|
72 | ctx.hidden = $.hidden.bind(ctx);
|
73 | ctx.strikethrough = $.strikethrough.bind(ctx);
|
74 |
|
75 | ctx.black = $.black.bind(ctx);
|
76 | ctx.red = $.red.bind(ctx);
|
77 | ctx.green = $.green.bind(ctx);
|
78 | ctx.yellow = $.yellow.bind(ctx);
|
79 | ctx.blue = $.blue.bind(ctx);
|
80 | ctx.magenta = $.magenta.bind(ctx);
|
81 | ctx.cyan = $.cyan.bind(ctx);
|
82 | ctx.white = $.white.bind(ctx);
|
83 | ctx.gray = $.gray.bind(ctx);
|
84 | ctx.grey = $.grey.bind(ctx);
|
85 |
|
86 | ctx.bgBlack = $.bgBlack.bind(ctx);
|
87 | ctx.bgRed = $.bgRed.bind(ctx);
|
88 | ctx.bgGreen = $.bgGreen.bind(ctx);
|
89 | ctx.bgYellow = $.bgYellow.bind(ctx);
|
90 | ctx.bgBlue = $.bgBlue.bind(ctx);
|
91 | ctx.bgMagenta = $.bgMagenta.bind(ctx);
|
92 | ctx.bgCyan = $.bgCyan.bind(ctx);
|
93 | ctx.bgWhite = $.bgWhite.bind(ctx);
|
94 |
|
95 | return ctx;
|
96 | }
|
97 |
|
98 | function init(open, close) {
|
99 | let blk = {
|
100 | open: `\x1b[${open}m`,
|
101 | close: `\x1b[${close}m`,
|
102 | rgx: new RegExp(`\\x1b\\[${close}m`, 'g')
|
103 | };
|
104 | return function (txt) {
|
105 | if (this !== void 0 && this.has !== void 0) {
|
106 | !!~this.has.indexOf(open) || (this.has.push(open),this.keys.push(blk));
|
107 | return txt === void 0 ? this : $.enabled ? run(this.keys, txt+'') : txt+'';
|
108 | }
|
109 | return txt === void 0 ? chain([open], [blk]) : $.enabled ? run([blk], txt+'') : txt+'';
|
110 | };
|
111 | }
|
112 |
|
113 | const noop = () => {};
|
114 |
|
115 |
|
116 |
|
117 |
|
118 | const options = {
|
119 | compilerOptions: {
|
120 | type: 'leaf',
|
121 | default: null,
|
122 | validate: noop
|
123 | },
|
124 |
|
125 | extensions: {
|
126 | type: 'leaf',
|
127 | default: ['.svelte'],
|
128 | validate: (option, keypath) => {
|
129 | if (!Array.isArray(option) || !option.every((page) => typeof page === 'string')) {
|
130 | throw new Error(`${keypath} must be an array of strings`);
|
131 | }
|
132 |
|
133 | option.forEach((extension) => {
|
134 | if (extension[0] !== '.') {
|
135 | throw new Error(`Each member of ${keypath} must start with '.' — saw '${extension}'`);
|
136 | }
|
137 |
|
138 | if (!/^(\.[a-z0-9]+)+$/i.test(extension)) {
|
139 | throw new Error(`File extensions must be alphanumeric — saw '${extension}'`);
|
140 | }
|
141 | });
|
142 |
|
143 | return option;
|
144 | }
|
145 | },
|
146 |
|
147 | kit: {
|
148 | type: 'branch',
|
149 | children: {
|
150 | adapter: {
|
151 | type: 'leaf',
|
152 | default: [null],
|
153 | validate: (option, keypath) => {
|
154 |
|
155 | if (!Array.isArray(option)) {
|
156 | option = [option];
|
157 | }
|
158 |
|
159 |
|
160 | assert_is_string(option[0], keypath);
|
161 |
|
162 | return option;
|
163 | }
|
164 | },
|
165 |
|
166 | amp: expect_boolean(false),
|
167 |
|
168 | appDir: expect_string('_app', false),
|
169 |
|
170 | files: {
|
171 | type: 'branch',
|
172 | children: {
|
173 | assets: expect_string('static'),
|
174 | lib: expect_string('src/lib'),
|
175 | routes: expect_string('src/routes'),
|
176 | serviceWorker: expect_string('src/service-worker'),
|
177 | setup: expect_string('src/setup'),
|
178 | template: expect_string('src/app.html')
|
179 | }
|
180 | },
|
181 |
|
182 | host: expect_string(null),
|
183 |
|
184 | hostHeader: expect_string(null),
|
185 |
|
186 | paths: {
|
187 | type: 'branch',
|
188 | children: {
|
189 | base: expect_string(''),
|
190 | assets: expect_string('')
|
191 | }
|
192 | },
|
193 |
|
194 | prerender: {
|
195 | type: 'branch',
|
196 | children: {
|
197 | crawl: expect_boolean(true),
|
198 | enabled: expect_boolean(true),
|
199 | force: expect_boolean(false),
|
200 | pages: {
|
201 | type: 'leaf',
|
202 | default: ['*'],
|
203 | validate: (option, keypath) => {
|
204 | if (!Array.isArray(option) || !option.every((page) => typeof page === 'string')) {
|
205 | throw new Error(`${keypath} must be an array of strings`);
|
206 | }
|
207 |
|
208 | option.forEach((page) => {
|
209 | if (page !== '*' && page[0] !== '/') {
|
210 | throw new Error(
|
211 | `Each member of ${keypath} must be either '*' or an absolute path beginning with '/' — saw '${page}'`
|
212 | );
|
213 | }
|
214 | });
|
215 |
|
216 | return option;
|
217 | }
|
218 | }
|
219 | }
|
220 | },
|
221 |
|
222 |
|
223 | startGlobal: expect_string(null),
|
224 |
|
225 | target: expect_string(null)
|
226 | }
|
227 | },
|
228 |
|
229 | preprocess: {
|
230 | type: 'leaf',
|
231 | default: null,
|
232 | validate: noop
|
233 | }
|
234 | };
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 | function expect_string(string, allow_empty = true) {
|
242 | return {
|
243 | type: 'leaf',
|
244 | default: string,
|
245 | validate: (option, keypath) => {
|
246 | assert_is_string(option, keypath);
|
247 | if (!allow_empty && option === '') {
|
248 | throw new Error(`${keypath} cannot be empty`);
|
249 | }
|
250 | return option;
|
251 | }
|
252 | };
|
253 | }
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | function expect_boolean(boolean) {
|
260 | return {
|
261 | type: 'leaf',
|
262 | default: boolean,
|
263 | validate: (option, keypath) => {
|
264 | if (typeof option !== 'boolean') {
|
265 | throw new Error(`${keypath} should be true or false, if specified`);
|
266 | }
|
267 | return option;
|
268 | }
|
269 | };
|
270 | }
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 | function assert_is_string(option, keypath) {
|
277 | if (typeof option !== 'string') {
|
278 | throw new Error(`${keypath} should be a string, if specified`);
|
279 | }
|
280 | }
|
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 | function validate(definition, option, keypath) {
|
291 | for (const key in option) {
|
292 | if (!(key in definition)) {
|
293 | let message = `Unexpected option ${keypath}.${key}`;
|
294 |
|
295 | if (keypath === 'config' && key in options.kit) {
|
296 | message += ` (did you mean config.kit.${key}?)`;
|
297 | } else if (keypath === 'config.kit' && key in options) {
|
298 | message += ` (did you mean config.${key}?)`;
|
299 | }
|
300 |
|
301 | throw new Error(message);
|
302 | }
|
303 | }
|
304 |
|
305 |
|
306 | const merged = {};
|
307 |
|
308 | for (const key in definition) {
|
309 | const expected = definition[key];
|
310 | const actual = option[key];
|
311 |
|
312 | const child_keypath = `${keypath}.${key}`;
|
313 |
|
314 | if (key in option) {
|
315 | if (expected.type === 'branch') {
|
316 | if (actual && (typeof actual !== 'object' || Array.isArray(actual))) {
|
317 | throw new Error(`${keypath}.${key} should be an object`);
|
318 | }
|
319 |
|
320 | merged[key] = validate(expected.children, actual, child_keypath);
|
321 | } else {
|
322 | merged[key] = expected.validate(actual, child_keypath);
|
323 | }
|
324 | } else {
|
325 | merged[key] =
|
326 | expected.type === 'branch'
|
327 | ? validate(expected.children, {}, child_keypath)
|
328 | : expected.default;
|
329 | }
|
330 | }
|
331 |
|
332 | return merged;
|
333 | }
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 | function resolve(from, to) {
|
340 |
|
341 |
|
342 | return remove_trailing_slash(resolve$1(add_trailing_slash(from), to)) || '/.';
|
343 | }
|
344 |
|
345 |
|
346 |
|
347 |
|
348 | function add_trailing_slash(str) {
|
349 | return str.endsWith('/') ? str : `${str}/`;
|
350 | }
|
351 |
|
352 |
|
353 |
|
354 |
|
355 | function remove_trailing_slash(str) {
|
356 | return str.endsWith('/') ? str.slice(0, -1) : str;
|
357 | }
|
358 |
|
359 | async function load_config({ cwd = process.cwd() } = {}) {
|
360 | const config_file = path.join(cwd, 'svelte.config.cjs');
|
361 | const config = await import(pathToFileURL(config_file).href);
|
362 | const validated = validate_config(config.default);
|
363 |
|
364 | validated.kit.files.assets = path.resolve(cwd, validated.kit.files.assets);
|
365 | validated.kit.files.lib = path.resolve(cwd, validated.kit.files.lib);
|
366 | validated.kit.files.routes = path.resolve(cwd, validated.kit.files.routes);
|
367 | validated.kit.files.serviceWorker = path.resolve(cwd, validated.kit.files.serviceWorker);
|
368 | validated.kit.files.setup = path.resolve(cwd, validated.kit.files.setup);
|
369 | validated.kit.files.template = path.resolve(cwd, validated.kit.files.template);
|
370 |
|
371 |
|
372 |
|
373 |
|
374 | return validated;
|
375 | }
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 | function validate_config(config) {
|
382 |
|
383 | const validated = validate(options, config, 'config');
|
384 |
|
385 |
|
386 | const { paths } = validated.kit;
|
387 |
|
388 | if (paths.base !== '' && !paths.base.startsWith('/')) {
|
389 | throw new Error('config.kit.paths.base must be a root-relative path');
|
390 | }
|
391 |
|
392 | paths.assets = resolve(paths.base, paths.assets);
|
393 |
|
394 | return validated;
|
395 | }
|
396 |
|
397 | async function get_config() {
|
398 |
|
399 | if (existsSync('snowpack.config.js') || existsSync('snowpack.config.cjs')) {
|
400 |
|
401 | console.error($.bold().red(
|
402 | 'SvelteKit now uses https://vitejs.dev. Please replace snowpack.config.js with vite.config.js:'
|
403 | ));
|
404 |
|
405 |
|
406 | console.error(`
|
407 | // Consult https://vitejs.dev/config/ to learn about these options
|
408 | import { join } from 'path';
|
409 | import { readFileSync } from 'fs';
|
410 | import { cwd } from 'process';
|
411 |
|
412 | const pkg = JSON.parse(readFileSync(join(cwd(), 'package.json')));
|
413 |
|
414 | /** @type {import('vite').UserConfig} */
|
415 | export default {
|
416 | ssr: {
|
417 | noExternal: Object.keys(pkg.dependencies || {})
|
418 | }
|
419 | };
|
420 |
|
421 | `.replace(/^\t{3}/gm, '').replace(/\t/gm, ' ').trim());
|
422 | }
|
423 |
|
424 | try {
|
425 | return await load_config();
|
426 | } catch (error) {
|
427 | let message = error.message;
|
428 |
|
429 | if (error.code === 'MODULE_NOT_FOUND') {
|
430 | if (existsSync('svelte.config.js')) {
|
431 |
|
432 | message =
|
433 | 'You must rename svelte.config.js to svelte.config.cjs, and snowpack.config.js to snowpack.config.cjs';
|
434 | } else {
|
435 | message = 'Missing svelte.config.cjs';
|
436 | }
|
437 | } else if (error.name === 'SyntaxError') {
|
438 | message = 'Malformed svelte.config.cjs';
|
439 | }
|
440 |
|
441 | console.error($.bold().red(message));
|
442 | console.error($.grey(error.stack));
|
443 | process.exit(1);
|
444 | }
|
445 | }
|
446 |
|
447 |
|
448 | function handle_error(error) {
|
449 | console.log($.bold().red(`> ${error.message}`));
|
450 | console.log($.gray(error.stack));
|
451 | process.exit(1);
|
452 | }
|
453 |
|
454 |
|
455 | async function launch(port) {
|
456 | const { exec } = await import('child_process');
|
457 | exec(`${process.platform == 'win32' ? 'start' : 'open'} http://localhost:${port}`);
|
458 | }
|
459 |
|
460 | const prog = sade('svelte-kit').version('1.0.0-next.48');
|
461 |
|
462 | prog
|
463 | .command('dev')
|
464 | .describe('Start a development server')
|
465 | .option('-p, --port', 'Port', 3000)
|
466 | .option('-o, --open', 'Open a browser tab', false)
|
467 | .action(async ({ port, open }) => {
|
468 | process.env.NODE_ENV = 'development';
|
469 | const config = await get_config();
|
470 |
|
471 | const { dev } = await import('./chunks/index.js');
|
472 |
|
473 | try {
|
474 | const watcher = await dev({ port, config });
|
475 |
|
476 | watcher.on('stdout', (data) => {
|
477 | process.stdout.write(data);
|
478 | });
|
479 |
|
480 | watcher.on('stderr', (data) => {
|
481 | process.stderr.write(data);
|
482 | });
|
483 |
|
484 | console.log($.bold().cyan(`> Listening on http://localhost:${watcher.port}`));
|
485 | if (open) launch(watcher.port);
|
486 | } catch (error) {
|
487 | handle_error(error);
|
488 | }
|
489 | });
|
490 |
|
491 | prog
|
492 | .command('build')
|
493 | .describe('Create a production build of your app')
|
494 | .option('--verbose', 'Log more stuff', false)
|
495 | .action(async ({ verbose }) => {
|
496 | process.env.NODE_ENV = 'production';
|
497 | const config = await get_config();
|
498 |
|
499 | try {
|
500 | const { build } = await import('./chunks/index4.js');
|
501 | await build(config);
|
502 |
|
503 | console.log(`\nRun ${$.bold().cyan('npm start')} to try your app locally.`);
|
504 |
|
505 | if (config.kit.adapter[0]) {
|
506 | const { adapt } = await import('./chunks/index5.js');
|
507 | await adapt(config, { verbose });
|
508 | } else {
|
509 | console.log($.bold().yellow('\nNo adapter specified'));
|
510 |
|
511 |
|
512 | console.log(
|
513 | `See ${$.bold().cyan('https://kit.svelte.dev/docs#adapters')} to learn how to configure your app to run on the platform of your choosing`
|
514 | );
|
515 | }
|
516 | } catch (error) {
|
517 | handle_error(error);
|
518 | }
|
519 | });
|
520 |
|
521 | prog
|
522 | .command('start')
|
523 | .describe('Serve an already-built app')
|
524 | .option('-p, --port', 'Port', 3000)
|
525 | .option('-o, --open', 'Open a browser tab', false)
|
526 | .action(async ({ port, open }) => {
|
527 | process.env.NODE_ENV = 'production';
|
528 | const config = await get_config();
|
529 |
|
530 | const { start } = await import('./chunks/index6.js');
|
531 |
|
532 | try {
|
533 | await start({ port, config });
|
534 |
|
535 | console.log($.bold().cyan(`> Listening on http://localhost:${port}`));
|
536 | if (open) if (open) launch(port);
|
537 | } catch (error) {
|
538 | handle_error(error);
|
539 | }
|
540 | });
|
541 |
|
542 |
|
543 | prog
|
544 | .command('adapt')
|
545 | .describe('Customise your production build for different platforms')
|
546 | .option('--verbose', 'Log more stuff', false)
|
547 | .action(async () => {
|
548 | console.log('"svelte-kit build" will now run the adapter');
|
549 | });
|
550 |
|
551 | prog.parse(process.argv, { unknown: (arg) => `Unknown option: ${arg}` });
|
552 |
|
553 | export { $ };
|