@sveltejs/kit 1.0.0-next.98 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +5 -1
  2. package/package.json +91 -77
  3. package/postinstall.js +47 -0
  4. package/src/cli.js +44 -0
  5. package/src/constants.js +5 -0
  6. package/src/core/adapt/builder.js +221 -0
  7. package/src/core/adapt/index.js +31 -0
  8. package/src/core/config/default-error.html +56 -0
  9. package/src/core/config/index.js +100 -0
  10. package/src/core/config/options.js +387 -0
  11. package/src/core/config/types.d.ts +1 -0
  12. package/src/core/env.js +138 -0
  13. package/src/core/generate_manifest/index.js +116 -0
  14. package/src/core/prerender/crawl.js +207 -0
  15. package/src/core/prerender/entities.js +2252 -0
  16. package/src/core/prerender/fallback.js +43 -0
  17. package/src/core/prerender/prerender.js +459 -0
  18. package/src/core/prerender/queue.js +80 -0
  19. package/src/core/sync/create_manifest_data/conflict.js +0 -0
  20. package/src/core/sync/create_manifest_data/index.js +523 -0
  21. package/src/core/sync/create_manifest_data/sort.js +161 -0
  22. package/src/core/sync/create_manifest_data/types.d.ts +37 -0
  23. package/src/core/sync/sync.js +59 -0
  24. package/src/core/sync/utils.js +33 -0
  25. package/src/core/sync/write_ambient.js +58 -0
  26. package/src/core/sync/write_client_manifest.js +107 -0
  27. package/src/core/sync/write_matchers.js +25 -0
  28. package/src/core/sync/write_root.js +91 -0
  29. package/src/core/sync/write_tsconfig.js +195 -0
  30. package/src/core/sync/write_types/index.js +809 -0
  31. package/src/core/utils.js +67 -0
  32. package/src/exports/hooks/index.js +1 -0
  33. package/src/exports/hooks/sequence.js +44 -0
  34. package/src/exports/index.js +55 -0
  35. package/src/exports/node/index.js +172 -0
  36. package/src/exports/node/polyfills.js +28 -0
  37. package/src/exports/vite/build/build_server.js +359 -0
  38. package/src/exports/vite/build/build_service_worker.js +85 -0
  39. package/src/exports/vite/build/utils.js +230 -0
  40. package/src/exports/vite/dev/index.js +597 -0
  41. package/src/exports/vite/graph_analysis/index.js +99 -0
  42. package/src/exports/vite/graph_analysis/types.d.ts +5 -0
  43. package/src/exports/vite/graph_analysis/utils.js +6 -0
  44. package/src/exports/vite/index.js +708 -0
  45. package/src/exports/vite/preview/index.js +194 -0
  46. package/src/exports/vite/types.d.ts +3 -0
  47. package/src/exports/vite/utils.js +184 -0
  48. package/src/runtime/app/env.js +1 -0
  49. package/src/runtime/app/environment.js +13 -0
  50. package/src/runtime/app/forms.js +135 -0
  51. package/src/runtime/app/navigation.js +22 -0
  52. package/src/runtime/app/paths.js +1 -0
  53. package/src/runtime/app/stores.js +57 -0
  54. package/src/runtime/client/ambient.d.ts +30 -0
  55. package/src/runtime/client/client.js +1725 -0
  56. package/src/runtime/client/constants.js +10 -0
  57. package/src/runtime/client/fetcher.js +127 -0
  58. package/src/runtime/client/parse.js +60 -0
  59. package/src/runtime/client/singletons.js +21 -0
  60. package/src/runtime/client/start.js +45 -0
  61. package/src/runtime/client/types.d.ts +86 -0
  62. package/src/runtime/client/utils.js +257 -0
  63. package/src/runtime/components/error.svelte +6 -0
  64. package/{assets → src/runtime}/components/layout.svelte +0 -0
  65. package/src/runtime/control.js +45 -0
  66. package/src/runtime/env/dynamic/private.js +1 -0
  67. package/src/runtime/env/dynamic/public.js +1 -0
  68. package/src/runtime/env-private.js +6 -0
  69. package/src/runtime/env-public.js +6 -0
  70. package/src/runtime/env.js +12 -0
  71. package/src/runtime/hash.js +20 -0
  72. package/src/runtime/paths.js +11 -0
  73. package/src/runtime/server/cookie.js +228 -0
  74. package/src/runtime/server/data/index.js +158 -0
  75. package/src/runtime/server/endpoint.js +86 -0
  76. package/src/runtime/server/fetch.js +175 -0
  77. package/src/runtime/server/index.js +405 -0
  78. package/src/runtime/server/page/actions.js +267 -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/index.js +326 -0
  82. package/src/runtime/server/page/load_data.js +270 -0
  83. package/src/runtime/server/page/render.js +393 -0
  84. package/src/runtime/server/page/respond_with_error.js +103 -0
  85. package/src/runtime/server/page/serialize_data.js +87 -0
  86. package/src/runtime/server/page/types.d.ts +35 -0
  87. package/src/runtime/server/utils.js +179 -0
  88. package/src/utils/array.js +9 -0
  89. package/src/utils/error.js +22 -0
  90. package/src/utils/escape.js +46 -0
  91. package/src/utils/exports.js +54 -0
  92. package/src/utils/filesystem.js +178 -0
  93. package/src/utils/functions.js +16 -0
  94. package/src/utils/http.js +72 -0
  95. package/src/utils/misc.js +1 -0
  96. package/src/utils/promises.js +17 -0
  97. package/src/utils/routing.js +201 -0
  98. package/src/utils/unit_test.js +11 -0
  99. package/src/utils/url.js +161 -0
  100. package/svelte-kit.js +1 -1
  101. package/types/ambient.d.ts +451 -0
  102. package/types/index.d.ts +1168 -5
  103. package/types/internal.d.ts +348 -160
  104. package/types/private.d.ts +237 -0
  105. package/types/synthetic/$env+dynamic+private.md +10 -0
  106. package/types/synthetic/$env+dynamic+public.md +8 -0
  107. package/types/synthetic/$env+static+private.md +19 -0
  108. package/types/synthetic/$env+static+public.md +7 -0
  109. package/types/synthetic/$lib.md +5 -0
  110. package/CHANGELOG.md +0 -819
  111. package/assets/components/error.svelte +0 -21
  112. package/assets/runtime/app/env.js +0 -16
  113. package/assets/runtime/app/navigation.js +0 -53
  114. package/assets/runtime/app/paths.js +0 -1
  115. package/assets/runtime/app/stores.js +0 -87
  116. package/assets/runtime/chunks/utils.js +0 -13
  117. package/assets/runtime/env.js +0 -8
  118. package/assets/runtime/internal/singletons.js +0 -20
  119. package/assets/runtime/internal/start.js +0 -1061
  120. package/assets/runtime/paths.js +0 -12
  121. package/dist/chunks/_commonjsHelpers.js +0 -8
  122. package/dist/chunks/cert.js +0 -29079
  123. package/dist/chunks/constants.js +0 -3
  124. package/dist/chunks/index.js +0 -3526
  125. package/dist/chunks/index2.js +0 -583
  126. package/dist/chunks/index3.js +0 -31
  127. package/dist/chunks/index4.js +0 -1005
  128. package/dist/chunks/index5.js +0 -327
  129. package/dist/chunks/index6.js +0 -325
  130. package/dist/chunks/standard.js +0 -99
  131. package/dist/chunks/utils.js +0 -149
  132. package/dist/cli.js +0 -711
  133. package/dist/http.js +0 -66
  134. package/dist/install-fetch.js +0 -1699
  135. package/dist/ssr.js +0 -1529
  136. package/types/ambient-modules.d.ts +0 -115
  137. package/types/config.d.ts +0 -101
  138. package/types/endpoint.d.ts +0 -23
  139. package/types/helper.d.ts +0 -19
  140. package/types/hooks.d.ts +0 -23
  141. package/types/page.d.ts +0 -30
@@ -1,1061 +0,0 @@
1
- import Root from '../../generated/root.svelte';
2
- import { routes, fallback } from '../../generated/manifest.js';
3
- import { 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
- function scroll_state() {
9
- return {
10
- x: pageXOffset,
11
- y: pageYOffset
12
- };
13
- }
14
-
15
- /**
16
- * @param {Node} node
17
- * @returns {HTMLAnchorElement | SVGAElement}
18
- */
19
- function find_anchor(node) {
20
- while (node && node.nodeName.toUpperCase() !== 'A') node = node.parentNode; // SVG <a> elements have a lowercase name
21
- return /** @type {HTMLAnchorElement | SVGAElement} */ (node);
22
- }
23
-
24
- class Router {
25
- /** @param {{
26
- * base: string;
27
- * routes: import('types/internal').CSRRoute[];
28
- * }} opts */
29
- constructor({ base, routes }) {
30
- this.base = base;
31
- this.routes = routes;
32
- }
33
-
34
- /** @param {import('./renderer').Renderer} renderer */
35
- init(renderer) {
36
- /** @type {import('./renderer').Renderer} */
37
- this.renderer = renderer;
38
- renderer.router = this;
39
-
40
- this.enabled = true;
41
-
42
- if ('scrollRestoration' in history) {
43
- 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
- history.scrollRestoration = 'auto';
52
- });
53
-
54
- // Setting scrollRestoration to manual again when returning to this page.
55
- addEventListener('load', () => {
56
- 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
- const trigger_prefetch = (event) => {
79
- const a = find_anchor(/** @type {Node} */ (event.target));
80
- if (a && a.href && a.hasAttribute('sveltekit:prefetch')) {
81
- this.prefetch(new URL(/** @type {string} */ (a.href)));
82
- }
83
- };
84
-
85
- /** @type {NodeJS.Timeout} */
86
- let mousemove_timeout;
87
-
88
- /** @param {MouseEvent} event */
89
- const handle_mousemove = (event) => {
90
- clearTimeout(mousemove_timeout);
91
- mousemove_timeout = setTimeout(() => {
92
- trigger_prefetch(event);
93
- }, 20);
94
- };
95
-
96
- addEventListener('touchstart', trigger_prefetch);
97
- addEventListener('mousemove', handle_mousemove);
98
-
99
- /** @param {MouseEvent} event */
100
- addEventListener('click', (event) => {
101
- if (!this.enabled) return;
102
-
103
- // Adapted from https://github.com/visionmedia/page.js
104
- // MIT license https://github.com/visionmedia/page.js#license
105
- if (event.button || event.which !== 1) return;
106
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
107
- if (event.defaultPrevented) return;
108
-
109
- const a = find_anchor(/** @type {Node} */ (event.target));
110
- if (!a) return;
111
-
112
- if (!a.href) return;
113
-
114
- // check if link is inside an svg
115
- // in this case, both href and target are always inside an object
116
- const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString';
117
- const href = String(svg ? /** @type {SVGAElement} */ (a).href.baseVal : a.href);
118
-
119
- if (href === location.href) {
120
- if (!location.hash) event.preventDefault();
121
- return;
122
- }
123
-
124
- // Ignore if tag has
125
- // 1. 'download' attribute
126
- // 2. 'rel' attribute includes external
127
- const rel = a.getAttribute('rel')?.split(/\s+/);
128
-
129
- if (a.hasAttribute('download') || (rel && rel.includes('external'))) {
130
- return;
131
- }
132
-
133
- // Ignore if <a> has a target
134
- if (svg ? /** @type {SVGAElement} */ (a).target.baseVal : a.target) return;
135
-
136
- const url = new URL(href);
137
-
138
- // Don't handle hash changes
139
- if (url.pathname === location.pathname && url.search === location.search) return;
140
-
141
- const noscroll = a.hasAttribute('sveltekit:noscroll');
142
- history.pushState({}, '', url.href);
143
- this._navigate(url, noscroll ? scroll_state() : null, [], url.hash);
144
- event.preventDefault();
145
- });
146
-
147
- addEventListener('popstate', (event) => {
148
- if (event.state && this.enabled) {
149
- const url = new URL(location.href);
150
- this._navigate(url, event.state['sveltekit:scroll'], []);
151
- }
152
- });
153
-
154
- // make it possible to reset focus
155
- document.body.setAttribute('tabindex', '-1');
156
-
157
- // create initial history entry, so we can return here
158
- history.replaceState(history.state || {}, '', location.href);
159
- }
160
-
161
- /**
162
- * @param {URL} url
163
- * @returns {import('./types').NavigationInfo}
164
- */
165
- parse(url) {
166
- if (url.origin !== location.origin) return null;
167
- if (!url.pathname.startsWith(this.base)) return null;
168
-
169
- const path = decodeURIComponent(url.pathname.slice(this.base.length) || '/');
170
-
171
- const routes = this.routes.filter(([pattern]) => pattern.test(path));
172
-
173
- const query = new URLSearchParams(url.search);
174
- const id = `${path}?${query}`;
175
-
176
- return { id, routes, path, query };
177
- }
178
-
179
- /**
180
- * @param {string} href
181
- * @param {{ noscroll?: boolean, replaceState?: boolean }} opts
182
- * @param {string[]} chain
183
- */
184
- async goto(href, { noscroll = false, replaceState = false } = {}, chain) {
185
- if (this.enabled) {
186
- const url = new URL(href, get_base_uri(document));
187
-
188
- history[replaceState ? 'replaceState' : 'pushState']({}, '', href);
189
- return this._navigate(url, noscroll ? scroll_state() : null, chain, url.hash);
190
- }
191
-
192
- location.href = href;
193
- return new Promise(() => {
194
- /* never resolves */
195
- });
196
- }
197
-
198
- enable() {
199
- this.enabled = true;
200
- }
201
-
202
- disable() {
203
- this.enabled = false;
204
- }
205
-
206
- /**
207
- * @param {URL} url
208
- * @returns {Promise<import('./types').NavigationResult>}
209
- */
210
- async prefetch(url) {
211
- return this.renderer.load(this.parse(url));
212
- }
213
-
214
- /**
215
- * @param {URL} url
216
- * @param {{ x: number, y: number }} scroll
217
- * @param {string[]} chain
218
- * @param {string} [hash]
219
- */
220
- async _navigate(url, scroll, chain, hash) {
221
- const info = this.parse(url);
222
-
223
- this.renderer.notify({
224
- path: info.path,
225
- query: info.query
226
- });
227
-
228
- // remove trailing slashes
229
- if (location.pathname.endsWith('/') && location.pathname !== '/') {
230
- history.replaceState({}, '', `${location.pathname.slice(0, -1)}${location.search}`);
231
- }
232
-
233
- await this.renderer.update(info, chain, false);
234
-
235
- document.body.focus();
236
-
237
- const deep_linked = hash && document.getElementById(hash.slice(1));
238
- if (scroll) {
239
- scrollTo(scroll.x, scroll.y);
240
- } else if (deep_linked) {
241
- // scroll is an element id (from a hash), we need to compute y
242
- scrollTo(0, deep_linked.getBoundingClientRect().top + scrollY);
243
- } else {
244
- scrollTo(0, 0);
245
- }
246
- }
247
- }
248
-
249
- /**
250
- * @param {import('types/page').LoadOutput} loaded
251
- * @returns {import('types/page').LoadOutput}
252
- */
253
- function normalize(loaded) {
254
- // TODO should this behaviour be dev-only?
255
-
256
- if (loaded.error) {
257
- const error = typeof loaded.error === 'string' ? new Error(loaded.error) : loaded.error;
258
- const status = loaded.status;
259
-
260
- if (!(error instanceof Error)) {
261
- return {
262
- status: 500,
263
- error: new Error(
264
- `"error" property returned from load() must be a string or instance of Error, received type "${typeof error}"`
265
- )
266
- };
267
- }
268
-
269
- if (!status || status < 400 || status > 599) {
270
- console.warn('"error" returned from load() without a valid status code — defaulting to 500');
271
- return { status: 500, error };
272
- }
273
-
274
- return { status, error };
275
- }
276
-
277
- if (loaded.redirect) {
278
- if (!loaded.status || Math.floor(loaded.status / 100) !== 3) {
279
- return {
280
- status: 500,
281
- error: new Error(
282
- '"redirect" property returned from load() must be accompanied by a 3xx status code'
283
- )
284
- };
285
- }
286
-
287
- if (typeof loaded.redirect !== 'string') {
288
- return {
289
- status: 500,
290
- error: new Error('"redirect" property returned from load() must be a string')
291
- };
292
- }
293
- }
294
-
295
- return loaded;
296
- }
297
-
298
- /** @param {any} value */
299
- function page_store(value) {
300
- const store = writable(value);
301
- let ready = true;
302
-
303
- function notify() {
304
- ready = true;
305
- store.update((val) => val);
306
- }
307
-
308
- /** @param {any} new_value */
309
- function set(new_value) {
310
- ready = false;
311
- store.set(new_value);
312
- }
313
-
314
- /** @param {(value: any) => void} run */
315
- function subscribe(run) {
316
- /** @type {any} */
317
- let old_value;
318
- return store.subscribe((new_value) => {
319
- if (old_value === undefined || (ready && new_value !== old_value)) {
320
- run((old_value = new_value));
321
- }
322
- });
323
- }
324
-
325
- return { notify, set, subscribe };
326
- }
327
-
328
- /**
329
- * @param {RequestInfo} resource
330
- * @param {RequestInit} opts
331
- */
332
- function initial_fetch(resource, opts) {
333
- const url = typeof resource === 'string' ? resource : resource.url;
334
- const script = document.querySelector(`script[type="svelte-data"][url="${url}"]`);
335
- if (script) {
336
- const { body, ...init } = JSON.parse(script.textContent);
337
- return Promise.resolve(new Response(body, init));
338
- }
339
-
340
- return fetch(resource, opts);
341
- }
342
-
343
- /** @typedef {import('types/internal').CSRComponent} CSRComponent */
344
-
345
- class Renderer {
346
- /** @param {{
347
- * Root: CSRComponent;
348
- * fallback: [CSRComponent, CSRComponent];
349
- * target: Node;
350
- * session: any;
351
- * host: string;
352
- * }} opts */
353
- constructor({ Root, fallback, target, session, host }) {
354
- this.Root = Root;
355
- this.fallback = fallback;
356
- this.host = host;
357
-
358
- /** @type {import('./router').Router} */
359
- this.router = null;
360
-
361
- this.target = target;
362
-
363
- this.started = false;
364
-
365
- this.session_id = 1;
366
- this.invalid = new Set();
367
- this.invalidating = null;
368
-
369
- /** @type {import('./types').NavigationState} */
370
- this.current = {
371
- page: null,
372
- session_id: null,
373
- branch: []
374
- };
375
-
376
- /** @type {Map<string, import('./types').NavigationResult>} */
377
- this.cache = new Map();
378
-
379
- this.loading = {
380
- id: null,
381
- promise: null
382
- };
383
-
384
- this.stores = {
385
- page: page_store({}),
386
- navigating: writable(null),
387
- session: writable(session)
388
- };
389
-
390
- this.$session = null;
391
-
392
- this.root = null;
393
-
394
- let ready = false;
395
- this.stores.session.subscribe(async (value) => {
396
- this.$session = value;
397
-
398
- if (!ready) return;
399
- this.session_id += 1;
400
-
401
- const info = this.router.parse(new URL(location.href));
402
- this.update(info, [], true);
403
- });
404
- ready = true;
405
- }
406
-
407
- /**
408
- * @param {{
409
- * status: number;
410
- * error: Error;
411
- * nodes: Array<Promise<CSRComponent>>;
412
- * page: import('types/page').Page;
413
- * }} selected
414
- */
415
- async start({ status, error, nodes, page }) {
416
- /** @type {import('./types').BranchNode[]} */
417
- const branch = [];
418
-
419
- /** @type {Record<string, any>} */
420
- let context = {};
421
-
422
- /** @type {import('./types').NavigationResult} */
423
- let result;
424
-
425
- /** @type {number} */
426
- let new_status;
427
-
428
- /** @type {Error} new_error */
429
- let new_error;
430
-
431
- try {
432
- for (let i = 0; i < nodes.length; i += 1) {
433
- const is_leaf = i === nodes.length - 1;
434
-
435
- const node = await this._load_node({
436
- module: await nodes[i],
437
- page,
438
- context,
439
- status: is_leaf && status,
440
- error: is_leaf && error
441
- });
442
-
443
- branch.push(node);
444
-
445
- if (node && node.loaded) {
446
- if (node.loaded.error) {
447
- if (error) throw node.loaded.error;
448
- new_status = node.loaded.status;
449
- new_error = node.loaded.error;
450
- } else if (node.loaded.context) {
451
- context = {
452
- ...context,
453
- ...node.loaded.context
454
- };
455
- }
456
- }
457
- }
458
-
459
- result = await this._get_navigation_result_from_branch({ page, branch });
460
- } catch (e) {
461
- if (error) throw e;
462
-
463
- new_status = 500;
464
- new_error = e;
465
- }
466
-
467
- if (new_error) {
468
- result = await this._load_error({
469
- status: new_status,
470
- error: new_error,
471
- path: page.path,
472
- query: page.query
473
- });
474
- }
475
-
476
- if (result.redirect) {
477
- // this is a real edge case — `load` would need to return
478
- // a redirect but only in the browser
479
- location.href = new URL(result.redirect, location.href).href;
480
- return;
481
- }
482
-
483
- this._init(result);
484
- }
485
-
486
- /** @param {{ path: string, query: URLSearchParams }} destination */
487
- notify({ path, query }) {
488
- dispatchEvent(new CustomEvent('sveltekit:navigation-start'));
489
-
490
- if (this.started) {
491
- this.stores.navigating.set({
492
- from: {
493
- path: this.current.page.path,
494
- query: this.current.page.query
495
- },
496
- to: {
497
- path,
498
- query
499
- }
500
- });
501
- }
502
- }
503
-
504
- /**
505
- * @param {import('./types').NavigationInfo} info
506
- * @param {string[]} chain
507
- * @param {boolean} no_cache
508
- */
509
- async update(info, chain, no_cache) {
510
- const token = (this.token = {});
511
- let navigation_result = await this._get_navigation_result(info, no_cache);
512
-
513
- // abort if user navigated during update
514
- if (token !== this.token) return;
515
-
516
- this.invalid.clear();
517
-
518
- if (navigation_result.redirect) {
519
- if (chain.length > 10 || chain.includes(info.path)) {
520
- navigation_result = await this._load_error({
521
- status: 500,
522
- error: new Error('Redirect loop'),
523
- path: info.path,
524
- query: info.query
525
- });
526
- } else {
527
- if (this.router) {
528
- this.router.goto(navigation_result.redirect, { replaceState: true }, [
529
- ...chain,
530
- info.path
531
- ]);
532
- } else {
533
- location.href = new URL(navigation_result.redirect, location.href).href;
534
- }
535
-
536
- return;
537
- }
538
- }
539
-
540
- if (navigation_result.reload) {
541
- location.reload();
542
- } else if (this.started) {
543
- this.current = navigation_result.state;
544
-
545
- this.root.$set(navigation_result.props);
546
- this.stores.navigating.set(null);
547
-
548
- await 0;
549
- } else {
550
- this._init(navigation_result);
551
- }
552
-
553
- dispatchEvent(new CustomEvent('sveltekit:navigation-end'));
554
- this.loading.promise = null;
555
- this.loading.id = null;
556
-
557
- const leaf_node = navigation_result.state.branch[navigation_result.state.branch.length - 1];
558
- if (leaf_node && leaf_node.module.router === false) {
559
- this.router.disable();
560
- } else {
561
- this.router.enable();
562
- }
563
- }
564
-
565
- /**
566
- * @param {import('./types').NavigationInfo} info
567
- * @returns {Promise<import('./types').NavigationResult>}
568
- */
569
- load(info) {
570
- this.loading.promise = this._get_navigation_result(info, false);
571
- this.loading.id = info.id;
572
-
573
- return this.loading.promise;
574
- }
575
-
576
- /** @param {string} href */
577
- invalidate(href) {
578
- this.invalid.add(href);
579
-
580
- if (!this.invalidating) {
581
- this.invalidating = Promise.resolve().then(async () => {
582
- const info = this.router.parse(new URL(location.href));
583
- await this.update(info, [], true);
584
-
585
- this.invalidating = null;
586
- });
587
- }
588
-
589
- return this.invalidating;
590
- }
591
-
592
- /** @param {import('./types').NavigationResult} result */
593
- _init(result) {
594
- this.current = result.state;
595
-
596
- const style = document.querySelector('style[data-svelte]');
597
- if (style) style.remove();
598
-
599
- this.root = new this.Root({
600
- target: this.target,
601
- props: {
602
- stores: this.stores,
603
- ...result.props
604
- },
605
- hydrate: true
606
- });
607
-
608
- this.started = true;
609
- }
610
-
611
- /**
612
- * @param {import('./types').NavigationInfo} info
613
- * @param {boolean} no_cache
614
- * @returns {Promise<import('./types').NavigationResult>}
615
- */
616
- async _get_navigation_result(info, no_cache) {
617
- if (this.loading.id === info.id) {
618
- return this.loading.promise;
619
- }
620
-
621
- for (let i = 0; i < info.routes.length; i += 1) {
622
- const route = info.routes[i];
623
-
624
- if (route.length === 1) {
625
- return { reload: true };
626
- }
627
-
628
- // load code for subsequent routes immediately, if they are as
629
- // likely to match the current path/query as the current one
630
- let j = i + 1;
631
- while (j < info.routes.length) {
632
- const next = info.routes[j];
633
- if (next[0].toString() === route[0].toString()) {
634
- if (next.length !== 1) next[1].forEach((loader) => loader());
635
- j += 1;
636
- } else {
637
- break;
638
- }
639
- }
640
-
641
- const result = await this._load(
642
- {
643
- route,
644
- path: info.path,
645
- query: info.query
646
- },
647
- no_cache
648
- );
649
- if (result) return result;
650
- }
651
-
652
- return await this._load_error({
653
- status: 404,
654
- error: new Error(`Not found: ${info.path}`),
655
- path: info.path,
656
- query: info.query
657
- });
658
- }
659
-
660
- /**
661
- *
662
- * @param {{
663
- * page: import('types/page').Page;
664
- * branch: import('./types').BranchNode[]
665
- * }} opts
666
- */
667
- async _get_navigation_result_from_branch({ page, branch }) {
668
- const filtered = branch.filter(Boolean);
669
-
670
- /** @type {import('./types').NavigationResult} */
671
- const result = {
672
- state: {
673
- page,
674
- branch,
675
- session_id: this.session_id
676
- },
677
- props: {
678
- components: filtered.map((node) => node.module.default)
679
- }
680
- };
681
-
682
- for (let i = 0; i < filtered.length; i += 1) {
683
- if (filtered[i].loaded) result.props[`props_${i}`] = await filtered[i].loaded.props;
684
- }
685
-
686
- if (
687
- !this.current.page ||
688
- page.path !== this.current.page.path ||
689
- page.query.toString() !== this.current.page.query.toString()
690
- ) {
691
- result.props.page = page;
692
- }
693
-
694
- const leaf = filtered[filtered.length - 1];
695
- const maxage = leaf.loaded && leaf.loaded.maxage;
696
-
697
- if (maxage) {
698
- const key = `${page.path}?${page.query}`;
699
- let ready = false;
700
-
701
- const clear = () => {
702
- if (this.cache.get(key) === result) {
703
- this.cache.delete(key);
704
- }
705
-
706
- unsubscribe();
707
- clearTimeout(timeout);
708
- };
709
-
710
- const timeout = setTimeout(clear, maxage * 1000);
711
-
712
- const unsubscribe = this.stores.session.subscribe(() => {
713
- if (ready) clear();
714
- });
715
-
716
- ready = true;
717
-
718
- this.cache.set(key, result);
719
- }
720
-
721
- return result;
722
- }
723
-
724
- /**
725
- *
726
- * @param {{
727
- * status?: number;
728
- * error?: Error;
729
- * module: CSRComponent;
730
- * page: import('types/page').Page;
731
- * context: Record<string, any>;
732
- * }} options
733
- * @returns
734
- */
735
- async _load_node({ status, error, module, page, context }) {
736
- /** @type {import('./types').BranchNode} */
737
- const node = {
738
- module,
739
- uses: {
740
- params: new Set(),
741
- path: false,
742
- query: false,
743
- session: false,
744
- context: false,
745
- dependencies: []
746
- },
747
- loaded: null,
748
- context
749
- };
750
-
751
- /** @type {Record<string, string>} */
752
- const params = {};
753
- for (const key in page.params) {
754
- Object.defineProperty(params, key, {
755
- get() {
756
- node.uses.params.add(key);
757
- return page.params[key];
758
- },
759
- enumerable: true
760
- });
761
- }
762
-
763
- const session = this.$session;
764
-
765
- if (module.load) {
766
- const { started } = this;
767
-
768
- /** @type {import('types/page').LoadInput | import('types/page').ErrorLoadInput} */
769
- const load_input = {
770
- page: {
771
- host: page.host,
772
- params,
773
- get path() {
774
- node.uses.path = true;
775
- return page.path;
776
- },
777
- get query() {
778
- node.uses.query = true;
779
- return page.query;
780
- }
781
- },
782
- get session() {
783
- node.uses.session = true;
784
- return session;
785
- },
786
- get context() {
787
- node.uses.context = true;
788
- return { ...context };
789
- },
790
- fetch(resource, info) {
791
- const url = typeof resource === 'string' ? resource : resource.url;
792
- const { href } = new URL(url, new URL(page.path, document.baseURI));
793
- node.uses.dependencies.push(href);
794
-
795
- return started ? fetch(resource, info) : initial_fetch(resource, info);
796
- }
797
- };
798
-
799
- if (error) {
800
- /** @type {import('types/page').ErrorLoadInput} */ (load_input).status = status;
801
- /** @type {import('types/page').ErrorLoadInput} */ (load_input).error = error;
802
- }
803
-
804
- const loaded = await module.load.call(null, load_input);
805
-
806
- // if the page component returns nothing from load, fall through
807
- if (!loaded) return;
808
-
809
- node.loaded = normalize(loaded);
810
- if (node.loaded.context) node.context = node.loaded.context;
811
- }
812
-
813
- return node;
814
- }
815
-
816
- /**
817
- * @param {import('./types').NavigationCandidate} selected
818
- * @param {boolean} no_cache
819
- * @returns {Promise<import('./types').NavigationResult>}
820
- */
821
- async _load({ route, path, query }, no_cache) {
822
- const key = `${path}?${query}`;
823
-
824
- if (!no_cache && this.cache.has(key)) {
825
- return this.cache.get(key);
826
- }
827
-
828
- const [pattern, a, b, get_params] = route;
829
- const params = get_params ? get_params(pattern.exec(path)) : {};
830
-
831
- const changed = this.current.page && {
832
- path: path !== this.current.page.path,
833
- params: Object.keys(params).filter((key) => this.current.page.params[key] !== params[key]),
834
- query: query.toString() !== this.current.page.query.toString(),
835
- session: this.session_id !== this.current.session_id
836
- };
837
-
838
- /** @type {import('types/page').Page} */
839
- const page = { host: this.host, path, query, params };
840
-
841
- /** @type {import('./types').BranchNode[]} */
842
- const branch = [];
843
-
844
- /** @type {Record<string, any>} */
845
- let context = {};
846
- let context_changed = false;
847
-
848
- /** @type {number} */
849
- let status = 200;
850
-
851
- /** @type {Error} */
852
- let error = null;
853
-
854
- // preload modules
855
- a.forEach((loader) => loader());
856
-
857
- load: for (let i = 0; i < a.length; i += 1) {
858
- /** @type {import('./types').BranchNode} */
859
- let node;
860
-
861
- try {
862
- if (!a[i]) continue;
863
-
864
- const module = await a[i]();
865
- const previous = this.current.branch[i];
866
-
867
- const changed_since_last_render =
868
- !previous ||
869
- module !== previous.module ||
870
- (changed.path && previous.uses.path) ||
871
- changed.params.some((param) => previous.uses.params.has(param)) ||
872
- (changed.query && previous.uses.query) ||
873
- (changed.session && previous.uses.session) ||
874
- previous.uses.dependencies.some((dep) => this.invalid.has(dep)) ||
875
- (context_changed && previous.uses.context);
876
-
877
- if (changed_since_last_render) {
878
- node = await this._load_node({
879
- module,
880
- page,
881
- context
882
- });
883
-
884
- const is_leaf = i === a.length - 1;
885
-
886
- if (node && node.loaded) {
887
- if (node.loaded.error) {
888
- status = node.loaded.status;
889
- error = node.loaded.error;
890
- }
891
-
892
- if (node.loaded.redirect) {
893
- return {
894
- redirect: node.loaded.redirect
895
- };
896
- }
897
-
898
- if (node.loaded.context) {
899
- context_changed = true;
900
- }
901
- } else if (is_leaf && module.load) {
902
- // if the leaf node has a `load` function
903
- // that returns nothing, fall through
904
- return;
905
- }
906
- } else {
907
- node = previous;
908
- }
909
- } catch (e) {
910
- status = 500;
911
- error = e;
912
- }
913
-
914
- if (error) {
915
- while (i--) {
916
- if (b[i]) {
917
- let error_loaded;
918
-
919
- /** @type {import('./types').BranchNode} */
920
- let node_loaded;
921
- let j = i;
922
- while (!(node_loaded = branch[j])) {
923
- j -= 1;
924
- }
925
-
926
- try {
927
- error_loaded = await this._load_node({
928
- status,
929
- error,
930
- module: await b[i](),
931
- page,
932
- context: node_loaded.context
933
- });
934
-
935
- if (error_loaded.loaded.error) {
936
- continue;
937
- }
938
-
939
- branch.push(error_loaded);
940
- break load;
941
- } catch (e) {
942
- continue;
943
- }
944
- }
945
- }
946
-
947
- return await this._load_error({
948
- status,
949
- error,
950
- path,
951
- query
952
- });
953
- } else {
954
- if (node && node.loaded && node.loaded.context) {
955
- context = {
956
- ...context,
957
- ...node.loaded.context
958
- };
959
- }
960
-
961
- branch.push(node);
962
- }
963
- }
964
-
965
- return await this._get_navigation_result_from_branch({ page, branch });
966
- }
967
-
968
- /**
969
- * @param {{
970
- * status: number;
971
- * error: Error;
972
- * path: string;
973
- * query: URLSearchParams
974
- * }} opts
975
- */
976
- async _load_error({ status, error, path, query }) {
977
- const page = {
978
- host: this.host,
979
- path,
980
- query,
981
- params: {}
982
- };
983
-
984
- const node = await this._load_node({
985
- module: await this.fallback[0],
986
- page,
987
- context: {}
988
- });
989
-
990
- const branch = [
991
- node,
992
- await this._load_node({
993
- status,
994
- error,
995
- module: await this.fallback[1],
996
- page,
997
- context: node && node.loaded && node.loaded.context
998
- })
999
- ];
1000
-
1001
- return await this._get_navigation_result_from_branch({ page, branch });
1002
- }
1003
- }
1004
-
1005
- // @ts-ignore
1006
-
1007
- /** @param {{
1008
- * paths: {
1009
- * assets: string;
1010
- * base: string;
1011
- * },
1012
- * target: Node;
1013
- * session: any;
1014
- * host: string;
1015
- * route: boolean;
1016
- * spa: boolean;
1017
- * hydrate: {
1018
- * status: number;
1019
- * error: Error;
1020
- * nodes: Array<Promise<import('types/internal').CSRComponent>>;
1021
- * page: import('types/page').Page;
1022
- * };
1023
- * }} opts */
1024
- async function start({ paths, target, session, host, route, spa, hydrate }) {
1025
- if (import.meta.env.DEV && !target) {
1026
- throw new Error('Missing target element. See https://kit.svelte.dev/docs#configuration-target');
1027
- }
1028
-
1029
- const router =
1030
- route &&
1031
- new Router({
1032
- base: paths.base,
1033
- routes
1034
- });
1035
-
1036
- const renderer = new Renderer({
1037
- Root,
1038
- fallback,
1039
- target,
1040
- session,
1041
- host
1042
- });
1043
-
1044
- init(router);
1045
- set_paths(paths);
1046
-
1047
- if (hydrate) await renderer.start(hydrate);
1048
- if (route) router.init(renderer);
1049
-
1050
- if (spa) router.goto(location.href, { replaceState: true }, []);
1051
-
1052
- dispatchEvent(new CustomEvent('sveltekit:start'));
1053
- }
1054
-
1055
- if (import.meta.env.VITE_SVELTEKIT_SERVICE_WORKER) {
1056
- if ('serviceWorker' in navigator) {
1057
- navigator.serviceWorker.register(import.meta.env.VITE_SVELTEKIT_SERVICE_WORKER);
1058
- }
1059
- }
1060
-
1061
- export { start };