@sveltejs/kit 2.15.3 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -6
- package/src/core/sync/utils.js +2 -9
- package/src/core/sync/write_types/index.js +10 -0
- package/src/exports/index.js +8 -0
- package/src/exports/public.d.ts +44 -44
- package/src/exports/vite/build/build_server.js +44 -8
- package/src/exports/vite/dev/index.js +1 -1
- package/src/exports/vite/index.js +2 -2
- package/src/runtime/app/forms.js +3 -0
- package/src/runtime/client/client.js +73 -27
- package/src/runtime/client/fetcher.js +2 -2
- package/src/runtime/client/utils.js +1 -1
- package/src/runtime/server/cookie.js +2 -2
- package/src/runtime/server/endpoint.js +5 -0
- package/src/runtime/server/respond.js +15 -16
- package/src/utils/import.js +11 -6
- package/src/version.js +1 -1
- package/types/index.d.ts +56 -44
- package/types/index.d.ts.map +1 -1
- package/postinstall.js +0 -55
|
@@ -8,13 +8,7 @@ import {
|
|
|
8
8
|
make_trackable,
|
|
9
9
|
normalize_path
|
|
10
10
|
} from '../../utils/url.js';
|
|
11
|
-
import {
|
|
12
|
-
initial_fetch,
|
|
13
|
-
lock_fetch,
|
|
14
|
-
native_fetch,
|
|
15
|
-
subsequent_fetch,
|
|
16
|
-
unlock_fetch
|
|
17
|
-
} from './fetcher.js';
|
|
11
|
+
import { dev_fetch, initial_fetch, lock_fetch, subsequent_fetch, unlock_fetch } from './fetcher.js';
|
|
18
12
|
import { parse } from './parse.js';
|
|
19
13
|
import * as storage from './session-storage.js';
|
|
20
14
|
import {
|
|
@@ -312,7 +306,9 @@ export async function start(_app, _target, hydrate) {
|
|
|
312
306
|
if (hydrate) {
|
|
313
307
|
await _hydrate(target, hydrate);
|
|
314
308
|
} else {
|
|
315
|
-
goto(location.href
|
|
309
|
+
goto(app.hash ? decode_hash(new URL(location.href)) : location.href, {
|
|
310
|
+
replaceState: true
|
|
311
|
+
});
|
|
316
312
|
}
|
|
317
313
|
|
|
318
314
|
_start_router();
|
|
@@ -380,7 +376,7 @@ function persist_state() {
|
|
|
380
376
|
|
|
381
377
|
/**
|
|
382
378
|
* @param {string | URL} url
|
|
383
|
-
* @param {{ replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; state?: Record<string, any> }} options
|
|
379
|
+
* @param {{ replaceState?: boolean; noScroll?: boolean; keepFocus?: boolean; invalidateAll?: boolean; invalidate?: Array<string | URL | ((url: URL) => boolean)>; state?: Record<string, any> }} options
|
|
384
380
|
* @param {number} redirect_count
|
|
385
381
|
* @param {{}} [nav_token]
|
|
386
382
|
*/
|
|
@@ -398,6 +394,10 @@ async function _goto(url, options, redirect_count, nav_token) {
|
|
|
398
394
|
if (options.invalidateAll) {
|
|
399
395
|
force_invalidation = true;
|
|
400
396
|
}
|
|
397
|
+
|
|
398
|
+
if (options.invalidate) {
|
|
399
|
+
options.invalidate.forEach(push_invalidated);
|
|
400
|
+
}
|
|
401
401
|
}
|
|
402
402
|
});
|
|
403
403
|
}
|
|
@@ -428,9 +428,15 @@ async function _preload_data(intent) {
|
|
|
428
428
|
return load_cache.promise;
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* @param {URL} url
|
|
433
|
+
* @returns {Promise<void>}
|
|
434
|
+
*/
|
|
432
435
|
async function _preload_code(url) {
|
|
433
|
-
const
|
|
436
|
+
const rerouted = get_rerouted_url(url);
|
|
437
|
+
if (!rerouted) return;
|
|
438
|
+
|
|
439
|
+
const route = routes.find((route) => route.exec(get_url_path(rerouted)));
|
|
434
440
|
|
|
435
441
|
if (route) {
|
|
436
442
|
await Promise.all([...route.layouts, route.leaf].map((load) => load?.[1]()));
|
|
@@ -1191,16 +1197,11 @@ async function load_root_error_page({ status, error, url, route }) {
|
|
|
1191
1197
|
}
|
|
1192
1198
|
|
|
1193
1199
|
/**
|
|
1194
|
-
* Resolve the
|
|
1195
|
-
*
|
|
1196
|
-
* returns undefined
|
|
1197
|
-
* @param {URL | undefined} url
|
|
1198
|
-
* @param {boolean} invalidating
|
|
1200
|
+
* Resolve the relative rerouted URL for a client-side navigation
|
|
1201
|
+
* @param {URL} url
|
|
1202
|
+
* @returns {URL | undefined}
|
|
1199
1203
|
*/
|
|
1200
|
-
function
|
|
1201
|
-
if (!url) return;
|
|
1202
|
-
if (is_external_url(url, base, app.hash)) return;
|
|
1203
|
-
|
|
1204
|
+
function get_rerouted_url(url) {
|
|
1204
1205
|
// reroute could alter the given URL, so we pass a copy
|
|
1205
1206
|
let rerouted;
|
|
1206
1207
|
try {
|
|
@@ -1227,9 +1228,26 @@ function get_navigation_intent(url, invalidating) {
|
|
|
1227
1228
|
}
|
|
1228
1229
|
|
|
1229
1230
|
// fall back to native navigation
|
|
1230
|
-
return
|
|
1231
|
+
return;
|
|
1231
1232
|
}
|
|
1232
1233
|
|
|
1234
|
+
return rerouted;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Resolve the full info (which route, params, etc.) for a client-side navigation from the URL,
|
|
1239
|
+
* taking the reroute hook into account. If this isn't a client-side-navigation (or the URL is undefined),
|
|
1240
|
+
* returns undefined.
|
|
1241
|
+
* @param {URL | undefined} url
|
|
1242
|
+
* @param {boolean} invalidating
|
|
1243
|
+
*/
|
|
1244
|
+
function get_navigation_intent(url, invalidating) {
|
|
1245
|
+
if (!url) return;
|
|
1246
|
+
if (is_external_url(url, base, app.hash)) return;
|
|
1247
|
+
|
|
1248
|
+
const rerouted = get_rerouted_url(url);
|
|
1249
|
+
if (!rerouted) return;
|
|
1250
|
+
|
|
1233
1251
|
const path = get_url_path(rerouted);
|
|
1234
1252
|
|
|
1235
1253
|
for (const route of routes) {
|
|
@@ -1811,6 +1829,7 @@ export function disableScrollHandling() {
|
|
|
1811
1829
|
* @param {boolean} [opts.noScroll] If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
|
|
1812
1830
|
* @param {boolean} [opts.keepFocus] If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
|
|
1813
1831
|
* @param {boolean} [opts.invalidateAll] If `true`, all `load` functions of the page will be rerun. See https://svelte.dev/docs/kit/load#rerunning-load-functions for more info on invalidation.
|
|
1832
|
+
* @param {Array<string | URL | ((url: URL) => boolean)>} [opts.invalidate] Causes any load functions to re-run if they depend on one of the urls
|
|
1814
1833
|
* @param {App.PageState} [opts.state] An optional object that will be available as `page.state`
|
|
1815
1834
|
* @returns {Promise<void>}
|
|
1816
1835
|
*/
|
|
@@ -1857,14 +1876,21 @@ export function invalidate(resource) {
|
|
|
1857
1876
|
throw new Error('Cannot call invalidate(...) on the server');
|
|
1858
1877
|
}
|
|
1859
1878
|
|
|
1879
|
+
push_invalidated(resource);
|
|
1880
|
+
|
|
1881
|
+
return _invalidate();
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
/**
|
|
1885
|
+
* @param {string | URL | ((url: URL) => boolean)} resource The invalidated URL
|
|
1886
|
+
*/
|
|
1887
|
+
function push_invalidated(resource) {
|
|
1860
1888
|
if (typeof resource === 'function') {
|
|
1861
1889
|
invalidated.push(resource);
|
|
1862
1890
|
} else {
|
|
1863
1891
|
const { href } = new URL(resource, location.href);
|
|
1864
1892
|
invalidated.push((url) => url.href === href);
|
|
1865
1893
|
}
|
|
1866
|
-
|
|
1867
|
-
return _invalidate();
|
|
1868
1894
|
}
|
|
1869
1895
|
|
|
1870
1896
|
/**
|
|
@@ -1936,13 +1962,20 @@ export function preloadCode(pathname) {
|
|
|
1936
1962
|
const url = new URL(pathname, current.url);
|
|
1937
1963
|
|
|
1938
1964
|
if (DEV) {
|
|
1965
|
+
if (!pathname.startsWith('/')) {
|
|
1966
|
+
throw new Error(
|
|
1967
|
+
'argument passed to preloadCode must be a pathname (i.e. "/about" rather than "http://example.com/about"'
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1939
1971
|
if (!pathname.startsWith(base)) {
|
|
1940
1972
|
throw new Error(
|
|
1941
|
-
`
|
|
1973
|
+
`pathname passed to preloadCode must start with \`paths.base\` (i.e. "${base}${pathname}" rather than "${pathname}")`
|
|
1942
1974
|
);
|
|
1943
1975
|
}
|
|
1944
1976
|
|
|
1945
|
-
|
|
1977
|
+
const rerouted = get_rerouted_url(url);
|
|
1978
|
+
if (!rerouted || !routes.find((route) => route.exec(get_url_path(rerouted)))) {
|
|
1946
1979
|
throw new Error(`'${pathname}' did not match any routes`);
|
|
1947
1980
|
}
|
|
1948
1981
|
}
|
|
@@ -2401,7 +2434,7 @@ function _start_router() {
|
|
|
2401
2434
|
// (surprisingly!) mutates `current.url`, allowing us to
|
|
2402
2435
|
// detect it and trigger a navigation
|
|
2403
2436
|
if (current.url.hash === location.hash) {
|
|
2404
|
-
navigate({ type: 'goto', url: current.url });
|
|
2437
|
+
navigate({ type: 'goto', url: decode_hash(current.url) });
|
|
2405
2438
|
}
|
|
2406
2439
|
}
|
|
2407
2440
|
});
|
|
@@ -2548,7 +2581,9 @@ async function load_data(url, invalid) {
|
|
|
2548
2581
|
}
|
|
2549
2582
|
data_url.searchParams.append(INVALIDATED_PARAM, invalid.map((i) => (i ? '1' : '0')).join(''));
|
|
2550
2583
|
|
|
2551
|
-
|
|
2584
|
+
// use window.fetch directly to allow using a 3rd party-patched fetch implementation
|
|
2585
|
+
const fetcher = DEV ? dev_fetch : window.fetch;
|
|
2586
|
+
const res = await fetcher(data_url.href, {});
|
|
2552
2587
|
|
|
2553
2588
|
if (!res.ok) {
|
|
2554
2589
|
// error message is a JSON-stringified string which devalue can't handle at the top level
|
|
@@ -2793,6 +2828,17 @@ function clone_page(page) {
|
|
|
2793
2828
|
};
|
|
2794
2829
|
}
|
|
2795
2830
|
|
|
2831
|
+
/**
|
|
2832
|
+
* @param {URL} url
|
|
2833
|
+
* @returns {URL}
|
|
2834
|
+
*/
|
|
2835
|
+
function decode_hash(url) {
|
|
2836
|
+
const new_url = new URL(url);
|
|
2837
|
+
// Safari, for some reason, does change # to %23, when entered through the address bar
|
|
2838
|
+
new_url.hash = decodeURIComponent(url.hash);
|
|
2839
|
+
return new_url;
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2796
2842
|
if (DEV) {
|
|
2797
2843
|
// Nasty hack to silence harmless warnings the user can do nothing about
|
|
2798
2844
|
const console_warn = console.warn;
|
|
@@ -5,7 +5,7 @@ import { b64_decode } from '../utils.js';
|
|
|
5
5
|
let loading = 0;
|
|
6
6
|
|
|
7
7
|
/** @type {typeof fetch} */
|
|
8
|
-
|
|
8
|
+
const native_fetch = BROWSER ? window.fetch : /** @type {any} */ (() => {});
|
|
9
9
|
|
|
10
10
|
export function lock_fetch() {
|
|
11
11
|
loading += 1;
|
|
@@ -137,7 +137,7 @@ export function subsequent_fetch(resource, resolved, opts) {
|
|
|
137
137
|
* @param {RequestInfo | URL} resource
|
|
138
138
|
* @param {RequestInit & Record<string, any> | undefined} opts
|
|
139
139
|
*/
|
|
140
|
-
function dev_fetch(resource, opts) {
|
|
140
|
+
export function dev_fetch(resource, opts) {
|
|
141
141
|
const patched_opts = { ...opts };
|
|
142
142
|
// This assigns the __sveltekit_fetch__ flag and makes it non-enumerable
|
|
143
143
|
Object.defineProperty(patched_opts, '__sveltekit_fetch__', {
|
|
@@ -55,7 +55,7 @@ export function get_cookies(request, url, trailing_slash) {
|
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* @param {string} name
|
|
58
|
-
* @param {import('cookie').CookieParseOptions} opts
|
|
58
|
+
* @param {import('cookie').CookieParseOptions} [opts]
|
|
59
59
|
*/
|
|
60
60
|
get(name, opts) {
|
|
61
61
|
const c = new_cookies[name];
|
|
@@ -91,7 +91,7 @@ export function get_cookies(request, url, trailing_slash) {
|
|
|
91
91
|
},
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
* @param {import('cookie').CookieParseOptions} opts
|
|
94
|
+
* @param {import('cookie').CookieParseOptions} [opts]
|
|
95
95
|
*/
|
|
96
96
|
getAll(opts) {
|
|
97
97
|
const cookies = parse(header, { decode: opts?.decode });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DEV } from 'esm-env';
|
|
1
2
|
import { ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
|
|
2
3
|
import { negotiate } from '../../utils/http.js';
|
|
3
4
|
import { Redirect } from '../control.js';
|
|
@@ -10,6 +11,10 @@ import { method_not_allowed } from './utils.js';
|
|
|
10
11
|
* @returns {Promise<Response>}
|
|
11
12
|
*/
|
|
12
13
|
export async function render_endpoint(event, mod, state) {
|
|
14
|
+
if (DEV && event.request.headers.get('x-sveltekit-action') === 'true') {
|
|
15
|
+
throw new Error('use:enhance should only be used with SvelteKit form actions');
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
const method = /** @type {import('types').HttpMethod} */ (event.request.method);
|
|
14
19
|
|
|
15
20
|
let handler = mod[method] || mod.fallback;
|
|
@@ -85,6 +85,21 @@ export async function respond(request, options, manifest, state) {
|
|
|
85
85
|
return text('Not found', { status: 404 });
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
const is_data_request = has_data_suffix(url.pathname);
|
|
89
|
+
/** @type {boolean[] | undefined} */
|
|
90
|
+
let invalidated_data_nodes;
|
|
91
|
+
if (is_data_request) {
|
|
92
|
+
url.pathname =
|
|
93
|
+
strip_data_suffix(url.pathname) +
|
|
94
|
+
(url.searchParams.get(TRAILING_SLASH_PARAM) === '1' ? '/' : '') || '/';
|
|
95
|
+
url.searchParams.delete(TRAILING_SLASH_PARAM);
|
|
96
|
+
invalidated_data_nodes = url.searchParams
|
|
97
|
+
.get(INVALIDATED_PARAM)
|
|
98
|
+
?.split('')
|
|
99
|
+
.map((node) => node === '1');
|
|
100
|
+
url.searchParams.delete(INVALIDATED_PARAM);
|
|
101
|
+
}
|
|
102
|
+
|
|
88
103
|
// reroute could alter the given URL, so we pass a copy
|
|
89
104
|
let rerouted_path;
|
|
90
105
|
try {
|
|
@@ -126,22 +141,6 @@ export async function respond(request, options, manifest, state) {
|
|
|
126
141
|
return text('Not found', { status: 404, headers });
|
|
127
142
|
}
|
|
128
143
|
|
|
129
|
-
const is_data_request = has_data_suffix(decoded);
|
|
130
|
-
/** @type {boolean[] | undefined} */
|
|
131
|
-
let invalidated_data_nodes;
|
|
132
|
-
if (is_data_request) {
|
|
133
|
-
decoded = strip_data_suffix(decoded) || '/';
|
|
134
|
-
url.pathname =
|
|
135
|
-
strip_data_suffix(url.pathname) +
|
|
136
|
-
(url.searchParams.get(TRAILING_SLASH_PARAM) === '1' ? '/' : '') || '/';
|
|
137
|
-
url.searchParams.delete(TRAILING_SLASH_PARAM);
|
|
138
|
-
invalidated_data_nodes = url.searchParams
|
|
139
|
-
.get(INVALIDATED_PARAM)
|
|
140
|
-
?.split('')
|
|
141
|
-
.map((node) => node === '1');
|
|
142
|
-
url.searchParams.delete(INVALIDATED_PARAM);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
144
|
if (!state.prerendering?.fallback) {
|
|
146
145
|
// TODO this could theoretically break — should probably be inside a try-catch
|
|
147
146
|
const matchers = await manifest._.matchers();
|
package/src/utils/import.js
CHANGED
|
@@ -4,17 +4,22 @@ import { pathToFileURL } from 'node:url';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Resolve a dependency relative to the current working directory,
|
|
7
|
-
* rather than relative to this package
|
|
7
|
+
* rather than relative to this package (but falls back to trying that, if necessary)
|
|
8
8
|
* @param {string} dependency
|
|
9
9
|
*/
|
|
10
|
-
export function resolve_peer_dependency(dependency) {
|
|
10
|
+
export async function resolve_peer_dependency(dependency) {
|
|
11
11
|
try {
|
|
12
12
|
// @ts-expect-error the types are wrong
|
|
13
13
|
const resolved = imr.resolve(dependency, pathToFileURL(process.cwd() + '/dummy.js'));
|
|
14
|
-
return import(resolved);
|
|
14
|
+
return await import(resolved);
|
|
15
15
|
} catch {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
try {
|
|
17
|
+
// both imr.resolve and await import above can throw, which is why we can't just do import(resolved).catch(...) above
|
|
18
|
+
return await import(dependency);
|
|
19
|
+
} catch {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Could not resolve peer dependency "${dependency}" relative to your project — please install it and try again.`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
19
24
|
}
|
|
20
25
|
}
|
package/src/version.js
CHANGED