From 90749671b06b1d154fca47e726cced3cba3c95c6 Mon Sep 17 00:00:00 2001 From: John Simons Date: Thu, 27 May 2021 14:31:49 -0700 Subject: [PATCH 01/11] Passing the Rollup output options through to Vite --- packages/kit/src/core/build/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 3137728009e7..70b3f2a83171 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -149,6 +149,9 @@ async function build_client({ ...(user_config.build && user_config.build.rollupOptions), input, output: { + ...(user_config.build && + user_config.build.rollupOptions && + user_config.build.rollupOptions.output), entryFileNames: '[name]-[hash].js', chunkFileNames: 'chunks/[name]-[hash].js', assetFileNames: 'assets/[name]-[hash][extname]' From d524b7596ca59730eed971ddfccfef0b6421c15c Mon Sep 17 00:00:00 2001 From: John Simons Date: Sun, 30 May 2021 14:00:43 -0700 Subject: [PATCH 02/11] Added deep_merge --- packages/kit/src/core/utils.js | 52 ++++++++++ packages/kit/src/core/utils.spec.js | 152 ++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 packages/kit/src/core/utils.spec.js diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index d80f38e89f9f..a26eefbdf395 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -106,3 +106,55 @@ function find_svelte_packages(cwd) { export function get_no_external(cwd, user_specified_deps = []) { return [...user_specified_deps, ...find_svelte_packages(cwd)]; } + +/** + * Merges b into a, recursively, mutating a. + * @param {Object} a + * @param {Object} b + * @param {string[]} path array of property names representing the current + * location in the tree + */ +function merge_into(a, b, conflicts = [], path = []) { + const is_object = (x) => typeof x === 'object' && !Array.isArray(x); + for (const prop in b) { + if (is_object(b[prop])) { + if (!is_object(a[prop])) { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = {}; + } + merge_into(a[prop], b[prop], conflicts, [...path, prop]); + } else if (Array.isArray(b[prop])) { + if (!Array.isArray(a[prop])) { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = []; + } + a[prop].push(...b[prop]); + } else { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = b[prop]; + } + } +} + +/** + * Takes zero or more objects and returns a new object that has all the values + * deeply merged together. None of the original objects will be mutated at any + * level, and the returned object will have no references to the original + * objects at any depth. If there's a conflict the last one wins, except for + * arrays which will be combined. + * @param {...Object} objects + * @returns {[Object, string[]]} a 2-tuple with the merged object, and a list of + * merge conflicts if there were any, in dotted notation + */ +export function deep_merge(...objects) { + const result = {}; + const conflicts = []; + objects.forEach((o) => merge_into(result, o, conflicts)); + return [result, conflicts]; +} diff --git a/packages/kit/src/core/utils.spec.js b/packages/kit/src/core/utils.spec.js new file mode 100644 index 000000000000..29366183fb3c --- /dev/null +++ b/packages/kit/src/core/utils.spec.js @@ -0,0 +1,152 @@ +import { test, suite } from 'uvu'; +import * as assert from 'uvu/assert'; +import { deep_merge } from './utils.js'; + +const deepMergeSuite = suite('deep_merge'); + +deepMergeSuite('basic test no conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + version: 1, + animalSounds: { + cow: 'moo' + } + }, + { + animalSounds: { + duck: 'quack' + }, + locale: 'en_US' + } + ); + assert.equal(merged, { + version: 1, + locale: 'en_US', + animalSounds: { + cow: 'moo', + duck: 'quack' + } + }); + assert.equal(conflicts, []); +}); + +deepMergeSuite('three way merge no conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + animalSounds: { + cow: 'moo' + } + }, + { + animalSounds: { + duck: 'quack' + } + }, + { + animalSounds: { + dog: { + singular: 'bark', + plural: 'barks' + } + } + } + ); + assert.equal(merged, { + animalSounds: { + cow: 'moo', + duck: 'quack', + dog: { + singular: 'bark', + plural: 'barks' + } + } + }); + assert.equal(conflicts, []); +}); + +deepMergeSuite('merge with conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + person: { + firstName: 'John', + lastName: 'Doe', + address: { + line1: '123 Main St', + city: 'Seattle', + state: 'WA' + } + } + }, + { + person: { + middleInitial: 'Q', + address: '123 Main St, Seattle, WA' + } + } + ); + assert.equal(merged, { + person: { + firstName: 'John', + middleInitial: 'Q', + lastName: 'Doe', + address: '123 Main St, Seattle, WA' + } + }); + assert.equal(conflicts, ['person.address']); +}); + +deepMergeSuite('merge with arrays', async () => { + const [merged, conflicts] = deep_merge( + { + paths: ['/foo', '/bar'] + }, + { + paths: ['/alpha', '/beta'] + } + ); + assert.equal(merged, { + paths: ['/foo', '/bar', '/alpha', '/beta'] + }); +}); + +deepMergeSuite('empty', async () => { + const [merged, conflicts] = deep_merge(); + assert.equal(merged, {}); +}); + +deepMergeSuite('mutability safety', () => { + const input1 = { + person: { + firstName: 'John', + lastName: 'Doe', + address: { + line1: '123 Main St', + city: 'Seattle' + } + } + }; + const input2 = { + person: { + middleInitial: 'L', + lastName: 'Smith', + address: { + state: 'WA' + } + } + }; + const snapshot1 = JSON.stringify(input1); + const snapshot2 = JSON.stringify(input2); + + const [merged, conflicts] = deep_merge(input1, input2); + + // Mess with the result + merged.person.middleInitial = 'Z'; + merged.person.address.zipCode = '98103'; + merged.person = {}; + + // Make sure nothing in the inputs changed + assert.snapshot(snapshot1, JSON.stringify(input1)); + assert.snapshot(snapshot2, JSON.stringify(input2)); +}); + +deepMergeSuite.run(); From 628cf5958c2e2b1155bdda6ebcd9bacb7ee9efcf Mon Sep 17 00:00:00 2001 From: John Simons Date: Sun, 30 May 2021 16:04:26 -0700 Subject: [PATCH 03/11] Using deep_merge in vite.build() --- packages/kit/src/core/build/index.js | 69 ++++++++++++++++++---------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 70b3f2a83171..77826cc78b89 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -2,12 +2,13 @@ import fs from 'fs'; import path from 'path'; import { rimraf } from '../filesystem/index.js'; import create_manifest_data from '../../core/create_manifest_data/index.js'; -import { copy_assets, get_no_external, posixify, resolve_entry } from '../utils.js'; +import { copy_assets, get_no_external, posixify, resolve_entry, deep_merge } from '../utils.js'; import { create_app } from '../../core/create_app/index.js'; import vite from 'vite'; import svelte from '@sveltejs/vite-plugin-svelte'; import glob from 'tiny-glob/sync.js'; import { SVELTE_KIT } from '../constants.js'; +import colors from 'kleur'; /** @param {any} value */ const s = (value) => JSON.stringify(value); @@ -134,24 +135,19 @@ async function build_client({ /** @type {any} */ const user_config = config.kit.vite(); - await vite.build({ - ...user_config, + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(user_config, { configFile: false, root: cwd, base, build: { - ...user_config.build, cssCodeSplit: true, manifest: true, outDir: client_out_dir, polyfillDynamicImport: false, rollupOptions: { - ...(user_config.build && user_config.build.rollupOptions), input, output: { - ...(user_config.build && - user_config.build.rollupOptions && - user_config.build.rollupOptions.output), entryFileNames: '[name]-[hash].js', chunkFileNames: 'chunks/[name]-[hash].js', assetFileNames: 'assets/[name]-[hash][extname]' @@ -160,15 +156,12 @@ async function build_client({ } }, resolve: { - ...user_config.resolve, alias: { - ...(user_config.resolve && user_config.resolve.alias), $app: path.resolve(`${build_dir}/runtime/app`), $lib: config.kit.files.lib } }, plugins: [ - ...(user_config.plugins || []), svelte({ extensions: config.extensions, emitCss: !config.kit.amp @@ -176,6 +169,18 @@ async function build_client({ ] }); + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `build_client: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + ) + ); + }); + + await vite.build(merged_config); + /** @type {ClientManifest} */ const client_manifest = JSON.parse(fs.readFileSync(client_manifest_file, 'utf-8')); fs.renameSync(client_manifest_file, `${output_dir}/manifest.json`); // inspectable but not shipped @@ -398,19 +403,17 @@ async function build_server( /** @type {any} */ const user_config = config.kit.vite(); - await vite.build({ - ...user_config, + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(user_config, { configFile: false, root: cwd, base, build: { target: 'es2018', - ...user_config.build, ssr: true, outDir: `${output_dir}/server`, polyfillDynamicImport: false, rollupOptions: { - ...(user_config.build && user_config.build.rollupOptions), input: { app: app_file }, @@ -425,15 +428,12 @@ async function build_server( } }, resolve: { - ...user_config.resolve, alias: { - ...(user_config.resolve && user_config.resolve.alias), $app: path.resolve(`${build_dir}/runtime/app`), $lib: config.kit.files.lib } }, plugins: [ - ...(user_config.plugins || []), svelte({ extensions: config.extensions }) @@ -443,7 +443,6 @@ async function build_server( // so we need to ignore the fact that it's missing // @ts-ignore ssr: { - ...user_config.ssr, // note to self: this _might_ need to be ['svelte', '@sveltejs/kit', ...get_no_external()] // but I'm honestly not sure. roll with this for now and see if it's ok noExternal: get_no_external(cwd, user_config.ssr && user_config.ssr.noExternal) @@ -452,6 +451,18 @@ async function build_server( entries: [] } }); + + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `build_server: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + ) + ); + }); + + await vite.build(merged_config); } /** @@ -507,20 +518,18 @@ async function build_service_worker( /** @type {any} */ const user_config = config.kit.vite(); - await vite.build({ - ...user_config, + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(user_config, { configFile: false, root: cwd, base, build: { - ...user_config.build, lib: { entry: service_worker_entry_file, name: 'app', formats: ['es'] }, rollupOptions: { - ...(user_config.build && user_config.build.rollupOptions), output: { entryFileNames: 'service-worker.js' } @@ -529,9 +538,7 @@ async function build_service_worker( emptyOutDir: false }, resolve: { - ...user_config.resolve, alias: { - ...(user_config.resolve && user_config.resolve.alias), '$service-worker': path.resolve(`${build_dir}/runtime/service-worker`) } }, @@ -539,6 +546,18 @@ async function build_service_worker( entries: [] } }); + + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `build_service_worker: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + ) + ); + }); + + await vite.build(merged_config); } /** @param {string[]} array */ From e81c5e0d1f4b81e05ce2b0db200109af85286128 Mon Sep 17 00:00:00 2001 From: John Simons Date: Sun, 30 May 2021 21:27:13 -0700 Subject: [PATCH 04/11] Updated the error message formatting. --- packages/kit/src/core/build/index.js | 12 +++++++++--- packages/kit/src/core/utils.js | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 77826cc78b89..9e27246815d1 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -174,7 +174,9 @@ async function build_client({ colors .bold() .red( - `build_client: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + `build_client: The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` ) ); }); @@ -457,7 +459,9 @@ async function build_server( colors .bold() .red( - `build_server: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + `build_server: The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` ) ); }); @@ -552,7 +556,9 @@ async function build_service_worker( colors .bold() .red( - `build_service_worker: The value for ${conflict} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` + `build_service_worker: The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` ) ); }); diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index a26eefbdf395..6b7b95e7a2df 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -111,6 +111,7 @@ export function get_no_external(cwd, user_specified_deps = []) { * Merges b into a, recursively, mutating a. * @param {Object} a * @param {Object} b + * @param {string[]} conflicts array to accumulate conflicts in * @param {string[]} path array of property names representing the current * location in the tree */ From 6f59e1d7e90dcb399d312feca3a3b5f2779537a3 Mon Sep 17 00:00:00 2001 From: John Simons Date: Sun, 30 May 2021 22:00:29 -0700 Subject: [PATCH 05/11] Forgot to lint --- packages/kit/src/core/utils.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/core/utils.spec.js b/packages/kit/src/core/utils.spec.js index 29366183fb3c..dc400419ea58 100644 --- a/packages/kit/src/core/utils.spec.js +++ b/packages/kit/src/core/utils.spec.js @@ -1,4 +1,4 @@ -import { test, suite } from 'uvu'; +import { suite } from 'uvu'; import * as assert from 'uvu/assert'; import { deep_merge } from './utils.js'; @@ -96,7 +96,7 @@ deepMergeSuite('merge with conflicts', async () => { }); deepMergeSuite('merge with arrays', async () => { - const [merged, conflicts] = deep_merge( + const [merged] = deep_merge( { paths: ['/foo', '/bar'] }, @@ -110,7 +110,7 @@ deepMergeSuite('merge with arrays', async () => { }); deepMergeSuite('empty', async () => { - const [merged, conflicts] = deep_merge(); + const [merged] = deep_merge(); assert.equal(merged, {}); }); @@ -137,7 +137,7 @@ deepMergeSuite('mutability safety', () => { const snapshot1 = JSON.stringify(input1); const snapshot2 = JSON.stringify(input2); - const [merged, conflicts] = deep_merge(input1, input2); + const [merged] = deep_merge(input1, input2); // Mess with the result merged.person.middleInitial = 'Z'; From c803ce0911dee937196b0a97595033ece4366b31 Mon Sep 17 00:00:00 2001 From: John Simons Date: Thu, 3 Jun 2021 20:57:51 -0700 Subject: [PATCH 06/11] Updated copy in error message, and TS annotation to pass "pnpm check" --- packages/kit/src/core/build/index.js | 55 +++++++++++----------------- packages/kit/src/core/utils.js | 13 +++++-- 2 files changed, 31 insertions(+), 37 deletions(-) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 9e27246815d1..bb182cc3f6bc 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -78,6 +78,25 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/ }; } +/** + * @param {string?} scope used to prefix the error message + * @param {string[]} conflicts array of conflicts in dotted notation + */ +function print_vite_config_conflicts(scope, conflicts) { + const prefix = scope ? scope + ': ' : ''; + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `${prefix}The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored. This is controlled by SvelteKit.` + ) + ); + }); +} + /** * @param {{ * cwd: string; @@ -169,17 +188,7 @@ async function build_client({ ] }); - conflicts.forEach((conflict) => { - console.error( - colors - .bold() - .red( - `build_client: The value for ${colors.italic( - `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` - ) - ); - }); + print_vite_config_conflicts('build_client', conflicts); await vite.build(merged_config); @@ -454,17 +463,7 @@ async function build_server( } }); - conflicts.forEach((conflict) => { - console.error( - colors - .bold() - .red( - `build_server: The value for ${colors.italic( - `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` - ) - ); - }); + print_vite_config_conflicts('build_server', conflicts); await vite.build(merged_config); } @@ -551,17 +550,7 @@ async function build_service_worker( } }); - conflicts.forEach((conflict) => { - console.error( - colors - .bold() - .red( - `build_service_worker: The value for ${colors.italic( - `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored, as this is controlled by SvelteKit` - ) - ); - }); + print_vite_config_conflicts('build_service_worker', conflicts); await vite.build(merged_config); } diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 6b7b95e7a2df..82c69e522e20 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -109,14 +109,18 @@ export function get_no_external(cwd, user_specified_deps = []) { /** * Merges b into a, recursively, mutating a. - * @param {Object} a - * @param {Object} b + * @param {Record} a + * @param {Record} b * @param {string[]} conflicts array to accumulate conflicts in * @param {string[]} path array of property names representing the current * location in the tree */ function merge_into(a, b, conflicts = [], path = []) { + /** + * @param {any} x + */ const is_object = (x) => typeof x === 'object' && !Array.isArray(x); + for (const prop in b) { if (is_object(b[prop])) { if (!is_object(a[prop])) { @@ -150,11 +154,12 @@ function merge_into(a, b, conflicts = [], path = []) { * objects at any depth. If there's a conflict the last one wins, except for * arrays which will be combined. * @param {...Object} objects - * @returns {[Object, string[]]} a 2-tuple with the merged object, and a list of - * merge conflicts if there were any, in dotted notation + * @returns {[Record, string[]]} a 2-tuple with the merged object, + * and a list of merge conflicts if there were any, in dotted notation */ export function deep_merge(...objects) { const result = {}; + /** @type {string[]} */ const conflicts = []; objects.forEach((o) => merge_into(result, o, conflicts)); return [result, conflicts]; From 7cc3e8dc538da87453cec901bf2fab39ebee0429 Mon Sep 17 00:00:00 2001 From: John Simons Date: Thu, 3 Jun 2021 21:03:04 -0700 Subject: [PATCH 07/11] Actual copy update. --- packages/kit/src/core/build/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index bb182cc3f6bc..05ae7f7ea64c 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -91,7 +91,7 @@ function print_vite_config_conflicts(scope, conflicts) { .red( `${prefix}The value for ${colors.italic( `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored. This is controlled by SvelteKit.` + )} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` ) ); }); From 1f2bab28f83a4222a3aa8a6c5d99545ecdc238ef Mon Sep 17 00:00:00 2001 From: John Simons Date: Fri, 4 Jun 2021 20:51:57 -0700 Subject: [PATCH 08/11] Also using deep_merge in core/dev/index.js --- packages/kit/src/core/dev/index.js | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js index 349673bfe358..516cc2984ba8 100644 --- a/packages/kit/src/core/dev/index.js +++ b/packages/kit/src/core/dev/index.js @@ -11,7 +11,7 @@ import { create_app } from '../../core/create_app/index.js'; import { rimraf } from '../filesystem/index.js'; import { respond } from '../../runtime/server/index.js'; import { getRawBody } from '../node/index.js'; -import { copy_assets, get_no_external, resolve_entry } from '../utils.js'; +import { copy_assets, get_no_external, resolve_entry, deep_merge } from '../utils.js'; import svelte from '@sveltejs/vite-plugin-svelte'; import { get_server } from '../server/index.js'; import '../../install-fetch.js'; @@ -79,23 +79,17 @@ class Watcher extends EventEmitter { /** @type {any} */ const user_config = (this.config.kit.vite && this.config.kit.vite()) || {}; - /** - * @type {vite.ViteDevServer} - */ - this.vite = await vite.createServer({ - ...user_config, + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(user_config, { configFile: false, root: this.cwd, resolve: { - ...user_config.resolve, alias: { - ...(user_config.resolve && user_config.resolve.alias), $app: path.resolve(`${this.dir}/runtime/app`), $lib: this.config.kit.files.lib } }, plugins: [ - ...(user_config.plugins || []), svelte({ extensions: this.config.extensions, emitCss: !this.config.kit.amp @@ -103,19 +97,33 @@ class Watcher extends EventEmitter { ], publicDir: this.config.kit.files.assets, server: { - ...user_config.server, middlewareMode: true }, optimizeDeps: { - ...user_config.optimizeDeps, entries: [] }, ssr: { - ...user_config.ssr, noExternal: get_no_external(this.cwd, user_config.ssr && user_config.ssr.noExternal) } }); + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` + ) + ); + }); + + /** + * @type {vite.ViteDevServer} + */ + this.vite = await vite.createServer(merged_config); + const validator = this.config.kit.amp && (await amp_validator.getInstance()); /** From 7190b9b9648522ac475994cd823c7908a194c9b9 Mon Sep 17 00:00:00 2001 From: John Simons Date: Sat, 5 Jun 2021 11:00:20 -0700 Subject: [PATCH 09/11] Re-do of the core/dev/index.html changes on updated origin/master. --- packages/kit/src/core/dev/index.js | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js index 9f3a92c9e55e..fc03c0d4119d 100644 --- a/packages/kit/src/core/dev/index.js +++ b/packages/kit/src/core/dev/index.js @@ -11,7 +11,7 @@ import { create_app } from '../../core/create_app/index.js'; import { rimraf } from '../filesystem/index.js'; import { respond } from '../../runtime/server/index.js'; import { getRawBody } from '../node/index.js'; -import { copy_assets, get_no_external, resolve_entry } from '../utils.js'; +import { copy_assets, get_no_external, resolve_entry, deep_merge } from '../utils.js'; import svelte from '@sveltejs/vite-plugin-svelte'; import { get_server } from '../server/index.js'; import '../../install-fetch.js'; @@ -84,23 +84,17 @@ class Watcher extends EventEmitter { this.server = await get_server(this.https, user_config, (req, res) => handler(req, res)); - /** - * @type {vite.ViteDevServer} - */ - this.vite = await vite.createServer({ - ...user_config, + /** @type {[any, string[]]} */ + const [merged_config, conflicts] = deep_merge(user_config, { configFile: false, root: this.cwd, resolve: { - ...user_config.resolve, alias: { - ...(user_config.resolve && user_config.resolve.alias), $app: path.resolve(`${this.dir}/runtime/app`), $lib: this.config.kit.files.lib } }, plugins: [ - ...(user_config.plugins || []), svelte({ extensions: this.config.extensions, emitCss: !this.config.kit.amp @@ -108,23 +102,36 @@ class Watcher extends EventEmitter { ], publicDir: this.config.kit.files.assets, server: { - ...user_config.server, middlewareMode: true, hmr: { - ...(user_config.server && user_config.server.hmr), ...(this.https ? { server: this.server, port: this.port } : {}) } }, optimizeDeps: { - ...user_config.optimizeDeps, entries: [] }, ssr: { - ...user_config.ssr, noExternal: get_no_external(this.cwd, user_config.ssr && user_config.ssr.noExternal) } }); + conflicts.forEach((conflict) => { + console.error( + colors + .bold() + .red( + `The value for ${colors.italic( + `kit.vite.${conflict}` + )} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` + ) + ); + }); + + /** + * @type {vite.ViteDevServer} + */ + this.vite = await vite.createServer(merged_config); + const validator = this.config.kit.amp && (await amp_validator.getInstance()); /** From 8a86cd66fdbadaacc6d44762824cc5c270982d99 Mon Sep 17 00:00:00 2001 From: John Simons Date: Fri, 11 Jun 2021 14:29:43 -0700 Subject: [PATCH 10/11] Common print_config_conflicts function, that uses the logger. --- packages/kit/src/core/build/index.js | 35 +++++++++------------------- packages/kit/src/core/dev/index.js | 20 +++++++--------- packages/kit/src/core/utils.js | 15 ++++++++++++ 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 47f063e4258f..c0c157601dfb 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -2,13 +2,19 @@ import fs from 'fs'; import path from 'path'; import { rimraf } from '../filesystem/index.js'; import create_manifest_data from '../../core/create_manifest_data/index.js'; -import { copy_assets, get_no_external, posixify, resolve_entry, deep_merge } from '../utils.js'; +import { + copy_assets, + get_no_external, + posixify, + resolve_entry, + deep_merge, + print_config_conflicts +} from '../utils.js'; import { create_app } from '../../core/create_app/index.js'; import vite from 'vite'; import svelte from '@sveltejs/vite-plugin-svelte'; import glob from 'tiny-glob/sync.js'; import { SVELTE_KIT } from '../constants.js'; -import colors from 'kleur'; /** @param {any} value */ const s = (value) => JSON.stringify(value); @@ -78,25 +84,6 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/ }; } -/** - * @param {string?} scope used to prefix the error message - * @param {string[]} conflicts array of conflicts in dotted notation - */ -function print_vite_config_conflicts(scope, conflicts) { - const prefix = scope ? scope + ': ' : ''; - conflicts.forEach((conflict) => { - console.error( - colors - .bold() - .red( - `${prefix}The value for ${colors.italic( - `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` - ) - ); - }); -} - /** * @param {{ * cwd: string; @@ -188,7 +175,7 @@ async function build_client({ ] }); - print_vite_config_conflicts('build_client', conflicts); + print_config_conflicts(conflicts, 'kit.vite.', 'build_client'); await vite.build(merged_config); @@ -463,7 +450,7 @@ async function build_server( } }); - print_vite_config_conflicts('build_server', conflicts); + print_config_conflicts(conflicts, 'kit.vite.', 'build_server'); await vite.build(merged_config); } @@ -550,7 +537,7 @@ async function build_service_worker( } }); - print_vite_config_conflicts('build_service_worker', conflicts); + print_config_conflicts(conflicts, 'kit.vite.', 'build_service_worker'); await vite.build(merged_config); } diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js index fc03c0d4119d..dd796f5ffb41 100644 --- a/packages/kit/src/core/dev/index.js +++ b/packages/kit/src/core/dev/index.js @@ -11,7 +11,13 @@ import { create_app } from '../../core/create_app/index.js'; import { rimraf } from '../filesystem/index.js'; import { respond } from '../../runtime/server/index.js'; import { getRawBody } from '../node/index.js'; -import { copy_assets, get_no_external, resolve_entry, deep_merge } from '../utils.js'; +import { + copy_assets, + get_no_external, + resolve_entry, + deep_merge, + print_config_conflicts +} from '../utils.js'; import svelte from '@sveltejs/vite-plugin-svelte'; import { get_server } from '../server/index.js'; import '../../install-fetch.js'; @@ -115,17 +121,7 @@ class Watcher extends EventEmitter { } }); - conflicts.forEach((conflict) => { - console.error( - colors - .bold() - .red( - `The value for ${colors.italic( - `kit.vite.${conflict}` - )} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` - ) - ); - }); + print_config_conflicts(conflicts, 'kit.vite.'); /** * @type {vite.ViteDevServer} diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index 82c69e522e20..d1c121cdf9c5 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -164,3 +164,18 @@ export function deep_merge(...objects) { objects.forEach((o) => merge_into(result, o, conflicts)); return [result, conflicts]; } + +/** + * @param {string[]} conflicts - array of conflicts in dotted notation + * @param {string=} pathPrefix - prepended in front of the path + * @param {string=} scope - used to prefix the whole error message + */ +export function print_config_conflicts(conflicts, pathPrefix = '', scope) { + const prefix = scope ? scope + ': ' : ''; + const log = logger({ verbose: false }); + conflicts.forEach((conflict) => { + log.error( + `${prefix}The value for ${pathPrefix}${conflict} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` + ); + }); +} From a11a64b95d688fddfb7ae13a57a9aaf4c8357662 Mon Sep 17 00:00:00 2001 From: John Simons Date: Fri, 11 Jun 2021 15:25:39 -0700 Subject: [PATCH 11/11] Moved load_config => config --- packages/kit/src/cli.js | 2 +- packages/kit/src/core/build/index.js | 10 +- .../src/core/{load_config => config}/index.js | 74 +++++++++ .../{load_config => config}/index.spec.js | 153 +++++++++++++++++- .../core/{load_config => config}/options.js | 0 .../test/fixtures/default-cjs/src/app.html | 0 .../fixtures/default-cjs/svelte.config.cjs | 0 .../test/fixtures/default-esm/src/app.html | 0 .../fixtures/default-esm/svelte.config.js | 0 .../{load_config => config}/test/index.js | 0 .../core/{load_config => config}/types.d.ts | 0 packages/kit/src/core/dev/index.js | 9 +- packages/kit/src/core/utils.js | 73 --------- packages/kit/src/core/utils.spec.js | 152 ----------------- packages/kit/test/test.js | 2 +- 15 files changed, 231 insertions(+), 244 deletions(-) rename packages/kit/src/core/{load_config => config}/index.js (63%) rename packages/kit/src/core/{load_config => config}/index.spec.js (64%) rename packages/kit/src/core/{load_config => config}/options.js (100%) rename packages/kit/src/core/{load_config => config}/test/fixtures/default-cjs/src/app.html (100%) rename packages/kit/src/core/{load_config => config}/test/fixtures/default-cjs/svelte.config.cjs (100%) rename packages/kit/src/core/{load_config => config}/test/fixtures/default-esm/src/app.html (100%) rename packages/kit/src/core/{load_config => config}/test/fixtures/default-esm/svelte.config.js (100%) rename packages/kit/src/core/{load_config => config}/test/index.js (100%) rename packages/kit/src/core/{load_config => config}/types.d.ts (100%) delete mode 100644 packages/kit/src/core/utils.spec.js diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index f80e01a461b2..e09d9711a858 100644 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -2,7 +2,7 @@ import { existsSync } from 'fs'; import sade from 'sade'; import colors from 'kleur'; import * as ports from 'port-authority'; -import { load_config } from './core/load_config/index.js'; +import { load_config } from './core/config/index.js'; import { networkInterfaces, release } from 'os'; async function get_config() { diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index c0c157601dfb..43f2dd688228 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -2,14 +2,8 @@ import fs from 'fs'; import path from 'path'; import { rimraf } from '../filesystem/index.js'; import create_manifest_data from '../../core/create_manifest_data/index.js'; -import { - copy_assets, - get_no_external, - posixify, - resolve_entry, - deep_merge, - print_config_conflicts -} from '../utils.js'; +import { copy_assets, get_no_external, posixify, resolve_entry } from '../utils.js'; +import { deep_merge, print_config_conflicts } from '../config/index.js'; import { create_app } from '../../core/create_app/index.js'; import vite from 'vite'; import svelte from '@sveltejs/vite-plugin-svelte'; diff --git a/packages/kit/src/core/load_config/index.js b/packages/kit/src/core/config/index.js similarity index 63% rename from packages/kit/src/core/load_config/index.js rename to packages/kit/src/core/config/index.js index 767304d9de1a..98465bb48032 100644 --- a/packages/kit/src/core/load_config/index.js +++ b/packages/kit/src/core/config/index.js @@ -2,6 +2,7 @@ import options from './options.js'; import * as url from 'url'; import path from 'path'; import fs from 'fs'; +import { logger } from '../utils.js'; /** @typedef {import('./types').ConfigDefinition} ConfigDefinition */ @@ -143,3 +144,76 @@ export function validate_config(config) { return validated; } + +/** + * Merges b into a, recursively, mutating a. + * @param {Record} a + * @param {Record} b + * @param {string[]} conflicts array to accumulate conflicts in + * @param {string[]} path array of property names representing the current + * location in the tree + */ +function merge_into(a, b, conflicts = [], path = []) { + /** + * @param {any} x + */ + const is_object = (x) => typeof x === 'object' && !Array.isArray(x); + + for (const prop in b) { + if (is_object(b[prop])) { + if (!is_object(a[prop])) { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = {}; + } + merge_into(a[prop], b[prop], conflicts, [...path, prop]); + } else if (Array.isArray(b[prop])) { + if (!Array.isArray(a[prop])) { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = []; + } + a[prop].push(...b[prop]); + } else { + if (a[prop] !== undefined) { + conflicts.push([...path, prop].join('.')); + } + a[prop] = b[prop]; + } + } +} + +/** + * Takes zero or more objects and returns a new object that has all the values + * deeply merged together. None of the original objects will be mutated at any + * level, and the returned object will have no references to the original + * objects at any depth. If there's a conflict the last one wins, except for + * arrays which will be combined. + * @param {...Object} objects + * @returns {[Record, string[]]} a 2-tuple with the merged object, + * and a list of merge conflicts if there were any, in dotted notation + */ +export function deep_merge(...objects) { + const result = {}; + /** @type {string[]} */ + const conflicts = []; + objects.forEach((o) => merge_into(result, o, conflicts)); + return [result, conflicts]; +} + +/** + * @param {string[]} conflicts - array of conflicts in dotted notation + * @param {string=} pathPrefix - prepended in front of the path + * @param {string=} scope - used to prefix the whole error message + */ +export function print_config_conflicts(conflicts, pathPrefix = '', scope) { + const prefix = scope ? scope + ': ' : ''; + const log = logger({ verbose: false }); + conflicts.forEach((conflict) => { + log.error( + `${prefix}The value for ${pathPrefix}${conflict} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` + ); + }); +} diff --git a/packages/kit/src/core/load_config/index.spec.js b/packages/kit/src/core/config/index.spec.js similarity index 64% rename from packages/kit/src/core/load_config/index.spec.js rename to packages/kit/src/core/config/index.spec.js index d1138752f849..327952a6219f 100644 --- a/packages/kit/src/core/load_config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -1,6 +1,6 @@ -import { test } from 'uvu'; +import { test, suite } from 'uvu'; import * as assert from 'uvu/assert'; -import { validate_config } from './index.js'; +import { validate_config, deep_merge } from './index.js'; test('fills in defaults', () => { const validated = validate_config({}); @@ -286,3 +286,152 @@ validate_paths( ); test.run(); + +const deepMergeSuite = suite('deep_merge'); + +deepMergeSuite('basic test no conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + version: 1, + animalSounds: { + cow: 'moo' + } + }, + { + animalSounds: { + duck: 'quack' + }, + locale: 'en_US' + } + ); + assert.equal(merged, { + version: 1, + locale: 'en_US', + animalSounds: { + cow: 'moo', + duck: 'quack' + } + }); + assert.equal(conflicts, []); +}); + +deepMergeSuite('three way merge no conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + animalSounds: { + cow: 'moo' + } + }, + { + animalSounds: { + duck: 'quack' + } + }, + { + animalSounds: { + dog: { + singular: 'bark', + plural: 'barks' + } + } + } + ); + assert.equal(merged, { + animalSounds: { + cow: 'moo', + duck: 'quack', + dog: { + singular: 'bark', + plural: 'barks' + } + } + }); + assert.equal(conflicts, []); +}); + +deepMergeSuite('merge with conflicts', async () => { + const [merged, conflicts] = deep_merge( + { + person: { + firstName: 'John', + lastName: 'Doe', + address: { + line1: '123 Main St', + city: 'Seattle', + state: 'WA' + } + } + }, + { + person: { + middleInitial: 'Q', + address: '123 Main St, Seattle, WA' + } + } + ); + assert.equal(merged, { + person: { + firstName: 'John', + middleInitial: 'Q', + lastName: 'Doe', + address: '123 Main St, Seattle, WA' + } + }); + assert.equal(conflicts, ['person.address']); +}); + +deepMergeSuite('merge with arrays', async () => { + const [merged] = deep_merge( + { + paths: ['/foo', '/bar'] + }, + { + paths: ['/alpha', '/beta'] + } + ); + assert.equal(merged, { + paths: ['/foo', '/bar', '/alpha', '/beta'] + }); +}); + +deepMergeSuite('empty', async () => { + const [merged] = deep_merge(); + assert.equal(merged, {}); +}); + +deepMergeSuite('mutability safety', () => { + const input1 = { + person: { + firstName: 'John', + lastName: 'Doe', + address: { + line1: '123 Main St', + city: 'Seattle' + } + } + }; + const input2 = { + person: { + middleInitial: 'L', + lastName: 'Smith', + address: { + state: 'WA' + } + } + }; + const snapshot1 = JSON.stringify(input1); + const snapshot2 = JSON.stringify(input2); + + const [merged] = deep_merge(input1, input2); + + // Mess with the result + merged.person.middleInitial = 'Z'; + merged.person.address.zipCode = '98103'; + merged.person = {}; + + // Make sure nothing in the inputs changed + assert.snapshot(snapshot1, JSON.stringify(input1)); + assert.snapshot(snapshot2, JSON.stringify(input2)); +}); + +deepMergeSuite.run(); diff --git a/packages/kit/src/core/load_config/options.js b/packages/kit/src/core/config/options.js similarity index 100% rename from packages/kit/src/core/load_config/options.js rename to packages/kit/src/core/config/options.js diff --git a/packages/kit/src/core/load_config/test/fixtures/default-cjs/src/app.html b/packages/kit/src/core/config/test/fixtures/default-cjs/src/app.html similarity index 100% rename from packages/kit/src/core/load_config/test/fixtures/default-cjs/src/app.html rename to packages/kit/src/core/config/test/fixtures/default-cjs/src/app.html diff --git a/packages/kit/src/core/load_config/test/fixtures/default-cjs/svelte.config.cjs b/packages/kit/src/core/config/test/fixtures/default-cjs/svelte.config.cjs similarity index 100% rename from packages/kit/src/core/load_config/test/fixtures/default-cjs/svelte.config.cjs rename to packages/kit/src/core/config/test/fixtures/default-cjs/svelte.config.cjs diff --git a/packages/kit/src/core/load_config/test/fixtures/default-esm/src/app.html b/packages/kit/src/core/config/test/fixtures/default-esm/src/app.html similarity index 100% rename from packages/kit/src/core/load_config/test/fixtures/default-esm/src/app.html rename to packages/kit/src/core/config/test/fixtures/default-esm/src/app.html diff --git a/packages/kit/src/core/load_config/test/fixtures/default-esm/svelte.config.js b/packages/kit/src/core/config/test/fixtures/default-esm/svelte.config.js similarity index 100% rename from packages/kit/src/core/load_config/test/fixtures/default-esm/svelte.config.js rename to packages/kit/src/core/config/test/fixtures/default-esm/svelte.config.js diff --git a/packages/kit/src/core/load_config/test/index.js b/packages/kit/src/core/config/test/index.js similarity index 100% rename from packages/kit/src/core/load_config/test/index.js rename to packages/kit/src/core/config/test/index.js diff --git a/packages/kit/src/core/load_config/types.d.ts b/packages/kit/src/core/config/types.d.ts similarity index 100% rename from packages/kit/src/core/load_config/types.d.ts rename to packages/kit/src/core/config/types.d.ts diff --git a/packages/kit/src/core/dev/index.js b/packages/kit/src/core/dev/index.js index dd796f5ffb41..fdd51dd7eb25 100644 --- a/packages/kit/src/core/dev/index.js +++ b/packages/kit/src/core/dev/index.js @@ -11,13 +11,8 @@ import { create_app } from '../../core/create_app/index.js'; import { rimraf } from '../filesystem/index.js'; import { respond } from '../../runtime/server/index.js'; import { getRawBody } from '../node/index.js'; -import { - copy_assets, - get_no_external, - resolve_entry, - deep_merge, - print_config_conflicts -} from '../utils.js'; +import { copy_assets, get_no_external, resolve_entry } from '../utils.js'; +import { deep_merge, print_config_conflicts } from '../config/index.js'; import svelte from '@sveltejs/vite-plugin-svelte'; import { get_server } from '../server/index.js'; import '../../install-fetch.js'; diff --git a/packages/kit/src/core/utils.js b/packages/kit/src/core/utils.js index d1c121cdf9c5..d80f38e89f9f 100644 --- a/packages/kit/src/core/utils.js +++ b/packages/kit/src/core/utils.js @@ -106,76 +106,3 @@ function find_svelte_packages(cwd) { export function get_no_external(cwd, user_specified_deps = []) { return [...user_specified_deps, ...find_svelte_packages(cwd)]; } - -/** - * Merges b into a, recursively, mutating a. - * @param {Record} a - * @param {Record} b - * @param {string[]} conflicts array to accumulate conflicts in - * @param {string[]} path array of property names representing the current - * location in the tree - */ -function merge_into(a, b, conflicts = [], path = []) { - /** - * @param {any} x - */ - const is_object = (x) => typeof x === 'object' && !Array.isArray(x); - - for (const prop in b) { - if (is_object(b[prop])) { - if (!is_object(a[prop])) { - if (a[prop] !== undefined) { - conflicts.push([...path, prop].join('.')); - } - a[prop] = {}; - } - merge_into(a[prop], b[prop], conflicts, [...path, prop]); - } else if (Array.isArray(b[prop])) { - if (!Array.isArray(a[prop])) { - if (a[prop] !== undefined) { - conflicts.push([...path, prop].join('.')); - } - a[prop] = []; - } - a[prop].push(...b[prop]); - } else { - if (a[prop] !== undefined) { - conflicts.push([...path, prop].join('.')); - } - a[prop] = b[prop]; - } - } -} - -/** - * Takes zero or more objects and returns a new object that has all the values - * deeply merged together. None of the original objects will be mutated at any - * level, and the returned object will have no references to the original - * objects at any depth. If there's a conflict the last one wins, except for - * arrays which will be combined. - * @param {...Object} objects - * @returns {[Record, string[]]} a 2-tuple with the merged object, - * and a list of merge conflicts if there were any, in dotted notation - */ -export function deep_merge(...objects) { - const result = {}; - /** @type {string[]} */ - const conflicts = []; - objects.forEach((o) => merge_into(result, o, conflicts)); - return [result, conflicts]; -} - -/** - * @param {string[]} conflicts - array of conflicts in dotted notation - * @param {string=} pathPrefix - prepended in front of the path - * @param {string=} scope - used to prefix the whole error message - */ -export function print_config_conflicts(conflicts, pathPrefix = '', scope) { - const prefix = scope ? scope + ': ' : ''; - const log = logger({ verbose: false }); - conflicts.forEach((conflict) => { - log.error( - `${prefix}The value for ${pathPrefix}${conflict} specified in svelte.config.js has been ignored. This option is controlled by SvelteKit.` - ); - }); -} diff --git a/packages/kit/src/core/utils.spec.js b/packages/kit/src/core/utils.spec.js deleted file mode 100644 index dc400419ea58..000000000000 --- a/packages/kit/src/core/utils.spec.js +++ /dev/null @@ -1,152 +0,0 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { deep_merge } from './utils.js'; - -const deepMergeSuite = suite('deep_merge'); - -deepMergeSuite('basic test no conflicts', async () => { - const [merged, conflicts] = deep_merge( - { - version: 1, - animalSounds: { - cow: 'moo' - } - }, - { - animalSounds: { - duck: 'quack' - }, - locale: 'en_US' - } - ); - assert.equal(merged, { - version: 1, - locale: 'en_US', - animalSounds: { - cow: 'moo', - duck: 'quack' - } - }); - assert.equal(conflicts, []); -}); - -deepMergeSuite('three way merge no conflicts', async () => { - const [merged, conflicts] = deep_merge( - { - animalSounds: { - cow: 'moo' - } - }, - { - animalSounds: { - duck: 'quack' - } - }, - { - animalSounds: { - dog: { - singular: 'bark', - plural: 'barks' - } - } - } - ); - assert.equal(merged, { - animalSounds: { - cow: 'moo', - duck: 'quack', - dog: { - singular: 'bark', - plural: 'barks' - } - } - }); - assert.equal(conflicts, []); -}); - -deepMergeSuite('merge with conflicts', async () => { - const [merged, conflicts] = deep_merge( - { - person: { - firstName: 'John', - lastName: 'Doe', - address: { - line1: '123 Main St', - city: 'Seattle', - state: 'WA' - } - } - }, - { - person: { - middleInitial: 'Q', - address: '123 Main St, Seattle, WA' - } - } - ); - assert.equal(merged, { - person: { - firstName: 'John', - middleInitial: 'Q', - lastName: 'Doe', - address: '123 Main St, Seattle, WA' - } - }); - assert.equal(conflicts, ['person.address']); -}); - -deepMergeSuite('merge with arrays', async () => { - const [merged] = deep_merge( - { - paths: ['/foo', '/bar'] - }, - { - paths: ['/alpha', '/beta'] - } - ); - assert.equal(merged, { - paths: ['/foo', '/bar', '/alpha', '/beta'] - }); -}); - -deepMergeSuite('empty', async () => { - const [merged] = deep_merge(); - assert.equal(merged, {}); -}); - -deepMergeSuite('mutability safety', () => { - const input1 = { - person: { - firstName: 'John', - lastName: 'Doe', - address: { - line1: '123 Main St', - city: 'Seattle' - } - } - }; - const input2 = { - person: { - middleInitial: 'L', - lastName: 'Smith', - address: { - state: 'WA' - } - } - }; - const snapshot1 = JSON.stringify(input1); - const snapshot2 = JSON.stringify(input2); - - const [merged] = deep_merge(input1, input2); - - // Mess with the result - merged.person.middleInitial = 'Z'; - merged.person.address.zipCode = '98103'; - merged.person = {}; - - // Make sure nothing in the inputs changed - assert.snapshot(snapshot1, JSON.stringify(input1)); - assert.snapshot(snapshot2, JSON.stringify(input2)); -}); - -deepMergeSuite.run(); diff --git a/packages/kit/test/test.js b/packages/kit/test/test.js index 78c4a3ae62d8..b70cd5876d2e 100644 --- a/packages/kit/test/test.js +++ b/packages/kit/test/test.js @@ -6,7 +6,7 @@ import { chromium } from 'playwright-chromium'; import { dev } from '../src/core/dev/index.js'; import { build } from '../src/core/build/index.js'; import { start } from '../src/core/start/index.js'; -import { load_config } from '../src/core/load_config/index.js'; +import { load_config } from '../src/core/config/index.js'; import { fileURLToPath, pathToFileURL } from 'url'; import { format } from 'util';