@sveltejs/kit
Advanced tools
Comparing version 1.25.1 to 1.27.2
{ | ||
"name": "@sveltejs/kit", | ||
"version": "1.25.1", | ||
"version": "1.27.2", | ||
"description": "The fastest way to build Svelte apps", | ||
@@ -21,3 +21,3 @@ "repository": { | ||
"magic-string": "^0.30.0", | ||
"mime": "^3.0.0", | ||
"mrmime": "^1.0.1", | ||
"sade": "^1.8.1", | ||
@@ -27,3 +27,3 @@ "set-cookie-parser": "^2.6.0", | ||
"tiny-glob": "^0.2.9", | ||
"undici": "~5.25.0" | ||
"undici": "~5.26.2" | ||
}, | ||
@@ -33,3 +33,2 @@ "devDependencies": { | ||
"@types/connect": "^3.4.35", | ||
"@types/mime": "^3.0.1", | ||
"@types/node": "^16.18.6", | ||
@@ -41,7 +40,7 @@ "@types/sade": "^1.7.4", | ||
"rollup": "^3.7.0", | ||
"svelte": "^4.0.5", | ||
"svelte": "^4.2.2", | ||
"svelte-preprocess": "^5.0.4", | ||
"typescript": "^4.9.4", | ||
"vite": "^4.4.2", | ||
"vitest": "^0.34.0" | ||
"vite": "^4.4.9", | ||
"vitest": "^0.34.5" | ||
}, | ||
@@ -48,0 +47,0 @@ "peerDependencies": { |
@@ -184,3 +184,6 @@ import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs'; | ||
writeClient(dest) { | ||
return copy(`${config.kit.outDir}/output/client`, dest); | ||
return copy(`${config.kit.outDir}/output/client`, dest, { | ||
// avoid making vite build artefacts public | ||
filter: (basename) => basename !== '.vite' | ||
}); | ||
}, | ||
@@ -187,0 +190,0 @@ |
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import colors from 'kleur'; | ||
import mime from 'mime'; | ||
import { lookup } from 'mrmime'; | ||
import { list_files, runtime_directory } from '../../utils.js'; | ||
@@ -51,3 +51,3 @@ import { posixify } from '../../../utils/filesystem.js'; | ||
size: fs.statSync(path.resolve(config.kit.files.assets, file)).size, | ||
type: mime.getType(file) | ||
type: lookup(file) || null | ||
})); | ||
@@ -54,0 +54,0 @@ } |
@@ -191,8 +191,16 @@ import fs from 'node:fs'; | ||
declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;'); | ||
// returns the predicate of a matcher's type guard - or string if there is no type guard | ||
declarations.push( | ||
`type RouteParams = { ${route.params | ||
.map((param) => `${param.name}${param.optional ? '?' : ''}: string`) | ||
.join('; ')} }` | ||
// TS complains on infer U, which seems weird, therefore ts-ignore it | ||
[ | ||
'// @ts-ignore', | ||
'type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;' | ||
].join('\n') | ||
); | ||
declarations.push( | ||
'type RouteParams = ' + generate_params_type(route.params, outdir, config) + ';' | ||
); | ||
if (route.params.length > 0) { | ||
@@ -269,3 +277,4 @@ exports.push( | ||
let all_pages_have_load = true; | ||
const layout_params = new Set(); | ||
/** @type {import('types').RouteParam[]} */ | ||
const layout_params = []; | ||
const ids = ['RouteId']; | ||
@@ -279,3 +288,5 @@ | ||
for (const param of leaf.route.params) { | ||
layout_params.add(param.name); | ||
// skip if already added | ||
if (layout_params.some((p) => p.name === param.name)) continue; | ||
layout_params.push({ ...param, optional: true }); | ||
} | ||
@@ -307,5 +318,3 @@ | ||
declarations.push( | ||
`type LayoutParams = RouteParams & { ${Array.from(layout_params).map( | ||
(param) => `${param}?: string` | ||
)} }` | ||
'type LayoutParams = RouteParams & ' + generate_params_type(layout_params, outdir, config) | ||
); | ||
@@ -575,2 +584,24 @@ | ||
/** | ||
* @param {import('types').RouteParam[]} params | ||
* @param {string} outdir | ||
* @param {import('types').ValidatedConfig} config | ||
*/ | ||
function generate_params_type(params, outdir, config) { | ||
/** @param {string} matcher */ | ||
const path_to_matcher = (matcher) => | ||
posixify(path.relative(outdir, path.join(config.kit.files.params, matcher))); | ||
return `{ ${params | ||
.map( | ||
(param) => | ||
`${param.name}${param.optional ? '?' : ''}: ${ | ||
param.matcher | ||
? `MatcherParam<typeof import('${path_to_matcher(param.matcher)}').match>` | ||
: 'string' | ||
}` | ||
) | ||
.join('; ')} }`; | ||
} | ||
/** | ||
* @param {string} content | ||
@@ -577,0 +608,0 @@ * @param {boolean} is_server |
@@ -6,8 +6,15 @@ import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web'; | ||
// @ts-expect-error | ||
const File = buffer.File ?? UndiciFile; | ||
// `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; | ||
/** @type {Record<string, any>} */ | ||
const globals = { | ||
const globals_post_node_18_11 = { | ||
crypto, | ||
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, | ||
@@ -25,12 +32,22 @@ Response, | ||
// exported for dev/preview and node environments | ||
// TODO: remove this once we only support Node 18.11+ (the version multipart/form-data was added) | ||
/** | ||
* Make various web APIs available as globals: | ||
* - `crypto` | ||
* - `fetch` | ||
* - `Headers` | ||
* - `Request` | ||
* - `Response` | ||
* - `fetch` (only in node < 18.11) | ||
* - `Headers` (only in node < 18.11) | ||
* - `Request` (only in node < 18.11) | ||
* - `Response` (only in node < 18.11) | ||
*/ | ||
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) { | ||
@@ -37,0 +54,0 @@ Object.defineProperty(globalThis, name, { |
@@ -206,3 +206,3 @@ import 'svelte'; // pick up `declare module "*.svelte"` | ||
* Gets all cookies that were previously set with `cookies.set`, or from the request headers. | ||
* @param opts the options, passed directily to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) | ||
* @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) | ||
*/ | ||
@@ -219,3 +219,3 @@ getAll(opts?: import('cookie').CookieParseOptions): Array<{ name: string; value: string }>; | ||
* @param value the cookie value | ||
* @param opts the options, passed directory to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) | ||
* @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) | ||
*/ | ||
@@ -229,3 +229,3 @@ set(name: string, value: string, opts?: import('cookie').CookieSerializeOptions): void; | ||
* @param name the name of the cookie | ||
* @param opts the options, passed directory 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) | ||
* @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) | ||
*/ | ||
@@ -243,3 +243,3 @@ delete(name: string, opts?: import('cookie').CookieSerializeOptions): void; | ||
* @param value the cookie value | ||
* @param opts the options, passed directory to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) | ||
* @param opts the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) | ||
*/ | ||
@@ -1289,4 +1289,5 @@ serialize(name: string, value: string, opts?: import('cookie').CookieSerializeOptions): string; | ||
* @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission. | ||
* @param invalidateAll Set `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission. | ||
*/ | ||
update(options?: { reset: boolean }): Promise<void>; | ||
update(options?: { reset?: boolean; invalidateAll?: boolean }): Promise<void>; | ||
}) => void) | ||
@@ -1293,0 +1294,0 @@ >; |
import path from 'node:path'; | ||
import { posixify } from '../../../utils/filesystem.js'; | ||
import { strip_virtual_prefix } from '../utils.js'; | ||
const ILLEGAL_IMPORTS = new Set(['\0$env/dynamic/private', '\0$env/static/private']); | ||
const ILLEGAL_IMPORTS = new Set([ | ||
'\0virtual:$env/dynamic/private', | ||
'\0virtual:$env/static/private' | ||
]); | ||
const ILLEGAL_MODULE_NAME_PATTERN = /.*\.server\..+/; | ||
@@ -54,6 +58,10 @@ | ||
return `${' '.repeat(i * 2)}- ${id} ${dynamic ? 'dynamically imports' : 'imports'}\n`; | ||
}) + `${' '.repeat(chain.length)}- ${id}`; | ||
return `${' '.repeat(i * 2)}- ${strip_virtual_prefix(id)} ${ | ||
dynamic ? 'dynamically imports' : 'imports' | ||
}\n`; | ||
}) + `${' '.repeat(chain.length)}- ${strip_virtual_prefix(id)}`; | ||
const message = `Cannot import ${id} into client-side code:\n${pyramid}`; | ||
const message = `Cannot import ${strip_virtual_prefix( | ||
id | ||
)} into client-side code:\n${pyramid}`; | ||
@@ -60,0 +68,0 @@ throw new Error(message); |
@@ -21,3 +21,3 @@ import fs from 'node:fs'; | ||
import { preview } from './preview/index.js'; | ||
import { get_config_aliases, get_env } from './utils.js'; | ||
import { get_config_aliases, get_env, strip_virtual_prefix } from './utils.js'; | ||
import { write_client_manifest } from '../../core/sync/write_client_manifest.js'; | ||
@@ -340,3 +340,3 @@ import prerender from '../../core/postbuild/prerender.js'; | ||
if (id.startsWith('$env/') || id.startsWith('__sveltekit/') || id === '$service-worker') { | ||
return `\0${id}`; | ||
return `\0virtual:${id}`; | ||
} | ||
@@ -363,3 +363,3 @@ }, | ||
const relative = normalize_id(id, normalized_lib, normalized_cwd); | ||
throw new Error(`Cannot import ${relative} into client-side code`); | ||
throw new Error(`Cannot import ${strip_virtual_prefix(relative)} into client-side code`); | ||
} | ||
@@ -369,9 +369,9 @@ } | ||
switch (id) { | ||
case '\0$env/static/private': | ||
case '\0virtual:$env/static/private': | ||
return create_static_module('$env/static/private', env.private); | ||
case '\0$env/static/public': | ||
case '\0virtual:$env/static/public': | ||
return create_static_module('$env/static/public', env.public); | ||
case '\0$env/dynamic/private': | ||
case '\0virtual:$env/dynamic/private': | ||
return create_dynamic_module( | ||
@@ -382,3 +382,3 @@ 'private', | ||
case '\0$env/dynamic/public': | ||
case '\0virtual:$env/dynamic/public': | ||
// populate `$env/dynamic/public` from `window` | ||
@@ -394,3 +394,3 @@ if (browser) { | ||
case '\0$service-worker': | ||
case '\0virtual:$service-worker': | ||
return create_service_worker_module(svelte_config); | ||
@@ -400,3 +400,3 @@ | ||
// we use this alias so that we won't collide with user aliases | ||
case '\0__sveltekit/paths': { | ||
case '\0virtual:__sveltekit/paths': { | ||
const { assets, base } = svelte_config.kit.paths; | ||
@@ -439,3 +439,3 @@ | ||
case '\0__sveltekit/environment': { | ||
case '\0virtual:__sveltekit/environment': { | ||
const { version } = svelte_config.kit; | ||
@@ -566,3 +566,3 @@ | ||
// don't use the default name to avoid collisions with 'static/manifest.json' | ||
manifest: 'vite-manifest.json', | ||
manifest: '.vite/manifest.json', // TODO: remove this after bumping peer dep to vite 5 | ||
outDir: `${out}/${ssr ? 'server' : 'client'}`, | ||
@@ -817,6 +817,2 @@ rollupOptions: { | ||
// avoid making the manifest available to users | ||
fs.unlinkSync(`${out}/client/${vite_config.build.manifest}`); | ||
fs.unlinkSync(`${out}/server/${vite_config.build.manifest}`); | ||
if (kit.adapter) { | ||
@@ -823,0 +819,0 @@ const { adapt } = await import('../../core/adapt/index.js'); |
import fs from 'node:fs'; | ||
import { join } from 'node:path'; | ||
import { pathToFileURL } from 'node:url'; | ||
import { lookup } from 'mrmime'; | ||
import sirv from 'sirv'; | ||
@@ -144,3 +145,3 @@ import { loadEnv, normalizePath } from 'vite'; | ||
res.writeHead(200, { | ||
'content-type': 'text/html', | ||
'content-type': lookup(pathname) || 'text/html', | ||
etag | ||
@@ -147,0 +148,0 @@ }); |
@@ -100,1 +100,3 @@ import path from 'node:path'; | ||
} | ||
export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', ''); |
@@ -107,2 +107,3 @@ import * as devalue from 'devalue'; | ||
* action: URL; | ||
* invalidateAll?: boolean; | ||
* result: import('@sveltejs/kit').ActionResult; | ||
@@ -112,9 +113,16 @@ * reset?: boolean | ||
*/ | ||
const fallback_callback = async ({ action, result, reset }) => { | ||
const fallback_callback = async ({ | ||
action, | ||
result, | ||
reset = true, | ||
invalidateAll: shouldInvalidateAll = true | ||
}) => { | ||
if (result.type === 'success') { | ||
if (reset !== false) { | ||
if (reset) { | ||
// We call reset from the prototype to avoid DOM clobbering | ||
HTMLFormElement.prototype.reset.call(form_element); | ||
} | ||
await invalidateAll(); | ||
if (shouldInvalidateAll) { | ||
await invalidateAll(); | ||
} | ||
} | ||
@@ -227,3 +235,9 @@ | ||
formElement: form_element, | ||
update: (opts) => fallback_callback({ action, result, reset: opts?.reset }), | ||
update: (opts) => | ||
fallback_callback({ | ||
action, | ||
result, | ||
reset: opts?.reset, | ||
invalidateAll: opts?.invalidateAll | ||
}), | ||
// @ts-expect-error generic constraints stuff we don't care about | ||
@@ -230,0 +244,0 @@ result |
@@ -176,3 +176,3 @@ import { DEV } from 'esm-env'; | ||
if (navigation_result.type === 'redirect') { | ||
return goto(new URL(navigation_result.location, url).href, {}, [url.pathname], nav_token); | ||
return goto(new URL(navigation_result.location, url).href, {}, 1, nav_token); | ||
} else { | ||
@@ -212,3 +212,3 @@ if (navigation_result.props.page !== undefined) { | ||
* @param {{ noScroll?: boolean; replaceState?: boolean; keepFocus?: boolean; state?: any; invalidateAll?: boolean }} opts | ||
* @param {string[]} redirect_chain | ||
* @param {number} redirect_count | ||
* @param {{}} [nav_token] | ||
@@ -225,3 +225,3 @@ */ | ||
}, | ||
redirect_chain, | ||
redirect_count, | ||
nav_token | ||
@@ -237,3 +237,3 @@ ) { | ||
keepfocus: keepFocus, | ||
redirect_chain, | ||
redirect_count, | ||
details: { | ||
@@ -948,3 +948,3 @@ state, | ||
* keepfocus: boolean; | ||
* redirect_chain: string[]; | ||
* redirect_count: number; | ||
* details: { | ||
@@ -965,3 +965,3 @@ * replaceState: boolean; | ||
keepfocus, | ||
redirect_chain, | ||
redirect_count, | ||
details, | ||
@@ -1023,3 +1023,4 @@ type, | ||
if (navigation_result.type === 'redirect') { | ||
if (redirect_chain.length > 10 || redirect_chain.includes(url.pathname)) { | ||
// whatwg fetch spec https://fetch.spec.whatwg.org/#http-redirect-fetch says to error after 20 redirects | ||
if (redirect_count >= 20) { | ||
navigation_result = await load_root_error_page({ | ||
@@ -1036,8 +1037,3 @@ status: 500, | ||
} else { | ||
goto( | ||
new URL(navigation_result.location, url).href, | ||
{}, | ||
[...redirect_chain, url.pathname], | ||
nav_token | ||
); | ||
goto(new URL(navigation_result.location, url).href, {}, redirect_count + 1, nav_token); | ||
return false; | ||
@@ -1390,3 +1386,3 @@ } | ||
goto: (href, opts = {}) => { | ||
return goto(href, opts, []); | ||
return goto(href, opts, 0); | ||
}, | ||
@@ -1452,3 +1448,3 @@ | ||
} else if (result.type === 'redirect') { | ||
goto(result.location, { invalidateAll: true }, []); | ||
goto(result.location, { invalidateAll: true }, 0); | ||
} else { | ||
@@ -1608,3 +1604,3 @@ /** @type {Record<string, any>} */ | ||
keepfocus: options.keep_focus ?? false, | ||
redirect_chain: [], | ||
redirect_count: 0, | ||
details: { | ||
@@ -1663,3 +1659,3 @@ state: {}, | ||
keepfocus: keep_focus ?? false, | ||
redirect_chain: [], | ||
redirect_count: 0, | ||
details: { | ||
@@ -1677,2 +1673,3 @@ state: {}, | ||
addEventListener('popstate', async (event) => { | ||
token = {}; | ||
if (event.state?.[INDEX_KEY]) { | ||
@@ -1684,6 +1681,8 @@ // if a popstate-driven navigation is cancelled, we need to counteract it | ||
const scroll = scroll_positions[event.state[INDEX_KEY]]; | ||
const url = new URL(location.href); | ||
// if the only change is the hash, we don't need to do anything... | ||
if (current.url.href.split('#')[0] === location.href.split('#')[0]) { | ||
// ...except handle scroll | ||
// ...except update our internal URL tracking and handle scroll | ||
update_url(url); | ||
scroll_positions[current_history_index] = scroll_state(); | ||
@@ -1698,6 +1697,6 @@ current_history_index = event.state[INDEX_KEY]; | ||
await navigate({ | ||
url: new URL(location.href), | ||
url, | ||
scroll, | ||
keepfocus: false, | ||
redirect_chain: [], | ||
redirect_count: 0, | ||
details: null, | ||
@@ -1711,3 +1710,4 @@ accepted: () => { | ||
type: 'popstate', | ||
delta | ||
delta, | ||
nav_token: token | ||
}); | ||
@@ -1714,0 +1714,0 @@ } else { |
@@ -26,2 +26,6 @@ import { DEV } from 'esm-env'; | ||
/** | ||
* @param {RequestInfo | URL} input | ||
* @param {RequestInit & Record<string, any> | undefined} init | ||
*/ | ||
window.fetch = (input, init) => { | ||
@@ -40,6 +44,10 @@ // Check if fetch was called via load_node. the lock method only checks if it was called at the | ||
const heuristic = can_inspect_stack_trace | ||
const in_load_heuristic = can_inspect_stack_trace | ||
? stack.includes('src/runtime/client/client.js') | ||
: loading; | ||
if (heuristic) { | ||
// This flag is set in initial_fetch and subsequent_fetch | ||
const used_kit_fetch = init?.__sveltekit_fetch__; | ||
if (in_load_heuristic && !used_kit_fetch) { | ||
console.warn( | ||
@@ -91,3 +99,3 @@ `Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/load#making-fetch-requests` | ||
return native_fetch(resource, opts); | ||
return DEV ? dev_fetch(resource, opts) : window.fetch(resource, opts); | ||
} | ||
@@ -118,6 +126,21 @@ | ||
return native_fetch(resolved, opts); | ||
return DEV ? dev_fetch(resolved, opts) : window.fetch(resolved, opts); | ||
} | ||
/** | ||
* @param {RequestInfo | URL} resource | ||
* @param {RequestInit & Record<string, any> | undefined} opts | ||
*/ | ||
function dev_fetch(resource, opts) { | ||
const patched_opts = { ...opts }; | ||
// This assigns the __sveltekit_fetch__ flag and makes it non-enumerable | ||
Object.defineProperty(patched_opts, '__sveltekit_fetch__', { | ||
value: true, | ||
writable: true, | ||
configurable: true | ||
}); | ||
return window.fetch(resource, patched_opts); | ||
} | ||
/** | ||
* Build the cache key for a given request | ||
@@ -124,0 +147,0 @@ * @param {URL | RequestInfo} resource |
// generated during release, do not modify | ||
/** @type {string} */ | ||
export const VERSION = '1.25.1'; | ||
export const VERSION = '1.27.2'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
673510
13
348980
19791
5
9
1
72
+ Addedmrmime@^1.0.1
+ Addedmrmime@1.0.1(transitive)
+ Addedundici@5.26.5(transitive)
- Removedmime@^3.0.0
- Removedmime@3.0.0(transitive)
- Removedundici@5.25.4(transitive)
Updatedundici@~5.26.2