@sveltejs/kit 1.0.0-next.296 → 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 -111
- package/assets/server/index.js +196 -146
- package/dist/chunks/index.js +94 -83
- package/dist/chunks/index2.js +17 -4
- package/dist/chunks/index3.js +31 -30
- package/dist/chunks/index4.js +1 -0
- package/dist/chunks/index5.js +10 -1
- package/dist/chunks/routing.js +39 -0
- package/dist/chunks/sync.js +127 -71
- package/dist/cli.js +7 -8
- package/package.json +1 -1
- package/types/index.d.ts +25 -19
- package/types/internal.d.ts +29 -25
- package/types/private.d.ts +17 -17
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,11 +957,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
875
957
|
};
|
|
876
958
|
}
|
|
877
959
|
|
|
878
|
-
|
|
879
|
-
// fallthrough
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
props = await res.json();
|
|
960
|
+
props = res.status === 204 ? {} : await res.json();
|
|
883
961
|
} else {
|
|
884
962
|
status = res.status;
|
|
885
963
|
error = new Error('Failed to load data');
|
|
@@ -892,7 +970,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
892
970
|
url,
|
|
893
971
|
params,
|
|
894
972
|
props,
|
|
895
|
-
stuff
|
|
973
|
+
stuff,
|
|
974
|
+
routeId: route.id
|
|
896
975
|
});
|
|
897
976
|
}
|
|
898
977
|
|
|
@@ -902,9 +981,14 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
902
981
|
}
|
|
903
982
|
|
|
904
983
|
if (node.loaded) {
|
|
984
|
+
// TODO remove for 1.0
|
|
985
|
+
// @ts-expect-error
|
|
905
986
|
if (node.loaded.fallthrough) {
|
|
906
|
-
|
|
987
|
+
throw new Error(
|
|
988
|
+
'fallthrough is no longer supported. Use validators instead: https://kit.svelte.dev/docs/routing#advanced-routing-validation'
|
|
989
|
+
);
|
|
907
990
|
}
|
|
991
|
+
|
|
908
992
|
if (node.loaded.error) {
|
|
909
993
|
status = node.loaded.status;
|
|
910
994
|
error = node.loaded.error;
|
|
@@ -950,7 +1034,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
950
1034
|
module: await b[i](),
|
|
951
1035
|
url,
|
|
952
1036
|
params,
|
|
953
|
-
stuff: node_loaded.stuff
|
|
1037
|
+
stuff: node_loaded.stuff,
|
|
1038
|
+
routeId: route.id
|
|
954
1039
|
});
|
|
955
1040
|
|
|
956
1041
|
if (error_loaded?.loaded?.error) {
|
|
@@ -975,7 +1060,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
975
1060
|
return await load_root_error_page({
|
|
976
1061
|
status,
|
|
977
1062
|
error,
|
|
978
|
-
url
|
|
1063
|
+
url,
|
|
1064
|
+
routeId: route.id
|
|
979
1065
|
});
|
|
980
1066
|
} else {
|
|
981
1067
|
if (node?.loaded?.stuff) {
|
|
@@ -995,7 +1081,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
995
1081
|
stuff,
|
|
996
1082
|
branch,
|
|
997
1083
|
status,
|
|
998
|
-
error
|
|
1084
|
+
error,
|
|
1085
|
+
routeId: route.id
|
|
999
1086
|
});
|
|
1000
1087
|
}
|
|
1001
1088
|
|
|
@@ -1004,26 +1091,29 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1004
1091
|
* status: number;
|
|
1005
1092
|
* error: Error;
|
|
1006
1093
|
* url: URL;
|
|
1094
|
+
* routeId: string | null
|
|
1007
1095
|
* }} opts
|
|
1008
1096
|
*/
|
|
1009
|
-
async function load_root_error_page({ status, error, url }) {
|
|
1097
|
+
async function load_root_error_page({ status, error, url, routeId }) {
|
|
1010
1098
|
/** @type {Record<string, string>} */
|
|
1011
1099
|
const params = {}; // error page does not have params
|
|
1012
1100
|
|
|
1013
1101
|
const root_layout = await load_node({
|
|
1014
|
-
module: await
|
|
1102
|
+
module: await default_layout,
|
|
1015
1103
|
url,
|
|
1016
1104
|
params,
|
|
1017
|
-
stuff: {}
|
|
1105
|
+
stuff: {},
|
|
1106
|
+
routeId
|
|
1018
1107
|
});
|
|
1019
1108
|
|
|
1020
1109
|
const root_error = await load_node({
|
|
1021
1110
|
status,
|
|
1022
1111
|
error,
|
|
1023
|
-
module: await
|
|
1112
|
+
module: await default_error,
|
|
1024
1113
|
url,
|
|
1025
1114
|
params,
|
|
1026
|
-
stuff: (root_layout && root_layout.loaded && root_layout.loaded.stuff) || {}
|
|
1115
|
+
stuff: (root_layout && root_layout.loaded && root_layout.loaded.stuff) || {},
|
|
1116
|
+
routeId
|
|
1027
1117
|
});
|
|
1028
1118
|
|
|
1029
1119
|
return await get_navigation_result_from_branch({
|
|
@@ -1035,28 +1125,32 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1035
1125
|
},
|
|
1036
1126
|
branch: [root_layout, root_error],
|
|
1037
1127
|
status,
|
|
1038
|
-
error
|
|
1128
|
+
error,
|
|
1129
|
+
routeId
|
|
1039
1130
|
});
|
|
1040
1131
|
}
|
|
1041
1132
|
|
|
1042
|
-
/** @param {URL} url */
|
|
1043
|
-
function owns(url) {
|
|
1044
|
-
return url.origin === location.origin && url.pathname.startsWith(base);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
1133
|
/** @param {URL} url */
|
|
1048
1134
|
function get_navigation_intent(url) {
|
|
1135
|
+
if (url.origin !== location.origin || !url.pathname.startsWith(base)) return;
|
|
1136
|
+
|
|
1049
1137
|
const path = decodeURI(url.pathname.slice(base.length) || '/');
|
|
1050
1138
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
id: url.pathname + url.search,
|
|
1054
|
-
routes: routes.filter(([pattern]) => pattern.test(path)),
|
|
1055
|
-
url,
|
|
1056
|
-
path
|
|
1057
|
-
};
|
|
1139
|
+
for (const route of routes) {
|
|
1140
|
+
const params = route.exec(path);
|
|
1058
1141
|
|
|
1059
|
-
|
|
1142
|
+
if (params) {
|
|
1143
|
+
/** @type {import('./types').NavigationIntent} */
|
|
1144
|
+
const intent = {
|
|
1145
|
+
id: url.pathname + url.search,
|
|
1146
|
+
route,
|
|
1147
|
+
params,
|
|
1148
|
+
url
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1151
|
+
return intent;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1060
1154
|
}
|
|
1061
1155
|
|
|
1062
1156
|
/**
|
|
@@ -1090,14 +1184,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1090
1184
|
return;
|
|
1091
1185
|
}
|
|
1092
1186
|
|
|
1093
|
-
if (!owns(url)) {
|
|
1094
|
-
await native_navigation(url);
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
1187
|
const pathname = normalize_path(url.pathname, trailing_slash);
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
const intent = get_navigation_intent(url);
|
|
1188
|
+
const normalized = new URL(url.origin + pathname + url.search + url.hash);
|
|
1101
1189
|
|
|
1102
1190
|
update_scroll_positions(current_history_index);
|
|
1103
1191
|
|
|
@@ -1110,11 +1198,11 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1110
1198
|
if (started) {
|
|
1111
1199
|
stores.navigating.set({
|
|
1112
1200
|
from: current.url,
|
|
1113
|
-
to:
|
|
1201
|
+
to: normalized
|
|
1114
1202
|
});
|
|
1115
1203
|
}
|
|
1116
1204
|
|
|
1117
|
-
await update(
|
|
1205
|
+
await update(normalized, redirect_chain, false, {
|
|
1118
1206
|
scroll,
|
|
1119
1207
|
keepfocus,
|
|
1120
1208
|
details
|
|
@@ -1126,7 +1214,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1126
1214
|
if (navigating_token !== current_navigating_token) return;
|
|
1127
1215
|
|
|
1128
1216
|
if (!navigating) {
|
|
1129
|
-
const navigation = { from, to:
|
|
1217
|
+
const navigation = { from, to: normalized };
|
|
1130
1218
|
callbacks.after_navigate.forEach((fn) => fn(navigation));
|
|
1131
1219
|
|
|
1132
1220
|
stores.navigating.set(null);
|
|
@@ -1186,8 +1274,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1186
1274
|
|
|
1187
1275
|
if (!invalidating) {
|
|
1188
1276
|
invalidating = Promise.resolve().then(async () => {
|
|
1189
|
-
|
|
1190
|
-
await update(intent, [], true);
|
|
1277
|
+
await update(new URL(location.href), [], true);
|
|
1191
1278
|
|
|
1192
1279
|
invalidating = null;
|
|
1193
1280
|
});
|
|
@@ -1204,10 +1291,10 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1204
1291
|
// TODO rethink this API
|
|
1205
1292
|
prefetch_routes: async (pathnames) => {
|
|
1206
1293
|
const matching = pathnames
|
|
1207
|
-
? routes.filter((route) => pathnames.some((pathname) => route
|
|
1294
|
+
? routes.filter((route) => pathnames.some((pathname) => route.exec(pathname)))
|
|
1208
1295
|
: routes;
|
|
1209
1296
|
|
|
1210
|
-
const promises = matching.map((r) => Promise.all(r
|
|
1297
|
+
const promises = matching.map((r) => Promise.all(r.a.map((load) => load())));
|
|
1211
1298
|
|
|
1212
1299
|
await Promise.all(promises);
|
|
1213
1300
|
},
|
|
@@ -1385,7 +1472,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1385
1472
|
});
|
|
1386
1473
|
},
|
|
1387
1474
|
|
|
1388
|
-
_hydrate: async ({ status, error, nodes, params }) => {
|
|
1475
|
+
_hydrate: async ({ status, error, nodes, params, routeId }) => {
|
|
1389
1476
|
const url = new URL(location.href);
|
|
1390
1477
|
|
|
1391
1478
|
/** @type {Array<import('./types').BranchNode | undefined>} */
|
|
@@ -1419,7 +1506,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1419
1506
|
stuff,
|
|
1420
1507
|
status: is_leaf ? status : undefined,
|
|
1421
1508
|
error: is_leaf ? error : undefined,
|
|
1422
|
-
props
|
|
1509
|
+
props,
|
|
1510
|
+
routeId
|
|
1423
1511
|
});
|
|
1424
1512
|
|
|
1425
1513
|
if (props) {
|
|
@@ -1435,7 +1523,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1435
1523
|
error_args = {
|
|
1436
1524
|
status: node.loaded.status,
|
|
1437
1525
|
error: node.loaded.error,
|
|
1438
|
-
url
|
|
1526
|
+
url,
|
|
1527
|
+
routeId
|
|
1439
1528
|
};
|
|
1440
1529
|
} else if (node.loaded.stuff) {
|
|
1441
1530
|
stuff = {
|
|
@@ -1454,7 +1543,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1454
1543
|
stuff,
|
|
1455
1544
|
branch,
|
|
1456
1545
|
status,
|
|
1457
|
-
error
|
|
1546
|
+
error,
|
|
1547
|
+
routeId
|
|
1458
1548
|
});
|
|
1459
1549
|
} catch (e) {
|
|
1460
1550
|
if (error) throw e;
|
|
@@ -1462,7 +1552,8 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1462
1552
|
result = await load_root_error_page({
|
|
1463
1553
|
status: 500,
|
|
1464
1554
|
error: coalesce_to_error(e),
|
|
1465
|
-
url
|
|
1555
|
+
url,
|
|
1556
|
+
routeId
|
|
1466
1557
|
});
|
|
1467
1558
|
}
|
|
1468
1559
|
|
|
@@ -1493,6 +1584,7 @@ function create_client({ target, session, base, trailing_slash }) {
|
|
|
1493
1584
|
* error: Error;
|
|
1494
1585
|
* nodes: Array<Promise<import('types').CSRComponent>>;
|
|
1495
1586
|
* params: Record<string, string>;
|
|
1587
|
+
* routeId: string | null;
|
|
1496
1588
|
* };
|
|
1497
1589
|
* }} opts
|
|
1498
1590
|
*/
|