@sveltejs/kit 1.0.0-next.50 → 1.0.0-next.500

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