diff --git a/.changeset/brave-clowns-behave.md b/.changeset/brave-clowns-behave.md new file mode 100644 index 000000000000..60c95caf6464 --- /dev/null +++ b/.changeset/brave-clowns-behave.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: add a `kit.files.src` option diff --git a/.changeset/social-hounds-jam.md b/.changeset/social-hounds-jam.md new file mode 100644 index 000000000000..f3349d8337c8 --- /dev/null +++ b/.changeset/social-hounds-jam.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +chore: deprecate `config.kit.files` options diff --git a/packages/kit/src/core/config/fixtures/custom-src/svelte.config.js b/packages/kit/src/core/config/fixtures/custom-src/svelte.config.js new file mode 100644 index 000000000000..cfbf957434bf --- /dev/null +++ b/packages/kit/src/core/config/fixtures/custom-src/svelte.config.js @@ -0,0 +1,7 @@ +export default { + kit: { + files: { + src: 'source' + } + } +}; diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 7fc38bc483dd..ae35a708132b 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -126,6 +126,17 @@ export function validate_config(config) { } const validated = options(config, 'config'); + const files = validated.kit.files; + + files.hooks.client ??= path.join(files.src, 'hooks.client'); + files.hooks.server ??= path.join(files.src, 'hooks.server'); + files.hooks.universal ??= path.join(files.src, 'hooks'); + files.lib ??= path.join(files.src, 'lib'); + files.params ??= path.join(files.src, 'params'); + files.routes ??= path.join(files.src, 'routes'); + files.serviceWorker ??= path.join(files.src, 'service-worker'); + files.appTemplate ??= path.join(files.src, 'app.html'); + files.errorTemplate ??= path.join(files.src, 'error.html'); if (validated.kit.router.resolution === 'server') { if (validated.kit.router.type === 'hash') { diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js index 90da427483d7..1a979613bba6 100644 --- a/packages/kit/src/core/config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -80,6 +80,7 @@ const get_defaults = (prefix = '') => ({ remoteFunctions: false }, files: { + src: join(prefix, 'src'), assets: join(prefix, 'static'), hooks: { client: join(prefix, 'src/hooks.client'), @@ -407,3 +408,15 @@ test('errors on loading config with incorrect default export', async () => { 'The Svelte config file must have a configuration object as its default export. See https://svelte.dev/docs/kit/configuration' ); }); + +test('uses src prefix for other kit.files options', async () => { + const cwd = join(__dirname, 'fixtures/custom-src'); + + const config = await load_config({ cwd }); + remove_keys(config, ([, v]) => typeof v === 'function'); + + const defaults = get_defaults(cwd + '/'); + defaults.kit.version.name = config.kit.version.name; + + expect(config.kit.files.lib).toEqual(join(cwd, 'source/lib')); +}); diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index 577ca4c9445d..8920514dd402 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -1,4 +1,3 @@ -import { join } from 'node:path'; import process from 'node:process'; /** @typedef {import('./types.js').Validator} Validator */ @@ -125,18 +124,19 @@ const options = object( }), files: object({ - assets: string('static'), + src: deprecate(string('src')), + assets: deprecate(string('static')), hooks: object({ - client: string(join('src', 'hooks.client')), - server: string(join('src', 'hooks.server')), - universal: string(join('src', 'hooks')) + client: deprecate(string(null)), + server: deprecate(string(null)), + universal: deprecate(string(null)) }), - lib: string(join('src', 'lib')), - params: string(join('src', 'params')), - routes: string(join('src', 'routes')), - serviceWorker: string(join('src', 'service-worker')), - appTemplate: string(join('src', 'app.html')), - errorTemplate: string(join('src', 'error.html')) + lib: deprecate(string(null)), + params: deprecate(string(null)), + routes: deprecate(string(null)), + serviceWorker: deprecate(string(null)), + appTemplate: deprecate(string(null)), + errorTemplate: deprecate(string(null)) }), inlineStyleThreshold: number(0), @@ -287,6 +287,25 @@ const options = object( true ); +/** + * @param {Validator} fn + * @param {(keypath: string) => string} get_message + * @returns {Validator} + */ +function deprecate( + fn, + get_message = (keypath) => + `The \`${keypath}\` option is deprecated, and will be removed in a future version` +) { + return (input, keypath) => { + if (input !== undefined) { + console.warn(get_message(keypath)); + } + + return fn(input, keypath); + }; +} + /** * @param {Record} children * @param {boolean} [allow_unknown] diff --git a/packages/kit/src/core/sync/create_manifest_data/index.spec.js b/packages/kit/src/core/sync/create_manifest_data/index.spec.js index c681184446a6..c321507a5b42 100644 --- a/packages/kit/src/core/sync/create_manifest_data/index.spec.js +++ b/packages/kit/src/core/sync/create_manifest_data/index.spec.js @@ -3,8 +3,8 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { assert, expect, test } from 'vitest'; import create_manifest_data from './index.js'; -import options from '../../config/options.js'; import { sort_routes } from './sort.js'; +import { validate_config } from '../../config/index.js'; const cwd = fileURLToPath(new URL('./test', import.meta.url)); @@ -13,7 +13,7 @@ const cwd = fileURLToPath(new URL('./test', import.meta.url)); * @param {import('@sveltejs/kit').Config} config */ const create = (dir, config = {}) => { - const initial = options(config, 'config'); + const initial = validate_config(config); initial.kit.files.assets = path.resolve(cwd, 'static'); initial.kit.files.params = path.resolve(cwd, 'params'); diff --git a/packages/kit/src/core/sync/write_types/index.spec.js b/packages/kit/src/core/sync/write_types/index.spec.js index 92ad3d68d0ca..d6bfc36f7578 100644 --- a/packages/kit/src/core/sync/write_types/index.spec.js +++ b/packages/kit/src/core/sync/write_types/index.spec.js @@ -4,9 +4,9 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { assert, expect, test } from 'vitest'; import { rimraf } from '../../../utils/filesystem.js'; -import options from '../../config/options.js'; import create_manifest_data from '../create_manifest_data/index.js'; import { tweak_types, write_all_types } from './index.js'; +import { validate_config } from '../../config/index.js'; const cwd = fileURLToPath(new URL('./test', import.meta.url)); @@ -16,7 +16,7 @@ const cwd = fileURLToPath(new URL('./test', import.meta.url)); function run_test(dir) { rimraf(path.join(cwd, dir, '.svelte-kit')); - const initial = options({}, 'config'); + const initial = validate_config({}); initial.kit.files.assets = path.resolve(cwd, 'static'); initial.kit.files.params = path.resolve(cwd, dir, 'params'); diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 1982000eb2f9..0a69946e19cd 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -420,26 +420,38 @@ export interface KitConfig { }; /** * Where to find various files within your project. + * @deprecated */ files?: { + /** + * the location of your source code + * @deprecated + * @default "src" + * @since 2.28 + */ + src?: string; /** * a place to put static files that should have stable URLs and undergo no processing, such as `favicon.ico` or `manifest.json` + * @deprecated * @default "static" */ assets?: string; hooks?: { /** * The location of your client [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks.client" */ client?: string; /** * The location of your server [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks.server" */ server?: string; /** * The location of your universal [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks" * @since 2.3.0 */ @@ -447,31 +459,37 @@ export interface KitConfig { }; /** * your app's internal library, accessible throughout the codebase as `$lib` + * @deprecated * @default "src/lib" */ lib?: string; /** * a directory containing [parameter matchers](https://svelte.dev/docs/kit/advanced-routing#Matching) + * @deprecated * @default "src/params" */ params?: string; /** * the files that define the structure of your app (see [Routing](https://svelte.dev/docs/kit/routing)) + * @deprecated * @default "src/routes" */ routes?: string; /** * the location of your service worker's entry point (see [Service workers](https://svelte.dev/docs/kit/service-workers)) + * @deprecated * @default "src/service-worker" */ serviceWorker?: string; /** * the location of the template for HTML responses + * @deprecated * @default "src/app.html" */ appTemplate?: string; /** * the location of the template for fallback error responses + * @deprecated * @default "src/error.html" */ errorTemplate?: string; diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 5458c54e9715..4739fba0e489 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -397,26 +397,38 @@ declare module '@sveltejs/kit' { }; /** * Where to find various files within your project. + * @deprecated */ files?: { + /** + * the location of your source code + * @deprecated + * @default "src" + * @since 2.28 + */ + src?: string; /** * a place to put static files that should have stable URLs and undergo no processing, such as `favicon.ico` or `manifest.json` + * @deprecated * @default "static" */ assets?: string; hooks?: { /** * The location of your client [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks.client" */ client?: string; /** * The location of your server [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks.server" */ server?: string; /** * The location of your universal [hooks](https://svelte.dev/docs/kit/hooks). + * @deprecated * @default "src/hooks" * @since 2.3.0 */ @@ -424,31 +436,37 @@ declare module '@sveltejs/kit' { }; /** * your app's internal library, accessible throughout the codebase as `$lib` + * @deprecated * @default "src/lib" */ lib?: string; /** * a directory containing [parameter matchers](https://svelte.dev/docs/kit/advanced-routing#Matching) + * @deprecated * @default "src/params" */ params?: string; /** * the files that define the structure of your app (see [Routing](https://svelte.dev/docs/kit/routing)) + * @deprecated * @default "src/routes" */ routes?: string; /** * the location of your service worker's entry point (see [Service workers](https://svelte.dev/docs/kit/service-workers)) + * @deprecated * @default "src/service-worker" */ serviceWorker?: string; /** * the location of the template for HTML responses + * @deprecated * @default "src/app.html" */ appTemplate?: string; /** * the location of the template for fallback error responses + * @deprecated * @default "src/error.html" */ errorTemplate?: string; diff --git a/packages/package/test/index.spec.js b/packages/package/test/index.spec.js index 5bc0412ad7af..c4cec8f8da56 100644 --- a/packages/package/test/index.spec.js +++ b/packages/package/test/index.spec.js @@ -133,11 +133,12 @@ test('create package with typescript using nodenext', async () => { await test_make_package('typescript-nodenext'); }); -// only run this test in older Node versions -// TODO: remove after dropping support for Node 20 -const is_node_without_ts_support = - process.versions.node && Number(process.versions.node.split('.', 1)[0]) < 22; -if (!is_node_without_ts_support) { +// only run this test in newer Node versions +// TODO: remove after dropping support for Node < 22.18 +const [major, minor] = process.versions.node.split('.', 2).map((str) => +str); +const has_ts_support = major > 22 || (major === 22 && minor >= 18); + +if (has_ts_support) { test('create package with typescript using nodenext and svelte.config.ts', async () => { await test_make_package('typescript-svelte-config'); });