@sveltejs/kit 1.0.0-next.55 → 1.0.0-next.550

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.
Files changed (128) hide show
  1. package/README.md +5 -2
  2. package/package.json +93 -67
  3. package/postinstall.js +47 -0
  4. package/scripts/special-types/$env+dynamic+private.md +10 -0
  5. package/scripts/special-types/$env+dynamic+public.md +8 -0
  6. package/scripts/special-types/$env+static+private.md +19 -0
  7. package/scripts/special-types/$env+static+public.md +7 -0
  8. package/scripts/special-types/$lib.md +5 -0
  9. package/src/cli.js +108 -0
  10. package/src/constants.js +5 -0
  11. package/src/core/adapt/builder.js +212 -0
  12. package/src/core/adapt/index.js +31 -0
  13. package/src/core/config/default-error.html +56 -0
  14. package/src/core/config/index.js +110 -0
  15. package/src/core/config/options.js +516 -0
  16. package/src/core/config/types.d.ts +1 -0
  17. package/src/core/env.js +121 -0
  18. package/src/core/generate_manifest/index.js +125 -0
  19. package/src/core/prerender/crawl.js +207 -0
  20. package/src/core/prerender/entities.js +2252 -0
  21. package/src/core/prerender/prerender.js +460 -0
  22. package/src/core/prerender/queue.js +80 -0
  23. package/src/core/sync/create_manifest_data/conflict.js +0 -0
  24. package/src/core/sync/create_manifest_data/index.js +513 -0
  25. package/src/core/sync/create_manifest_data/sort.js +161 -0
  26. package/src/core/sync/create_manifest_data/types.d.ts +37 -0
  27. package/src/core/sync/sync.js +78 -0
  28. package/src/core/sync/utils.js +33 -0
  29. package/src/core/sync/write_ambient.js +53 -0
  30. package/src/core/sync/write_client_manifest.js +106 -0
  31. package/src/core/sync/write_matchers.js +25 -0
  32. package/src/core/sync/write_root.js +91 -0
  33. package/src/core/sync/write_tsconfig.js +195 -0
  34. package/src/core/sync/write_types/index.js +809 -0
  35. package/src/core/utils.js +67 -0
  36. package/src/exports/hooks/index.js +1 -0
  37. package/src/exports/hooks/sequence.js +44 -0
  38. package/src/exports/index.js +45 -0
  39. package/src/exports/node/index.js +172 -0
  40. package/src/exports/node/polyfills.js +28 -0
  41. package/src/exports/vite/build/build_server.js +384 -0
  42. package/src/exports/vite/build/build_service_worker.js +92 -0
  43. package/src/exports/vite/build/utils.js +195 -0
  44. package/src/exports/vite/dev/index.js +588 -0
  45. package/src/exports/vite/graph_analysis/index.js +107 -0
  46. package/src/exports/vite/graph_analysis/types.d.ts +5 -0
  47. package/src/exports/vite/graph_analysis/utils.js +6 -0
  48. package/src/exports/vite/index.js +651 -0
  49. package/src/exports/vite/preview/index.js +193 -0
  50. package/src/exports/vite/types.d.ts +3 -0
  51. package/src/exports/vite/utils.js +171 -0
  52. package/src/runtime/app/env.js +1 -0
  53. package/src/runtime/app/environment.js +11 -0
  54. package/src/runtime/app/forms.js +141 -0
  55. package/src/runtime/app/navigation.js +23 -0
  56. package/src/runtime/app/paths.js +1 -0
  57. package/src/runtime/app/stores.js +102 -0
  58. package/src/runtime/client/ambient.d.ts +30 -0
  59. package/src/runtime/client/client.js +1726 -0
  60. package/src/runtime/client/fetcher.js +121 -0
  61. package/src/runtime/client/parse.js +60 -0
  62. package/src/runtime/client/singletons.js +21 -0
  63. package/src/runtime/client/start.js +43 -0
  64. package/src/runtime/client/types.d.ts +84 -0
  65. package/src/runtime/client/utils.js +166 -0
  66. package/src/runtime/components/error.svelte +16 -0
  67. package/{assets → src/runtime}/components/layout.svelte +0 -0
  68. package/src/runtime/control.js +98 -0
  69. package/src/runtime/env/dynamic/private.js +1 -0
  70. package/src/runtime/env/dynamic/public.js +1 -0
  71. package/src/runtime/env-private.js +6 -0
  72. package/src/runtime/env-public.js +6 -0
  73. package/src/runtime/env.js +6 -0
  74. package/src/runtime/hash.js +20 -0
  75. package/src/runtime/paths.js +11 -0
  76. package/src/runtime/server/cookie.js +231 -0
  77. package/src/runtime/server/data/index.js +144 -0
  78. package/src/runtime/server/endpoint.js +89 -0
  79. package/src/runtime/server/fetch.js +164 -0
  80. package/src/runtime/server/index.js +375 -0
  81. package/src/runtime/server/page/actions.js +258 -0
  82. package/src/runtime/server/page/crypto.js +239 -0
  83. package/src/runtime/server/page/csp.js +250 -0
  84. package/src/runtime/server/page/index.js +303 -0
  85. package/src/runtime/server/page/load_data.js +258 -0
  86. package/src/runtime/server/page/render.js +391 -0
  87. package/src/runtime/server/page/respond_with_error.js +102 -0
  88. package/src/runtime/server/page/serialize_data.js +87 -0
  89. package/src/runtime/server/page/types.d.ts +35 -0
  90. package/src/runtime/server/utils.js +205 -0
  91. package/src/utils/array.js +9 -0
  92. package/src/utils/error.js +22 -0
  93. package/src/utils/escape.js +46 -0
  94. package/src/utils/filesystem.js +166 -0
  95. package/src/utils/functions.js +16 -0
  96. package/src/utils/http.js +72 -0
  97. package/src/utils/misc.js +1 -0
  98. package/src/utils/promises.js +17 -0
  99. package/src/utils/routing.js +168 -0
  100. package/src/utils/unit_test.js +11 -0
  101. package/src/utils/url.js +159 -0
  102. package/svelte-kit.js +1 -1
  103. package/types/ambient.d.ts +469 -0
  104. package/types/index.d.ts +775 -0
  105. package/types/internal.d.ts +381 -0
  106. package/types/private.d.ts +229 -0
  107. package/CHANGELOG.md +0 -519
  108. package/assets/components/error.svelte +0 -13
  109. package/assets/runtime/app/env.js +0 -5
  110. package/assets/runtime/app/navigation.js +0 -48
  111. package/assets/runtime/app/paths.js +0 -1
  112. package/assets/runtime/app/stores.js +0 -93
  113. package/assets/runtime/chunks/utils.js +0 -22
  114. package/assets/runtime/internal/singletons.js +0 -23
  115. package/assets/runtime/internal/start.js +0 -823
  116. package/assets/runtime/paths.js +0 -12
  117. package/dist/chunks/index.js +0 -3544
  118. package/dist/chunks/index2.js +0 -572
  119. package/dist/chunks/index3.js +0 -246
  120. package/dist/chunks/index4.js +0 -569
  121. package/dist/chunks/index5.js +0 -751
  122. package/dist/chunks/index6.js +0 -323
  123. package/dist/chunks/standard.js +0 -99
  124. package/dist/chunks/utils.js +0 -83
  125. package/dist/cli.js +0 -558
  126. package/dist/ssr.js +0 -2620
  127. package/types.d.ts +0 -74
  128. package/types.internal.d.ts +0 -237
@@ -1,823 +0,0 @@
1
- import Root from '../../generated/root.svelte';
2
- import { routes, layout } from '../../generated/manifest.js';
3
- import { f as find_anchor, g as get_base_uri } from '../chunks/utils.js';
4
- import { writable } from 'svelte/store';
5
- import { init } from './singletons.js';
6
- import { set_paths } from '../paths.js';
7
-
8
- /** @param {MouseEvent} event */
9
- function which(event) {
10
- return event.which === null ? event.button : event.which;
11
- }
12
-
13
- function scroll_state() {
14
- return {
15
- x: pageXOffset,
16
- y: pageYOffset
17
- };
18
- }
19
-
20
- class Router {
21
- /** @param {{
22
- * base: string;
23
- * routes: import('types.internal').CSRRoute[];
24
- * }} opts */
25
- constructor({ base, routes }) {
26
- this.base = base;
27
- this.routes = routes;
28
-
29
- this.history = window.history || {
30
- pushState: () => {},
31
- replaceState: () => {},
32
- scrollRestoration: 'auto'
33
- };
34
- }
35
-
36
- /** @param {import('./renderer').Renderer} renderer */
37
- init(renderer) {
38
- /** @type {import('./renderer').Renderer} */
39
- this.renderer = renderer;
40
- renderer.router = this;
41
-
42
- if ('scrollRestoration' in this.history) {
43
- this.history.scrollRestoration = 'manual';
44
- }
45
-
46
- // Adopted from Nuxt.js
47
- // Reset scrollRestoration to auto when leaving page, allowing page reload
48
- // and back-navigation from other pages to use the browser to restore the
49
- // scrolling position.
50
- addEventListener('beforeunload', () => {
51
- this.history.scrollRestoration = 'auto';
52
- });
53
-
54
- // Setting scrollRestoration to manual again when returning to this page.
55
- addEventListener('load', () => {
56
- this.history.scrollRestoration = 'manual';
57
- });
58
-
59
- // There's no API to capture the scroll location right before the user
60
- // hits the back/forward button, so we listen for scroll events
61
-
62
- /** @type {NodeJS.Timeout} */
63
- let scroll_timer;
64
- addEventListener('scroll', () => {
65
- clearTimeout(scroll_timer);
66
- scroll_timer = setTimeout(() => {
67
- // Store the scroll location in the history
68
- // This will persist even if we navigate away from the site and come back
69
- const new_state = {
70
- ...(history.state || {}),
71
- 'sveltekit:scroll': scroll_state()
72
- };
73
- history.replaceState(new_state, document.title, window.location.href);
74
- }, 50);
75
- });
76
-
77
- /** @param {MouseEvent} event */
78
- addEventListener('click', (event) => {
79
- // Adapted from https://github.com/visionmedia/page.js
80
- // MIT license https://github.com/visionmedia/page.js#license
81
- if (which(event) !== 1) return;
82
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
83
- if (event.defaultPrevented) return;
84
-
85
- const a = find_anchor(/** @type {Node} */ (event.target));
86
- if (!a) return;
87
-
88
- if (!a.href) return;
89
-
90
- // check if link is inside an svg
91
- // in this case, both href and target are always inside an object
92
- const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString';
93
- const href = String(svg ? /** @type {SVGAElement} */ (a).href.baseVal : a.href);
94
-
95
- if (href === location.href) {
96
- if (!location.hash) event.preventDefault();
97
- return;
98
- }
99
-
100
- // Ignore if tag has
101
- // 1. 'download' attribute
102
- // 2. rel='external' attribute
103
- if (a.hasAttribute('download') || a.getAttribute('rel') === 'external') return;
104
-
105
- // Ignore if <a> has a target
106
- if (svg ? /** @type {SVGAElement} */ (a).target.baseVal : a.target) return;
107
-
108
- const url = new URL(href);
109
-
110
- // Don't handle hash changes
111
- if (url.pathname === location.pathname && url.search === location.search) return;
112
-
113
- const info = this.parse(url);
114
- if (info) {
115
- const noscroll = a.hasAttribute('sveltekit:noscroll');
116
- this.history.pushState({}, '', url.href);
117
- this._navigate(info, noscroll ? scroll_state() : null, [], url.hash);
118
- event.preventDefault();
119
- }
120
- });
121
-
122
- addEventListener('popstate', (event) => {
123
- if (event.state) {
124
- const url = new URL(location.href);
125
- const info = this.parse(url);
126
- if (info) {
127
- this._navigate(info, event.state['sveltekit:scroll'], []);
128
- } else {
129
- // eslint-disable-next-line
130
- location.href = location.href; // nosonar
131
- }
132
- }
133
- });
134
-
135
- // make it possible to reset focus
136
- document.body.setAttribute('tabindex', '-1');
137
-
138
- // create initial history entry, so we can return here
139
- this.history.replaceState({}, '', location.href);
140
- }
141
-
142
- /**
143
- * @param {URL} url
144
- * @returns {import('./types').NavigationInfo}
145
- */
146
- parse(url) {
147
- if (url.origin !== location.origin) return null;
148
- if (!url.pathname.startsWith(this.base)) return null;
149
-
150
- const path = url.pathname.slice(this.base.length) || '/';
151
-
152
- const routes = this.routes.filter((route) => route.pattern.test(path));
153
-
154
- if (routes.length > 0) {
155
- return {
156
- routes,
157
- path,
158
- query: new URLSearchParams(url.search)
159
- };
160
- }
161
- }
162
-
163
- /**
164
- * @param {string} href
165
- * @param {{ noscroll?: boolean, replaceState?: boolean }} opts
166
- * @param {string[]} chain
167
- */
168
- async goto(href, { noscroll = false, replaceState = false } = {}, chain) {
169
- const url = new URL(href, get_base_uri(document));
170
- const info = this.parse(url);
171
-
172
- if (info) {
173
- // TODO shouldn't need to pass the hash here
174
- this.history[replaceState ? 'replaceState' : 'pushState']({}, '', href);
175
- return this._navigate(info, noscroll ? scroll_state() : null, chain, url.hash);
176
- }
177
-
178
- location.href = href;
179
- return new Promise(() => {
180
- /* never resolves */
181
- });
182
- }
183
-
184
- /**
185
- * @param {import('./types').NavigationInfo} info
186
- * @param {{ x: number, y: number }} scroll
187
- * @param {string[]} chain
188
- * @param {string} [hash]
189
- */
190
- async _navigate(info, scroll, chain, hash) {
191
- this.renderer.notify({
192
- path: info.path,
193
- query: info.query
194
- });
195
-
196
- // remove trailing slashes
197
- if (location.pathname.endsWith('/') && location.pathname !== '/') {
198
- history.replaceState({}, '', `${location.pathname.slice(0, -1)}${location.search}`);
199
- }
200
-
201
- await this.renderer.update(info, chain);
202
-
203
- document.body.focus();
204
-
205
- const deep_linked = hash && document.getElementById(hash.slice(1));
206
- if (scroll) {
207
- scrollTo(scroll.x, scroll.y);
208
- } else if (deep_linked) {
209
- // scroll is an element id (from a hash), we need to compute y
210
- scrollTo(0, deep_linked.getBoundingClientRect().top + scrollY);
211
- } else {
212
- scrollTo(0, 0);
213
- }
214
- }
215
- }
216
-
217
- /**
218
- * @param {import('../../types.internal').LoadOutput} loaded
219
- * @returns {import('../../types.internal').LoadOutput}
220
- */
221
- function normalize(loaded) {
222
- // TODO should this behaviour be dev-only?
223
-
224
- if (loaded.error) {
225
- const error = typeof loaded.error === 'string' ? new Error(loaded.error) : loaded.error;
226
- const status = loaded.status;
227
-
228
- if (!(error instanceof Error)) {
229
- return {
230
- status: 500,
231
- error: new Error(
232
- `"error" property returned from load() must be a string or instance of Error, received type "${typeof error}"`
233
- )
234
- };
235
- }
236
-
237
- if (!status || status < 400 || status > 599) {
238
- console.warn('"error" returned from load() without a valid status code — defaulting to 500');
239
- return { status: 500, error };
240
- }
241
-
242
- return { status, error };
243
- }
244
-
245
- if (loaded.redirect) {
246
- if (!loaded.status || Math.floor(loaded.status / 100) !== 3) {
247
- return {
248
- status: 500,
249
- error: new Error(
250
- '"redirect" property returned from load() must be accompanied by a 3xx status code'
251
- )
252
- };
253
- }
254
-
255
- if (typeof loaded.redirect !== 'string') {
256
- return {
257
- status: 500,
258
- error: new Error('"redirect" property returned from load() must be a string')
259
- };
260
- }
261
- }
262
-
263
- return loaded;
264
- }
265
-
266
- /** @param {any} value */
267
- function page_store(value) {
268
- const store = writable(value);
269
- let ready = true;
270
-
271
- function notify() {
272
- ready = true;
273
- store.update((val) => val);
274
- }
275
-
276
- /** @param {any} new_value */
277
- function set(new_value) {
278
- ready = false;
279
- store.set(new_value);
280
- }
281
-
282
- /** @param {(value: any) => void} run */
283
- function subscribe(run) {
284
- /** @type {any} */
285
- let old_value;
286
- return store.subscribe((new_value) => {
287
- if (old_value === undefined || (ready && new_value !== old_value)) {
288
- run((old_value = new_value));
289
- }
290
- });
291
- }
292
-
293
- return { notify, set, subscribe };
294
- }
295
-
296
- class Renderer {
297
- /** @param {{
298
- * Root: import('types.internal').CSRComponent;
299
- * layout: import('types.internal').CSRComponent;
300
- * target: Node;
301
- * session: any;
302
- * host: string;
303
- * }} opts */
304
- constructor({ Root, layout, target, session, host }) {
305
- this.Root = Root;
306
- this.layout = layout;
307
- this.host = host;
308
-
309
- /** @type {import('./router').Router} */
310
- this.router = null;
311
-
312
- // TODO ideally we wouldn't need to store these...
313
- this.target = target;
314
-
315
- this.started = false;
316
-
317
- /** @type {import('./types').NavigationState} */
318
- this.current = {
319
- page: null,
320
- query: null,
321
- session_changed: false,
322
- nodes: [],
323
- contexts: []
324
- };
325
-
326
- this.caches = new Map();
327
-
328
- this.prefetching = {
329
- href: null,
330
- promise: null
331
- };
332
-
333
- this.stores = {
334
- page: page_store({}),
335
- navigating: writable(null),
336
- session: writable(session)
337
- };
338
-
339
- this.$session = null;
340
-
341
- this.root = null;
342
-
343
- /** @param {MouseEvent} event */
344
- const trigger_prefetch = (event) => {
345
- const a = find_anchor(/** @type {Node} */ (event.target));
346
- if (a && a.hasAttribute('sveltekit:prefetch')) {
347
- this.prefetch(new URL(/** @type {string} */ (a.href)));
348
- }
349
- };
350
-
351
- /** @type {NodeJS.Timeout} */
352
- let mousemove_timeout;
353
-
354
- /** @param {MouseEvent} event */
355
- const handle_mousemove = (event) => {
356
- clearTimeout(mousemove_timeout);
357
- mousemove_timeout = setTimeout(() => {
358
- trigger_prefetch(event);
359
- }, 20);
360
- };
361
-
362
- addEventListener('touchstart', trigger_prefetch);
363
- addEventListener('mousemove', handle_mousemove);
364
-
365
- let ready = false;
366
- this.stores.session.subscribe(async (value) => {
367
- this.$session = value;
368
-
369
- if (!ready) return;
370
- this.current.session_changed = true;
371
-
372
- const info = this.router.parse(new URL(location.href));
373
- this.update(info, []);
374
- });
375
- ready = true;
376
- }
377
-
378
- /**
379
- * @param {import('./types').NavigationCandidate} selected
380
- * @param {number} status
381
- * @param {Error} error
382
- */
383
- async start(selected, status, error) {
384
- /** @type {Record<string, any>} */
385
- const props = {
386
- stores: this.stores,
387
- error,
388
- status,
389
- page: selected.page
390
- };
391
-
392
- if (error) {
393
- props.components = [this.layout.default];
394
- } else {
395
- const hydrated = await this._hydrate(selected);
396
-
397
- if (hydrated.redirect) {
398
- throw new Error('TODO client-side redirects');
399
- }
400
-
401
- Object.assign(props, hydrated.props);
402
- this.current = hydrated.state;
403
- }
404
-
405
- // remove dev-mode SSR <style> insert, since it doesn't apply
406
- // to hydrated markup (HMR requires hashes to be rewritten)
407
- // TODO only in dev
408
- // TODO it seems this doesn't always work with the classname
409
- // stabilisation in vite-plugin-svelte? see e.g.
410
- // hn.svelte.dev
411
- // const style = document.querySelector('style[data-svelte]');
412
- // if (style) style.remove();
413
-
414
- this.root = new this.Root({
415
- target: this.target,
416
- props,
417
- hydrate: true
418
- });
419
-
420
- this.started = true;
421
- }
422
-
423
- /** @param {{ path: string, query: URLSearchParams }} destination */
424
- notify({ path, query }) {
425
- dispatchEvent(new CustomEvent('sveltekit:navigation-start'));
426
-
427
- this.stores.navigating.set({
428
- from: {
429
- path: this.current.page.path,
430
- query: this.current.page.query
431
- },
432
- to: {
433
- path,
434
- query
435
- }
436
- });
437
- }
438
-
439
- /**
440
- * @param {import('./types').NavigationInfo} info
441
- * @param {string[]} chain
442
- */
443
- async update(info, chain) {
444
- const token = (this.token = {});
445
- const navigation_result = await this._get_navigation_result(info);
446
-
447
- // abort if user navigated during update
448
- if (token !== this.token) return;
449
-
450
- if (navigation_result.reload) {
451
- location.reload();
452
- } else if (navigation_result.redirect) {
453
- if (chain.length > 10 || chain.includes(this.current.page.path)) {
454
- this.root.$set({
455
- status: 500,
456
- error: new Error('Redirect loop')
457
- });
458
- } else {
459
- this.router.goto(navigation_result.redirect, { replaceState: true }, [
460
- ...chain,
461
- this.current.page.path
462
- ]);
463
-
464
- return;
465
- }
466
- } else {
467
- this.current = navigation_result.state;
468
-
469
- this.root.$set(navigation_result.props);
470
- this.stores.navigating.set(null);
471
-
472
- await 0;
473
- }
474
-
475
- dispatchEvent(new CustomEvent('sveltekit:navigation-end'));
476
- }
477
-
478
- /**
479
- * @param {URL} url
480
- * @returns {Promise<import('./types').NavigationResult>}
481
- */
482
- async prefetch(url) {
483
- const info = this.router.parse(url);
484
- if (info) {
485
- if (url.href !== this.prefetching.href) {
486
- this.prefetching = {
487
- href: url.href,
488
- promise: this._get_navigation_result(info)
489
- };
490
- }
491
-
492
- return this.prefetching.promise;
493
- } else {
494
- throw new Error(`Could not prefetch ${url.href}`);
495
- }
496
- }
497
-
498
- /**
499
- * @param {import('./types').NavigationInfo} info
500
- * @returns {Promise<import('./types').NavigationResult>}
501
- */
502
- async _get_navigation_result(info) {
503
- for (let i = 0; i < info.routes.length; i += 1) {
504
- const route = info.routes[i];
505
-
506
- if (route.type === 'endpoint') {
507
- return { reload: true };
508
- }
509
-
510
- // load code for subsequent routes immediately, if they are as
511
- // likely to match the current path/query as the current one
512
- let j = i + 1;
513
- while (j < info.routes.length) {
514
- const next = info.routes[j];
515
- if (next.pattern.toString() === route.pattern.toString()) {
516
- if (next.type === 'page') next.parts.forEach((loader) => loader());
517
- j += 1;
518
- } else {
519
- break;
520
- }
521
- }
522
-
523
- const nodes = route.parts.map((loader) => loader());
524
- const page = {
525
- host: this.host,
526
- path: info.path,
527
- params: route.params(route.pattern.exec(info.path)),
528
- query: info.query
529
- };
530
-
531
- const hydrated = await this._hydrate({ nodes, page });
532
- if (hydrated) return hydrated;
533
- }
534
-
535
- return {
536
- state: {
537
- page: null,
538
- query: null,
539
- session_changed: false,
540
- contexts: [],
541
- nodes: []
542
- },
543
- props: {
544
- status: 404,
545
- error: new Error(`Not found: ${info.path}`)
546
- }
547
- };
548
- }
549
-
550
- /** @param {import('./types').NavigationCandidate} selected */
551
- async _hydrate({ nodes, page }) {
552
- /** @type {Record<string, any>} */
553
- const props = {
554
- status: 200,
555
-
556
- /** @type {Error} */
557
- error: null,
558
-
559
- /** @type {import('types.internal').CSRComponent[]} */
560
- components: []
561
- };
562
-
563
- /**
564
- * @param {string} url
565
- * @param {RequestInit} opts
566
- */
567
- const fetcher = (url, opts) => {
568
- if (!this.started) {
569
- const script = document.querySelector(`script[type="svelte-data"][url="${url}"]`);
570
- if (script) {
571
- const { body, ...init } = JSON.parse(script.textContent);
572
- return Promise.resolve(new Response(body, init));
573
- }
574
- }
575
-
576
- return fetch(url, opts);
577
- };
578
-
579
- const query = page.query.toString();
580
-
581
- /** @type {import('./types').NavigationState} */
582
- const state = {
583
- page,
584
- query,
585
- session_changed: false,
586
- nodes: [],
587
- contexts: []
588
- };
589
-
590
- const component_promises = [this.layout, ...nodes];
591
- const props_promises = [];
592
-
593
- /** @type {Record<string, any>} */
594
- let context;
595
- let redirect;
596
-
597
- const changed = {
598
- params: Object.keys(page.params).filter((key) => {
599
- return !this.current.page || this.current.page.params[key] !== page.params[key];
600
- }),
601
- query: query !== this.current.query,
602
- session: this.current.session_changed,
603
- context: false
604
- };
605
-
606
- try {
607
- for (let i = 0; i < component_promises.length; i += 1) {
608
- const previous = this.current.nodes[i];
609
- const previous_context = this.current.contexts[i];
610
-
611
- const { default: component, preload, load } = await component_promises[i];
612
- props.components[i] = component;
613
-
614
- if (preload) {
615
- throw new Error(
616
- 'preload has been deprecated in favour of load. Please consult the documentation: https://kit.svelte.dev/docs#load'
617
- );
618
- }
619
-
620
- const changed_since_last_render =
621
- !previous ||
622
- component !== previous.component ||
623
- changed.params.some((param) => previous.uses.params.has(param)) ||
624
- (changed.query && previous.uses.query) ||
625
- (changed.session && previous.uses.session) ||
626
- (changed.context && previous.uses.context);
627
-
628
- if (changed_since_last_render) {
629
- const hash = page.path + query;
630
-
631
- // see if we have some cached data
632
- const cache = this.caches.get(component);
633
- const cached = cache && cache.get(hash);
634
-
635
- /** @type {import('./types').PageNode} */
636
- let node;
637
-
638
- /** @type {import('types.internal').LoadOutput} */
639
- let loaded;
640
-
641
- if (cached && (!changed.context || !cached.node.uses.context)) {
642
- ({ node, loaded } = cached);
643
- } else {
644
- node = {
645
- component,
646
- uses: {
647
- params: new Set(),
648
- query: false,
649
- session: false,
650
- context: false
651
- }
652
- };
653
-
654
- const params = {};
655
- for (const key in page.params) {
656
- Object.defineProperty(params, key, {
657
- get() {
658
- node.uses.params.add(key);
659
- return page.params[key];
660
- },
661
- enumerable: true
662
- });
663
- }
664
-
665
- const session = this.$session;
666
-
667
- if (load) {
668
- loaded = await load.call(null, {
669
- page: {
670
- host: page.host,
671
- path: page.path,
672
- params,
673
- get query() {
674
- node.uses.query = true;
675
- return page.query;
676
- }
677
- },
678
- get session() {
679
- node.uses.session = true;
680
- return session;
681
- },
682
- get context() {
683
- node.uses.context = true;
684
- return { ...context };
685
- },
686
- fetch: fetcher
687
- });
688
-
689
- if (!loaded) return;
690
- }
691
- }
692
-
693
- if (loaded) {
694
- loaded = normalize(loaded);
695
-
696
- if (loaded.error) {
697
- props.error = loaded.error;
698
- props.status = loaded.status || 500;
699
- state.nodes = [];
700
- return { redirect, props, state };
701
- }
702
-
703
- if (loaded.redirect) {
704
- // TODO return from here?
705
- redirect = loaded.redirect;
706
- break;
707
- }
708
-
709
- if (loaded.context) {
710
- changed.context = true;
711
-
712
- context = {
713
- ...context,
714
- ...loaded.context
715
- };
716
- }
717
-
718
- if (loaded.maxage) {
719
- if (!this.caches.has(component)) {
720
- this.caches.set(component, new Map());
721
- }
722
-
723
- const cache = this.caches.get(component);
724
- const cached = { node, loaded };
725
-
726
- cache.set(hash, cached);
727
-
728
- let ready = false;
729
-
730
- const timeout = setTimeout(() => {
731
- clear();
732
- }, loaded.maxage * 1000);
733
-
734
- const clear = () => {
735
- if (cache.get(hash) === cached) {
736
- cache.delete(hash);
737
- }
738
-
739
- unsubscribe();
740
- clearTimeout(timeout);
741
- };
742
-
743
- const unsubscribe = this.stores.session.subscribe(() => {
744
- if (ready) clear();
745
- });
746
-
747
- ready = true;
748
- }
749
-
750
- props_promises[i] = loaded.props;
751
- }
752
-
753
- state.nodes[i] = node;
754
- state.contexts[i] = context;
755
- } else {
756
- state.nodes[i] = previous;
757
- state.contexts[i] = context = previous_context;
758
- }
759
- }
760
-
761
- const new_props = await Promise.all(props_promises);
762
-
763
- new_props.forEach((p, i) => {
764
- if (p) {
765
- props[`props_${i}`] = p;
766
- }
767
- });
768
-
769
- if (!this.current.page || page.path !== this.current.page.path || changed.query) {
770
- props.page = page;
771
- }
772
- } catch (error) {
773
- props.error = error;
774
- props.status = 500;
775
- state.nodes = [];
776
- }
777
-
778
- return { redirect, props, state };
779
- }
780
- }
781
-
782
- // @ts-ignore
783
-
784
- /** @param {{
785
- * paths: {
786
- * assets: string;
787
- * base: string;
788
- * },
789
- * target: Node;
790
- * session: any;
791
- * error: Error;
792
- * status: number;
793
- * nodes: import('./types').NavigationCandidate["nodes"];
794
- * page: import('./types').NavigationCandidate["page"];
795
- * }} opts */
796
- async function start({ paths, target, session, error, status, nodes, page }) {
797
- const router = new Router({
798
- base: paths.base,
799
- routes
800
- });
801
-
802
- const renderer = new Renderer({
803
- Root,
804
- layout,
805
- target,
806
- session,
807
- host: page.host
808
- });
809
-
810
- init({ router, renderer });
811
- set_paths(paths);
812
-
813
- router.init(renderer);
814
- await renderer.start({ nodes, page }, status, error);
815
-
816
- dispatchEvent(new CustomEvent('sveltekit:start'));
817
- }
818
-
819
- if (import.meta.env.VITE_SVELTEKIT_SERVICE_WORKER) {
820
- navigator.serviceWorker.register(import.meta.env.VITE_SVELTEKIT_SERVICE_WORKER);
821
- }
822
-
823
- export { start };