Socket
Socket
Sign inDemoInstall

@sveltejs/kit

Package Overview
Dependencies
Maintainers
4
Versions
785
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sveltejs/kit - npm Package Compare versions

Comparing version 1.30.3 to 2.0.0

src/core/sync/write_non_ambient.js

48

package.json
{
"name": "@sveltejs/kit",
"version": "1.30.3",
"version": "2.0.0",
"description": "The fastest way to build Svelte apps",

@@ -14,33 +14,33 @@ "repository": {

"dependencies": {
"@sveltejs/vite-plugin-svelte": "^2.5.0",
"@types/cookie": "^0.5.1",
"cookie": "^0.5.0",
"devalue": "^4.3.1",
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0",
"devalue": "^4.3.2",
"esm-env": "^1.0.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.0",
"magic-string": "^0.30.5",
"mrmime": "^1.0.1",
"sade": "^1.8.1",
"set-cookie-parser": "^2.6.0",
"sirv": "^2.0.2",
"tiny-glob": "^0.2.9",
"undici": "~5.26.2"
"sirv": "^2.0.3",
"tiny-glob": "^0.2.9"
},
"devDependencies": {
"@playwright/test": "1.30.0",
"@types/connect": "^3.4.35",
"@types/node": "^16.18.6",
"@types/sade": "^1.7.4",
"@types/set-cookie-parser": "^2.4.2",
"dts-buddy": "^0.2.4",
"rollup": "^3.29.4",
"svelte": "^4.2.7",
"svelte-preprocess": "^5.1.1",
"typescript": "^4.9.4",
"vite": "^4.4.9",
"vitest": "^0.34.5"
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"@types/connect": "^3.4.38",
"@types/node": "^18.19.3",
"@types/sade": "^1.7.8",
"@types/set-cookie-parser": "^2.4.7",
"dts-buddy": "^0.4.3",
"rollup": "^4.8.0",
"svelte": "^4.2.8",
"svelte-preprocess": "^5.1.2",
"typescript": "^5.3.3",
"vite": "^5.0.8",
"vitest": "^1.0.4"
},
"peerDependencies": {
"svelte": "^3.54.0 || ^4.0.0-next.0 || ^5.0.0-next.0",
"vite": "^4.0.0"
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"svelte": "^4.0.0 || ^5.0.0-next.0",
"vite": "^5.0.3"
},

@@ -84,7 +84,7 @@ "bin": {

"engines": {
"node": "^16.14 || >=18"
"node": ">=18.13"
},
"scripts": {
"lint": "prettier --config ../../.prettierrc --check .",
"check": "tsc",
"check": "tsc && cd ./test/types && tsc",
"check:all": "tsc && pnpm -r --filter=\"./**\" check",

@@ -91,0 +91,0 @@ "format": "prettier --config ../../.prettierrc --write .",

@@ -159,2 +159,9 @@ import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';

generateEnvModule() {
const dest = `${config.kit.outDir}/output/prerendered/dependencies/${config.kit.appDir}/env.js`;
const env = get_env(config.kit.env, vite_config.mode);
write(dest, `export const env=${JSON.stringify(env.public)}`);
},
generateManifest({ relativePath, routes: subset }) {

@@ -217,3 +224,3 @@ return generate_manifest({

}
})
})
: zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });

@@ -220,0 +227,0 @@

@@ -72,3 +72,11 @@ import fs from 'node:fs';

return process_config(config.default, { cwd });
try {
return process_config(config.default, { cwd });
} catch (e) {
const error = /** @type {Error} */ (e);
// redact the stack trace — it's not helpful to users
error.stack = `Could not load svelte.config.js: ${error.message}\n`;
throw error;
}
}

@@ -75,0 +83,0 @@

@@ -114,7 +114,2 @@ import { join } from 'node:path';

dangerZone: object({
// TODO 2.0: Remove this
trackServerFetches: boolean(false)
}),
embedded: boolean(false),

@@ -183,9 +178,3 @@

}),
relative: validate(undefined, (input, keypath) => {
if (typeof input !== 'boolean') {
throw new Error(`${keypath} option must be a boolean or undefined`);
}
return input;
})
relative: boolean(true)
}),

@@ -192,0 +181,0 @@

@@ -13,7 +13,6 @@ import { join } from 'node:path';

import { forked } from '../../utils/fork.js';
import { should_polyfill } from '../../utils/platform.js';
import { installPolyfills } from '../../exports/node/polyfills.js';
import { resolvePath } from '../../exports/index.js';
import { ENDPOINT_METHODS } from '../../constants.js';
import { filter_private_env, filter_public_env } from '../../utils/env.js';
import { resolve_route } from '../../utils/routing.js';

@@ -40,5 +39,3 @@ export default forked(import.meta.url, analyse);

if (should_polyfill) {
installPolyfills();
}
installPolyfills();

@@ -51,4 +48,7 @@ // configure `import { building } from '$app/environment'` —

const { publicPrefix: public_prefix, privatePrefix: private_prefix } = config.env;
internal.set_private_env(filter_private_env(env, { public_prefix, private_prefix }));
internal.set_public_env(filter_public_env(env, { public_prefix, private_prefix }));
const private_env = filter_private_env(env, { public_prefix, private_prefix });
const public_env = filter_public_env(env, { public_prefix, private_prefix });
internal.set_private_env(private_env);
internal.set_public_env(public_env);
internal.set_safe_public_env(public_env);

@@ -61,6 +61,6 @@ /** @type {import('types').ServerMetadata} */

const nodes = await Promise.all(manifest._.nodes.map((loader) => loader()));
// analyse nodes
for (const loader of manifest._.nodes) {
const node = await loader();
for (const node of nodes) {
metadata.nodes[node.index] = {

@@ -73,74 +73,31 @@ has_server_load: node.server?.load !== undefined || node.server?.trailingSlash !== undefined

for (const route of manifest._.routes) {
/** @type {Array<'GET' | 'POST'>} */
const page_methods = [];
const page =
route.page &&
analyse_page(
route.page.layouts.map((n) => (n === undefined ? n : nodes[n])),
nodes[route.page.leaf]
);
/** @type {(import('types').HttpMethod | '*')[]} */
const api_methods = [];
const endpoint = route.endpoint && analyse_endpoint(route, await route.endpoint());
/** @type {import('types').PrerenderOption | undefined} */
let prerender = undefined;
/** @type {any} */
let config = undefined;
/** @type {import('types').PrerenderEntryGenerator | undefined} */
let entries = undefined;
if (page?.prerender && endpoint?.prerender) {
throw new Error(`Cannot prerender a route with both +page and +server files (${route.id})`);
}
if (route.endpoint) {
const mod = await route.endpoint();
if (mod.prerender !== undefined) {
validate_server_exports(mod, route.id);
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
if (page?.config && endpoint?.config) {
for (const key in { ...page.config, ...endpoint.config }) {
if (JSON.stringify(page.config[key]) !== JSON.stringify(endpoint.config[key])) {
throw new Error(
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
`Mismatched route config for ${route.id} — the +page and +server files must export the same config, if any`
);
}
prerender = mod.prerender;
}
for (const method of /** @type {import('types').HttpMethod[]} */ (ENDPOINT_METHODS)) {
if (mod[method]) api_methods.push(method);
}
if (mod.fallback) {
api_methods.push('*');
}
config = mod.config;
entries = mod.entries;
}
if (route.page) {
const nodes = await Promise.all(
[...route.page.layouts, route.page.leaf].map((n) => {
if (n !== undefined) return manifest._.nodes[n]();
})
);
const page_methods = page?.methods ?? [];
const api_methods = endpoint?.methods ?? [];
const entries = page?.entries ?? endpoint?.entries;
const layouts = nodes.slice(0, -1);
const page = nodes.at(-1);
for (const layout of layouts) {
if (layout) {
validate_layout_server_exports(layout.server, layout.server_id);
validate_layout_exports(layout.universal, layout.universal_id);
}
}
if (page) {
page_methods.push('GET');
if (page.server?.actions) page_methods.push('POST');
validate_page_server_exports(page.server, page.server_id);
validate_page_exports(page.universal, page.universal_id);
}
prerender = get_option(nodes, 'prerender') ?? false;
config = get_config(nodes);
entries ??= get_option(nodes, 'entries');
}
metadata.routes.set(route.id, {
config,
config: page?.config ?? endpoint?.config,
methods: Array.from(new Set([...page_methods, ...api_methods])),

@@ -153,5 +110,5 @@ page: {

},
prerender,
prerender: page?.prerender ?? endpoint?.prerender,
entries:
entries && (await entries()).map((entry_object) => resolvePath(route.id, entry_object))
entries && (await entries()).map((entry_object) => resolve_route(route.id, entry_object))
});

@@ -164,2 +121,61 @@ }

/**
* @param {import('types').SSRRoute} route
* @param {import('types').SSREndpoint} mod
*/
function analyse_endpoint(route, mod) {
validate_server_exports(mod, route.id);
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
throw new Error(
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
);
}
/** @type {Array<import('types').HttpMethod | '*'>} */
const methods = [];
for (const method of /** @type {import('types').HttpMethod[]} */ (ENDPOINT_METHODS)) {
if (mod[method]) methods.push(method);
}
if (mod.fallback) {
methods.push('*');
}
return {
config: mod.config,
entries: mod.entries,
methods,
prerender: mod.prerender ?? false
};
}
/**
* @param {Array<import('types').SSRNode | undefined>} layouts
* @param {import('types').SSRNode} leaf
*/
function analyse_page(layouts, leaf) {
for (const layout of layouts) {
if (layout) {
validate_layout_server_exports(layout.server, layout.server_id);
validate_layout_exports(layout.universal, layout.universal_id);
}
}
/** @type {Array<'GET' | 'POST'>} */
const methods = ['GET'];
if (leaf.server?.actions) methods.push('POST');
validate_page_server_exports(leaf.server, leaf.server_id);
validate_page_exports(leaf.universal, leaf.universal_id);
return {
config: get_config([...layouts, leaf]),
entries: leaf.universal?.entries ?? leaf.server?.entries,
methods,
prerender: get_option([...layouts, leaf], 'prerender') ?? false
};
}
/**
* Do a shallow merge (first level) of the config object

@@ -169,11 +185,13 @@ * @param {Array<import('types').SSRNode | undefined>} nodes

function get_config(nodes) {
/** @type {any} */
let current = {};
for (const node of nodes) {
const config = node?.universal?.config ?? node?.server?.config;
if (config) {
current = {
...current,
...config
};
}
if (!node?.universal?.config && !node?.server?.config) continue;
current = {
...current,
...node?.universal?.config,
...node?.server?.config
};
}

@@ -180,0 +198,0 @@

@@ -6,3 +6,2 @@ import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';

import { mkdirp, posixify, walk } from '../../utils/filesystem.js';
import { should_polyfill } from '../../utils/platform.js';
import { decode_uri, is_root_relative, resolve } from '../../utils/url.js';

@@ -98,5 +97,3 @@ import { escape_html_attr } from '../../utils/escape.js';

if (should_polyfill) {
installPolyfills();
}
installPolyfills();

@@ -158,2 +155,3 @@ /** @type {Map<string, string>} */

const files = new Set(walk(`${out}/client`).map(posixify));
files.add(`${config.appDir}/env.js`);

@@ -435,4 +433,8 @@ const immutable = `${config.appDir}/immutable`;

if (prerender) {
if (id.includes('[')) continue;
const path = `/${get_route_segments(id).join('/')}`;
// remove optional parameters from the route
const segments = get_route_segments(id).filter((segment) => !segment.startsWith('[['));
const processed_id = '/' + segments.join('/');
if (processed_id.includes('[')) continue;
const path = `/${get_route_segments(processed_id).join('/')}`;
enqueue(null, config.paths.base + path);

@@ -479,6 +481,6 @@ }

if (not_prerendered.length > 0) {
const list = not_prerendered.map((id) => ` - ${id}`).join('\n');
throw new Error(
`The following routes were marked as prerenderable, but were not prerendered because they were not found while crawling your app:\n${not_prerendered.map(
(id) => ` - ${id}`
)}\n\nSee https://kit.svelte.dev/docs/page-options#prerender-troubleshooting for info on how to solve this`
`The following routes were marked as prerenderable, but were not prerendered because they were not found while crawling your app:\n${list}\n\nSee https://kit.svelte.dev/docs/page-options#prerender-troubleshooting for info on how to solve this`
);

@@ -485,0 +487,0 @@ }

@@ -8,2 +8,3 @@ import path from 'node:path';

import { write_ambient } from './write_ambient.js';
import { write_non_ambient } from './write_non_ambient.js';
import { write_server } from './write_server.js';

@@ -19,2 +20,3 @@

write_ambient(config.kit, mode);
write_non_ambient(config.kit);
}

@@ -21,0 +23,0 @@

@@ -31,9 +31,9 @@ import path from 'node:path';

import { set_assets } from '__sveltekit/paths';
import { set_private_env, set_public_env } from '${runtime_directory}/shared-server.js';
import { set_private_env, set_public_env, set_safe_public_env } from '${runtime_directory}/shared-server.js';
export const options = {
app_dir: ${s(config.kit.appDir)},
app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
csp: ${s(config.kit.csp)},
csrf_check_origin: ${s(config.kit.csrf.checkOrigin)},
track_server_fetches: ${s(config.kit.dangerZone.trackServerFetches)},
embedded: ${config.kit.embedded},

@@ -67,3 +67,3 @@ env_public_prefix: '${config.kit.env.publicPrefix}',

export { set_assets, set_building, set_private_env, set_public_env };
export { set_assets, set_building, set_private_env, set_public_env, set_safe_public_env };
`;

@@ -70,0 +70,0 @@

@@ -6,3 +6,2 @@ import fs from 'node:fs';

import { write_if_changed } from './utils.js';
import { ts } from './ts.js';

@@ -46,34 +45,5 @@ /**

const user_config = load_user_tsconfig(cwd);
if (user_config) validate_user_config(kit, cwd, out, user_config);
if (user_config) validate_user_config(cwd, out, user_config);
// only specify baseUrl if a) the user doesn't specify their own baseUrl
// and b) they have non-relative paths. this causes problems with auto-imports,
// so we print a suggestion that they use relative paths instead
// TODO(v2): never include base URL, and skip the check below
let include_base_url = false;
if (user_config && !user_config.options.compilerOptions?.baseUrl) {
const non_relative_paths = new Set();
for (const paths of Object.values(user_config?.options.compilerOptions?.paths || {})) {
for (const path of paths) {
if (!path.startsWith('.')) non_relative_paths.add(path);
}
}
if (non_relative_paths.size) {
include_base_url = true;
console.log(colors.bold().yellow('Please replace non-relative compilerOptions.paths:\n'));
for (const path of non_relative_paths) {
console.log(` - "${path}" -> "./${path}"`);
}
console.log(
'\nDoing so allows us to omit "baseUrl" — which causes problems with imports — from the generated tsconfig.json. See https://github.com/sveltejs/kit/pull/8437 for more information.'
);
}
}
write_if_changed(out, JSON.stringify(get_tsconfig(kit, include_base_url), null, '\t'));
write_if_changed(out, JSON.stringify(get_tsconfig(kit), null, '\t'));
}

@@ -84,5 +54,4 @@

* @param {import('types').ValidatedKitConfig} kit
* @param {boolean} include_base_url
*/
export function get_tsconfig(kit, include_base_url) {
export function get_tsconfig(kit) {
/** @param {string} file */

@@ -93,2 +62,3 @@ const config_relative = (file) => posixify(path.relative(kit.outDir, file));

'ambient.d.ts',
'non-ambient.d.ts',
'./types/**/$types.d.ts',

@@ -117,3 +87,3 @@ config_relative('vite.config.js'),

const exclude = [config_relative('node_modules/**'), './[!ambient.d.ts]**'];
const exclude = [config_relative('node_modules/**')];
if (path.extname(kit.files.serviceWorker)) {

@@ -130,4 +100,3 @@ exclude.push(config_relative(kit.files.serviceWorker));

// generated options
baseUrl: include_base_url ? config_relative('.') : undefined,
paths: get_tsconfig_paths(kit, include_base_url),
paths: get_tsconfig_paths(kit),
rootDirs: [config_relative('.'), './types'],

@@ -138,8 +107,7 @@

// to enforce using \`import type\` instead of \`import\` for Types.
importsNotUsedAsValues: 'error',
// Also, TypeScript doesn't know about import usages in the template because it only sees the
// script of a Svelte file. Therefore preserve all value imports.
verbatimModuleSyntax: true,
// Vite compiles modules one at a time
isolatedModules: true,
// TypeScript doesn't know about import usages in the template because it only sees the
// script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
preserveValueImports: true,

@@ -149,9 +117,6 @@ // This is required for svelte-package to work as expected

lib: ['esnext', 'DOM', 'DOM.Iterable'],
moduleResolution: 'node', // TODO change to "bundler" in SvelteKit v2
moduleResolution: 'bundler',
module: 'esnext',
noEmit: true, // prevent tsconfig error "overwriting input files" - Vite handles the build and ignores this
target: 'esnext',
// TODO(v2): use the new flag verbatimModuleSyntax instead (requires support by Vite/Esbuild)
ignoreDeprecations: ts && Number(ts.version.split('.')[0]) >= 5 ? '5.0' : undefined
target: 'esnext'
},

@@ -181,3 +146,2 @@ include: [...include],

/**
* @param {import('types').ValidatedKitConfig} kit
* @param {string} cwd

@@ -187,3 +151,3 @@ * @param {string} out

*/
function validate_user_config(kit, cwd, out, config) {
function validate_user_config(cwd, out, config) {
// we need to check that the user's tsconfig extends the framework config

@@ -195,4 +159,4 @@ const extend = config.options.extends;

: Array.isArray(extend)
? extend.some((e) => path.resolve(cwd, e) === out)
: false;
? extend.some((e) => path.resolve(cwd, e) === out)
: false;

@@ -202,25 +166,13 @@ const options = config.options.compilerOptions || {};

if (extends_framework_config) {
const { paths: user_paths } = options;
const { paths, baseUrl } = options;
if (user_paths && fs.existsSync(kit.files.lib)) {
/** @type {string[]} */
const lib = user_paths['$lib'] || [];
/** @type {string[]} */
const lib_ = user_paths['$lib/*'] || [];
// TODO(v2): check needs to be adjusted when we remove the base path
const missing_lib_paths =
!lib.some((relative) => path.resolve(cwd, relative) === kit.files.lib) ||
!lib_.some((relative) => path.resolve(cwd, relative) === path.join(kit.files.lib, '/*'));
if (missing_lib_paths) {
console.warn(
colors
.bold()
.yellow(`Your compilerOptions.paths in ${config.kind} should include the following:`)
);
let relative = posixify(path.relative('.', kit.files.lib));
if (!relative.startsWith('.')) relative = `./${relative}`;
console.warn(`{\n "$lib":["${relative}"],\n "$lib/*":["${relative}/*"]\n}`);
}
if (baseUrl || paths) {
console.warn(
colors
.bold()
.yellow(
`You have specified a baseUrl and/or paths in your ${config.kind} which interferes with SvelteKit's auto-generated tsconfig.json. ` +
'Remove it to avoid problems with intellisense. For path aliases, use `kit.alias` instead: https://kit.svelte.dev/docs/configuration#alias'
)
);
}

@@ -250,5 +202,4 @@ } else {

* @param {import('types').ValidatedKitConfig} config
* @param {boolean} include_base_url
*/
function get_tsconfig_paths(config, include_base_url) {
function get_tsconfig_paths(config) {
/** @param {string} file */

@@ -272,5 +223,3 @@ const config_relative = (file) => posixify(path.relative(config.outDir, file));

const rel_path = (include_base_url ? project_relative : config_relative)(
remove_trailing_slashstar(value)
);
const rel_path = config_relative(remove_trailing_slashstar(value));
const slashstar = key_match[2];

@@ -277,0 +226,0 @@

@@ -483,3 +483,3 @@ import fs from 'node:fs';

: path_to_original(outdir, file_path);
const type = `Kit.AwaitedProperties<Awaited<ReturnType<typeof import('${from}').load>>>`;
const type = `Kit.LoadProperties<Awaited<ReturnType<typeof import('${from}').load>>>`;
return expand ? `Expand<OptionalUnion<EnsureDefined<${type}>>>` : type;

@@ -486,0 +486,0 @@ } else {

@@ -114,3 +114,3 @@ /**

preload
})
})
: resolve(event, { transformPageChunk, filterSerializedResponseHeaders, preload });

@@ -117,0 +117,0 @@ }

import { HttpError, Redirect, ActionFailure } from '../runtime/control.js';
import { BROWSER, DEV } from 'esm-env';
import { get_route_segments } from '../utils/routing.js';

@@ -8,22 +7,54 @@ export { VERSION } from '../version.js';

/**
* @template {number} TNumber
* @template {any[]} [TArray=[]]
* @typedef {TNumber extends TArray['length'] ? TArray[number] : LessThan<TNumber, [...TArray, TArray['length']]>} LessThan
*/
/**
* @template {number} TStart
* @template {number} TEnd
* @typedef {Exclude<TEnd | LessThan<TEnd>, LessThan<TStart>>} NumericRange
*/
// we have to repeat the JSDoc because the display for function overloads is broken
// see https://github.com/microsoft/TypeScript/issues/55056
/**
* Throws an error with a HTTP status code and an optional message.
* When called during request handling, this will cause SvelteKit to
* return an error response without invoking `handleError`.
* Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
* @param {NumericRange<400, 599>} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @param {App.Error} body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
* @overload
* @param {number} status
* @param {NumericRange<400, 599>} status
* @param {App.Error} body
* @return {HttpError}
* @return {never}
* @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling.
* @throws {Error} If the provided status is invalid (not between 400 and 599).
*/
/**
* Throws an error with a HTTP status code and an optional message.
* When called during request handling, this will cause SvelteKit to
* return an error response without invoking `handleError`.
* Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
* @param {NumericRange<400, 599>} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} [body] An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
* @overload
* @param {number} status
* @param {NumericRange<400, 599>} status
* @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} [body]
* @return {HttpError}
* @return {never}
* @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling.
* @throws {Error} If the provided status is invalid (not between 400 and 599).
*/
/**
* Creates an `HttpError` object with an HTTP status code and an optional message.
* This object, if thrown during request handling, will cause SvelteKit to
* Throws an error with a HTTP status code and an optional message.
* When called during request handling, this will cause SvelteKit to
* return an error response without invoking `handleError`.
* Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it.
* @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @param {NumericRange<400, 599>} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @param {{ message: string } extends App.Error ? App.Error | string | undefined : never} body An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
* @return {never}
* @throws {HttpError} This error instructs SvelteKit to initiate HTTP error handling.
* @throws {Error} If the provided status is invalid (not between 400 and 599).
*/

@@ -35,10 +66,25 @@ export function error(status, body) {

return new HttpError(status, body);
throw new HttpError(status, body);
}
/**
* Create a `Redirect` object. If thrown during request handling, SvelteKit will return a redirect response.
* Checks whether this is an error thrown by {@link error}.
* @template {number} T
* @param {unknown} e
* @param {T} [status] The status to filter for.
* @return {e is (HttpError & { status: T extends undefined ? never : T })}
*/
export function isHttpError(e, status) {
if (!(e instanceof HttpError)) return false;
return !status || e.status === status;
}
/**
* Redirect a request. When called during request handling, SvelteKit will return a redirect response.
* Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it.
* @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
* @param {NumericRange<300, 308>} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages). Must be in the range 300-308.
* @param {string | URL} location The location to redirect to.
* @throws {Redirect} This error instructs SvelteKit to redirect to the specified location.
* @throws {Error} If the provided status is invalid.
* @return {never}
*/

@@ -50,6 +96,15 @@ export function redirect(status, location) {

return new Redirect(status, location.toString());
throw new Redirect(status, location.toString());
}
/**
* Checks whether this is a redirect thrown by {@link redirect}.
* @param {unknown} e The object to check.
* @return {e is Redirect}
*/
export function isRedirect(e) {
return e instanceof Redirect;
}
/**
* Create a JSON `Response` object from the supplied data.

@@ -108,64 +163,26 @@ * @param {any} data The value that will be serialized as JSON.

* Create an `ActionFailure` object.
* @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @overload
* @param {number} status
* @returns {import('./public.js').ActionFailure<undefined>}
*/
/**
* Create an `ActionFailure` object.
* @template {Record<string, unknown> | undefined} [T=undefined]
* @param {number} status The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). Must be in the range 400-599.
* @param {T} [data] Data associated with the failure (e.g. validation errors)
* @returns {ActionFailure<T>}
* @param {T} data Data associated with the failure (e.g. validation errors)
* @overload
* @param {number} status
* @param {T} data
* @returns {import('./public.js').ActionFailure<T>}
*/
/**
* Create an `ActionFailure` object.
* @param {number} status
* @param {any} [data]
* @returns {import('./public.js').ActionFailure<any>}
*/
export function fail(status, data) {
// @ts-expect-error unique symbol missing
return new ActionFailure(status, data);
}
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
let warned = false;
/**
* @deprecated Use `resolveRoute` from `$app/paths` instead.
*
* Populate a route ID with params to resolve a pathname.
* @example
* ```js
* resolvePath(
* `/blog/[slug]/[...somethingElse]`,
* {
* slug: 'hello-world',
* somethingElse: 'something/else'
* }
* ); // `/blog/hello-world/something/else`
* ```
* @param {string} id
* @param {Record<string, string | undefined>} params
* @returns {string}
*/
export function resolvePath(id, params) {
if (!warned) {
console.warn('`resolvePath` is deprecated. Use `resolveRoute` from `$app/paths` instead.');
warned = true;
}
const segments = get_route_segments(id);
return (
'/' +
segments
.map((segment) =>
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
const param_value = params[name];
// This is nested so TS correctly narrows the type
if (!param_value) {
if (optional) return '';
if (rest && param_value !== undefined) return '';
throw new Error(`Missing parameter '${name}' in route ${id}`);
}
if (param_value.startsWith('/') || param_value.endsWith('/'))
throw new Error(
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
);
return param_value;
})
)
.filter(Boolean)
.join('/')
);
}
import * as set_cookie_parser from 'set-cookie-parser';
import { error } from '../index.js';
import { SvelteKitError } from '../../runtime/control.js';

@@ -25,15 +25,2 @@ /**

let length = content_length;
if (body_size_limit) {
if (!length) {
length = body_size_limit;
} else if (length > body_size_limit) {
throw error(
413,
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
);
}
}
if (req.destroyed) {

@@ -50,2 +37,13 @@ const readable = new ReadableStream();

start(controller) {
if (body_size_limit !== undefined && content_length > body_size_limit) {
const error = new SvelteKitError(
413,
'Payload Too Large',
`Content-length of ${content_length} exceeds limit of ${body_size_limit} bytes.`
);
controller.error(error);
return;
}
req.on('error', (error) => {

@@ -65,12 +63,11 @@ cancelled = true;

size += chunk.length;
if (size > length) {
if (size > content_length) {
cancelled = true;
controller.error(
error(
413,
`request body size exceeded ${
content_length ? "'content-length'" : 'BODY_SIZE_LIMIT'
} of ${length}`
)
);
const constraint = content_length ? 'content-length' : 'BODY_SIZE_LIMIT';
const message = `request body size exceeded ${constraint} of ${content_length}`;
const error = new SvelteKitError(413, 'Payload Too Large', message);
controller.error(error);
return;

@@ -130,3 +127,3 @@ }

/** @type {string}*/ (response.headers.get(key))
)
)
: value

@@ -133,0 +130,0 @@ );

@@ -1,11 +0,9 @@

import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web';
import buffer from 'node:buffer';
import { webcrypto as crypto } from 'node:crypto';
import { fetch, Response, Request, Headers, FormData, File as UndiciFile } from 'undici';
// `buffer.File` was added in Node 18.13.0 while the `File` global was added in Node 20.0.0
const File = /** @type {import('node:buffer') & { File?: File}} */ (buffer).File ?? UndiciFile;
const File = /** @type {import('node:buffer') & { File?: File}} */ (buffer).File;
/** @type {Record<string, any>} */
const globals_post_node_18_11 = {
const globals = {
crypto,

@@ -15,17 +13,2 @@ File

/** @type {Record<string, any>} */
// TODO: remove this once we only support Node 18.11+ (the version multipart/form-data was added)
const globals_pre_node_18_11 = {
crypto,
fetch,
Response,
Request,
Headers,
ReadableStream,
TransformStream,
WritableStream,
FormData,
File
};
// exported for dev/preview and node environments

@@ -35,20 +18,8 @@ /**

* - `crypto`
* - `fetch` (only in node < 18.11)
* - `Headers` (only in node < 18.11)
* - `Request` (only in node < 18.11)
* - `Response` (only in node < 18.11)
* - `File`
*/
export function installPolyfills() {
// Be defensive (we don't know in which environments this is called) and always apply if something goes wrong
let globals = globals_pre_node_18_11;
try {
const version = process.versions.node.split('.').map((n) => parseInt(n, 10));
if ((version[0] === 18 && version[1] >= 11) || version[0] > 18) {
globals = globals_post_node_18_11;
}
} catch (e) {
// ignore
}
for (const name in globals) {
if (name in globalThis) continue;
for (const name in globals) {
Object.defineProperty(globalThis, name, {

@@ -55,0 +26,0 @@ enumerable: true,

@@ -5,3 +5,3 @@ import 'svelte'; // pick up `declare module "*.svelte"`

import { CompileOptions } from 'svelte/types/compiler/interfaces';
import { CompileOptions } from 'svelte/compiler';
import {

@@ -21,3 +21,2 @@ AdapterEntry,

} from '../types/private.js';
import { ActionFailure } from '../runtime/control.js';
import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from 'types';

@@ -27,3 +26,2 @@ import type { PluginOptions } from '@sveltejs/vite-plugin-svelte';

export { PrerenderOption } from '../types/private.js';
export { ActionFailure };

@@ -45,17 +43,8 @@ /**

type AwaitedPropertiesUnion<input extends Record<string, any> | void> = input extends void
export type LoadProperties<input extends Record<string, any> | void> = input extends void
? undefined // needs to be undefined, because void will break intellisense
: input extends Record<string, any>
? {
[key in keyof input]: Awaited<input[key]>;
}
: {} extends input // handles the any case
? input
: unknown;
? input
: unknown;
export type AwaitedProperties<input extends Record<string, any> | void> =
AwaitedPropertiesUnion<input> extends Record<string, any>
? OptionalUnion<AwaitedPropertiesUnion<input>>
: AwaitedPropertiesUnion<input>;
export type AwaitedActions<T extends Record<string, (...args: any) => any>> = OptionalUnion<

@@ -74,7 +63,15 @@ {

declare const uniqueSymbol: unique symbol;
export interface ActionFailure<T extends Record<string, unknown> | undefined = undefined> {
status: number;
data: T;
[uniqueSymbol]: true; // necessary or else UnpackValidationError could wrongly unpack objects with the same shape as ActionFailure
}
type UnpackValidationError<T> = T extends ActionFailure<infer X>
? X
: T extends void
? undefined // needs to be undefined, because void will corrupt union type
: T;
? undefined // needs to be undefined, because void will corrupt union type
: T;

@@ -113,2 +110,7 @@ /**

/**
* Generate a module exposing build-time environment variables as `$env/dynamic/public`.
*/
generateEnvModule(): void;
/**
* Generate a server-side manifest to initialise the SvelteKit [server](https://kit.svelte.dev/docs/types#public-types-server) with.

@@ -221,3 +223,3 @@ * @param opts a relative path to the base directory of the app and optionally in which format (esm or cjs) the manifest should be generated

*
* By default, the `path` of a cookie is the 'directory' of the current pathname. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app.
* You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children
* @param name the name of the cookie

@@ -227,3 +229,7 @@ * @param value the cookie value

*/
set(name: string, value: string, opts?: import('cookie').CookieSerializeOptions): void;
set(
name: string,
value: string,
opts: import('cookie').CookieSerializeOptions & { path: string }
): void;

@@ -233,7 +239,7 @@ /**

*
* By default, the `path` of a cookie is the 'directory' of the current pathname. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app.
* You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children
* @param name the name of the cookie
* @param opts the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options)
*/
delete(name: string, opts?: import('cookie').CookieSerializeOptions): void;
delete(name: string, opts: import('cookie').CookieSerializeOptions & { path: string }): void;

@@ -245,3 +251,3 @@ /**

*
* By default, the `path` of a cookie is the current pathname. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app.
* You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children
*

@@ -252,3 +258,7 @@ * @param name the name of the cookie

*/
serialize(name: string, value: string, opts?: import('cookie').CookieSerializeOptions): string;
serialize(
name: string,
value: string,
opts: import('cookie').CookieSerializeOptions & { path: string }
): string;
}

@@ -293,3 +303,5 @@

/**
* The directory relative to `paths.assets` where the built JS and CSS (and imported assets) are served from. (The filenames therein contain content-based hashes, meaning they can be cached indefinitely). Must not start or end with `/`.
* The directory where SvelteKit keeps its stuff, including static assets (such as JS and CSS) and internally-used routes.
*
* If `paths.assets` is specified, there will be two app directories — `${paths.assets}/${appDir}` and `${paths.base}/${appDir}`.
* @default "_app"

@@ -359,12 +371,2 @@ */

/**
* Here be dragons. Enable at your peril.
*/
dangerZone?: {
/**
* Automatically add server-side `fetch`ed URLs to the `dependencies` map of `load` functions. This will expose secrets
* to the client if your URL contains them.
*/
trackServerFetches?: boolean;
};
/**
* Whether or not the app is embedded inside a larger app. If `true`, SvelteKit will add its event listeners related to navigation etc on the parent of `%sveltekit.body%` instead of `window`, and will pass `params` from the server rather than inferring them from `location.pathname`.

@@ -489,5 +491,5 @@ * @default false

/**
* Whether to use relative asset paths. By default, if `paths.assets` is not external, SvelteKit will replace `%sveltekit.assets%` with a relative path and use relative paths to reference build artifacts, but `base` and `assets` imported from `$app/paths` will be as specified in your config.
* Whether to use relative asset paths.
*
* If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in portable HTML.
* If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in more portable HTML.
* If `false`, `%sveltekit.assets%` and references to build artifacts will always be root-relative paths, unless `paths.assets` is an external URL

@@ -498,5 +500,8 @@ *

* If your app uses a `<base>` element, you should set this to `false`, otherwise asset URLs will incorrectly be resolved against the `<base>` URL rather than the current page.
* @default undefined
*
* In 1.0, `undefined` was a valid value, which was set by default. In that case, if `paths.assets` was not external, SvelteKit would replace `%sveltekit.assets%` with a relative path and use relative paths to reference build artifacts, but `base` and `assets` imported from `$app/paths` would be as specified in your config.
*
* @default true
*/
relative?: boolean | undefined;
relative?: boolean;
};

@@ -518,3 +523,3 @@ /**

/**
* An array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all non-dynamic routes (i.e. pages with no `[parameters]`, because SvelteKit doesn't know what value the parameters should have).
* An array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all routes containing no required `[parameters]` with optional parameters included as being empty (since SvelteKit doesn't know what value any parameters should have).
* @default ["*"]

@@ -671,2 +676,4 @@ */

event: RequestEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>;

@@ -683,2 +690,4 @@

event: NavigationEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>;

@@ -802,3 +811,17 @@

*/
depends(...deps: string[]): void;
depends(...deps: Array<`${string}:${string}`>): void;
/**
* Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:
*
* ```js
* /// file: src/routes/+page.server.js
* export async function load({ untrack, url }) {
* // Untrack url.pathname so that path changes don't trigger a rerun
* if (untrack(() => url.pathname === '/')) {
* return { message: 'Welcome!' };
* }
* }
* ```
*/
untrack<T>(fn: () => T): T;
}

@@ -870,3 +893,3 @@

* - `form`: The user submitted a `<form>`
* - `leave`: The user is leaving the app by closing the tab or using the back/forward buttons to go to a different document
* - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring
* - `link`: Navigation was triggered by a link click

@@ -976,2 +999,6 @@ * - `goto`: Navigation was triggered by a `goto(...)` call or a redirect

/**
* The page state, which can be manipulated using the [`pushState`](https://kit.svelte.dev/docs/modules#$app-navigation-pushstate) and [`replaceState`](https://kit.svelte.dev/docs/modules#$app-navigation-replacestate) functions from `$app/navigation`.
*/
state: App.PageState;
/**
* Filled only after a form submission. See [form actions](https://kit.svelte.dev/docs/form-actions) for more info.

@@ -1207,2 +1234,16 @@ */

depends(...deps: string[]): void;
/**
* Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:
*
* ```js
* /// file: src/routes/+page.js
* export async function load({ untrack, url }) {
* // Untrack url.pathname so that path changes don't trigger a rerun
* if (untrack(() => url.pathname === '/')) {
* return { message: 'Welcome!' };
* }
* }
* ```
*/
untrack<T>(fn: () => T): T;
}

@@ -1274,13 +1315,3 @@

action: URL;
/**
* use `formData` instead of `data`
* @deprecated
*/
data: FormData;
formData: FormData;
/**
* use `formElement` instead of `form`
* @deprecated
*/
form: HTMLFormElement;
formElement: HTMLFormElement;

@@ -1293,13 +1324,3 @@ controller: AbortController;

| ((opts: {
/**
* use `formData` instead of `data`
* @deprecated
*/
data: FormData;
formData: FormData;
/**
* use `formElement` instead of `form`
* @deprecated
*/
form: HTMLFormElement;
formElement: HTMLFormElement;

@@ -1306,0 +1327,0 @@ action: URL;

@@ -11,3 +11,2 @@ import fs from 'node:fs';

import { posixify, resolve_entry, to_fs } from '../../../utils/filesystem.js';
import { should_polyfill } from '../../../utils/platform.js';
import { load_error_page } from '../../../core/config/index.js';

@@ -30,5 +29,3 @@ import { SVELTE_KIT_ASSETS } from '../../../constants.js';

export async function dev(vite, vite_config, svelte_config) {
if (should_polyfill) {
installPolyfills();
}
installPolyfills();

@@ -128,3 +125,4 @@ const fetch = globalThis.fetch;

stylesheets: [],
fonts: []
fonts: [],
uses_env_dynamic_public: true
},

@@ -229,3 +227,3 @@ nodes: manifest_data.nodes.map((node, index) => {

return await loud_ssr_load_module(url);
}
}
: null,

@@ -364,3 +362,4 @@ endpoint_id: endpoint?.file

HttpError: control_module_vite.HttpError,
Redirect: control_module_vite.Redirect
Redirect: control_module_vite.Redirect,
SvelteKitError: control_module_vite.SvelteKitError
});

@@ -481,14 +480,7 @@ }

let request;
const request = await getRequest({
base,
request: req
});
try {
request = await getRequest({
base,
request: req
});
} catch (/** @type {any} */ err) {
res.statusCode = err.status || 400;
return res.end('Invalid request body');
}
if (manifest_error) {

@@ -546,3 +538,3 @@ console.error(colors.bold().red(manifest_error.message));

function remove_static_middlewares(server) {
const static_middlewares = ['viteServeStaticMiddleware'];
const static_middlewares = ['viteServeStaticMiddleware', 'viteServePublicMiddleware'];
for (let i = server.stack.length - 1; i > 0; i--) {

@@ -549,0 +541,0 @@ // @ts-expect-error using internals

import path from 'node:path';
import { posixify } from '../../../utils/filesystem.js';
import { strip_virtual_prefix } from '../utils.js';
import { env_dynamic_private, env_static_private } from '../module_ids.js';
const ILLEGAL_IMPORTS = new Set([
'\0virtual:$env/dynamic/private',
'\0virtual:$env/static/private'
]);
const ILLEGAL_IMPORTS = new Set([env_dynamic_private, env_static_private]);
const ILLEGAL_MODULE_NAME_PATTERN = /.*\.server\..+/;

@@ -10,0 +8,0 @@

import fs from 'node:fs';
import path from 'node:path';
import path, { join } from 'node:path';

@@ -22,2 +22,3 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';

import { get_config_aliases, get_env, strip_virtual_prefix } from './utils.js';
import { SVELTE_KIT_ASSETS } from '../../constants.js';
import { write_client_manifest } from '../../core/sync/write_client_manifest.js';

@@ -29,5 +30,13 @@ import prerender from '../../core/postbuild/prerender.js';

import { dedent, isSvelte5Plus } from '../../core/sync/utils.js';
import sirv from 'sirv';
import {
env_dynamic_private,
env_dynamic_public,
env_static_private,
env_static_public,
service_worker,
sveltekit_environment,
sveltekit_paths
} from './module_ids.js';
export { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const cwd = process.cwd();

@@ -77,3 +86,3 @@

/** @type {import('@sveltejs/vite-plugin-svelte').PreprocessorGroup} */
/** @type {import('svelte/compiler').PreprocessorGroup} */
const warning_preprocessor = {

@@ -369,9 +378,9 @@ script: ({ content, filename }) => {

switch (id) {
case '\0virtual:$env/static/private':
case env_static_private:
return create_static_module('$env/static/private', env.private);
case '\0virtual:$env/static/public':
case env_static_public:
return create_static_module('$env/static/public', env.public);
case '\0virtual:$env/dynamic/private':
case env_dynamic_private:
return create_dynamic_module(

@@ -382,6 +391,6 @@ 'private',

case '\0virtual:$env/dynamic/public':
case env_dynamic_public:
// populate `$env/dynamic/public` from `window`
if (browser) {
return `export const env = ${global}.env;`;
return `export const env = ${global}.env ?? (await import(/* @vite-ignore */ ${global}.base + '/' + '${kit.appDir}/env.js')).env;`;
}

@@ -394,3 +403,3 @@

case '\0virtual:$service-worker':
case service_worker:
return create_service_worker_module(svelte_config);

@@ -400,3 +409,3 @@

// we use this alias so that we won't collide with user aliases
case '\0virtual:__sveltekit/paths': {
case sveltekit_paths: {
const { assets, base } = svelte_config.kit.paths;

@@ -439,3 +448,3 @@

case '\0virtual:__sveltekit/environment': {
case sveltekit_environment: {
const { version } = svelte_config.kit;

@@ -581,3 +590,3 @@

ssrEmitAssets: true,
target: ssr ? 'node16.14' : undefined
target: ssr ? 'node18.13' : 'es2022'
},

@@ -629,2 +638,27 @@ publicDir: kit.files.assets,

configurePreviewServer(vite) {
// generated client assets and the contents of `static`
// should we use Vite's built-in asset server for this?
// we would need to set the outDir to do so
const { paths } = svelte_config.kit;
const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base;
vite.middlewares.use(
scoped(
assets,
sirv(join(svelte_config.kit.outDir, 'output/client'), {
setHeaders: (res, pathname) => {
if (pathname.startsWith(`/${svelte_config.kit.appDir}/immutable`)) {
res.setHeader('cache-control', 'public,max-age=31536000,immutable');
}
if (vite_config.preview.cors) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, Content-Type, Accept, Range'
);
}
}
})
)
);
return preview(vite, vite_config, svelte_config);

@@ -751,3 +785,6 @@ },

stylesheets: [...start.stylesheets, ...app.stylesheets],
fonts: [...start.fonts, ...app.fonts]
fonts: [...start.fonts, ...app.fonts],
uses_env_dynamic_public: output.some(
(chunk) => chunk.type === 'chunk' && chunk.modules[env_dynamic_public]
)
};

@@ -920,1 +957,23 @@

`;
/**
* @param {string} scope
* @param {(req: import('http').IncomingMessage, res: import('http').ServerResponse, next: () => void) => void} handler
* @returns {(req: import('http').IncomingMessage, res: import('http').ServerResponse, next: () => void) => void}
*/
function scoped(scope, handler) {
if (scope === '') return handler;
return (req, res, next) => {
if (req.url?.startsWith(scope)) {
const original_url = req.url;
req.url = req.url.slice(scope.length);
handler(req, res, () => {
req.url = original_url;
next();
});
} else {
next();
}
};
}

@@ -10,4 +10,2 @@ import fs from 'node:fs';

import { SVELTE_KIT_ASSETS } from '../../../constants.js';
import { should_polyfill } from '../../../utils/platform.js';
import { not_found } from '../utils.js';

@@ -24,8 +22,5 @@ /** @typedef {import('http').IncomingMessage} Req */

export async function preview(vite, vite_config, svelte_config) {
if (should_polyfill) {
installPolyfills();
}
installPolyfills();
const { paths } = svelte_config.kit;
const base = paths.base;
const assets = paths.assets ? SVELTE_KIT_ASSETS : paths.base;

@@ -59,29 +54,18 @@

return () => {
// generated client assets and the contents of `static`
// prerendered dependencies
vite.middlewares.use(
scoped(
assets,
sirv(join(svelte_config.kit.outDir, 'output/client'), {
setHeaders: (res, pathname) => {
// only apply to immutable directory, not e.g. version.json
if (pathname.startsWith(`/${svelte_config.kit.appDir}/immutable`)) {
res.setHeader('cache-control', 'public,max-age=31536000,immutable');
}
}
})
)
mutable(join(svelte_config.kit.outDir, 'output/prerendered/dependencies'))
);
// prerendered pages (we can't just use sirv because we need to
// preserve the correct trailingSlash behaviour)
vite.middlewares.use((req, res, next) => {
const original_url = /** @type {string} */ (req.url);
const { pathname, search } = new URL(original_url, 'http://dummy');
let if_none_match_value = req.headers['if-none-match'];
// if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`,
// regardless of the `trailingSlash` route option
if (base.length > 1 && pathname === base) {
let location = base + '/';
if (search) location += search;
res.writeHead(307, {
location
});
if (if_none_match_value?.startsWith('W/"')) {
if_none_match_value = if_none_match_value.substring(2);
}
if (if_none_match_value === etag) {
res.statusCode = 304;
res.end();

@@ -91,80 +75,50 @@ return;

if (pathname.startsWith(base)) {
next();
} else {
res.statusCode = 404;
not_found(req, res, base);
}
});
const { pathname, search } = new URL(/** @type {string} */ (req.url), 'http://dummy');
// prerendered dependencies
vite.middlewares.use(
scoped(base, mutable(join(svelte_config.kit.outDir, 'output/prerendered/dependencies')))
);
let filename = normalizePath(
join(svelte_config.kit.outDir, 'output/prerendered/pages' + pathname)
);
let prerendered = is_file(filename);
// prerendered pages (we can't just use sirv because we need to
// preserve the correct trailingSlash behaviour)
vite.middlewares.use(
scoped(base, (req, res, next) => {
let if_none_match_value = req.headers['if-none-match'];
if (!prerendered) {
const has_trailing_slash = pathname.endsWith('/');
const html_filename = `${filename}${has_trailing_slash ? 'index.html' : '.html'}`;
if (if_none_match_value?.startsWith('W/"')) {
if_none_match_value = if_none_match_value.substring(2);
}
/** @type {string | undefined} */
let redirect;
if (if_none_match_value === etag) {
res.statusCode = 304;
res.end();
return;
if (is_file(html_filename)) {
filename = html_filename;
prerendered = true;
} else if (has_trailing_slash) {
if (is_file(filename.slice(0, -1) + '.html')) {
redirect = pathname.slice(0, -1);
}
} else if (is_file(filename + '/index.html')) {
redirect = pathname + '/';
}
const { pathname, search } = new URL(/** @type {string} */ (req.url), 'http://dummy');
if (redirect) {
if (search) redirect += search;
res.writeHead(307, {
location: redirect
});
let filename = normalizePath(
join(svelte_config.kit.outDir, 'output/prerendered/pages' + pathname)
);
let prerendered = is_file(filename);
res.end();
if (!prerendered) {
const has_trailing_slash = pathname.endsWith('/');
const html_filename = `${filename}${has_trailing_slash ? 'index.html' : '.html'}`;
/** @type {string | undefined} */
let redirect;
if (is_file(html_filename)) {
filename = html_filename;
prerendered = true;
} else if (has_trailing_slash) {
if (is_file(filename.slice(0, -1) + '.html')) {
redirect = pathname.slice(0, -1);
}
} else if (is_file(filename + '/index.html')) {
redirect = pathname + '/';
}
if (redirect) {
if (search) redirect += search;
res.writeHead(307, {
location: redirect
});
res.end();
return;
}
return;
}
}
if (prerendered) {
res.writeHead(200, {
'content-type': lookup(pathname) || 'text/html',
etag
});
if (prerendered) {
res.writeHead(200, {
'content-type': lookup(pathname) || 'text/html',
etag
});
fs.createReadStream(filename).pipe(res);
} else {
next();
}
})
);
fs.createReadStream(filename).pipe(res);
} else {
next();
}
});

@@ -174,15 +128,9 @@ // SSR

const host = req.headers['host'];
req.url = req.originalUrl;
let request;
const request = await getRequest({
base: `${protocol}://${host}`,
request: req
});
try {
request = await getRequest({
base: `${protocol}://${host}`,
request: req
});
} catch (/** @type {any} */ err) {
res.statusCode = err.status || 400;
return res.end('Invalid request body');
}
setResponse(

@@ -212,27 +160,5 @@ res,

maxAge: 0
})
})
: (_req, _res, next) => next();
/**
* @param {string} scope
* @param {Handler} handler
* @returns {Handler}
*/
function scoped(scope, handler) {
if (scope === '') return handler;
return (req, res, next) => {
if (req.url?.startsWith(scope)) {
const original_url = req.url;
req.url = req.url.slice(scope.length);
handler(req, res, () => {
req.url = original_url;
next();
});
} else {
next();
}
};
}
/** @param {string} path */

@@ -239,0 +165,0 @@ function is_file(path) {

@@ -53,16 +53,2 @@ import * as devalue from 'devalue';

/**
* @param {string} old_name
* @param {string} new_name
* @param {string} call_location
* @returns void
*/
function warn_on_access(old_name, new_name, call_location) {
if (!DEV) return;
// TODO 2.0: Remove this code
console.warn(
`\`${old_name}\` has been deprecated in favor of \`${new_name}\`. \`${old_name}\` will be removed in a future version. (Called from ${call_location})`
);
}
/**
* Shallow clone an element, so that we can access e.g. `form.action` without worrying

@@ -161,7 +147,5 @@ * that someone has added an `<input name="action">` (https://github.com/sveltejs/kit/issues/7593)

if (value instanceof File) {
// TODO 2.0: Upgrade to `throw Error`
console.warn(
'Your form contains <input type="file"> fields, but is missing the `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819. This will be upgraded to an error in v2.0.'
throw new Error(
'Your form contains <input type="file"> fields, but is missing the necessary `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819.'
);
break;
}

@@ -181,3 +165,2 @@ }

// TODO 2.0: Remove `data` and `form`
const callback =

@@ -188,11 +171,3 @@ (await submit({

controller,
get data() {
warn_on_access('data', 'formData', 'use:enhance submit function');
return form_data;
},
formData: form_data,
get form() {
warn_on_access('form', 'formElement', 'use:enhance submit function');
return form_element;
},
formElement: form_element,

@@ -227,11 +202,3 @@ submitter: event.submitter

action,
get data() {
warn_on_access('data', 'formData', 'callback returned from use:enhance submit function');
return form_data;
},
formData: form_data,
get form() {
warn_on_access('form', 'formElement', 'callback returned from use:enhance submit function');
return form_element;
},
formElement: form_element,

@@ -238,0 +205,0 @@ update: (opts) =>

@@ -14,9 +14,3 @@ import { client_method } from '../client/singletons.js';

*
* @type {(url: string | URL, opts?: {
* replaceState?: boolean;
* noScroll?: boolean;
* keepFocus?: boolean;
* invalidateAll?: boolean;
* state?: any
* }) => Promise<void>}
* @type {(url: string | URL, opts?: { replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; }) => Promise<void>}
* @param {string | URL} url Where to navigate to. Note that if you've set [`config.kit.paths.base`](https://kit.svelte.dev/docs/configuration#paths) and the URL is root-relative, you need to prepend the base path if you want to navigate within the app.

@@ -27,4 +21,3 @@ * @param {Object} [opts] Options related to the navigation

* @param {boolean} [opts.keepFocus] If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
* @param {boolean} [invalidateAll] If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#rerunning-load-functions for more info on invalidation.
* @param {any} [opts.state] The state of the new/updated history entry
* @param {boolean} [opts.invalidateAll] If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#rerunning-load-functions for more info on invalidation.
* @returns {Promise<void>}

@@ -69,7 +62,7 @@ */

* If the next navigation is to `href`, the values returned from load will be used, making navigation instantaneous.
* Returns a Promise that resolves when the preload is complete.
* Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete.
*
* @type {(href: string) => Promise<void>}
* @type {(href: string) => Promise<Record<string, any>>}
* @param {string} href Page to preload
* @returns {Promise<void>}
* @returns {Promise<{ type: 'loaded'; status: number; data: Record<string, any> } | { type: 'redirect'; location: string }>}
*/

@@ -87,4 +80,4 @@ export const preloadData = /* @__PURE__ */ client_method('preload_data');

*
* @type {(...urls: string[]) => Promise<void>}
* @param {...string[]} urls
* @type {(url: string) => Promise<void>}
* @param {string} url
* @returns {Promise<void>}

@@ -118,3 +111,3 @@ */

* `onNavigate` must be called during a component initialization. It remains active as long as the component is mounted.
* @type {(callback: (navigation: import('@sveltejs/kit').OnNavigate) => import('../../types/internal.js').MaybePromise<(() => void) | void>) => void}
* @type {(callback: (navigation: import('@sveltejs/kit').OnNavigate) => import('types').MaybePromise<(() => void) | void>) => void}
* @param {(navigation: import('@sveltejs/kit').OnNavigate) => void} callback

@@ -134,1 +127,21 @@ * @returns {void}

export const afterNavigate = /* @__PURE__ */ client_method('after_navigate');
/**
* Programmatically create a new history entry with the given `$page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://kit.svelte.dev/docs/shallow-routing).
*
* @type {(url: string | URL, state: App.PageState) => void}
* @param {string | URL} url
* @param {App.PageState} state
* @returns {void}
*/
export const pushState = /* @__PURE__ */ client_method('push_state');
/**
* Programmatically replace the current history entry with the given `$page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](https://kit.svelte.dev/docs/shallow-routing).
*
* @type {(url: string | URL, state: App.PageState) => void}
* @param {string | URL} url
* @param {App.PageState} state
* @returns {void}
*/
export const replaceState = /* @__PURE__ */ client_method('replace_state');
export { base, assets } from '__sveltekit/paths';
import { base } from '__sveltekit/paths';
import { get_route_segments } from '../../utils/routing.js';
import { resolve_route } from '../../utils/routing.js';
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
/**

@@ -24,28 +22,3 @@ * Populate a route ID with params to resolve a pathname.

export function resolveRoute(id, params) {
const segments = get_route_segments(id);
return (
base +
'/' +
segments
.map((segment) =>
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
const param_value = params[name];
// This is nested so TS correctly narrows the type
if (!param_value) {
if (optional) return '';
if (rest && param_value !== undefined) return '';
throw new Error(`Missing parameter '${name}' in route ${id}`);
}
if (param_value.startsWith('/') || param_value.endsWith('/'))
throw new Error(
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
);
return param_value;
})
)
.filter(Boolean)
.join('/')
);
return base + resolve_route(id, params);
}
export const SNAPSHOT_KEY = 'sveltekit:snapshot';
export const SCROLL_KEY = 'sveltekit:scroll';
export const INDEX_KEY = 'sveltekit:index';
export const STATES_KEY = 'sveltekit:states';
export const PAGE_URL_KEY = 'sveltekit:pageurl';
export const HISTORY_INDEX = 'sveltekit:history';
export const NAVIGATION_INDEX = 'sveltekit:navigation';
export const PRELOAD_PRIORITIES = /** @type {const} */ ({

@@ -6,0 +10,0 @@ tap: 1,

/**
* Read a value from `sessionStorage`
* @param {string} key
* @param {(value: string) => any} parse
*/
export function get(key) {
export function get(key, parse = JSON.parse) {
try {
return JSON.parse(sessionStorage[key]);
return parse(sessionStorage[key]);
} catch {

@@ -17,7 +18,8 @@ // do nothing

* @param {any} value
* @param {(value: any) => string} stringify
*/
export function set(key, value) {
const json = JSON.stringify(value);
export function set(key, value, stringify = JSON.stringify) {
const data = stringify(value);
try {
sessionStorage[key] = json;
sessionStorage[key] = data;
} catch {

@@ -24,0 +26,0 @@ // do nothing

@@ -24,3 +24,9 @@ import { writable } from 'svelte/store';

if (!BROWSER) {
if (key === 'before_navigate' || key === 'after_navigate' || key === 'on_navigate') {
if (
key === 'before_navigate' ||
key === 'after_navigate' ||
key === 'on_navigate' ||
key === 'push_state' ||
key === 'replace_state'
) {
// @ts-expect-error doesn't recognize that both keys here return void so expects a async function

@@ -27,0 +33,0 @@ return () => {};

@@ -10,3 +10,5 @@ import { applyAction } from '../app/forms.js';

preloadCode,
preloadData
preloadData,
pushState,
replaceState
} from '../app/navigation.js';

@@ -55,2 +57,4 @@ import { SvelteComponent } from 'svelte';

preload_data: typeof preloadData;
push_state: typeof pushState;
replace_state: typeof replaceState;
apply_action: typeof applyAction;

@@ -97,3 +101,3 @@

components?: Array<SvelteComponent>;
page?: Page;
page: Page;
form?: Record<string, any> | null;

@@ -100,0 +104,0 @@ [key: `data_${number}`]: Record<string, any>;

@@ -11,12 +11,14 @@ import { BROWSER, DEV } from 'esm-env';

/** @param {HTMLDocument} doc */
export function get_base_uri(doc) {
let baseURI = doc.baseURI;
/** @param {string | URL} url */
export function resolve_url(url) {
if (url instanceof URL) return url;
let baseURI = document.baseURI;
if (!baseURI) {
const baseTags = doc.getElementsByTagName('base');
baseURI = baseTags.length ? baseTags[0].href : doc.URL;
const baseTags = document.getElementsByTagName('base');
baseURI = baseTags.length ? baseTags[0].href : document.URL;
}
return baseURI;
return new URL(url, baseURI);
}

@@ -151,3 +153,3 @@

/** @type {ValidLinkOptions<'keepfocus'> | null} */
let keep_focus = null;
let keepfocus = null;

@@ -175,3 +177,3 @@ /** @type {ValidLinkOptions<'noscroll'> | null} */

if (preload_data === null) preload_data = link_option(el, 'preload-data');
if (keep_focus === null) keep_focus = link_option(el, 'keepfocus');
if (keepfocus === null) keepfocus = link_option(el, 'keepfocus');
if (noscroll === null) noscroll = link_option(el, 'noscroll');

@@ -194,3 +196,3 @@ if (reload === null) reload = link_option(el, 'reload');

default:
return null;
return undefined;
}

@@ -202,3 +204,3 @@ }

preload_data: levels[preload_data ?? 'off'],
keep_focus: get_option_state(keep_focus),
keepfocus: get_option_state(keepfocus),
noscroll: get_option_state(noscroll),

@@ -205,0 +207,0 @@ reload: get_option_state(reload),

@@ -33,11 +33,16 @@ export class HttpError {

export class NotFound extends Error {
/**
* An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
* `SvelteKitError` goes through `handleError`.
*/
export class SvelteKitError extends Error {
/**
* @param {string} pathname
* @param {number} status
* @param {string} text
* @param {string} message
*/
constructor(pathname) {
super();
this.status = 404;
this.message = `Not found: ${pathname}`;
constructor(status, text, message) {
super(message);
this.status = status;
this.text = text;
}

@@ -52,3 +57,3 @@ }

* @param {number} status
* @param {T} [data]
* @param {T} data
*/

@@ -71,2 +76,3 @@ constructor(status, data) {

* Redirect: typeof Redirect;
* SvelteKitError: typeof SvelteKitError;
* }} implementations

@@ -81,2 +87,4 @@ */

Redirect = implementations.Redirect; // eslint-disable-line no-class-assign
// @ts-expect-error
SvelteKitError = implementations.SvelteKitError; // eslint-disable-line no-class-assign
}
import { parse, serialize } from 'cookie';
import { normalize_path, resolve } from '../../utils/url.js';
import { warn_with_callsite } from './utils.js';
import { add_data_suffix, normalize_path, resolve } from '../../utils/url.js';

@@ -18,21 +17,8 @@ /**

/**
*
* @param {import('cookie').CookieSerializeOptions} opts
* @param {'set' | 'delete' | 'serialize'} method
*/
function deprecate_missing_path(opts, method) {
if (opts.path === undefined) {
warn_with_callsite(
`Calling \`cookies.${method}(...)\` without specifying a \`path\` is deprecated, and will be disallowed in SvelteKit 2.0. Relative paths can be used`,
1
);
// TODO 3.0 remove this check
/** @param {import('./page/types.js').Cookie['options']} options */
function validate_options(options) {
if (options?.path === undefined) {
throw new Error('You must specify a `path` when setting, deleting or serializing cookies');
}
if (opts.path === '') {
warn_with_callsite(
`Calling \`cookies.${method}(...)\` with \`path: ''\` will behave differently in SvelteKit 2.0. Instead of using the browser default behaviour, it will set the cookie path to the current pathname`,
1
);
}
}

@@ -50,4 +36,2 @@

const normalized_url = normalize_path(url.pathname, trailing_slash);
// Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
const default_path = normalized_url.split('/').slice(0, -1).join('/') || '/';

@@ -131,7 +115,7 @@ /** @type {Record<string, import('./page/types.js').Cookie>} */

* @param {string} value
* @param {import('cookie').CookieSerializeOptions} opts
* @param {import('./page/types.js').Cookie['options']} options
*/
set(name, value, opts = {}) {
deprecate_missing_path(opts, 'set');
set_internal(name, value, { ...defaults, ...opts });
set(name, value, options) {
validate_options(options);
set_internal(name, value, { ...defaults, ...options });
},

@@ -141,12 +125,7 @@

* @param {string} name
* @param {import('cookie').CookieSerializeOptions} opts
* @param {import('./page/types.js').Cookie['options']} options
*/
delete(name, opts = {}) {
deprecate_missing_path(opts, 'delete');
cookies.set(name, '', {
path: default_path, // TODO 2.0 remove this
...opts,
maxAge: 0
});
delete(name, options) {
validate_options(options);
cookies.set(name, '', { ...options, maxAge: 0 });
},

@@ -157,11 +136,14 @@

* @param {string} value
* @param {import('cookie').CookieSerializeOptions} opts
* @param {import('./page/types.js').Cookie['options']} options
*/
serialize(name, value, opts = {}) {
deprecate_missing_path(opts, 'serialize');
serialize(name, value, options) {
validate_options(options);
return serialize(name, value, {
...defaults,
...opts
});
let path = options.path;
if (!options.domain || options.domain === url.hostname) {
path = resolve(normalized_url, path);
}
return serialize(name, value, { ...defaults, ...options, path });
}

@@ -207,23 +189,12 @@ };

* @param {string} value
* @param {import('cookie').CookieSerializeOptions} opts
* @param {import('./page/types.js').Cookie['options']} options
*/
function set_internal(name, value, opts) {
let path = opts.path;
function set_internal(name, value, options) {
let path = options.path;
if (!opts.domain || opts.domain === url.hostname) {
if (path) {
if (path[0] === '.') path = resolve(url.pathname, path);
} else {
path = default_path;
}
if (!options.domain || options.domain === url.hostname) {
path = resolve(normalized_url, path);
}
new_cookies[name] = {
name,
value,
options: {
...opts,
path
}
};
new_cookies[name] = { name, value, options: { ...options, path } };

@@ -239,6 +210,4 @@ if (__SVELTEKIT_DEV__) {

if (!value) {
// @ts-expect-error temporary
cookie_paths[name].delete(path);
} else {
// @ts-expect-error temporary
cookie_paths[name].add(path);

@@ -286,2 +255,10 @@ }

headers.append('set-cookie', serialize(name, value, options));
// special case — for routes ending with .html, the route data lives in a sibling
// `.html__data.json` file rather than a child `/__data.json` file, which means
// we need to duplicate the cookie
if (options.path.endsWith('.html')) {
const path = add_data_suffix(options.path);
headers.append('set-cookie', serialize(name, value, { ...options, path }));
}
}

@@ -288,0 +265,0 @@ }

@@ -1,2 +0,2 @@

import { HttpError, Redirect } from '../../control.js';
import { HttpError, SvelteKitError, Redirect } from '../../control.js';
import { normalize_error } from '../../../utils/error.js';

@@ -79,4 +79,3 @@ import { once } from '../../../utils/functions.js';

return data;
},
track_server_fetches: options.track_server_fetches
}
});

@@ -114,3 +113,6 @@ } catch (e) {

error: await handle_error_and_jsonify(event, options, error),
status: error instanceof HttpError ? error.status : undefined
status:
error instanceof HttpError || error instanceof SvelteKitError
? error.status
: undefined
});

@@ -117,0 +119,0 @@ })

@@ -12,3 +12,3 @@ import * as set_cookie_parser from 'set-cookie-parser';

* get_cookie_header: (url: URL, header: string | null) => string;
* set_internal: (name: string, value: string, opts: import('cookie').CookieSerializeOptions) => void;
* set_internal: (name: string, value: string, opts: import('./page/types.js').Cookie['options']) => void;
* }} opts

@@ -138,8 +138,9 @@ * @returns {typeof fetch}

const path = options.path ?? (url.pathname.split('/').slice(0, -1).join('/') || '/');
// options.sameSite is string, something more specific is required - type cast is safe
set_internal(
name,
value,
/** @type {import('cookie').CookieSerializeOptions} */ (options)
);
set_internal(name, value, {
path,
.../** @type {import('cookie').CookieSerializeOptions} */ (options)
});
}

@@ -146,0 +147,0 @@ }

import { respond } from './respond.js';
import { set_private_env, set_public_env } from '../shared-server.js';
import { set_private_env, set_public_env, set_safe_public_env } from '../shared-server.js';
import { options, get_hooks } from '__SERVER__/internal.js';
import { DEV } from 'esm-env';
import { filter_private_env, filter_public_env } from '../../utils/env.js';
import { building } from '../app/environment.js';
/** @type {ProxyHandler<{ type: 'public' | 'private' }>} */
const prerender_env_handler = {
get({ type }, prop) {
throw new Error(
`Cannot read values from $env/dynamic/${type} while prerendering (attempted to read env.${prop.toString()}). Use $env/static/${type} instead`
);
}
};
export class Server {

@@ -30,16 +40,16 @@ /** @type {import('types').SSROptions} */

// been done already.
// set env, in case it's used in initialisation
set_private_env(
filter_private_env(env, {
public_prefix: this.#options.env_public_prefix,
private_prefix: this.#options.env_private_prefix
})
);
set_public_env(
filter_public_env(env, {
public_prefix: this.#options.env_public_prefix,
private_prefix: this.#options.env_private_prefix
})
);
const prefixes = {
public_prefix: this.#options.env_public_prefix,
private_prefix: this.#options.env_private_prefix
};
const private_env = filter_private_env(env, prefixes);
const public_env = filter_public_env(env, prefixes);
set_private_env(building ? new Proxy({ type: 'private' }, prerender_env_handler) : private_env);
set_public_env(building ? new Proxy({ type: 'public' }, prerender_env_handler) : public_env);
set_safe_public_env(public_env);
if (!this.#options.hooks) {

@@ -75,9 +85,2 @@ try {

async respond(request, options) {
// TODO this should probably have been removed for 1.0 — i think we can get rid of it?
if (!(request instanceof Request)) {
throw new Error(
'The first argument to server.respond must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details'
);
}
return respond(request, this.#options, this.#manifest, {

@@ -84,0 +87,0 @@ ...options,

import * as devalue from 'devalue';
import { error, json } from '../../../exports/index.js';
import { normalize_error } from '../../../utils/error.js';
import { json } from '../../../exports/index.js';
import { get_status, normalize_error } from '../../../utils/error.js';
import { is_form_content_type, negotiate } from '../../../utils/http.js';
import { HttpError, Redirect, ActionFailure } from '../../control.js';
import { HttpError, Redirect, ActionFailure, SvelteKitError } from '../../control.js';
import { handle_error_and_jsonify } from '../utils.js';

@@ -27,4 +27,7 @@

if (!actions) {
// TODO should this be a different error altogether?
const no_actions_error = error(405, 'POST method not allowed. No actions exist for this page');
const no_actions_error = new SvelteKitError(
405,
'Method Not Allowed',
'POST method not allowed. No actions exist for this page'
);
return action_json(

@@ -85,3 +88,3 @@ {

{
status: err instanceof HttpError ? err.status : 500
status: get_status(err)
}

@@ -144,3 +147,7 @@ );

type: 'error',
error: error(405, 'POST method not allowed. No actions exist for this page')
error: new SvelteKitError(
405,
'Method Not Allowed',
'POST method not allowed. No actions exist for this page'
)
};

@@ -204,3 +211,3 @@ }

* @param {NonNullable<import('types').SSRNode['server']['actions']>} actions
* @throws {Redirect | ActionFailure | HttpError | Error}
* @throws {Redirect | HttpError | SvelteKitError | Error}
*/

@@ -223,8 +230,12 @@ async function call_action(event, actions) {

if (!action) {
throw new Error(`No action with name '${name}' found`);
throw new SvelteKitError(404, 'Not Found', `No action with name '${name}' found`);
}
if (!is_form_content_type(event.request)) {
throw new Error(
`Actions expect form-encoded data (received ${event.request.headers.get('content-type')})`
throw new SvelteKitError(
415,
'Unsupported Media Type',
`Form actions expect form-encoded data — received ${event.request.headers.get(
'content-type'
)}`
);

@@ -239,9 +250,7 @@ }

if (data instanceof Redirect) {
throw new Error('Cannot `return redirect(...)` — use `throw redirect(...)` instead');
throw new Error('Cannot `return redirect(...)` — use `redirect(...)` instead');
}
if (data instanceof HttpError) {
throw new Error(
'Cannot `return error(...)` — use `throw error(...)` or `return fail(...)` instead'
);
throw new Error('Cannot `return error(...)` — use `error(...)` or `return fail(...)` instead');
}

@@ -248,0 +257,0 @@ }

import { text } from '../../../exports/index.js';
import { compact } from '../../../utils/array.js';
import { normalize_error } from '../../../utils/error.js';
import { get_status, normalize_error } from '../../../utils/error.js';
import { add_data_suffix } from '../../../utils/url.js';
import { HttpError, Redirect } from '../../control.js';
import { Redirect } from '../../control.js';
import { redirect_response, static_error_page, handle_error_and_jsonify } from '../utils.js';

@@ -68,4 +68,3 @@ import {

if (action_result?.type === 'error') {
const error = action_result.error;
status = error instanceof HttpError ? error.status : 500;
status = get_status(action_result.error);
}

@@ -82,3 +81,3 @@ if (action_result?.type === 'failure') {

// SvelteKit will erroneously believe that the path has been prerendered,
// causing functions to be omitted from the manifesst generated later
// causing functions to be omitted from the manifest generated later
const should_prerender = get_option(nodes, 'prerender') ?? false;

@@ -155,4 +154,3 @@ if (should_prerender) {

return data;
},
track_server_fetches: options.track_server_fetches
}
});

@@ -228,3 +226,3 @@ } catch (e) {

const status = err instanceof HttpError ? err.status : 500;
const status = get_status(err);
const error = await handle_error_and_jsonify(event, options, err);

@@ -231,0 +229,0 @@

@@ -0,4 +1,3 @@

import { DEV } from 'esm-env';
import { disable_search, make_trackable } from '../../../utils/url.js';
import { unwrap_promises } from '../../../utils/promises.js';
import { DEV } from 'esm-env';
import { validate_depends } from '../../shared.js';

@@ -13,17 +12,10 @@

* parent: () => Promise<Record<string, any>>;
* track_server_fetches: boolean;
* }} opts
* @returns {Promise<import('types').ServerDataNode | null>}
*/
export async function load_server_data({
event,
state,
node,
parent,
// TODO 2.0: Remove this
track_server_fetches
}) {
export async function load_server_data({ event, state, node, parent }) {
if (!node?.server) return null;
let done = false;
let is_tracking = true;

@@ -35,15 +27,32 @@ const uses = {

route: false,
url: false
url: false,
search_params: new Set()
};
const url = make_trackable(event.url, () => {
if (DEV && done && !uses.url) {
console.warn(
`${node.server_id}: Accessing URL properties in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the URL changes`
);
const url = make_trackable(
event.url,
() => {
if (DEV && done && !uses.url) {
console.warn(
`${node.server_id}: Accessing URL properties in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the URL changes`
);
}
if (is_tracking) {
uses.url = true;
}
},
(param) => {
if (DEV && done && !uses.search_params.has(param)) {
console.warn(
`${node.server_id}: Accessing URL properties in a promise handler after \`load(...)\` has returned will not cause the function to re-run when the URL changes`
);
}
if (is_tracking) {
uses.search_params.add(param);
}
}
);
uses.url = true;
});
if (state.prerendering) {

@@ -64,7 +73,3 @@ disable_search(url);

// TODO 2.0: Remove this
if (track_server_fetches) {
uses.dependencies.add(url.href);
}
// Note: server fetches are not added to uses.depends due to security concerns
return event.fetch(info, init);

@@ -100,3 +105,5 @@ },

uses.params.add(key);
if (is_tracking) {
uses.params.add(key);
}
return target[/** @type {string} */ (key)];

@@ -112,3 +119,5 @@ }

uses.parent = true;
if (is_tracking) {
uses.parent = true;
}
return parent();

@@ -126,12 +135,21 @@ },

uses.route = true;
if (is_tracking) {
uses.route = true;
}
return target[/** @type {'id'} */ (key)];
}
}),
url
url,
untrack(fn) {
is_tracking = false;
try {
return fn();
} finally {
is_tracking = true;
}
}
});
const data = result ? await unwrap_promises(result, node.server_id) : null;
if (__SVELTEKIT_DEV__) {
validate_load_response(data, node.server_id);
validate_load_response(result, node.server_id);
}

@@ -143,3 +161,3 @@

type: 'data',
data,
data: result ?? null,
uses,

@@ -188,11 +206,11 @@ slash: node.server.trailingSlash

depends: () => {},
parent
parent,
untrack: (fn) => fn()
});
const data = result ? await unwrap_promises(result, node.universal_id) : null;
if (__SVELTEKIT_DEV__) {
validate_load_response(data, node.universal_id);
validate_load_response(result, node.universal_id);
}
return data;
return result ?? null;
}

@@ -409,6 +427,6 @@

: data instanceof Response
? 'a Response object'
: Array.isArray(data)
? 'an array'
: 'a non-plain object'
? 'a Response object'
: Array.isArray(data)
? 'an array'
: 'a non-plain object'
}, but must return a plain object at the top level (i.e. \`return {...}\`)`

@@ -415,0 +433,0 @@ );

@@ -11,3 +11,3 @@ import * as devalue from 'devalue';

import { clarify_devalue_error, stringify_uses, handle_error_and_jsonify } from '../utils.js';
import { public_env } from '../../shared-server.js';
import { public_env, safe_public_env } from '../../shared-server.js';
import { text } from '../../../exports/index.js';

@@ -99,3 +99,3 @@ import { create_async_iterator } from '../../../utils/streaming.js';

// if appropriate, use relative paths for greater portability
if (paths.relative !== false && !state.prerendering?.fallback) {
if (paths.relative && !state.prerendering?.fallback) {
const segments = event.url.pathname.slice(paths.base.length).split('/').slice(2);

@@ -146,3 +146,4 @@

data,
form: form_value
form: form_value,
state: {}
};

@@ -282,2 +283,6 @@

if (page_config.csr) {
if (client.uses_env_dynamic_public && state.prerendering) {
modulepreloads.add(`${options.app_dir}/env.js`);
}
const included_modulepreloads = Array.from(modulepreloads, (dep) => prefixed(dep)).filter(

@@ -302,3 +307,3 @@ (path) => resolve_opts.preload({ type: 'js', path })

`base: ${base_expression}`,
`env: ${s(public_env)}`
`env: ${!client.uses_env_dynamic_public || state.prerendering ? null : s(public_env)}`
].filter(Boolean);

@@ -439,3 +444,3 @@

nonce: /** @type {string} */ (csp.nonce),
env: public_env
env: safe_public_env
});

@@ -476,3 +481,3 @@

headers
})
})
: new Response(

@@ -495,3 +500,3 @@ new ReadableStream({

}
);
);
}

@@ -498,0 +503,0 @@

@@ -5,3 +5,4 @@ import { render_response } from './render.js';

import { get_option } from '../../../utils/options.js';
import { HttpError, Redirect } from '../../control.js';
import { Redirect } from '../../control.js';
import { get_status } from '../../../utils/error.js';

@@ -53,4 +54,3 @@ /**

node: default_layout,
parent: async () => ({}),
track_server_fetches: options.track_server_fetches
parent: async () => ({})
});

@@ -109,3 +109,3 @@

options,
e instanceof HttpError ? e.status : 500,
get_status(e),
(await handle_error_and_jsonify(event, options, e)).message

@@ -112,0 +112,0 @@ );

@@ -35,3 +35,3 @@ import { CookieSerializeOptions } from 'cookie';

value: string;
options: CookieSerializeOptions;
options: CookieSerializeOptions & { path: string };
}

@@ -21,3 +21,3 @@ import { DEV } from 'esm-env';

import { create_fetch } from './fetch.js';
import { Redirect, NotFound } from '../control.js';
import { HttpError, Redirect, SvelteKitError } from '../control.js';
import {

@@ -31,5 +31,6 @@ validate_layout_exports,

import { get_option } from '../../utils/options.js';
import { error, json, text } from '../../exports/index.js';
import { json, text } from '../../exports/index.js';
import { action_json_redirect, is_action_json_request } from './page/actions.js';
import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
import { get_public_env } from './env_module.js';

@@ -72,3 +73,6 @@ /* global __SVELTEKIT_ADAPTER_NAME__ */

if (forbidden) {
const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);
const csrf_error = new HttpError(
403,
`Cross-site ${request.method} form submissions are forbidden`
);
if (request.headers.get('accept') === 'application/json') {

@@ -101,2 +105,6 @@ return json(csrf_error.body, { status: csrf_error.status });

if (decoded === `/${options.app_dir}/env.js`) {
return get_public_env(request);
}
const is_data_request = has_data_suffix(decoded);

@@ -348,4 +356,4 @@ /** @type {boolean[] | undefined} */

: route?.page && is_action_json_request(event)
? action_json_redirect(e)
: redirect_response(e.status, e.location);
? action_json_redirect(e)
: redirect_response(e.status, e.location);
add_cookies_to_headers(response.headers, Object.values(cookies_to_add));

@@ -364,8 +372,2 @@ return response;

if (opts) {
if ('ssr' in opts) {
throw new Error(
'ssr has been removed, set it in the appropriate +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197'
);
}
resolve_opts = {

@@ -489,3 +491,3 @@ transformPageChunk: opts.transformPageChunk || default_transform,

status: 404,
error: new NotFound(event.url.pathname),
error: new SvelteKitError(404, 'Not Found', `Not found: ${event.url.pathname}`),
resolve_opts

@@ -492,0 +494,0 @@ });

import { DEV } from 'esm-env';
import { json, text } from '../../exports/index.js';
import { coalesce_to_error } from '../../utils/error.js';
import { coalesce_to_error, get_message, get_status } from '../../utils/error.js';
import { negotiate } from '../../utils/http.js';
import { HttpError, NotFound } from '../control.js';
import { HttpError } from '../control.js';
import { fix_stack_trace } from '../shared-server.js';

@@ -73,3 +73,3 @@ import { ENDPOINT_METHODS } from '../../constants.js';

error = error instanceof HttpError ? error : coalesce_to_error(error);
const status = error instanceof HttpError ? error.status : 500;
const status = get_status(error);
const body = await handle_error_and_jsonify(event, options, error);

@@ -107,7 +107,6 @@

return (
(await options.hooks.handleError({ error, event })) ?? {
message: event.route.id === null && error instanceof NotFound ? 'Not Found' : 'Internal Error'
}
);
const status = get_status(error);
const message = get_message(error);
return (await options.hooks.handleError({ error, event, status, message })) ?? { message };
}

@@ -154,2 +153,6 @@

if (node.uses && node.uses.search_params.size > 0) {
uses.push(`"search_params":${JSON.stringify(Array.from(node.uses.search_params))}`);
}
if (node.uses && node.uses.params.size > 0) {

@@ -156,0 +159,0 @@ uses.push(`"params":${JSON.stringify(Array.from(node.uses.params))}`);

@@ -1,7 +0,19 @@

/** @type {Record<string, string>} */
/**
* `$env/dynamic/private`
* @type {Record<string, string>}
*/
export let private_env = {};
/** @type {Record<string, string>} */
/**
* `$env/dynamic/public`. When prerendering, this will be a proxy that forbids reads
* @type {Record<string, string>}
*/
export let public_env = {};
/**
* The same as `public_env`, but without the proxy. Use for `%sveltekit.env.PUBLIC_FOO%`
* @type {Record<string, string>}
*/
export let safe_public_env = {};
/** @param {any} error */

@@ -20,2 +32,7 @@ export let fix_stack_trace = (error) => error?.stack;

/** @type {(environment: Record<string, string>) => void} */
export function set_safe_public_env(environment) {
safe_public_env = environment;
}
/** @param {(error: Error) => string} value */

@@ -22,0 +39,0 @@ export function set_fix_stack_trace(value) {

@@ -10,2 +10,3 @@ /**

* // interface PageData {}
* // interface PageState {}
* // interface Platform {}

@@ -44,2 +45,7 @@ * }

/**
* The shape of the `$page.state` object, which can be manipulated using the [`pushState`](https://kit.svelte.dev/docs/modules#$app-navigation-pushstate) and [`replaceState`](https://kit.svelte.dev/docs/modules#$app-navigation-replacestate) functions from `$app/navigation`.
*/
export interface PageState {}
/**
* If your adapter provides [platform-specific context](https://kit.svelte.dev/docs/adapters#platform-specific-context) via `event.platform`, you can specify it here.

@@ -106,3 +112,3 @@ */

export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets';
export let relative: boolean | undefined; // TODO in 2.0, make this a `boolean` that defaults to `true`
export let relative: boolean;
export function reset(): void;

@@ -109,0 +115,0 @@ export function override(paths: { base: string; assets: string }): void;

@@ -34,2 +34,3 @@ import { SvelteComponent } from 'svelte';

set_public_env(environment: Record<string, string>): void;
set_safe_public_env(environment: Record<string, string>): void;
set_version(version: string): void;

@@ -63,2 +64,3 @@ set_fix_stack_trace(fix_stack_trace: (error: unknown) => string): void;

fonts: string[];
uses_env_dynamic_public: boolean;
} | null;

@@ -335,6 +337,6 @@ server_manifest: import('vite').Manifest;

export interface SSROptions {
app_dir: string;
app_template_contains_nonce: boolean;
csp: ValidatedConfig['kit']['csp'];
csrf_check_origin: boolean;
track_server_fetches: boolean;
embedded: boolean;

@@ -414,2 +416,3 @@ env_public_prefix: string;

url: boolean;
search_params: Set<string>;
}

@@ -416,0 +419,0 @@

@@ -5,2 +5,4 @@ This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node) (or running [`vite preview`](https://kit.svelte.dev/docs/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://kit.svelte.dev/docs/configuration#env) (if configured).

Dynamic environment variables cannot be used during prerendering.
```ts

@@ -7,0 +9,0 @@ import { env } from '$env/dynamic/private';

@@ -5,2 +5,4 @@ Similar to [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.

Dynamic environment variables cannot be used during prerendering.
```ts

@@ -7,0 +9,0 @@ import { env } from '$env/dynamic/public';

@@ -0,1 +1,3 @@

import { HttpError, SvelteKitError } from '../runtime/control.js';
/**

@@ -19,5 +21,19 @@ * @param {unknown} err

export function normalize_error(error) {
return /** @type {import('../runtime/control.js').Redirect | import('../runtime/control.js').HttpError | Error} */ (
return /** @type {import('../runtime/control.js').Redirect | HttpError | SvelteKitError | Error} */ (
error
);
}
/**
* @param {unknown} error
*/
export function get_status(error) {
return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500;
}
/**
* @param {unknown} error
*/
export function get_message(error) {
return error instanceof SvelteKitError ? error.text : 'Internal Error';
}

@@ -94,3 +94,3 @@ const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;

.join('')}/?$`
);
);

@@ -218,1 +218,47 @@ return { pattern, params };

}
const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
/**
* Populate a route ID with params to resolve a pathname.
* @example
* ```js
* resolveRoute(
* `/blog/[slug]/[...somethingElse]`,
* {
* slug: 'hello-world',
* somethingElse: 'something/else'
* }
* ); // `/blog/hello-world/something/else`
* ```
* @param {string} id
* @param {Record<string, string | undefined>} params
* @returns {string}
*/
export function resolve_route(id, params) {
const segments = get_route_segments(id);
return (
'/' +
segments
.map((segment) =>
segment.replace(basic_param_pattern, (_, optional, rest, name) => {
const param_value = params[name];
// This is nested so TS correctly narrows the type
if (!param_value) {
if (optional) return '';
if (rest && param_value !== undefined) return '';
throw new Error(`Missing parameter '${name}' in route ${id}`);
}
if (param_value.startsWith('/') || param_value.endsWith('/'))
throw new Error(
`Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
);
return param_value;
})
)
.filter(Boolean)
.join('/')
);
}

@@ -9,3 +9,3 @@ import { BROWSER } from 'esm-env';

const absolute = /^([a-z]+:)?\/?\//;
const internal = new URL('sveltekit-internal://');

@@ -17,27 +17,9 @@ /**

export function resolve(base, path) {
if (SCHEME.test(path)) return path;
if (path[0] === '#') return base + path;
// special case
if (path[0] === '/' && path[1] === '/') return path;
const base_match = absolute.exec(base);
const path_match = absolute.exec(path);
let url = new URL(base, internal);
url = new URL(path, url);
if (!base_match) {
throw new Error(`bad base path: "${base}"`);
}
const baseparts = path_match ? [] : base.slice(base_match[0].length).split('/');
const pathparts = path_match ? path.slice(path_match[0].length).split('/') : path.split('/');
baseparts.pop();
for (let i = 0; i < pathparts.length; i += 1) {
const part = pathparts[i];
if (part === '.') continue;
else if (part === '..') baseparts.pop();
else baseparts.push(part);
}
const prefix = (path_match && path_match[0]) || (base_match && base_match[0]) || '';
return `${prefix}${baseparts.join('/')}`;
return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href;
}

@@ -101,2 +83,10 @@

/**
* Returns everything up to the first `#` in a URL
* @param {{href: string}} url_like
*/
export function strip_hash({ href }) {
return href.split('#')[0];
}
/**
* URL properties that could change during the lifetime of the page,

@@ -109,3 +99,2 @@ * which excludes things like `origin`

'search',
'searchParams',
'toString',

@@ -118,6 +107,29 @@ 'toJSON'

* @param {() => void} callback
* @param {(search_param: string) => void} search_params_callback
*/
export function make_trackable(url, callback) {
export function make_trackable(url, callback, search_params_callback) {
const tracked = new URL(url);
Object.defineProperty(tracked, 'searchParams', {
value: new Proxy(tracked.searchParams, {
get(obj, key) {
if (key === 'get' || key === 'getAll' || key === 'has') {
return (/**@type {string}*/ param) => {
search_params_callback(param);
return obj[key](param);
};
}
// if they try to access something different from what is in `tracked_search_params_properties`
// we track the whole url (entries, values, keys etc)
callback();
const value = Reflect.get(obj, key);
return typeof value === 'function' ? value.bind(obj) : value;
}
}),
enumerable: true,
configurable: true
});
for (const property of tracked_url_properties) {

@@ -193,6 +205,7 @@ Object.defineProperty(tracked, property, {

const DATA_SUFFIX = '/__data.json';
const HTML_DATA_SUFFIX = '.html__data.json';
/** @param {string} pathname */
export function has_data_suffix(pathname) {
return pathname.endsWith(DATA_SUFFIX);
return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX);
}

@@ -202,2 +215,3 @@

export function add_data_suffix(pathname) {
if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX);
return pathname.replace(/\/$/, '') + DATA_SUFFIX;

@@ -208,3 +222,7 @@ }

export function strip_data_suffix(pathname) {
if (pathname.endsWith(HTML_DATA_SUFFIX)) {
return pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';
}
return pathname.slice(0, -DATA_SUFFIX.length);
}
// generated during release, do not modify
/** @type {string} */
export const VERSION = '1.30.3';
export const VERSION = '2.0.0';

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc