@sveltejs/kit 3.0.0-next.1 → 3.0.0-next.10

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 (127) hide show
  1. package/package.json +33 -21
  2. package/src/core/adapt/builder.js +29 -43
  3. package/src/core/adapt/index.js +1 -4
  4. package/src/core/config/index.js +132 -71
  5. package/src/core/config/options.js +294 -244
  6. package/src/core/config/types.d.ts +1 -1
  7. package/src/core/env.js +121 -5
  8. package/src/core/generate_manifest/index.js +12 -15
  9. package/src/core/postbuild/analyse.js +7 -19
  10. package/src/core/postbuild/crawl.js +22 -6
  11. package/src/core/postbuild/prerender.js +42 -23
  12. package/src/core/sync/create_manifest_data/index.js +53 -50
  13. package/src/core/sync/sync.js +0 -2
  14. package/src/core/sync/write_client_manifest.js +8 -15
  15. package/src/core/sync/write_env.js +2 -1
  16. package/src/core/sync/write_non_ambient.js +12 -9
  17. package/src/core/sync/write_server.js +13 -14
  18. package/src/core/sync/write_tsconfig.js +16 -8
  19. package/src/core/sync/write_tsconfig_test/package.json +7 -0
  20. package/src/core/sync/write_types/index.js +28 -24
  21. package/src/core/utils.js +2 -2
  22. package/src/exports/env/index.js +12 -0
  23. package/src/exports/hooks/index.js +3 -9
  24. package/src/exports/hooks/sequence.js +3 -2
  25. package/src/exports/index.js +35 -13
  26. package/src/exports/internal/client.js +5 -0
  27. package/src/exports/internal/env.js +2 -2
  28. package/src/exports/internal/index.js +1 -90
  29. package/src/exports/internal/{event.js → server/event.js} +1 -2
  30. package/src/exports/internal/server/index.js +33 -0
  31. package/src/exports/internal/shared.js +89 -0
  32. package/src/exports/node/index.js +62 -15
  33. package/src/exports/params.js +63 -0
  34. package/src/exports/public.d.ts +323 -170
  35. package/src/exports/url.js +86 -0
  36. package/src/exports/vite/build/build_server.js +53 -59
  37. package/src/exports/vite/build/remote.js +18 -11
  38. package/src/exports/vite/build/utils.js +0 -8
  39. package/src/exports/vite/dev/index.js +42 -44
  40. package/src/exports/vite/index.js +810 -593
  41. package/src/exports/vite/preview/index.js +29 -22
  42. package/src/exports/vite/static_analysis/index.js +2 -4
  43. package/src/exports/vite/static_analysis/types.d.ts +14 -0
  44. package/src/exports/vite/utils.js +21 -36
  45. package/src/runtime/app/env/internal.js +4 -4
  46. package/src/runtime/app/env/types.d.ts +1 -1
  47. package/src/runtime/app/environment/index.js +3 -3
  48. package/src/runtime/app/forms.js +24 -7
  49. package/src/runtime/app/paths/client.js +4 -10
  50. package/src/runtime/app/paths/internal/client.js +4 -2
  51. package/src/runtime/app/paths/internal/server.js +2 -23
  52. package/src/runtime/app/paths/public.d.ts +0 -28
  53. package/src/runtime/app/paths/server.js +9 -5
  54. package/src/runtime/app/server/remote/command.js +0 -3
  55. package/src/runtime/app/server/remote/form.js +27 -15
  56. package/src/runtime/app/server/remote/prerender.js +29 -36
  57. package/src/runtime/app/server/remote/query.js +101 -99
  58. package/src/runtime/app/server/remote/requested.js +22 -14
  59. package/src/runtime/app/server/remote/shared.js +30 -26
  60. package/src/runtime/app/state/client.js +1 -2
  61. package/src/runtime/app/stores.js +13 -76
  62. package/src/runtime/client/bundle.js +1 -1
  63. package/src/runtime/client/client-entry.js +3 -0
  64. package/src/runtime/client/client.js +411 -318
  65. package/src/runtime/client/entry.js +24 -3
  66. package/src/runtime/client/fetcher.js +3 -2
  67. package/src/runtime/client/ndjson.js +6 -33
  68. package/src/runtime/client/payload.js +17 -0
  69. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  70. package/src/runtime/client/remote-functions/command.svelte.js +7 -32
  71. package/src/runtime/client/remote-functions/form.svelte.js +183 -112
  72. package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
  73. package/src/runtime/client/remote-functions/query/index.js +7 -14
  74. package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
  75. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  76. package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
  77. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
  78. package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
  79. package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
  80. package/src/runtime/client/sse.js +32 -0
  81. package/src/runtime/client/state.svelte.js +65 -49
  82. package/src/runtime/client/stream.js +38 -0
  83. package/src/runtime/client/types.d.ts +11 -7
  84. package/src/runtime/client/utils.js +0 -96
  85. package/src/runtime/components/root.svelte +66 -0
  86. package/src/runtime/env/dynamic/private.js +7 -0
  87. package/src/runtime/env/dynamic/public.js +7 -0
  88. package/src/runtime/env/static/private.js +6 -0
  89. package/src/runtime/env/static/public.js +6 -0
  90. package/src/runtime/form-utils.js +100 -22
  91. package/src/runtime/server/cookie.js +69 -52
  92. package/src/runtime/server/csrf.js +65 -0
  93. package/src/runtime/server/data/index.js +14 -18
  94. package/src/runtime/server/env_module.js +0 -5
  95. package/src/runtime/server/index.js +2 -2
  96. package/src/runtime/server/page/actions.js +41 -26
  97. package/src/runtime/server/page/index.js +9 -15
  98. package/src/runtime/server/page/load_data.js +1 -1
  99. package/src/runtime/server/page/render.js +112 -187
  100. package/src/runtime/server/page/respond_with_error.js +7 -8
  101. package/src/runtime/server/page/server_routing.js +27 -18
  102. package/src/runtime/server/remote.js +355 -216
  103. package/src/runtime/server/respond.js +97 -61
  104. package/src/runtime/server/utils.js +32 -9
  105. package/src/runtime/shared.js +83 -13
  106. package/src/runtime/telemetry/otel.js +1 -1
  107. package/src/runtime/types.d.ts +8 -0
  108. package/src/types/ambient.d.ts +10 -5
  109. package/src/types/global-private.d.ts +15 -22
  110. package/src/types/internal.d.ts +89 -74
  111. package/src/types/private.d.ts +33 -1
  112. package/src/utils/error.js +24 -4
  113. package/src/utils/import.js +6 -1
  114. package/src/utils/imports.js +83 -0
  115. package/src/utils/mime.js +9 -0
  116. package/src/utils/params.js +66 -0
  117. package/src/utils/routing.js +90 -44
  118. package/src/utils/shared-iterator.js +5 -0
  119. package/src/utils/streaming.js +14 -4
  120. package/src/utils/url.js +20 -2
  121. package/src/version.js +1 -1
  122. package/types/index.d.ts +467 -537
  123. package/types/index.d.ts.map +22 -39
  124. package/src/core/sync/write_root.js +0 -148
  125. package/src/exports/internal/server.js +0 -22
  126. package/src/types/synthetic/$lib.md +0 -5
  127. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -1,7 +1,8 @@
1
- /** @import { RemoteFunctionResponse, RemoteSingleflightMap, RemoteSingleflightEntry } from 'types' */
1
+ /** @import { RemoteFunctionResponse, RemoteFunctionData, RemoteFunctionDataNode } from 'types' */
2
2
  /** @import { RemoteQueryUpdate } from '@sveltejs/kit' */
3
+ /** @import { CacheEntry } from './cache.svelte.js' */
3
4
  import * as devalue from 'devalue';
4
- import { app, goto, live_query_map, query_map } from '../client.js';
5
+ import { app, _goto, live_query_map, query_map, query_responses } from '../client.js';
5
6
  import { HttpError, Redirect } from '@sveltejs/kit/internal';
6
7
  import { untrack } from 'svelte';
7
8
  import { create_remote_key, split_remote_key } from '../../shared.js';
@@ -77,6 +78,20 @@ export function pin_while_resolving(cache_map, cache, id, payload, then) {
77
78
  /**
78
79
  * @returns {{ 'x-sveltekit-pathname': string, 'x-sveltekit-search': string }}
79
80
  */
81
+ /**
82
+ * Unwraps a `RemoteFunctionDataNode` that was serialized during SSR,
83
+ * rethrowing serialized errors so the consuming resource ends up
84
+ * in the same failed state it had on the server
85
+ * @param {RemoteFunctionDataNode} node
86
+ */
87
+ export function unwrap_node(node) {
88
+ if (node.e) {
89
+ throw new HttpError(node.e.status, node.e);
90
+ }
91
+
92
+ return node.v;
93
+ }
94
+
80
95
  export function get_remote_request_headers() {
81
96
  // This will be the correct value of the current or soon-current url,
82
97
  // even in forks because it's state-based - therefore not using window.location.
@@ -93,25 +108,82 @@ export function get_remote_request_headers() {
93
108
 
94
109
  /**
95
110
  * @param {string} url
96
- * @param {HeadersInit} headers
111
+ * @param {RequestInit} [init]
97
112
  */
98
- export async function remote_request(url, headers) {
99
- const response = await fetch(url, {
100
- headers: {
101
- 'Content-Type': 'application/json',
102
- ...headers
103
- }
104
- });
113
+ export async function remote_request(url, init) {
114
+ const response = await fetch(url, init);
105
115
 
106
116
  if (!response.ok) {
107
- throw new HttpError(500, 'Failed to execute remote function');
117
+ const result = await response.json().catch(() => ({
118
+ type: 'error',
119
+ status: response.status,
120
+ error: response.statusText
121
+ }));
122
+
123
+ throw new HttpError(
124
+ result.error?.status ?? result.status ?? response.status ?? 500,
125
+ result.error
126
+ );
108
127
  }
109
128
 
110
129
  const result = /** @type {RemoteFunctionResponse} */ (await response.json());
111
130
 
112
- const resolved = await handle_side_channel_response(result);
131
+ if (result.type === 'error') {
132
+ throw new HttpError(result.error.status, result.error);
133
+ }
134
+
135
+ const data = /** @type {RemoteFunctionData} */ (
136
+ result.data ? devalue.parse(result.data, app.decoders) : {}
137
+ );
138
+
139
+ /**
140
+ * @param {string} key
141
+ * @param {CacheEntry | undefined} entry
142
+ * @param {any} result
143
+ */
144
+ function refresh(key, entry, result) {
145
+ if (entry?.resource) {
146
+ if (result.e) {
147
+ entry.resource.fail(new HttpError(result.e.status, result.e));
148
+ } else {
149
+ entry.resource.set(result.v);
150
+ }
151
+ } else if (!result.e) {
152
+ // `query_responses` stores `{ v }`/`{ e }` nodes, not raw values.
153
+ // Errors are deliberately dropped here: they are responses to a specific
154
+ // refresh, not durable state a future resource should initialize with
155
+ query_responses[key] = result;
156
+ }
157
+ }
158
+
159
+ // update queries with refreshed data
160
+ if (data.q) {
161
+ for (const key in data.q) {
162
+ const parts = split_remote_key(key);
163
+ const entry = query_map.get(parts.id)?.get(parts.payload);
164
+
165
+ refresh(key, entry, data.q[key]);
166
+ }
167
+ }
168
+
169
+ // reconnect live queries
170
+ if (data.l) {
171
+ for (const key in data.l) {
172
+ const parts = split_remote_key(key);
173
+ const entry = live_query_map.get(parts.id)?.get(parts.payload);
113
174
 
114
- return resolved.result;
175
+ refresh(key, entry, data.l[key]);
176
+
177
+ // `fail()` is terminal, so only reconnect on the success path —
178
+ // reconnecting after a hard failure would wipe the error state and
179
+ // restart the stream (see commit 63a3e83 regression).
180
+ if (!data.l[key].e) {
181
+ void entry?.resource.reconnect();
182
+ }
183
+ }
184
+ }
185
+
186
+ return data;
115
187
  }
116
188
 
117
189
  /**
@@ -120,12 +192,13 @@ export async function remote_request(url, headers) {
120
192
  */
121
193
  export async function handle_side_channel_response(response) {
122
194
  if (response.type === 'redirect') {
123
- await goto(response.location);
195
+ // Use internal version to allow redirects to external URLs
196
+ await _goto(response.location, {}, 0);
124
197
  throw new Redirect(307, response.location);
125
198
  }
126
199
 
127
200
  if (response.type === 'error') {
128
- throw new HttpError(response.status ?? 500, response.error);
201
+ throw new HttpError(response.error.status, response.error);
129
202
  }
130
203
 
131
204
  return response;
@@ -206,50 +279,3 @@ export function categorize_updates(updates) {
206
279
 
207
280
  return { overrides, refreshes };
208
281
  }
209
-
210
- /**
211
- * @template TResource
212
- * @param {string} stringified_singleflight
213
- * @param {Map<string, Map<string, { resource: TResource }>>} map
214
- * @param {(resource: TResource, value: RemoteSingleflightEntry) => void} callback
215
- */
216
- function apply_singleflight(stringified_singleflight, map, callback) {
217
- const singleflight = /** @type {RemoteSingleflightMap} */ (
218
- devalue.parse(stringified_singleflight, app.decoders)
219
- );
220
-
221
- for (const [key, value] of Object.entries(singleflight)) {
222
- const parts = split_remote_key(key);
223
- const entry = map.get(parts.id)?.get(parts.payload);
224
- if (entry?.resource) {
225
- callback(entry.resource, value);
226
- }
227
- }
228
- }
229
-
230
- /**
231
- * Apply refresh data from the server to the relevant queries
232
- *
233
- * @param {string} stringified_refreshes
234
- */
235
- export const apply_refreshes = (stringified_refreshes) => {
236
- apply_singleflight(stringified_refreshes, query_map, (resource, value) => {
237
- if (value.type === 'result') {
238
- resource?.set(value.data);
239
- } else {
240
- resource?.fail(new HttpError(value.status ?? 500, value.error));
241
- }
242
- });
243
- };
244
-
245
- /** @param {string} stringified_reconnects */
246
- export const apply_reconnections = (stringified_reconnects) => {
247
- apply_singleflight(stringified_reconnects, live_query_map, (resource, value) => {
248
- if (value.type === 'result') {
249
- resource?.set(value.data);
250
- void resource?.reconnect();
251
- } else {
252
- resource?.fail(new HttpError(value.status ?? 500, value.error));
253
- }
254
- });
255
- };
@@ -0,0 +1,32 @@
1
+ import { read_stream } from './stream.js';
2
+
3
+ /**
4
+ * @param {string} block
5
+ * @returns {string | undefined}
6
+ */
7
+ function parse_sse_event_data(block) {
8
+ const lines = block.split('\n');
9
+ let data = '';
10
+
11
+ for (const line of lines) {
12
+ if (line.startsWith('data:')) {
13
+ data += (data ? '\n' : '') + line.slice(5).trimStart();
14
+ }
15
+ }
16
+
17
+ return data || undefined;
18
+ }
19
+
20
+ /**
21
+ * Yields parsed JSON objects from a ReadableStream of Server-Sent Events.
22
+ * Each yielded value is the raw `JSON.parse`'d object from a `data:` field.
23
+ * @param {ReadableStreamDefaultReader<Uint8Array>} reader
24
+ */
25
+ export async function* read_sse(reader) {
26
+ for await (const block of read_stream(reader, '\n\n')) {
27
+ const data = parse_sse_event_data(block);
28
+ if (data) {
29
+ yield JSON.parse(data);
30
+ }
31
+ }
32
+ }
@@ -1,54 +1,70 @@
1
- import { onMount } from 'svelte';
2
- import { updated_listener } from './utils.js';
1
+ import { version } from '$app/env';
2
+ import { assets } from '$app/paths/internal/client';
3
+ import { BROWSER, DEV } from 'esm-env';
3
4
 
4
5
  /** @type {import('@sveltejs/kit').Page} */
5
- export let page;
6
-
7
- /** @type {{ current: import('@sveltejs/kit').Navigation | null }} */
8
- export let navigating;
9
-
10
- /** @type {{ current: boolean }} */
11
- export let updated;
12
-
13
- // this is a bootleg way to tell if we're in old svelte or new svelte
14
- const is_legacy =
15
- onMount.toString().includes('$$') || /function \w+\(\) \{\}/.test(onMount.toString());
16
-
17
- const placeholder_url = 'a:';
18
-
19
- if (is_legacy) {
20
- page = {
21
- data: {},
22
- form: null,
23
- error: null,
24
- params: {},
25
- route: { id: null },
26
- state: {},
27
- status: -1,
28
- url: new URL(placeholder_url)
29
- };
30
- navigating = { current: null };
31
- updated = { current: false };
32
- } else {
33
- page = new (class Page {
34
- data = $state.raw({});
35
- form = $state.raw(null);
36
- error = $state.raw(null);
37
- params = $state.raw({});
38
- route = $state.raw({ id: null });
39
- state = $state.raw({});
40
- status = $state.raw(-1);
41
- url = $state.raw(new URL(placeholder_url));
42
- })();
43
-
44
- navigating = new (class Navigating {
45
- current = $state.raw(null);
46
- })();
47
-
48
- updated = new (class Updated {
49
- current = $state.raw(false);
50
- })();
51
- updated_listener.v = () => (updated.current = true);
6
+ export const page = new (class Page {
7
+ data = $state.raw({});
8
+ form = $state.raw(null);
9
+ error = $state.raw(null);
10
+ params = $state.raw({});
11
+ route = $state.raw({ id: null });
12
+ state = $state.raw({});
13
+ status = $state.raw(-1);
14
+ url = $state.raw(new URL('a:'));
15
+ })();
16
+
17
+ export const navigating = new (class Navigating {
18
+ /** @type {import('@sveltejs/kit').Navigation | null} */
19
+ current = $state.raw(null);
20
+ })();
21
+
22
+ export const updated = new (class Updated {
23
+ current = $state.raw(false);
24
+ // eslint-disable-next-line @typescript-eslint/require-await
25
+ check = async () => false;
26
+ })();
27
+
28
+ if (!DEV && BROWSER) {
29
+ const interval = __SVELTEKIT_APP_VERSION_POLL_INTERVAL__;
30
+
31
+ /** @type {number} */
32
+ let timeout;
33
+
34
+ /** @type {() => Promise<boolean>} */
35
+ async function check() {
36
+ window.clearTimeout(timeout);
37
+
38
+ if (interval) timeout = window.setTimeout(check, interval);
39
+
40
+ try {
41
+ const res = await fetch(`${assets}/${__SVELTEKIT_APP_VERSION_FILE__}`, {
42
+ headers: {
43
+ 'cache-control': 'no-cache'
44
+ }
45
+ });
46
+
47
+ if (!res.ok) {
48
+ return false;
49
+ }
50
+
51
+ const data = await res.json();
52
+ const new_update = data.version !== version;
53
+
54
+ if (new_update) {
55
+ updated.current = true;
56
+ window.clearTimeout(timeout);
57
+ }
58
+
59
+ return new_update;
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ if (interval) timeout = window.setTimeout(check, interval);
66
+
67
+ updated.check = check;
52
68
  }
53
69
 
54
70
  /**
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Reads from a stream, decoding it as text and yielding each block of content
3
+ * separated by `delimiter`. The trailing block (if any) is yielded once the
4
+ * stream closes.
5
+ * @param {ReadableStreamDefaultReader<Uint8Array>} reader
6
+ * @param {string} delimiter
7
+ */
8
+ export async function* read_stream(reader, delimiter) {
9
+ let done = false;
10
+ let buffer = '';
11
+ const decoder = new TextDecoder();
12
+
13
+ while (true) {
14
+ let split = buffer.indexOf(delimiter);
15
+ while (split !== -1) {
16
+ yield buffer.slice(0, split);
17
+ buffer = buffer.slice(split + delimiter.length);
18
+ split = buffer.indexOf(delimiter);
19
+ }
20
+
21
+ if (done) {
22
+ if (buffer) {
23
+ yield buffer;
24
+ }
25
+ return;
26
+ }
27
+
28
+ const chunk = await reader.read();
29
+ done = chunk.done;
30
+ if (chunk.value) {
31
+ buffer += decoder.decode(chunk.value, { stream: true });
32
+ }
33
+
34
+ if (done) {
35
+ buffer += decoder.decode();
36
+ }
37
+ }
38
+ }
@@ -10,6 +10,7 @@ import {
10
10
  Uses
11
11
  } from 'types';
12
12
  import { Page, ParamMatcher } from '@sveltejs/kit';
13
+ import { RenderNode } from '../types.js';
13
14
 
14
15
  export interface SvelteKitApp {
15
16
  /**
@@ -39,7 +40,7 @@ export interface SvelteKitApp {
39
40
  dictionary: Record<string, [leaf: number, layouts: number[], errors?: number[]]>;
40
41
 
41
42
  /**
42
- * A map of `[matcherName: string]: (..) => boolean`, which is used to match route parameters.
43
+ * A map of `[matcherName: string]: ParamMatcher`, which is used to match and parse route parameters.
43
44
  *
44
45
  * In case of router.resolution=server, this object is empty, as resolution happens on the server.
45
46
  */
@@ -57,7 +58,11 @@ export interface SvelteKitApp {
57
58
  */
58
59
  hash: boolean;
59
60
 
60
- root: typeof SvelteComponent;
61
+ /**
62
+ * Lazily loads the contents of src/error.html, used as a last-resort
63
+ * error page when the root layout's load function throws during client-side rendering.
64
+ */
65
+ get_error_template: () => Promise<(data: { status: number; message: string }) => string>;
61
66
  }
62
67
 
63
68
  export type NavigationIntent = {
@@ -77,6 +82,7 @@ export type NavigationResult = NavigationRedirect | NavigationFinished;
77
82
 
78
83
  export type NavigationRedirect = {
79
84
  type: 'redirect';
85
+ status: number;
80
86
  location: string;
81
87
  };
82
88
 
@@ -84,13 +90,10 @@ export type NavigationFinished = {
84
90
  type: 'loaded';
85
91
  state: NavigationState;
86
92
  props: {
87
- constructors: Array<typeof SvelteComponent>;
88
- errors?: Array<typeof SvelteComponent | undefined>;
89
- components?: SvelteComponent[];
90
93
  page: Page;
91
94
  form?: Record<string, any> | null;
92
95
  error?: App.Error;
93
- [key: `data_${number}`]: Record<string, any>;
96
+ tree: RenderNode;
94
97
  };
95
98
  };
96
99
 
@@ -119,7 +122,8 @@ export interface NavigationState {
119
122
  }
120
123
 
121
124
  export interface HydrateOptions {
122
- status: number;
125
+ /** Provided in the case of a form action that returns `fail`, but otherwise derived from `error` */
126
+ status?: number;
123
127
  error: App.Error | null;
124
128
  node_ids: number[];
125
129
  params: Record<string, string>;
@@ -1,12 +1,6 @@
1
1
  import { BROWSER, DEV } from 'esm-env';
2
- import { writable } from 'svelte/store';
3
- import { assets } from '$app/paths';
4
- import { version } from '$app/env';
5
- import { noop } from '../../utils/functions.js';
6
2
  import { PRELOAD_PRIORITIES } from './constants.js';
7
3
 
8
- /* global __SVELTEKIT_APP_VERSION_FILE__, __SVELTEKIT_APP_VERSION_POLL_INTERVAL__ */
9
-
10
4
  export const origin = BROWSER ? location.origin : '';
11
5
 
12
6
  /** @param {string | URL} url */
@@ -211,96 +205,6 @@ export function get_router_options(element) {
211
205
  };
212
206
  }
213
207
 
214
- /** @param {any} value */
215
- export function notifiable_store(value) {
216
- const store = writable(value);
217
- let ready = true;
218
-
219
- function notify() {
220
- ready = true;
221
- store.update((val) => val);
222
- }
223
-
224
- /** @param {any} new_value */
225
- function set(new_value) {
226
- ready = false;
227
- store.set(new_value);
228
- }
229
-
230
- /** @param {(value: any) => void} run */
231
- function subscribe(run) {
232
- /** @type {any} */
233
- let old_value;
234
- return store.subscribe((new_value) => {
235
- if (old_value === undefined || (ready && new_value !== old_value)) {
236
- run((old_value = new_value));
237
- }
238
- });
239
- }
240
-
241
- return { notify, set, subscribe };
242
- }
243
-
244
- export const updated_listener = {
245
- v: noop
246
- };
247
-
248
- export function create_updated_store() {
249
- const { set, subscribe } = writable(false);
250
-
251
- if (__SVELTEKIT_DEV__ || !BROWSER) {
252
- return {
253
- subscribe,
254
- // eslint-disable-next-line @typescript-eslint/require-await
255
- check: async () => false
256
- };
257
- }
258
-
259
- const interval = __SVELTEKIT_APP_VERSION_POLL_INTERVAL__;
260
-
261
- /** @type {NodeJS.Timeout} */
262
- let timeout;
263
-
264
- /** @type {() => Promise<boolean>} */
265
- async function check() {
266
- clearTimeout(timeout);
267
-
268
- if (interval) timeout = setTimeout(check, interval);
269
-
270
- try {
271
- const res = await fetch(`${assets}/${__SVELTEKIT_APP_VERSION_FILE__}`, {
272
- headers: {
273
- 'cache-control': 'no-cache'
274
- }
275
- });
276
-
277
- if (!res.ok) {
278
- return false;
279
- }
280
-
281
- const data = await res.json();
282
- const updated = data.version !== version;
283
-
284
- if (updated) {
285
- set(true);
286
- updated_listener.v();
287
- clearTimeout(timeout);
288
- }
289
-
290
- return updated;
291
- } catch {
292
- return false;
293
- }
294
- }
295
-
296
- if (interval) timeout = setTimeout(check, interval);
297
-
298
- return {
299
- subscribe,
300
- check
301
- };
302
- }
303
-
304
208
  /**
305
209
  * Is external if
306
210
  * - origin different
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ import { afterNavigate } from '$app/navigation';
3
+ import type { Page } from '@sveltejs/kit';
4
+ import type { RenderNode } from '../types.js';
5
+
6
+ interface Props {
7
+ page: Page;
8
+ tree: RenderNode;
9
+ components: any[];
10
+ resetters: Array<(() => void) | undefined>;
11
+ form?: any;
12
+ error?: App.Error;
13
+ }
14
+
15
+ const { page, components, resetters, tree, form, error }: Props = $props();
16
+
17
+ let mounted = $state(false);
18
+ let navigated = $state(false);
19
+ let title = $state('');
20
+
21
+ afterNavigate(() => {
22
+ if (mounted) {
23
+ navigated = true;
24
+ title = document.title || 'untitled page';
25
+ } else {
26
+ mounted = true;
27
+ }
28
+ });
29
+ </script>
30
+
31
+ {#snippet node(n: RenderNode, depth: number)}
32
+ {const Component = $derived(n.component)}
33
+ {const Error = $derived(n.error)}
34
+ {const data = $derived(n.data)}
35
+
36
+ <svelte:boundary onerror={(_, reset) => (resetters[depth] = reset)}>
37
+ {#if n.child}
38
+ <!-- svelte-ignore binding_property_non_reactive -->
39
+ <Component bind:this={components[depth]} {data} {form} params={page.params}>
40
+ {@render node(n.child, depth + 1)}
41
+ </Component>
42
+ {:else}
43
+ <!-- svelte-ignore binding_property_non_reactive -->
44
+ <Component bind:this={components[depth]} {data} {form} params={page.params} {error} />
45
+ {/if}
46
+
47
+ {#snippet failed(error)}
48
+ <Error {error} />
49
+ {/snippet}
50
+ </svelte:boundary>
51
+ {/snippet}
52
+
53
+ {@render node(tree, 0)}
54
+
55
+ {#if mounted}
56
+ <div
57
+ id="svelte-announcer"
58
+ aria-live="assertive"
59
+ aria-atomic="true"
60
+ style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px"
61
+ >
62
+ {#if navigated}
63
+ {title}
64
+ {/if}
65
+ </div>
66
+ {/if}
@@ -0,0 +1,7 @@
1
+ import { DEV } from 'esm-env';
2
+ import * as env from '../../app/env/private.js';
3
+ export { env };
4
+
5
+ if (DEV) {
6
+ console.warn('`$env/dynamic/private` is deprecated, use `$app/env/private` instead');
7
+ }
@@ -0,0 +1,7 @@
1
+ import { DEV } from 'esm-env';
2
+ import * as env from '../../app/env/public/index.js';
3
+ export { env };
4
+
5
+ if (DEV) {
6
+ console.warn('`$env/dynamic/public` is deprecated, use `$app/env/public` instead');
7
+ }
@@ -0,0 +1,6 @@
1
+ import { DEV } from 'esm-env';
2
+ export * from '../../app/env/private.js';
3
+
4
+ if (DEV) {
5
+ console.warn('`$env/static/private` is deprecated, use `$app/env/private` instead');
6
+ }
@@ -0,0 +1,6 @@
1
+ import { DEV } from 'esm-env';
2
+ export * from '../../app/env/public/index.js';
3
+
4
+ if (DEV) {
5
+ console.warn('`$env/static/public` is deprecated, use `$app/env/public` instead');
6
+ }