@sveltejs/kit 3.0.0-next.0 → 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.
- package/package.json +33 -21
- package/src/core/adapt/builder.js +29 -43
- package/src/core/adapt/index.js +1 -4
- package/src/core/config/index.js +132 -71
- package/src/core/config/options.js +294 -244
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +121 -5
- package/src/core/generate_manifest/index.js +12 -15
- package/src/core/postbuild/analyse.js +7 -19
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/prerender.js +42 -23
- package/src/core/sync/create_manifest_data/index.js +53 -50
- package/src/core/sync/sync.js +0 -2
- package/src/core/sync/write_client_manifest.js +8 -15
- package/src/core/sync/write_env.js +2 -1
- package/src/core/sync/write_non_ambient.js +12 -9
- package/src/core/sync/write_server.js +13 -14
- package/src/core/sync/write_tsconfig.js +16 -8
- package/src/core/sync/write_tsconfig_test/package.json +7 -0
- package/src/core/sync/write_types/index.js +28 -24
- package/src/core/utils.js +2 -2
- package/src/exports/env/index.js +12 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/sequence.js +3 -2
- package/src/exports/index.js +35 -13
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +2 -2
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +33 -0
- package/src/exports/internal/shared.js +89 -0
- package/src/exports/node/index.js +62 -15
- package/src/exports/params.js +63 -0
- package/src/exports/public.d.ts +323 -170
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +53 -59
- package/src/exports/vite/build/remote.js +18 -11
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +42 -44
- package/src/exports/vite/index.js +810 -593
- package/src/exports/vite/preview/index.js +29 -22
- package/src/exports/vite/static_analysis/index.js +2 -4
- package/src/exports/vite/static_analysis/types.d.ts +14 -0
- package/src/exports/vite/utils.js +21 -36
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +6 -0
- package/src/runtime/app/forms.js +24 -7
- package/src/runtime/app/paths/client.js +4 -10
- package/src/runtime/app/paths/internal/client.js +4 -2
- package/src/runtime/app/paths/internal/server.js +2 -23
- package/src/runtime/app/paths/public.d.ts +0 -28
- package/src/runtime/app/paths/server.js +9 -5
- package/src/runtime/app/server/remote/command.js +0 -3
- package/src/runtime/app/server/remote/form.js +27 -15
- package/src/runtime/app/server/remote/prerender.js +29 -36
- package/src/runtime/app/server/remote/query.js +101 -99
- package/src/runtime/app/server/remote/requested.js +22 -14
- package/src/runtime/app/server/remote/shared.js +30 -26
- package/src/runtime/app/state/client.js +1 -2
- package/src/runtime/app/stores.js +13 -76
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +411 -318
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +3 -2
- package/src/runtime/client/ndjson.js +6 -33
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +7 -32
- package/src/runtime/client/remote-functions/form.svelte.js +183 -112
- package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
- package/src/runtime/client/remote-functions/query/index.js +7 -14
- package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
- package/src/runtime/client/remote-functions/query/proxy.js +3 -3
- package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
- package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
- package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
- package/src/runtime/client/sse.js +32 -0
- package/src/runtime/client/state.svelte.js +65 -49
- package/src/runtime/client/stream.js +38 -0
- package/src/runtime/client/types.d.ts +11 -7
- package/src/runtime/client/utils.js +0 -96
- package/src/runtime/components/root.svelte +66 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +100 -22
- package/src/runtime/server/cookie.js +69 -52
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +14 -18
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/actions.js +41 -26
- package/src/runtime/server/page/index.js +9 -15
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +112 -187
- package/src/runtime/server/page/respond_with_error.js +7 -8
- package/src/runtime/server/page/server_routing.js +27 -18
- package/src/runtime/server/remote.js +355 -216
- package/src/runtime/server/respond.js +97 -61
- package/src/runtime/server/utils.js +32 -9
- package/src/runtime/shared.js +83 -13
- package/src/runtime/telemetry/otel.js +1 -1
- package/src/runtime/types.d.ts +8 -0
- package/src/types/ambient.d.ts +10 -5
- package/src/types/global-private.d.ts +15 -22
- package/src/types/internal.d.ts +89 -74
- package/src/types/private.d.ts +33 -1
- package/src/utils/error.js +24 -4
- package/src/utils/import.js +6 -1
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/params.js +66 -0
- package/src/utils/routing.js +90 -44
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +20 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +467 -537
- package/types/index.d.ts.map +22 -39
- package/src/core/sync/write_root.js +0 -148
- package/src/exports/internal/server.js +0 -22
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/** @import { RemoteFunctionResponse,
|
|
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,
|
|
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 {
|
|
111
|
+
* @param {RequestInit} [init]
|
|
97
112
|
*/
|
|
98
|
-
export async function remote_request(url,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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]:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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}
|