@sveltejs/kit 3.0.0-next.18 → 3.0.0-next.19
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 +12 -5
- package/src/cli.js +1 -1
- package/src/constants.js +3 -0
- package/src/core/config/index.js +1 -1
- package/src/core/env.js +1 -1
- package/src/core/postbuild/analyse.js +1 -1
- package/src/core/postbuild/prerender.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +9 -0
- package/src/core/sync/sync.js +22 -9
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/write_app_types.js +1 -1
- package/src/core/sync/write_client_manifest.js +1 -1
- package/src/core/sync/write_server.js +1 -3
- package/src/core/sync/write_tsconfig/index.js +1 -1
- package/src/core/sync/write_types/index.js +6 -3
- package/src/exports/index.js +9 -9
- package/src/exports/internal/server/event.js +1 -1
- package/src/exports/internal/server/telemetry.js +1 -1
- package/src/exports/internal/shared.js +9 -0
- package/src/exports/{params.js → params/index.js} +6 -4
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +77 -447
- package/src/exports/vite/build/build_server.js +2 -2
- package/src/exports/vite/dev/index.js +2 -3
- package/src/exports/vite/index.js +14 -3
- package/src/pathname.js +55 -0
- package/src/runtime/app/{forms.js → forms/index.js} +9 -8
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -2
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +14 -8
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +4 -0
- package/src/runtime/app/paths/internal/server.js +4 -0
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -1
- package/src/runtime/app/paths/server.js +6 -4
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/form.js +3 -4
- package/src/runtime/app/server/remote/prerender.js +3 -3
- package/src/runtime/app/server/remote/shared.js +3 -10
- package/src/runtime/app/state/index.js +4 -2
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/stores.js +2 -2
- package/src/runtime/client/client.js +65 -54
- package/src/runtime/client/entry.js +2 -2
- package/src/runtime/client/remote-functions/command.svelte.js +36 -34
- package/src/runtime/client/remote-functions/form.svelte.js +76 -78
- package/src/runtime/client/remote-functions/prerender.svelte.js +3 -3
- package/src/runtime/client/remote-functions/query/index.js +1 -1
- package/src/runtime/client/remote-functions/query/instance.svelte.js +4 -3
- package/src/runtime/client/remote-functions/query-batch.svelte.js +3 -3
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +5 -5
- package/src/runtime/client/remote-functions/query-live/iterator.js +5 -7
- package/src/runtime/client/remote-functions/shared.svelte.js +9 -14
- package/src/runtime/client/state.svelte.js +5 -3
- package/src/runtime/client/types.d.ts +2 -1
- package/src/runtime/pathname.js +6 -61
- package/src/runtime/props.svelte.js +1 -1
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/errors.js +53 -28
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +9 -14
- package/src/runtime/server/page/actions.js +2 -1
- package/src/runtime/server/page/index.js +7 -3
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +17 -11
- package/src/runtime/server/page/server_routing.js +3 -2
- package/src/runtime/server/remote-functions.js +3 -2
- package/src/runtime/server/respond.js +4 -8
- package/src/runtime/server/state.js +3 -6
- package/src/types/ambient.d.ts +1 -1
- package/src/types/internal.d.ts +8 -10
- package/src/types/private.d.ts +12 -3
- package/src/utils/error.js +30 -14
- package/src/utils/page_nodes.js +3 -2
- package/src/utils/params.js +3 -2
- package/src/utils/routing.js +5 -4
- package/src/version.js +1 -1
- package/types/index.d.ts +992 -932
- package/types/index.d.ts.map +43 -31
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
|
|
2
2
|
/** @import { RemoteFormInput, RemoteForm, RemoteQueryUpdate } from '@sveltejs/kit' */
|
|
3
3
|
/** @import { InternalRemoteFormIssue } from 'types' */
|
|
4
|
-
import { app_dir, base } from '
|
|
4
|
+
import { app_dir, base } from '#app/paths';
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
import {
|
|
8
8
|
query_responses,
|
|
9
9
|
_goto,
|
|
@@ -222,82 +222,84 @@ export function form(id) {
|
|
|
222
222
|
/** @type {Error | undefined} */
|
|
223
223
|
let updates_error;
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
const promise =
|
|
226
|
+
/** @type {Promise<boolean> & { updates: (...args: RemoteQueryUpdate[]) => Promise<boolean> }} */ (
|
|
227
|
+
(async () => {
|
|
228
|
+
try {
|
|
229
|
+
await Promise.resolve();
|
|
229
230
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (should_preflight) {
|
|
235
|
-
const valid = await preflight(form_data);
|
|
236
|
-
if (!valid) return false;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const { blob } = serialize_binary_form(convert(form_data), {
|
|
240
|
-
remote_refreshes: Array.from(refreshes ?? [])
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
const response = await remote_request(
|
|
244
|
-
`${base}/${app_dir}/remote/${action_id_without_key}`,
|
|
245
|
-
{
|
|
246
|
-
method: 'POST',
|
|
247
|
-
headers: {
|
|
248
|
-
'Content-Type': BINARY_FORM_CONTENT_TYPE,
|
|
249
|
-
// Forms cannot be called during rendering, so it's save to use location here
|
|
250
|
-
'x-sveltekit-pathname': location.pathname,
|
|
251
|
-
'x-sveltekit-search': location.search
|
|
252
|
-
},
|
|
253
|
-
body: blob
|
|
254
|
-
}
|
|
255
|
-
);
|
|
231
|
+
if (updates_error) {
|
|
232
|
+
throw updates_error;
|
|
233
|
+
}
|
|
256
234
|
|
|
257
|
-
|
|
235
|
+
if (should_preflight) {
|
|
236
|
+
const valid = await preflight(form_data);
|
|
237
|
+
if (!valid) return false;
|
|
238
|
+
}
|
|
258
239
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
240
|
+
const { blob } = serialize_binary_form(convert(form_data), {
|
|
241
|
+
remote_refreshes: Array.from(refreshes ?? [])
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const response = await remote_request(
|
|
245
|
+
`${base}/${app_dir}/remote/${action_id_without_key}`,
|
|
246
|
+
{
|
|
247
|
+
method: 'POST',
|
|
248
|
+
headers: {
|
|
249
|
+
'Content-Type': BINARY_FORM_CONTENT_TYPE,
|
|
250
|
+
// Forms cannot be called during rendering, so it's save to use location here
|
|
251
|
+
'x-sveltekit-pathname': location.pathname,
|
|
252
|
+
'x-sveltekit-search': location.search
|
|
253
|
+
},
|
|
254
|
+
body: blob
|
|
255
|
+
}
|
|
256
|
+
);
|
|
262
257
|
|
|
263
|
-
|
|
264
|
-
// Use internal version to allow redirects to external URLs
|
|
265
|
-
void _goto(response.redirect, {
|
|
266
|
-
refreshAll: should_refresh
|
|
267
|
-
});
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
258
|
+
({ issues: raw_issues = [], result } = response._ ?? {});
|
|
270
259
|
|
|
271
|
-
|
|
260
|
+
// if the developer took control of updates via `.updates(...)` (even with
|
|
261
|
+
// no arguments), or the server performed explicit refreshes, don't invalidateAll
|
|
262
|
+
const should_refresh = refreshes === null && !response.r;
|
|
272
263
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
}
|
|
264
|
+
if (response.redirect) {
|
|
265
|
+
// Use internal version to allow redirects to external URLs
|
|
266
|
+
void _goto(response.redirect, {
|
|
267
|
+
refreshAll: should_refresh
|
|
268
|
+
});
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
282
271
|
|
|
283
|
-
|
|
284
|
-
} catch (e) {
|
|
285
|
-
result = undefined;
|
|
286
|
-
raw_issues = [];
|
|
287
|
-
throw e;
|
|
288
|
-
} finally {
|
|
289
|
-
overrides?.forEach((fn) => fn());
|
|
272
|
+
const succeeded = raw_issues.length === 0;
|
|
290
273
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
274
|
+
if (succeeded) {
|
|
275
|
+
if (should_refresh) {
|
|
276
|
+
void refreshAll();
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
if (DEV) {
|
|
280
|
+
warn_on_missing_issue_reads();
|
|
281
|
+
}
|
|
296
282
|
}
|
|
283
|
+
|
|
284
|
+
return succeeded;
|
|
285
|
+
} catch (e) {
|
|
286
|
+
result = undefined;
|
|
287
|
+
raw_issues = [];
|
|
288
|
+
throw e;
|
|
289
|
+
} finally {
|
|
290
|
+
overrides?.forEach((fn) => fn());
|
|
291
|
+
|
|
292
|
+
void tick().then(() => {
|
|
293
|
+
if (entry) {
|
|
294
|
+
entry.count--;
|
|
295
|
+
if (entry.count === 0) {
|
|
296
|
+
instances.delete(key);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
297
300
|
}
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
})();
|
|
301
|
+
})()
|
|
302
|
+
);
|
|
301
303
|
|
|
302
304
|
let updates_called = false;
|
|
303
305
|
promise.updates = (...args) => {
|
|
@@ -376,8 +378,7 @@ export function form(id) {
|
|
|
376
378
|
return true;
|
|
377
379
|
}
|
|
378
380
|
|
|
379
|
-
/** @type {RemoteForm<T, U>} */
|
|
380
|
-
const instance = {};
|
|
381
|
+
const instance = /** @type {RemoteForm<T, U>} */ ({});
|
|
381
382
|
|
|
382
383
|
instance.method = 'POST';
|
|
383
384
|
Object.defineProperty(instance, 'action', {
|
|
@@ -477,14 +478,11 @@ export function form(id) {
|
|
|
477
478
|
|
|
478
479
|
await enhance_callback(create_enhance_callback_instance(form, form_data));
|
|
479
480
|
} catch (e) {
|
|
480
|
-
const error =
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
route: { id: null },
|
|
486
|
-
url: new URL(location.href)
|
|
487
|
-
});
|
|
481
|
+
const error = await handle_error(e, {
|
|
482
|
+
params: {},
|
|
483
|
+
route: { id: null },
|
|
484
|
+
url: new URL(location.href)
|
|
485
|
+
});
|
|
488
486
|
void set_nearest_error_page(error);
|
|
489
487
|
} finally {
|
|
490
488
|
pending_count--;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** @import { RemotePrerenderFunction } from '@sveltejs/kit' */
|
|
2
|
-
import { app_dir, base } from '
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
3
|
import { version } from '$app/env';
|
|
4
4
|
import * as devalue from 'devalue';
|
|
5
5
|
import { app, _goto, handle_error, prerender_responses } from '../client.js';
|
|
6
6
|
import { get_remote_request_headers, remote_request, unwrap_node } from './shared.svelte.js';
|
|
7
7
|
import { create_remote_key, stringify_remote_arg } from '../../shared.js';
|
|
8
8
|
import { noop } from '../../../utils/functions.js';
|
|
9
|
-
import {
|
|
9
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
10
10
|
|
|
11
11
|
// Initialize Cache API for prerender functions
|
|
12
12
|
const CACHE_NAME = __SVELTEKIT_DEV__ ? `sveltekit:${Date.now()}` : `sveltekit:${version}`;
|
|
@@ -172,7 +172,7 @@ class Prerender {
|
|
|
172
172
|
});
|
|
173
173
|
this.#loading = false;
|
|
174
174
|
this.#error = error;
|
|
175
|
-
throw new
|
|
175
|
+
throw new HandledHttpError(error);
|
|
176
176
|
}
|
|
177
177
|
);
|
|
178
178
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import { RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
-
import { app_dir, base } from '
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
3
|
import { _goto, query_map } from '../../client.js';
|
|
4
4
|
import { QUERY_FUNCTION_ID, remote_request } from '../shared.svelte.js';
|
|
5
5
|
import { DEV } from 'esm-env';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
/** @import { HttpError } from '@sveltejs/kit' */
|
|
1
2
|
import { query_responses, handle_error } from '../../client.js';
|
|
2
|
-
import {
|
|
3
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
3
4
|
import { QUERY_OVERRIDE_KEY } from '../shared.svelte.js';
|
|
4
5
|
import { noop } from '../../../../utils/functions.js';
|
|
5
6
|
import { tick, untrack } from 'svelte';
|
|
@@ -70,7 +71,7 @@ export class Query {
|
|
|
70
71
|
delete query_responses[key];
|
|
71
72
|
|
|
72
73
|
if (node.e) {
|
|
73
|
-
this.fail(new
|
|
74
|
+
this.fail(new HandledHttpError(node.e));
|
|
74
75
|
} else {
|
|
75
76
|
this.set(/** @type {T} */ (node.v));
|
|
76
77
|
}
|
|
@@ -152,7 +153,7 @@ export class Query {
|
|
|
152
153
|
this.#loading = false;
|
|
153
154
|
});
|
|
154
155
|
|
|
155
|
-
reject(new
|
|
156
|
+
reject(new HandledHttpError(error));
|
|
156
157
|
});
|
|
157
158
|
|
|
158
159
|
return promise;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** @import { RemoteQueryFunction } from '@sveltejs/kit' */
|
|
2
|
-
import { app_dir, base } from '
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
3
|
import { _goto } from '../client.js';
|
|
4
4
|
import { QUERY_FUNCTION_ID, remote_request } from './shared.svelte.js';
|
|
5
5
|
import { QueryProxy } from './query/proxy.js';
|
|
6
|
-
import {
|
|
6
|
+
import { HandledHttpError } from '@sveltejs/kit/internal';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @param {string} id
|
|
@@ -71,7 +71,7 @@ export function query_batch(id) {
|
|
|
71
71
|
|
|
72
72
|
for (const { resolve, reject } of resolvers) {
|
|
73
73
|
if (result.type === 'error') {
|
|
74
|
-
reject(new
|
|
74
|
+
reject(new HandledHttpError(result.error));
|
|
75
75
|
} else {
|
|
76
76
|
resolve(result.data);
|
|
77
77
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { query_responses, handle_error } from '../../client.js';
|
|
2
|
-
import { HttpError, Redirect } from '@sveltejs/kit/internal';
|
|
2
|
+
import { HttpError, Redirect, HandledHttpError } from '@sveltejs/kit/internal';
|
|
3
3
|
import { noop, once } from '../../../../utils/functions.js';
|
|
4
4
|
import { SharedIterator } from '../../../../utils/shared-iterator.js';
|
|
5
5
|
import { tick } from 'svelte';
|
|
@@ -91,7 +91,7 @@ export class LiveQuery {
|
|
|
91
91
|
// the query failed during SSR — seed the failed state (mirroring `fail()`,
|
|
92
92
|
// minus its terminal `#done`), so the main loop still connects as usual
|
|
93
93
|
// and the query can recover
|
|
94
|
-
const error = new
|
|
94
|
+
const error = new HandledHttpError(node.e);
|
|
95
95
|
this.#loading = false;
|
|
96
96
|
this.#error = error.body;
|
|
97
97
|
|
|
@@ -181,8 +181,8 @@ export class LiveQuery {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
if (error instanceof HttpError) {
|
|
184
|
-
// Server intentionally
|
|
185
|
-
this
|
|
184
|
+
// Server or client intentionally produced an error. Surface it and stop.
|
|
185
|
+
await this.#fail(error);
|
|
186
186
|
break;
|
|
187
187
|
}
|
|
188
188
|
|
|
@@ -417,7 +417,7 @@ export class LiveQuery {
|
|
|
417
417
|
route: { id: null },
|
|
418
418
|
url: new URL(location.href)
|
|
419
419
|
});
|
|
420
|
-
this.fail(new
|
|
420
|
+
this.fail(new HandledHttpError(error));
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
get [Symbol.toStringTag]() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** @import { RemoteFunctionResponse } from 'types' */
|
|
2
|
-
import { app_dir, base } from '
|
|
2
|
+
import { app_dir, base } from '#app/paths';
|
|
3
3
|
import { app } from '../../client.js';
|
|
4
4
|
import { notify_version } from '../../state.svelte.js';
|
|
5
5
|
import { handle_side_channel_response } from '../shared.svelte.js';
|
|
6
6
|
import * as devalue from 'devalue';
|
|
7
|
-
import { HttpError } from '@sveltejs/kit/internal';
|
|
7
|
+
import { HttpError, HandledHttpError } from '@sveltejs/kit/internal';
|
|
8
8
|
import { noop } from '../../../../utils/functions.js';
|
|
9
9
|
import { read_sse } from '../../sse.js';
|
|
10
10
|
|
|
@@ -35,11 +35,9 @@ export async function* create_live_iterator(
|
|
|
35
35
|
/** @type {RemoteFunctionResponse | undefined} */
|
|
36
36
|
const result = await response.json().catch(() => undefined);
|
|
37
37
|
|
|
38
|
-
throw
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
: { status: response.status, message: response.statusText }
|
|
42
|
-
);
|
|
38
|
+
throw result?.type === 'error'
|
|
39
|
+
? new HandledHttpError(result.error)
|
|
40
|
+
: new HttpError({ status: response.status, message: response.statusText });
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
if (response.headers.get('content-type')?.includes('application/json')) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/** @import { CacheEntry } from './cache.svelte.js' */
|
|
4
4
|
import * as devalue from 'devalue';
|
|
5
5
|
import { app, _goto, live_query_map, query_map, query_responses } from '../client.js';
|
|
6
|
-
import { HttpError, Redirect } from '@sveltejs/kit/internal';
|
|
6
|
+
import { HttpError, Redirect, HandledHttpError } from '@sveltejs/kit/internal';
|
|
7
7
|
import { untrack } from 'svelte';
|
|
8
8
|
import { create_remote_key, split_remote_key } from '../../shared.js';
|
|
9
9
|
import { navigating, page, notify_version } from '../state.svelte.js';
|
|
@@ -86,7 +86,7 @@ export function pin_while_resolving(cache_map, cache, id, payload, then) {
|
|
|
86
86
|
*/
|
|
87
87
|
export function unwrap_node(node) {
|
|
88
88
|
if (node.e) {
|
|
89
|
-
throw new
|
|
89
|
+
throw new HandledHttpError(node.e);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
return node.v;
|
|
@@ -118,22 +118,17 @@ export async function remote_request(url, init) {
|
|
|
118
118
|
notify_version(response.headers.get('x-sveltekit-version'));
|
|
119
119
|
|
|
120
120
|
if (!response.ok) {
|
|
121
|
-
const result = await response.json().catch(() =>
|
|
122
|
-
type: 'error',
|
|
123
|
-
status,
|
|
124
|
-
error: {
|
|
125
|
-
status,
|
|
126
|
-
message: response.statusText
|
|
127
|
-
}
|
|
128
|
-
}));
|
|
121
|
+
const result = await response.json().catch(() => undefined);
|
|
129
122
|
|
|
130
|
-
throw
|
|
123
|
+
throw result?.type === 'error'
|
|
124
|
+
? new HandledHttpError({ status, ...result.error })
|
|
125
|
+
: new HttpError({ status, message: response.statusText });
|
|
131
126
|
}
|
|
132
127
|
|
|
133
128
|
const result = /** @type {RemoteFunctionResponse} */ (await response.json());
|
|
134
129
|
|
|
135
130
|
if (result.type === 'error') {
|
|
136
|
-
throw new
|
|
131
|
+
throw new HandledHttpError(result.error);
|
|
137
132
|
}
|
|
138
133
|
|
|
139
134
|
const data = /** @type {RemoteFunctionData} */ (
|
|
@@ -148,7 +143,7 @@ export async function remote_request(url, init) {
|
|
|
148
143
|
function refresh(key, entry, result) {
|
|
149
144
|
if (entry?.resource) {
|
|
150
145
|
if (result.e) {
|
|
151
|
-
entry.resource.fail(new
|
|
146
|
+
entry.resource.fail(new HandledHttpError(result.e));
|
|
152
147
|
} else {
|
|
153
148
|
entry.resource.set(result.v);
|
|
154
149
|
}
|
|
@@ -202,7 +197,7 @@ export async function handle_side_channel_response(response) {
|
|
|
202
197
|
}
|
|
203
198
|
|
|
204
199
|
if (response.type === 'error') {
|
|
205
|
-
throw new
|
|
200
|
+
throw new HandledHttpError(response.error);
|
|
206
201
|
}
|
|
207
202
|
|
|
208
203
|
return response;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
/** @import { Navigation } from '$app/navigation' */
|
|
2
|
+
/** @import { Page } from '$app/state' */
|
|
1
3
|
import { version } from '$app/env';
|
|
2
|
-
import { assets } from '
|
|
4
|
+
import { assets } from '#app/paths';
|
|
3
5
|
import { BROWSER, DEV } from 'esm-env';
|
|
4
6
|
|
|
5
|
-
/** @type {
|
|
7
|
+
/** @type {Page} */
|
|
6
8
|
export const page = new (class Page {
|
|
7
9
|
data = $state.raw({});
|
|
8
10
|
form = $state.raw(null);
|
|
@@ -16,7 +18,7 @@ export const page = new (class Page {
|
|
|
16
18
|
})();
|
|
17
19
|
|
|
18
20
|
export const navigating = new (class Navigating {
|
|
19
|
-
/** @type {
|
|
21
|
+
/** @type {Navigation | null} */
|
|
20
22
|
current = $state.raw(null);
|
|
21
23
|
})();
|
|
22
24
|
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
TrailingSlash,
|
|
9
9
|
Uses
|
|
10
10
|
} from 'types';
|
|
11
|
-
import {
|
|
11
|
+
import { ParamMatcher } from '@sveltejs/kit/params';
|
|
12
|
+
import { Page } from '$app/state';
|
|
12
13
|
import { RenderNode } from '../props.svelte.js';
|
|
13
14
|
|
|
14
15
|
export interface SvelteKitApp {
|
package/src/runtime/pathname.js
CHANGED
|
@@ -1,69 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { app_dir, base } from '#app/paths';
|
|
2
|
+
import { add_resolution_suffix } from '../pathname.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
export function has_data_suffix(pathname) {
|
|
6
|
-
return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/** @param {string} pathname */
|
|
10
|
-
export function add_data_suffix(pathname) {
|
|
11
|
-
if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX);
|
|
12
|
-
return pathname.replace(/\/$/, '') + DATA_SUFFIX;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** @param {string} pathname */
|
|
16
|
-
export function strip_data_suffix(pathname) {
|
|
17
|
-
if (pathname.endsWith(HTML_DATA_SUFFIX)) {
|
|
18
|
-
return pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return pathname.slice(0, -DATA_SUFFIX.length);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const ROUTE_SUFFIX = '/__route.js';
|
|
25
|
-
const HTML_ROUTE_SUFFIX = '.html__route.js';
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} pathname
|
|
29
|
-
* @returns {boolean}
|
|
30
|
-
*/
|
|
31
|
-
export function has_resolution_suffix(pathname) {
|
|
32
|
-
return pathname.endsWith(ROUTE_SUFFIX) || pathname.endsWith(HTML_ROUTE_SUFFIX);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Convert a regular URL to a route to send to SvelteKit's server-side route resolution endpoint
|
|
37
|
-
* @param {string} pathname
|
|
38
|
-
* @returns {string}
|
|
39
|
-
*/
|
|
40
|
-
export function add_resolution_suffix(pathname) {
|
|
41
|
-
if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_ROUTE_SUFFIX);
|
|
42
|
-
return pathname.replace(/\/$/, '') + ROUTE_SUFFIX;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {string} pathname
|
|
47
|
-
* @returns {string}
|
|
48
|
-
*/
|
|
49
|
-
export function strip_resolution_suffix(pathname) {
|
|
50
|
-
if (pathname.endsWith(HTML_ROUTE_SUFFIX)) {
|
|
51
|
-
return pathname.slice(0, -HTML_ROUTE_SUFFIX.length) + '.html';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return pathname.slice(0, -ROUTE_SUFFIX.length);
|
|
55
|
-
}
|
|
4
|
+
export * from '../pathname.js';
|
|
56
5
|
|
|
57
6
|
const ROUTES_PREFIX = '/routes';
|
|
58
7
|
|
|
59
8
|
/**
|
|
60
9
|
* The pathname of the route-ID-keyed resolution module for a given route ID,
|
|
61
10
|
* e.g. `/_app/routes/blog/[slug]/__route.js` (before prefixing with `base`).
|
|
62
|
-
* @param {string} app_dir
|
|
63
11
|
* @param {string} route_id
|
|
64
12
|
* @returns {string}
|
|
65
13
|
*/
|
|
66
|
-
export function route_id_resolution_pathname(
|
|
14
|
+
export function route_id_resolution_pathname(route_id) {
|
|
67
15
|
return add_resolution_suffix(`/${app_dir}${ROUTES_PREFIX}${route_id === '/' ? '' : route_id}`);
|
|
68
16
|
}
|
|
69
17
|
|
|
@@ -71,11 +19,9 @@ export function route_id_resolution_pathname(app_dir, route_id) {
|
|
|
71
19
|
* Whether a pathname (with the `/__route.js` suffix already stripped, and `base` NOT yet stripped)
|
|
72
20
|
* is a route-ID resolution request rather than a pathname resolution request.
|
|
73
21
|
* @param {string} pathname
|
|
74
|
-
* @param {string} base
|
|
75
|
-
* @param {string} app_dir
|
|
76
22
|
* @returns {boolean}
|
|
77
23
|
*/
|
|
78
|
-
export function is_route_id_resolution_path(pathname
|
|
24
|
+
export function is_route_id_resolution_path(pathname) {
|
|
79
25
|
const prefix = `${base}/${app_dir}${ROUTES_PREFIX}`;
|
|
80
26
|
return pathname === prefix || pathname.startsWith(prefix + '/');
|
|
81
27
|
}
|
|
@@ -84,9 +30,8 @@ export function is_route_id_resolution_path(pathname, base, app_dir) {
|
|
|
84
30
|
* Extract the route ID from a decoded, base-stripped, suffix-stripped pathname,
|
|
85
31
|
* e.g. `/_app/routes/blog/[slug]` -> `/blog/[slug]`, `/_app/routes` -> `/`.
|
|
86
32
|
* @param {string} pathname
|
|
87
|
-
* @param {string} app_dir
|
|
88
33
|
* @returns {string}
|
|
89
34
|
*/
|
|
90
|
-
export function extract_route_id(pathname
|
|
35
|
+
export function extract_route_id(pathname) {
|
|
91
36
|
return pathname.slice(`/${app_dir}${ROUTES_PREFIX}`.length) || '/';
|
|
92
37
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { json, text } from '@sveltejs/kit';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
HandledHttpError,
|
|
4
|
+
HttpError,
|
|
5
|
+
SvelteKitError,
|
|
6
|
+
ValidationError
|
|
7
|
+
} from '@sveltejs/kit/internal';
|
|
3
8
|
import { with_request_store } from '@sveltejs/kit/internal/server';
|
|
4
|
-
import {
|
|
9
|
+
import { add_deprecated_handle_error_properties, coalesce_to_error } from '../../utils/error.js';
|
|
5
10
|
import { negotiate } from '../../utils/http.js';
|
|
6
11
|
import { fix_stack_trace } from './internal.js';
|
|
7
12
|
import { escape_html } from '../../utils/escape.js';
|
|
@@ -13,7 +18,6 @@ import { escape_html } from '../../utils/escape.js';
|
|
|
13
18
|
* @param {unknown} error
|
|
14
19
|
*/
|
|
15
20
|
export async function handle_fatal_error(event, state, options, error) {
|
|
16
|
-
error = error instanceof HttpError ? error : coalesce_to_error(error);
|
|
17
21
|
const body = await handle_error_and_jsonify(event, state, options, error);
|
|
18
22
|
const status = body.status;
|
|
19
23
|
|
|
@@ -40,29 +44,56 @@ export async function handle_fatal_error(event, state, options, error) {
|
|
|
40
44
|
* @returns {App.Error | Promise<App.Error>}
|
|
41
45
|
*/
|
|
42
46
|
export function handle_error_and_jsonify(event, state, options, error) {
|
|
43
|
-
if (error instanceof
|
|
44
|
-
|
|
45
|
-
return { message: 'Unknown Error', ...error.body };
|
|
47
|
+
if (error instanceof HandledHttpError) {
|
|
48
|
+
return error.body;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
/** @type {import('@sveltejs/kit').CaughtError} */
|
|
52
|
+
let caught;
|
|
53
|
+
|
|
54
|
+
if (error instanceof HttpError) {
|
|
55
|
+
caught = { kind: 'app', error: error.body };
|
|
56
|
+
} else if (error instanceof SvelteKitError) {
|
|
57
|
+
caught = { kind: 'framework', error: { status: error.status, message: error.text } };
|
|
58
|
+
} else if (error instanceof ValidationError) {
|
|
59
|
+
caught = {
|
|
60
|
+
kind: 'validation',
|
|
61
|
+
error: { status: 400, message: 'Bad Request' },
|
|
62
|
+
issues: error.issues
|
|
63
|
+
};
|
|
64
|
+
} else {
|
|
65
|
+
caught = { kind: 'unknown', error };
|
|
66
|
+
|
|
67
|
+
let e = error;
|
|
68
|
+
while (e instanceof Error) {
|
|
69
|
+
fix_stack_trace(e);
|
|
70
|
+
e = e.cause;
|
|
71
|
+
}
|
|
52
72
|
}
|
|
53
73
|
|
|
54
|
-
const
|
|
55
|
-
|
|
74
|
+
const fallback =
|
|
75
|
+
caught.kind === 'unknown' ? { status: 500, message: 'Internal Error' } : caught.error;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The hook returns only the properties it wants to override; anything it omits
|
|
79
|
+
* (including by returning nothing at all) is inherited from the caught error.
|
|
80
|
+
* @param {Awaited<ReturnType<import('@sveltejs/kit').HandleServerError>>} body
|
|
81
|
+
* @returns {App.Error}
|
|
82
|
+
*/
|
|
83
|
+
function merge(body) {
|
|
84
|
+
return { ...fallback, ...body };
|
|
85
|
+
}
|
|
56
86
|
|
|
57
87
|
// TODO 4.0 await this, rather than handling the non-Promise case
|
|
58
88
|
let result;
|
|
59
89
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
const input = { ...caught, event };
|
|
91
|
+
if (__SVELTEKIT_DEV__) add_deprecated_handle_error_properties(input, fallback);
|
|
92
|
+
|
|
93
|
+
result = with_request_store({ event, state }, () => options.hooks.handleError(input));
|
|
63
94
|
} catch (hook_error) {
|
|
64
95
|
log_handle_error_hook_failure(error, hook_error);
|
|
65
|
-
return { status, message: 'Internal Error' };
|
|
96
|
+
return { status: fallback.status, message: 'Internal Error' };
|
|
66
97
|
}
|
|
67
98
|
|
|
68
99
|
if (result instanceof Promise) {
|
|
@@ -76,24 +107,18 @@ export function handle_error_and_jsonify(event, state, options, error) {
|
|
|
76
107
|
result.catch((hook_error) => log_handle_error_hook_failure(error, hook_error));
|
|
77
108
|
|
|
78
109
|
return {
|
|
79
|
-
status,
|
|
110
|
+
status: fallback.status,
|
|
80
111
|
message: 'Internal Error'
|
|
81
112
|
};
|
|
82
113
|
}
|
|
83
114
|
|
|
84
|
-
return result.then(
|
|
85
|
-
(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
},
|
|
89
|
-
(hook_error) => {
|
|
90
|
-
log_handle_error_hook_failure(error, hook_error);
|
|
91
|
-
return { status, message: 'Internal Error' };
|
|
92
|
-
}
|
|
93
|
-
);
|
|
115
|
+
return result.then(merge, (hook_error) => {
|
|
116
|
+
log_handle_error_hook_failure(error, hook_error);
|
|
117
|
+
return { status: fallback.status, message: 'Internal Error' };
|
|
118
|
+
});
|
|
94
119
|
}
|
|
95
120
|
|
|
96
|
-
return
|
|
121
|
+
return merge(result);
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
/**
|