@sveltejs/kit 1.0.0-next.298 → 1.0.0-next.299
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/assets/client/start.js +203 -115
- package/assets/server/index.js +170 -141
- package/dist/chunks/index.js +30 -29
- package/dist/chunks/index2.js +8 -4
- package/dist/chunks/index3.js +31 -30
- package/dist/chunks/index4.js +1 -0
- package/dist/chunks/routing.js +39 -0
- package/dist/chunks/sync.js +93 -53
- package/dist/cli.js +7 -8
- package/package.json +1 -1
- package/types/index.d.ts +13 -15
- package/types/internal.d.ts +25 -22
- package/types/private.d.ts +4 -8
package/assets/client/start.js
CHANGED
|
@@ -2,7 +2,7 @@ import { onMount, tick } from 'svelte';
|
|
|
2
2
|
import { writable } from 'svelte/store';
|
|
3
3
|
import { assets, set_paths } from '../paths.js';
|
|
4
4
|
import Root from '__GENERATED__/root.svelte';
|
|
5
|
-
import {
|
|
5
|
+
import { components, dictionary, validators } from '__GENERATED__/client-manifest.js';
|
|
6
6
|
import { init } from './singletons.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -250,9 +250,108 @@ function initial_fetch(resource, opts) {
|
|
|
250
250
|
return fetch(resource, opts);
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
/** @param {string} key */
|
|
254
|
+
function parse_route_id(key) {
|
|
255
|
+
/** @type {string[]} */
|
|
256
|
+
const names = [];
|
|
257
|
+
|
|
258
|
+
/** @type {string[]} */
|
|
259
|
+
const types = [];
|
|
260
|
+
|
|
261
|
+
const pattern =
|
|
262
|
+
key === ''
|
|
263
|
+
? /^\/$/
|
|
264
|
+
: new RegExp(
|
|
265
|
+
`^${decodeURIComponent(key)
|
|
266
|
+
.split('/')
|
|
267
|
+
.map((segment) => {
|
|
268
|
+
// special case — /[...rest]/ could contain zero segments
|
|
269
|
+
const match = /^\[\.\.\.(\w+)(?:=\w+)?\]$/.exec(segment);
|
|
270
|
+
if (match) {
|
|
271
|
+
names.push(match[1]);
|
|
272
|
+
types.push(match[2]);
|
|
273
|
+
return '(?:/(.*))?';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
'/' +
|
|
278
|
+
segment.replace(/\[(\.\.\.)?(\w+)(?:=(\w+))?\]/g, (m, rest, name, type) => {
|
|
279
|
+
names.push(name);
|
|
280
|
+
types.push(type);
|
|
281
|
+
return rest ? '(.*?)' : '([^/]+?)';
|
|
282
|
+
})
|
|
283
|
+
);
|
|
284
|
+
})
|
|
285
|
+
.join('')}/?$`
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
return { pattern, names, types };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @param {RegExpMatchArray} match
|
|
293
|
+
* @param {string[]} names
|
|
294
|
+
* @param {string[]} types
|
|
295
|
+
* @param {Record<string, import('types').ParamValidator>} validators
|
|
296
|
+
*/
|
|
297
|
+
function exec(match, names, types, validators) {
|
|
298
|
+
/** @type {Record<string, string>} */
|
|
299
|
+
const params = {};
|
|
300
|
+
|
|
301
|
+
for (let i = 0; i < names.length; i += 1) {
|
|
302
|
+
const name = names[i];
|
|
303
|
+
const type = types[i];
|
|
304
|
+
const value = match[i + 1] || '';
|
|
305
|
+
|
|
306
|
+
if (type) {
|
|
307
|
+
const validator = validators[type];
|
|
308
|
+
if (!validator) throw new Error(`Missing "${type}" param validator`); // TODO do this ahead of time?
|
|
309
|
+
|
|
310
|
+
if (!validator(value)) return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
params[name] = value;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return params;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @param {import('types').CSRComponentLoader[]} components
|
|
321
|
+
* @param {Record<string, [number[], number[], 1?]>} dictionary
|
|
322
|
+
* @param {Record<string, (param: string) => boolean>} validators
|
|
323
|
+
* @returns {import('types').CSRRoute[]}
|
|
324
|
+
*/
|
|
325
|
+
function parse(components, dictionary, validators) {
|
|
326
|
+
const routes = Object.entries(dictionary).map(([id, [a, b, has_shadow]]) => {
|
|
327
|
+
const { pattern, names, types } = parse_route_id(id);
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
id,
|
|
331
|
+
/** @param {string} path */
|
|
332
|
+
exec: (path) => {
|
|
333
|
+
const match = pattern.exec(path);
|
|
334
|
+
if (match) return exec(match, names, types, validators);
|
|
335
|
+
},
|
|
336
|
+
a: a.map((n) => components[n]),
|
|
337
|
+
b: b.map((n) => components[n]),
|
|
338
|
+
has_shadow: !!has_shadow
|
|
339
|
+
};
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
return routes;
|
|
343
|
+
}
|
|
344
|
+
|
|
253
345
|
const SCROLL_KEY = 'sveltekit:scroll';
|
|
254
346
|
const INDEX_KEY = 'sveltekit:index';
|
|
255
347
|
|
|
348
|
+
const routes = parse(components, dictionary, validators);
|
|
349
|
+
|
|
350
|
+
// we import the root layout/error components eagerly, so that
|
|
351
|
+
// connectivity errors after initialisation don't nuke the app
|
|
352
|
+
const default_layout = components[0]();
|
|
353
|
+
const default_error = components[1]();
|
|
354
|
+
|
|
256
355
|
// We track the scroll position associated with each history entry in sessionStorage,
|
|
257
356
|
// rather than on history.state itself, because when navigation is driven by
|
|
258
357
|
// popstate it's too late to update the scroll position associated with the
|
|
@@ -339,8 +438,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
339
438
|
if (!ready) return;
|
|
340
439
|
session_id += 1;
|
|
341
440
|
|
|
342
|
-
|
|
343
|
-
update(intent, [], true);
|
|
441
|
+
update(new URL(location.href), [], true);
|
|
344
442
|
});
|
|
345
443
|
ready = true;
|
|
346
444
|
|
|
@@ -405,29 +503,31 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
405
503
|
|
|
406
504
|
/** @param {URL} url */
|
|
407
505
|
async function prefetch(url) {
|
|
408
|
-
|
|
506
|
+
const intent = get_navigation_intent(url);
|
|
507
|
+
|
|
508
|
+
if (!intent) {
|
|
409
509
|
throw new Error('Attempted to prefetch a URL that does not belong to this app');
|
|
410
510
|
}
|
|
411
511
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
load_cache.promise = get_navigation_result(intent, false);
|
|
512
|
+
load_cache.promise = load_route(intent, false);
|
|
415
513
|
load_cache.id = intent.id;
|
|
416
514
|
|
|
417
515
|
return load_cache.promise;
|
|
418
516
|
}
|
|
419
517
|
|
|
420
518
|
/**
|
|
421
|
-
* @param {
|
|
519
|
+
* @param {URL} url
|
|
422
520
|
* @param {string[]} redirect_chain
|
|
423
521
|
* @param {boolean} no_cache
|
|
424
522
|
* @param {{hash?: string, scroll: { x: number, y: number } | null, keepfocus: boolean, details: { replaceState: boolean, state: any } | null}} [opts]
|
|
425
523
|
*/
|
|
426
|
-
async function update(
|
|
524
|
+
async function update(url, redirect_chain, no_cache, opts) {
|
|
525
|
+
const intent = get_navigation_intent(url);
|
|
526
|
+
|
|
427
527
|
const current_token = (token = {});
|
|
428
|
-
let navigation_result = await
|
|
528
|
+
let navigation_result = intent && (await load_route(intent, no_cache));
|
|
429
529
|
|
|
430
|
-
if (!navigation_result &&
|
|
530
|
+
if (!navigation_result && url.pathname === location.pathname) {
|
|
431
531
|
// this could happen in SPA fallback mode if the user navigated to
|
|
432
532
|
// `/non-existent-page`. if we fall back to reloading the page, it
|
|
433
533
|
// will create an infinite loop. so whereas we normally handle
|
|
@@ -435,13 +535,14 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
435
535
|
// we render a client-side error page instead
|
|
436
536
|
navigation_result = await load_root_error_page({
|
|
437
537
|
status: 404,
|
|
438
|
-
error: new Error(`Not found: ${
|
|
439
|
-
url
|
|
538
|
+
error: new Error(`Not found: ${url.pathname}`),
|
|
539
|
+
url,
|
|
540
|
+
routeId: null
|
|
440
541
|
});
|
|
441
542
|
}
|
|
442
543
|
|
|
443
544
|
if (!navigation_result) {
|
|
444
|
-
await native_navigation(
|
|
545
|
+
await native_navigation(url);
|
|
445
546
|
return; // unnecessary, but TypeScript prefers it this way
|
|
446
547
|
}
|
|
447
548
|
|
|
@@ -451,17 +552,18 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
451
552
|
invalidated.clear();
|
|
452
553
|
|
|
453
554
|
if (navigation_result.redirect) {
|
|
454
|
-
if (redirect_chain.length > 10 || redirect_chain.includes(
|
|
555
|
+
if (redirect_chain.length > 10 || redirect_chain.includes(url.pathname)) {
|
|
455
556
|
navigation_result = await load_root_error_page({
|
|
456
557
|
status: 500,
|
|
457
558
|
error: new Error('Redirect loop'),
|
|
458
|
-
url
|
|
559
|
+
url,
|
|
560
|
+
routeId: null
|
|
459
561
|
});
|
|
460
562
|
} else {
|
|
461
563
|
if (router_enabled) {
|
|
462
|
-
goto(new URL(navigation_result.redirect,
|
|
564
|
+
goto(new URL(navigation_result.redirect, url).href, {}, [
|
|
463
565
|
...redirect_chain,
|
|
464
|
-
|
|
566
|
+
url.pathname
|
|
465
567
|
]);
|
|
466
568
|
} else {
|
|
467
569
|
await native_navigation(new URL(navigation_result.redirect, location.href));
|
|
@@ -472,7 +574,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
472
574
|
} else if (navigation_result.props?.page?.status >= 400) {
|
|
473
575
|
const updated = await stores.updated.check();
|
|
474
576
|
if (updated) {
|
|
475
|
-
await native_navigation(
|
|
577
|
+
await native_navigation(url);
|
|
476
578
|
}
|
|
477
579
|
}
|
|
478
580
|
|
|
@@ -482,7 +584,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
482
584
|
const { details } = opts;
|
|
483
585
|
const change = details.replaceState ? 0 : 1;
|
|
484
586
|
details.state[INDEX_KEY] = current_history_index += change;
|
|
485
|
-
history[details.replaceState ? 'replaceState' : 'pushState'](details.state, '',
|
|
587
|
+
history[details.replaceState ? 'replaceState' : 'pushState'](details.state, '', url);
|
|
486
588
|
}
|
|
487
589
|
|
|
488
590
|
if (started) {
|
|
@@ -522,7 +624,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
522
624
|
await tick();
|
|
523
625
|
|
|
524
626
|
if (autoscroll) {
|
|
525
|
-
const deep_linked =
|
|
627
|
+
const deep_linked = url.hash && document.getElementById(url.hash.slice(1));
|
|
526
628
|
if (scroll) {
|
|
527
629
|
scrollTo(scroll.x, scroll.y);
|
|
528
630
|
} else if (deep_linked) {
|
|
@@ -575,36 +677,6 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
575
677
|
}
|
|
576
678
|
}
|
|
577
679
|
|
|
578
|
-
/**
|
|
579
|
-
* @param {import('./types').NavigationIntent} intent
|
|
580
|
-
* @param {boolean} no_cache
|
|
581
|
-
*/
|
|
582
|
-
async function get_navigation_result(intent, no_cache) {
|
|
583
|
-
if (load_cache.id === intent.id && load_cache.promise) {
|
|
584
|
-
return load_cache.promise;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
for (let i = 0; i < intent.routes.length; i += 1) {
|
|
588
|
-
const route = intent.routes[i];
|
|
589
|
-
|
|
590
|
-
// load code for subsequent routes immediately, if they are as
|
|
591
|
-
// likely to match the current path/query as the current one
|
|
592
|
-
let j = i + 1;
|
|
593
|
-
while (j < intent.routes.length) {
|
|
594
|
-
const next = intent.routes[j];
|
|
595
|
-
if (next[0].toString() === route[0].toString()) {
|
|
596
|
-
next[1].forEach((loader) => loader());
|
|
597
|
-
j += 1;
|
|
598
|
-
} else {
|
|
599
|
-
break;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
const result = await load_route(route, intent, no_cache);
|
|
604
|
-
if (result) return result;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
680
|
/**
|
|
609
681
|
*
|
|
610
682
|
* @param {{
|
|
@@ -614,9 +686,18 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
614
686
|
* branch: Array<import('./types').BranchNode | undefined>;
|
|
615
687
|
* status: number;
|
|
616
688
|
* error?: Error;
|
|
689
|
+
* routeId: string | null;
|
|
617
690
|
* }} opts
|
|
618
691
|
*/
|
|
619
|
-
async function get_navigation_result_from_branch({
|
|
692
|
+
async function get_navigation_result_from_branch({
|
|
693
|
+
url,
|
|
694
|
+
params,
|
|
695
|
+
stuff,
|
|
696
|
+
branch,
|
|
697
|
+
status,
|
|
698
|
+
error,
|
|
699
|
+
routeId
|
|
700
|
+
}) {
|
|
620
701
|
const filtered = /** @type {import('./types').BranchNode[] } */ (branch.filter(Boolean));
|
|
621
702
|
const redirect = filtered.find((f) => f.loaded?.redirect);
|
|
622
703
|
|
|
@@ -640,7 +721,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
640
721
|
}
|
|
641
722
|
|
|
642
723
|
if (!current.url || url.href !== current.url.href) {
|
|
643
|
-
result.props.page = {
|
|
724
|
+
result.props.page = { error, params, routeId, status, stuff, url };
|
|
644
725
|
|
|
645
726
|
// TODO remove this for 1.0
|
|
646
727
|
/**
|
|
@@ -699,9 +780,10 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
699
780
|
* params: Record<string, string>;
|
|
700
781
|
* stuff: Record<string, any>;
|
|
701
782
|
* props?: Record<string, any>;
|
|
783
|
+
* routeId: string | null;
|
|
702
784
|
* }} options
|
|
703
785
|
*/
|
|
704
|
-
async function load_node({ status, error, module, url, params, stuff, props }) {
|
|
786
|
+
async function load_node({ status, error, module, url, params, stuff, props, routeId }) {
|
|
705
787
|
/** @type {import('./types').BranchNode} */
|
|
706
788
|
const node = {
|
|
707
789
|
module,
|
|
@@ -738,6 +820,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
738
820
|
if (module.load) {
|
|
739
821
|
/** @type {import('types').LoadInput | import('types').ErrorLoadInput} */
|
|
740
822
|
const load_input = {
|
|
823
|
+
routeId,
|
|
741
824
|
params: uses_params,
|
|
742
825
|
props: props || {},
|
|
743
826
|
get url() {
|
|
@@ -791,21 +874,20 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
791
874
|
}
|
|
792
875
|
|
|
793
876
|
/**
|
|
794
|
-
* @param {import('types').CSRRoute} route
|
|
795
877
|
* @param {import('./types').NavigationIntent} intent
|
|
796
878
|
* @param {boolean} no_cache
|
|
797
879
|
*/
|
|
798
|
-
async function load_route(
|
|
880
|
+
async function load_route({ id, url, params, route }, no_cache) {
|
|
881
|
+
if (load_cache.id === id && load_cache.promise) {
|
|
882
|
+
return load_cache.promise;
|
|
883
|
+
}
|
|
884
|
+
|
|
799
885
|
if (!no_cache) {
|
|
800
886
|
const cached = cache.get(id);
|
|
801
887
|
if (cached) return cached;
|
|
802
888
|
}
|
|
803
889
|
|
|
804
|
-
const
|
|
805
|
-
const params = get_params
|
|
806
|
-
? // the pattern is for the route which we've already matched to this path
|
|
807
|
-
get_params(/** @type {RegExpExecArray} */ (pattern.exec(path)))
|
|
808
|
-
: {};
|
|
890
|
+
const { a, b, has_shadow } = route;
|
|
809
891
|
|
|
810
892
|
const changed = current.url && {
|
|
811
893
|
url: id !== current.url.pathname + current.url.search,
|
|
@@ -852,14 +934,14 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
852
934
|
/** @type {Record<string, any>} */
|
|
853
935
|
let props = {};
|
|
854
936
|
|
|
855
|
-
const is_shadow_page =
|
|
937
|
+
const is_shadow_page = has_shadow && i === a.length - 1;
|
|
856
938
|
|
|
857
939
|
if (is_shadow_page) {
|
|
858
940
|
const res = await fetch(
|
|
859
941
|
`${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`,
|
|
860
942
|
{
|
|
861
943
|
headers: {
|
|
862
|
-
'x-sveltekit-load':
|
|
944
|
+
'x-sveltekit-load': 'true'
|
|
863
945
|
}
|
|
864
946
|
}
|
|
865
947
|
);
|
|
@@ -875,15 +957,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
875
957
|
};
|
|
876
958
|
}
|
|
877
959
|
|
|
878
|
-
|
|
879
|
-
if (route !== routes[routes.length - 1]) {
|
|
880
|
-
// fallthrough
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
props = {};
|
|
884
|
-
} else {
|
|
885
|
-
props = await res.json();
|
|
886
|
-
}
|
|
960
|
+
props = res.status === 204 ? {} : await res.json();
|
|
887
961
|
} else {
|
|
888
962
|
status = res.status;
|
|
889
963
|
error = new Error('Failed to load data');
|
|
@@ -896,7 +970,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
896
970
|
url,
|
|
897
971
|
params,
|
|
898
972
|
props,
|
|
899
|
-
stuff
|
|
973
|
+
stuff,
|
|
974
|
+
routeId: route.id
|
|
900
975
|
});
|
|
901
976
|
}
|
|
902
977
|
|
|
@@ -906,9 +981,14 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
906
981
|
}
|
|
907
982
|
|
|
908
983
|
if (node.loaded) {
|
|
984
|
+
// TODO remove for 1.0
|
|
985
|
+
// @ts-expect-error
|
|
909
986
|
if (node.loaded.fallthrough) {
|
|
910
|
-
|
|
987
|
+
throw new Error(
|
|
988
|
+
'fallthrough is no longer supported. Use validators instead: https://kit.svelte.dev/docs/routing#advanced-routing-validation'
|
|
989
|
+
);
|
|
911
990
|
}
|
|
991
|
+
|
|
912
992
|
if (node.loaded.error) {
|
|
913
993
|
status = node.loaded.status;
|
|
914
994
|
error = node.loaded.error;
|
|
@@ -954,7 +1034,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
954
1034
|
module: await b[i](),
|
|
955
1035
|
url,
|
|
956
1036
|
params,
|
|
957
|
-
stuff: node_loaded.stuff
|
|
1037
|
+
stuff: node_loaded.stuff,
|
|
1038
|
+
routeId: route.id
|
|
958
1039
|
});
|
|
959
1040
|
|
|
960
1041
|
if (error_loaded?.loaded?.error) {
|
|
@@ -979,7 +1060,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
979
1060
|
return await load_root_error_page({
|
|
980
1061
|
status,
|
|
981
1062
|
error,
|
|
982
|
-
url
|
|
1063
|
+
url,
|
|
1064
|
+
routeId: route.id
|
|
983
1065
|
});
|
|
984
1066
|
} else {
|
|
985
1067
|
if (node?.loaded?.stuff) {
|
|
@@ -999,7 +1081,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
999
1081
|
stuff,
|
|
1000
1082
|
branch,
|
|
1001
1083
|
status,
|
|
1002
|
-
error
|
|
1084
|
+
error,
|
|
1085
|
+
routeId: route.id
|
|
1003
1086
|
});
|
|
1004
1087
|
}
|
|
1005
1088
|
|
|
@@ -1008,26 +1091,29 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1008
1091
|
* status: number;
|
|
1009
1092
|
* error: Error;
|
|
1010
1093
|
* url: URL;
|
|
1094
|
+
* routeId: string | null
|
|
1011
1095
|
* }} opts
|
|
1012
1096
|
*/
|
|
1013
|
-
async function load_root_error_page({ status, error, url }) {
|
|
1097
|
+
async function load_root_error_page({ status, error, url, routeId }) {
|
|
1014
1098
|
/** @type {Record<string, string>} */
|
|
1015
1099
|
const params = {}; // error page does not have params
|
|
1016
1100
|
|
|
1017
1101
|
const root_layout = await load_node({
|
|
1018
|
-
module: await
|
|
1102
|
+
module: await default_layout,
|
|
1019
1103
|
url,
|
|
1020
1104
|
params,
|
|
1021
|
-
stuff: {}
|
|
1105
|
+
stuff: {},
|
|
1106
|
+
routeId
|
|
1022
1107
|
});
|
|
1023
1108
|
|
|
1024
1109
|
const root_error = await load_node({
|
|
1025
1110
|
status,
|
|
1026
1111
|
error,
|
|
1027
|
-
module: await
|
|
1112
|
+
module: await default_error,
|
|
1028
1113
|
url,
|
|
1029
1114
|
params,
|
|
1030
|
-
stuff: (root_layout && root_layout.loaded && root_layout.loaded.stuff) || {}
|
|
1115
|
+
stuff: (root_layout && root_layout.loaded && root_layout.loaded.stuff) || {},
|
|
1116
|
+
routeId
|
|
1031
1117
|
});
|
|
1032
1118
|
|
|
1033
1119
|
return await get_navigation_result_from_branch({
|
|
@@ -1039,28 +1125,32 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1039
1125
|
},
|
|
1040
1126
|
branch: [root_layout, root_error],
|
|
1041
1127
|
status,
|
|
1042
|
-
error
|
|
1128
|
+
error,
|
|
1129
|
+
routeId
|
|
1043
1130
|
});
|
|
1044
1131
|
}
|
|
1045
1132
|
|
|
1046
|
-
/** @param {URL} url */
|
|
1047
|
-
function owns(url) {
|
|
1048
|
-
return url.origin === location.origin && url.pathname.startsWith(base);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1133
|
/** @param {URL} url */
|
|
1052
1134
|
function get_navigation_intent(url) {
|
|
1135
|
+
if (url.origin !== location.origin || !url.pathname.startsWith(base)) return;
|
|
1136
|
+
|
|
1053
1137
|
const path = decodeURI(url.pathname.slice(base.length) || '/');
|
|
1054
1138
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1139
|
+
for (const route of routes) {
|
|
1140
|
+
const params = route.exec(path);
|
|
1141
|
+
|
|
1142
|
+
if (params) {
|
|
1143
|
+
/** @type {import('./types').NavigationIntent} */
|
|
1144
|
+
const intent = {
|
|
1145
|
+
id: url.pathname + url.search,
|
|
1146
|
+
route,
|
|
1147
|
+
params,
|
|
1148
|
+
url
|
|
1149
|
+
};
|
|
1062
1150
|
|
|
1063
|
-
|
|
1151
|
+
return intent;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1064
1154
|
}
|
|
1065
1155
|
|
|
1066
1156
|
/**
|
|
@@ -1094,14 +1184,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1094
1184
|
return;
|
|
1095
1185
|
}
|
|
1096
1186
|
|
|
1097
|
-
if (!owns(url)) {
|
|
1098
|
-
await native_navigation(url);
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
1187
|
const pathname = normalize_path(url.pathname, trailing_slash);
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
const intent = get_navigation_intent(url);
|
|
1188
|
+
const normalized = new URL(url.origin + pathname + url.search + url.hash);
|
|
1105
1189
|
|
|
1106
1190
|
update_scroll_positions(current_history_index);
|
|
1107
1191
|
|
|
@@ -1114,11 +1198,11 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1114
1198
|
if (started) {
|
|
1115
1199
|
stores.navigating.set({
|
|
1116
1200
|
from: current.url,
|
|
1117
|
-
to:
|
|
1201
|
+
to: normalized
|
|
1118
1202
|
});
|
|
1119
1203
|
}
|
|
1120
1204
|
|
|
1121
|
-
await update(
|
|
1205
|
+
await update(normalized, redirect_chain, false, {
|
|
1122
1206
|
scroll,
|
|
1123
1207
|
keepfocus,
|
|
1124
1208
|
details
|
|
@@ -1130,7 +1214,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1130
1214
|
if (navigating_token !== current_navigating_token) return;
|
|
1131
1215
|
|
|
1132
1216
|
if (!navigating) {
|
|
1133
|
-
const navigation = { from, to:
|
|
1217
|
+
const navigation = { from, to: normalized };
|
|
1134
1218
|
callbacks.after_navigate.forEach((fn) => fn(navigation));
|
|
1135
1219
|
|
|
1136
1220
|
stores.navigating.set(null);
|
|
@@ -1190,8 +1274,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1190
1274
|
|
|
1191
1275
|
if (!invalidating) {
|
|
1192
1276
|
invalidating = Promise.resolve().then(async () => {
|
|
1193
|
-
|
|
1194
|
-
await update(intent, [], true);
|
|
1277
|
+
await update(new URL(location.href), [], true);
|
|
1195
1278
|
|
|
1196
1279
|
invalidating = null;
|
|
1197
1280
|
});
|
|
@@ -1208,10 +1291,10 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1208
1291
|
// TODO rethink this API
|
|
1209
1292
|
prefetch_routes: async (pathnames) => {
|
|
1210
1293
|
const matching = pathnames
|
|
1211
|
-
? routes.filter((route) => pathnames.some((pathname) => route
|
|
1294
|
+
? routes.filter((route) => pathnames.some((pathname) => route.exec(pathname)))
|
|
1212
1295
|
: routes;
|
|
1213
1296
|
|
|
1214
|
-
const promises = matching.map((r) => Promise.all(r
|
|
1297
|
+
const promises = matching.map((r) => Promise.all(r.a.map((load) => load())));
|
|
1215
1298
|
|
|
1216
1299
|
await Promise.all(promises);
|
|
1217
1300
|
},
|
|
@@ -1389,7 +1472,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1389
1472
|
});
|
|
1390
1473
|
},
|
|
1391
1474
|
|
|
1392
|
-
_hydrate: async ({ status, error, nodes, params }) => {
|
|
1475
|
+
_hydrate: async ({ status, error, nodes, params, routeId }) => {
|
|
1393
1476
|
const url = new URL(location.href);
|
|
1394
1477
|
|
|
1395
1478
|
/** @type {Array<import('./types').BranchNode | undefined>} */
|
|
@@ -1423,7 +1506,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1423
1506
|
stuff,
|
|
1424
1507
|
status: is_leaf ? status : undefined,
|
|
1425
1508
|
error: is_leaf ? error : undefined,
|
|
1426
|
-
props
|
|
1509
|
+
props,
|
|
1510
|
+
routeId
|
|
1427
1511
|
});
|
|
1428
1512
|
|
|
1429
1513
|
if (props) {
|
|
@@ -1439,7 +1523,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1439
1523
|
error_args = {
|
|
1440
1524
|
status: node.loaded.status,
|
|
1441
1525
|
error: node.loaded.error,
|
|
1442
|
-
url
|
|
1526
|
+
url,
|
|
1527
|
+
routeId
|
|
1443
1528
|
};
|
|
1444
1529
|
} else if (node.loaded.stuff) {
|
|
1445
1530
|
stuff = {
|
|
@@ -1458,7 +1543,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1458
1543
|
stuff,
|
|
1459
1544
|
branch,
|
|
1460
1545
|
status,
|
|
1461
|
-
error
|
|
1546
|
+
error,
|
|
1547
|
+
routeId
|
|
1462
1548
|
});
|
|
1463
1549
|
} catch (e) {
|
|
1464
1550
|
if (error) throw e;
|
|
@@ -1466,7 +1552,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1466
1552
|
result = await load_root_error_page({
|
|
1467
1553
|
status: 500,
|
|
1468
1554
|
error: coalesce_to_error(e),
|
|
1469
|
-
url
|
|
1555
|
+
url,
|
|
1556
|
+
routeId
|
|
1470
1557
|
});
|
|
1471
1558
|
}
|
|
1472
1559
|
|
|
@@ -1497,6 +1584,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1497
1584
|
* error: Error;
|
|
1498
1585
|
* nodes: Array<Promise<import('types').CSRComponent>>;
|
|
1499
1586
|
* params: Record<string, string>;
|
|
1587
|
+
* routeId: string | null;
|
|
1500
1588
|
* };
|
|
1501
1589
|
* }} opts
|
|
1502
1590
|
*/
|