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

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 (88) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +8 -8
  3. package/src/constants.js +3 -1
  4. package/src/core/adapt/builder.js +3 -6
  5. package/src/core/config/index.js +6 -1
  6. package/src/core/config/options.js +54 -104
  7. package/src/core/env.js +25 -11
  8. package/src/core/postbuild/fallback.js +2 -1
  9. package/src/core/postbuild/prerender.js +75 -28
  10. package/src/core/postbuild/queue.js +2 -1
  11. package/src/core/sync/sync.js +11 -14
  12. package/src/core/sync/utils.js +21 -1
  13. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
  14. package/src/core/sync/write_client_manifest.js +4 -12
  15. package/src/core/sync/write_env.js +6 -4
  16. package/src/core/sync/write_server.js +12 -17
  17. package/src/core/sync/write_tsconfig/index.js +245 -0
  18. package/src/core/sync/write_tsconfig/utils.js +162 -0
  19. package/src/core/sync/write_types/index.js +80 -88
  20. package/src/core/utils.js +28 -3
  21. package/src/exports/env/index.js +68 -3
  22. package/src/exports/internal/env.js +6 -3
  23. package/src/exports/internal/server/index.js +3 -1
  24. package/src/exports/params.js +9 -4
  25. package/src/exports/public.d.ts +69 -71
  26. package/src/exports/vite/dev/index.js +112 -56
  27. package/src/exports/vite/index.js +483 -258
  28. package/src/exports/vite/module_ids.js +2 -2
  29. package/src/exports/vite/preview/index.js +3 -2
  30. package/src/exports/vite/utils.js +21 -10
  31. package/src/runner.js +13 -0
  32. package/src/runtime/app/forms.js +4 -0
  33. package/src/runtime/app/manifest/index.js +1 -0
  34. package/src/runtime/app/paths/client.js +30 -30
  35. package/src/runtime/app/paths/internal/client.js +26 -0
  36. package/src/runtime/app/paths/server.js +23 -10
  37. package/src/runtime/app/paths/types.d.ts +11 -19
  38. package/src/runtime/app/server/index.js +1 -1
  39. package/src/runtime/app/server/remote/command.js +12 -7
  40. package/src/runtime/app/server/remote/form.js +29 -26
  41. package/src/runtime/app/server/remote/prerender.js +9 -2
  42. package/src/runtime/app/server/remote/query.js +6 -5
  43. package/src/runtime/app/server/remote/shared.js +48 -30
  44. package/src/runtime/app/service-worker/index.js +24 -0
  45. package/src/runtime/app/state/index.js +1 -1
  46. package/src/runtime/client/client.js +46 -9
  47. package/src/runtime/client/ndjson.js +1 -1
  48. package/src/runtime/client/remote-functions/form.svelte.js +43 -51
  49. package/src/runtime/client/remote-functions/query/index.js +2 -2
  50. package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
  51. package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
  52. package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
  53. package/src/runtime/client/state.svelte.js +54 -21
  54. package/src/runtime/client/stream.js +3 -2
  55. package/src/runtime/form-utils.js +89 -54
  56. package/src/runtime/server/cookie.js +1 -1
  57. package/src/runtime/server/data/index.js +32 -29
  58. package/src/runtime/server/errors.js +135 -0
  59. package/src/runtime/server/fetch.js +1 -1
  60. package/src/runtime/server/index.js +20 -10
  61. package/src/runtime/server/internal.js +25 -0
  62. package/src/runtime/server/page/actions.js +4 -3
  63. package/src/runtime/server/page/data_serializer.js +10 -10
  64. package/src/runtime/server/page/index.js +3 -2
  65. package/src/runtime/server/page/load_data.js +1 -1
  66. package/src/runtime/server/page/render.js +22 -35
  67. package/src/runtime/server/page/respond_with_error.js +6 -5
  68. package/src/runtime/server/{remote.js → remote-functions.js} +67 -36
  69. package/src/runtime/server/respond.js +58 -20
  70. package/src/runtime/server/sourcemaps.js +183 -0
  71. package/src/runtime/server/utils.js +12 -157
  72. package/src/types/ambient-private.d.ts +10 -0
  73. package/src/types/ambient.d.ts +22 -27
  74. package/src/types/global-private.d.ts +12 -5
  75. package/src/types/internal.d.ts +19 -9
  76. package/src/types/private.d.ts +8 -0
  77. package/src/utils/escape.js +9 -25
  78. package/src/utils/features.js +1 -1
  79. package/src/utils/fork.js +7 -2
  80. package/src/utils/page_nodes.js +3 -5
  81. package/src/utils/url.js +12 -0
  82. package/src/version.js +1 -1
  83. package/types/index.d.ts +152 -120
  84. package/types/index.d.ts.map +6 -1
  85. package/src/core/sync/write_ambient.js +0 -18
  86. package/src/core/sync/write_tsconfig.js +0 -258
  87. package/src/runtime/shared-server.js +0 -7
  88. /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
@@ -1,15 +1,7 @@
1
1
  /** @import { ServerHooks } from 'types' */
2
2
  import * as devalue from 'devalue';
3
- import { DEV } from 'esm-env';
4
- import { json, text } from '@sveltejs/kit';
5
- import { HttpError } from '@sveltejs/kit/internal';
6
- import { with_request_store } from '@sveltejs/kit/internal/server';
7
- import { coalesce_to_error, get_message, get_status } from '../../utils/error.js';
8
- import { negotiate } from '../../utils/http.js';
9
- import { fix_stack_trace } from '../shared-server.js';
3
+ import { text } from '@sveltejs/kit';
10
4
  import { ENDPOINT_METHODS } from '../../constants.js';
11
- import { escape_html } from '../../utils/escape.js';
12
- import * as path from '../../utils/path.js';
13
5
 
14
6
  /**
15
7
  * @param {Partial<Record<import('types').HttpMethod, any>>} mod
@@ -46,103 +38,6 @@ export function get_global_name(options) {
46
38
  return __SVELTEKIT_DEV__ ? '__sveltekit_dev' : `__sveltekit_${options.version_hash}`;
47
39
  }
48
40
 
49
- /**
50
- * Return as a response that renders the error.html
51
- *
52
- * @param {import('types').SSROptions} options
53
- * @param {number} status
54
- * @param {string} message
55
- */
56
- export function static_error_page(options, status, message) {
57
- let page = options.templates.error({ status, message: escape_html(message) });
58
-
59
- if (__SVELTEKIT_DEV__) {
60
- // inject Vite HMR client, for easier debugging
61
- page = page.replace('</head>', '<script type="module" src="/@vite/client"></script></head>');
62
- }
63
-
64
- return text(page, {
65
- headers: { 'content-type': 'text/html; charset=utf-8' },
66
- status
67
- });
68
- }
69
-
70
- /**
71
- * @param {import('@sveltejs/kit').RequestEvent} event
72
- * @param {import('types').RequestState} state
73
- * @param {import('types').SSROptions} options
74
- * @param {unknown} error
75
- */
76
- export async function handle_fatal_error(event, state, options, error) {
77
- error = error instanceof HttpError ? error : coalesce_to_error(error);
78
- const body = await handle_error_and_jsonify(event, state, options, error);
79
- const status = body.status;
80
-
81
- // ideally we'd use sec-fetch-dest instead, but Safari — quelle surprise — doesn't support it
82
- const type = negotiate(event.request.headers.get('accept') || 'text/html', [
83
- 'application/json',
84
- 'text/html'
85
- ]);
86
-
87
- if (event.isDataRequest || type === 'application/json') {
88
- return json(body, {
89
- status
90
- });
91
- }
92
-
93
- return static_error_page(options, status, body.message);
94
- }
95
-
96
- /**
97
- * @param {import('@sveltejs/kit').RequestEvent} event
98
- * @param {import('types').RequestState} state
99
- * @param {import('types').SSROptions} options
100
- * @param {any} error
101
- * @returns {App.Error | Promise<App.Error>}
102
- */
103
- export function handle_error_and_jsonify(event, state, options, error) {
104
- if (error instanceof HttpError) {
105
- // @ts-expect-error custom user errors may not have a message field if App.Error is overwritten
106
- return { message: 'Unknown Error', ...error.body };
107
- }
108
-
109
- if (__SVELTEKIT_DEV__ && typeof error == 'object') {
110
- fix_stack_trace(error);
111
- }
112
-
113
- const status = get_status(error);
114
- const message = get_message(error);
115
-
116
- // TODO 4.0 await this, rather than handling the non-Promise case
117
- const result = with_request_store({ event, state }, () =>
118
- options.hooks.handleError({ error, event, status, message })
119
- ) ?? { status, message };
120
-
121
- if (result instanceof Promise) {
122
- if (!__SVELTEKIT_SUPPORTS_ASYNC__ && state.is_in_render) {
123
- console.warn(
124
- `To use an async \`handleError\` hook to handle errors that occur during rendering, you must enable \`compilerOptions.experimental.async\` in the SvelteKit plugin of your Vite config. The returned error has been replaced with a generic object`
125
- );
126
-
127
- // we're discarding the result, but we still need to prevent an unhandled
128
- // rejection if the user's async `handleError` hook rejects
129
- result.catch(() => {});
130
-
131
- return {
132
- status,
133
- message: 'Internal Error'
134
- };
135
- }
136
-
137
- return result.then((body) => {
138
- body ??= { status, message };
139
- return { ...body, status: get_status(body, error) };
140
- });
141
- }
142
-
143
- return { ...result, status: get_status(result, error) };
144
- }
145
-
146
41
  /**
147
42
  * @param {number} status
148
43
  * @param {string} location
@@ -155,6 +50,16 @@ export function redirect_response(status, location) {
155
50
  return response;
156
51
  }
157
52
 
53
+ /**
54
+ * @param {Response} response
55
+ */
56
+ export function with_version_header(response) {
57
+ if (__SVELTEKIT_APP_VERSION_CHECKS_ENABLED__) {
58
+ response.headers.set('x-sveltekit-version', __SVELTEKIT_APP_VERSION__);
59
+ }
60
+ return response;
61
+ }
62
+
158
63
  /**
159
64
  * @param {import('@sveltejs/kit').RequestEvent} event
160
65
  * @param {Error & { path: string }} error
@@ -163,7 +68,7 @@ export function clarify_devalue_error(event, error) {
163
68
  if (error.path) {
164
69
  return (
165
70
  `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (${error.path}). ` +
166
- `If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#Universal-hooks-transport.`
71
+ `If you need to serialize/deserialize custom types, use transport hooks: https://svelte.dev/docs/kit/hooks#transport.`
167
72
  );
168
73
  }
169
74
 
@@ -212,56 +117,6 @@ export function has_prerendered_path(manifest, pathname) {
212
117
  );
213
118
  }
214
119
 
215
- /**
216
- * Formats the error into a nice message with sanitized stack trace
217
- * @param {number} status
218
- * @param {Error} error
219
- * @param {import('@sveltejs/kit').RequestEvent} event
220
- */
221
- export function format_server_error(status, error, event) {
222
- const formatted_text = `\n\x1b[1;31m[${status}] ${event.request.method} ${event.url.pathname}\x1b[0m`;
223
-
224
- if (status === 404) {
225
- return formatted_text;
226
- }
227
-
228
- return `${formatted_text}\n${DEV ? clean_up_stack_trace(error) : error.stack}`;
229
- }
230
-
231
- /**
232
- * In dev, tidy up stack traces by making paths relative to the current project directory
233
- * @param {string} file
234
- */
235
- let relative = (file) => file;
236
-
237
- if (DEV) {
238
- try {
239
- relative = (file) => path.relative(__SVELTEKIT_ROOT__, file);
240
- } catch {
241
- // do nothing
242
- }
243
- }
244
-
245
- /**
246
- * Provides a refined stack trace by excluding lines following the last occurrence of a line containing +page. +layout. or +server.
247
- * @param {Error} error
248
- */
249
- export function clean_up_stack_trace(error) {
250
- const stack_trace = (error.stack?.split('\n') ?? []).map((line) => {
251
- return line.replace(/\((.+)(:\d+:\d+)\)$/, (_, file, loc) => `(${relative(file)}${loc})`);
252
- });
253
-
254
- // progressive enhancement for people who haven't configured files.src to something else
255
- const last_line_from_src_code = stack_trace.findLastIndex((line) => /\(src[\\/]/.test(line));
256
-
257
- if (last_line_from_src_code === -1) {
258
- // default to the whole stack trace
259
- return error.stack;
260
- }
261
-
262
- return stack_trace.slice(0, last_line_from_src_code + 1).join('\n');
263
- }
264
-
265
120
  /**
266
121
  * Returns the filename without the extension. e.g., `+page.server`, `+page`, etc.
267
122
  * @param {string | undefined} node_id
@@ -13,8 +13,10 @@ declare module '__sveltekit/paths' {
13
13
  declare module '__sveltekit/server' {
14
14
  import { SSRManifest } from '@sveltejs/kit';
15
15
 
16
+ export let fix_stack_trace: (error: Error) => string;
16
17
  export let manifest: SSRManifest;
17
18
  export function read_implementation(path: string): ReadableStream;
19
+ export function set_fix_stack_trace(fn: (error: Error) => string): void;
18
20
  export function set_manifest(manifest: SSRManifest): void;
19
21
  export function set_read_implementation(fn: (path: string) => ReadableStream): void;
20
22
  }
@@ -43,3 +45,11 @@ declare module '__sveltekit/env/public/client' {
43
45
  declare module '__sveltekit/env/public/server' {
44
46
  // exported environment variables are defined in env.d.ts
45
47
  }
48
+
49
+ /** Internal version of $app/manifest */
50
+ declare module '__sveltekit/manifest-data' {
51
+ export const immutable: Array<{ path: string }>;
52
+ export const assets: Array<{ path: string }>;
53
+ export const prerendered: Array<{ path: string }>;
54
+ export const routes: Array<{ id: string }>;
55
+ }
@@ -57,32 +57,30 @@ declare namespace App {
57
57
  }
58
58
 
59
59
  /**
60
- * This module is only available to [service workers](https://svelte.dev/docs/kit/service-workers).
60
+ * This module is available to [service workers](https://svelte.dev/docs/kit/service-workers) and other contexts.
61
+ * It exports information about the build output, static files, prerendered pages, and routes.
61
62
  */
62
- declare module '$service-worker' {
63
+ declare module '$app/manifest' {
63
64
  /**
64
- * The `base` path of the deployment. Typically this is equivalent to `config.paths.base`, but it is calculated from `location.pathname` meaning that it will continue to work correctly if the site is deployed to a subdirectory.
65
- * Note that there is a `base` but no `assets`, since service workers cannot be used if `config.paths.assets` is specified.
66
- */
67
- export const base: string;
68
- /**
69
- * An array of URL strings representing the files generated by Vite, suitable for caching with `cache.addAll(build)`.
65
+ * An array of `{ path: string }` objects representing the files generated by Vite.
66
+ * The path is relative to the [base path](https://svelte.dev/docs/kit/configuration#paths), and is intended for use with `cache.add(...)` inside a [service worker](https://svelte.dev/docs/kit/service-workers).
70
67
  * During development, this is an empty array.
71
68
  */
72
- export const build: string[];
69
+ export const immutable: Array<{ path: string }>;
73
70
  /**
74
- * An array of URL strings representing the files in your static directory, or whatever directory is specified by `config.files.assets`. You can customize which files are included from `static` directory using [`config.serviceWorker.files`](https://svelte.dev/docs/kit/configuration#serviceWorker)
71
+ * An array of `{ path: AssetPath }` objects representing the files in your `static` directory, or whatever directory is specified by `config.files.assets`.
72
+ * The path is relative to the [base path](https://svelte.dev/docs/kit/configuration#paths), and can be used with [`asset(...)`](https://svelte.dev/docs/kit/$app-paths#asset).
75
73
  */
76
- export const files: string[];
74
+ export const assets: Array<{ path: import('$app/types').AssetPath }>;
77
75
  /**
78
- * An array of pathnames corresponding to prerendered pages and endpoints.
76
+ * An array of `{ path: Path }` objects representing prerendered pages and endpoints, relative to the [base path](https://svelte.dev/docs/kit/configuration#paths).
79
77
  * During development, this is an empty array.
80
78
  */
81
- export const prerendered: string[];
79
+ export const prerendered: Array<{ path: import('$app/types').Path }>;
82
80
  /**
83
- * See [`config.version`](https://svelte.dev/docs/kit/configuration#version). It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.
81
+ * An array of objects with an `id` property representing the routes in your app.
84
82
  */
85
- export const version: string;
83
+ export const routes: Array<{ id: import('$app/types').RouteId }>;
86
84
  }
87
85
 
88
86
  /**
@@ -99,9 +97,9 @@ declare module '$app/types' {
99
97
  RouteId(): string;
100
98
  RouteParams(): Record<string, Record<string, string>>;
101
99
  LayoutParams(): Record<string, Record<string, string>>;
102
- Pathname(): string;
100
+ Path(): string;
103
101
  ResolvedPathname(): string;
104
- Asset(): string;
102
+ AssetPath(): string;
105
103
  }
106
104
 
107
105
  /**
@@ -129,25 +127,22 @@ declare module '$app/types' {
129
127
  : Record<string, never>;
130
128
 
131
129
  /**
132
- * A union of all valid pathnames in your app.
130
+ * A union of all valid paths in your app, relative to the `base` path.
133
131
  */
134
- export type Pathname = ReturnType<AppTypes['Pathname']>;
132
+ export type Path = ReturnType<AppTypes['Path']>;
135
133
 
136
134
  /**
137
- * `Pathname`, but possibly suffixed with a search string and/or hash.
135
+ * `Path`, but possibly suffixed with a search string and/or hash.
138
136
  */
139
- export type PathnameWithSearchOrHash =
140
- | Pathname
141
- | `${Pathname}?${string}`
142
- | `${Pathname}#${string}`;
137
+ export type PathnameWithSearchOrHash = Path | `${Path}?${string}` | `${Path}#${string}`;
143
138
 
144
139
  /**
145
- * `Pathname`, but possibly prefixed with a base path. Used for `page.url.pathname`.
140
+ * `Path`, but prefixed with a base path. Used for `page.url.pathname`.
146
141
  */
147
142
  export type ResolvedPathname = ReturnType<AppTypes['ResolvedPathname']>;
148
143
 
149
144
  /**
150
- * A union of all the filenames of assets contained in your `static` directory.
145
+ * A union of all the filenames of assets contained in your `static` directory, relative to the `base` path.
151
146
  */
152
- export type Asset = ReturnType<AppTypes['Asset']>;
147
+ export type AssetPath = ReturnType<AppTypes['AssetPath']>;
153
148
  }
@@ -6,6 +6,8 @@ declare global {
6
6
  const __SVELTEKIT_APP_VERSION__: string;
7
7
  const __SVELTEKIT_APP_VERSION_FILE__: string;
8
8
  const __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: number;
9
+ /** True if version checks are enabled (i.e. `bundleStrategy !== 'inline'`) */
10
+ const __SVELTEKIT_APP_VERSION_CHECKS_ENABLED__: boolean;
9
11
  /**
10
12
  * True if the user ran `vite dev`. This is different from `esm-env` because
11
13
  * it is influenced by `NODE_ENV` which can still be true during `vite preview`
@@ -38,15 +40,20 @@ declare global {
38
40
  * Should only be used when bundleStrategy !== 'inline' to avoid SvelteKit runtime changing on every build, preventing cacheability.
39
41
  */
40
42
  const __SVELTEKIT_PAYLOAD__: SvelteKitPayload;
41
- /**
42
- * The Vite `root` setting used to construct paths to nodes and components
43
- * for the SSR manifest during development
44
- */
45
- const __SVELTEKIT_ROOT__: string;
46
43
  /**
47
44
  * Whether the `experimental.async` flag is applied
48
45
  */
49
46
  const __SVELTEKIT_SUPPORTS_ASYNC__: boolean;
47
+ /**
48
+ * Manifest data placeholders used by `$app/manifest`. During build, these
49
+ * are bare identifiers (fake globals) that the bundler leaves as unresolved
50
+ * references. They are replaced with real values by scanning the output
51
+ * chunks after each build completes.
52
+ */
53
+ const __SVELTEKIT_MANIFEST_IMMUTABLE__: string[];
54
+ const __SVELTEKIT_MANIFEST_ASSETS__: string[];
55
+ const __SVELTEKIT_MANIFEST_PRERENDERED__: string[];
56
+ const __SVELTEKIT_MANIFEST_ROUTES__: { id: string }[];
50
57
  /**
51
58
  * This makes the use of specific features visible at both dev and build time, in such a
52
59
  * way that we can error when they are not supported by the target platform.
@@ -47,7 +47,7 @@ export interface ServerInternalModule {
47
47
  set_prerendering(): void;
48
48
  set_read_implementation(implementation: (path: string) => ReadableStream): void;
49
49
  set_version(version: string): void;
50
- set_fix_stack_trace(fix_stack_trace: (error: unknown) => string): void;
50
+ set_fix_stack_trace(fix_stack_trace: (error: Error) => void): void;
51
51
  get_hooks: () => Promise<Record<string, any>>;
52
52
  }
53
53
 
@@ -394,7 +394,7 @@ export interface ServerErrorNode {
394
394
  }
395
395
 
396
396
  export interface ServerMetadataRoute {
397
- config: any;
397
+ config: Record<string, any>;
398
398
  api: {
399
399
  methods: Array<HttpMethod | '*'>;
400
400
  };
@@ -426,7 +426,7 @@ export interface UniversalNode {
426
426
  ssr?: boolean;
427
427
  csr?: boolean;
428
428
  trailingSlash?: TrailingSlash;
429
- config?: any;
429
+ config?: Record<string, any>;
430
430
  entries?: PrerenderEntryGenerator;
431
431
  }
432
432
 
@@ -437,7 +437,7 @@ export interface ServerNode {
437
437
  csr?: boolean;
438
438
  trailingSlash?: TrailingSlash;
439
439
  actions?: Actions;
440
- config?: any;
440
+ config?: Record<string, any>;
441
441
  entries?: PrerenderEntryGenerator;
442
442
  }
443
443
 
@@ -496,6 +496,7 @@ export interface SSROptions {
496
496
  }): string;
497
497
  error(values: { message: string; status: number }): string;
498
498
  };
499
+ version: string;
499
500
  version_hash: string;
500
501
  }
501
502
 
@@ -511,7 +512,7 @@ export type RemotePrerenderInputsGenerator<Input = any> = () => MaybePromise<Inp
511
512
  export type SSREndpoint = Partial<Record<HttpMethod, RequestHandler>> & {
512
513
  prerender?: PrerenderOption;
513
514
  trailingSlash?: TrailingSlash;
514
- config?: any;
515
+ config?: Record<string, any>;
515
516
  entries?: PrerenderEntryGenerator;
516
517
  fallback?: RequestHandler;
517
518
  };
@@ -560,7 +561,7 @@ export interface SSRState {
560
561
  */
561
562
  before_handle?: (
562
563
  event: RequestEvent,
563
- config: any,
564
+ config: Record<string, any>,
564
565
  prerender: PrerenderOption,
565
566
  handle: () => Promise<Response>
566
567
  ) => Promise<Response>;
@@ -646,7 +647,7 @@ export interface RemoteFormInternals extends BaseRemoteInternals {
646
647
  * For keyed (`form.for(key)`) instances: the id as the client computes it
647
648
  * (the key is JSON-stringified but not URI-encoded, unlike `id`)
648
649
  */
649
- action_id?: string;
650
+ key?: string;
650
651
  fn(body: Record<string, any>, meta: BinaryFormMeta, form_data: FormData | null): Promise<any>;
651
652
  }
652
653
 
@@ -700,8 +701,11 @@ export interface RequestState {
700
701
  */
701
702
  implicit: null | Map<RemoteInternals, Record<string, () => MaybePromise<any>>>;
702
703
  /**
703
- * Data that is explicitly included because of a `set(...)` or `refresh()`.
704
- * This is always awaited
704
+ * Data that is explicitly included because of a `set(...)`, `refresh()` or
705
+ * `reconnect()`. The stored function is invoked lazily at the end of the
706
+ * request by `collect_remote_data`; if the query was already read (and thus
707
+ * cached) earlier in the request, invoking it does no additional work. This
708
+ * is always awaited and serialized.
705
709
  */
706
710
  explicit: null | Map<
707
711
  string,
@@ -736,8 +740,14 @@ export interface RequestState {
736
740
  readonly is_in_remote_function: boolean;
737
741
  readonly is_in_remote_form_or_command: boolean;
738
742
  readonly is_in_remote_query: boolean;
743
+ readonly is_in_remote_prerender: boolean;
739
744
  readonly is_in_render: boolean;
740
745
  readonly is_in_universal_load: boolean;
746
+ /**
747
+ * The event before `derive_remote_function_event` hid or stubbed properties.
748
+ * Hooks like `handleValidationError` receive this so `url` etc. stay accessible
749
+ */
750
+ readonly original_event?: RequestEvent;
741
751
  }
742
752
 
743
753
  export interface RequestStore {
@@ -159,10 +159,18 @@ export type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' |
159
159
  export interface Logger {
160
160
  (msg: string): void;
161
161
  success(msg: string): void;
162
+ /** Print a bold red message to stderr */
162
163
  error(msg: string): void;
164
+ /** Print a bold yellow message to stderr */
163
165
  warn(msg: string): void;
166
+ /** Print faded text to stdout if `verbose === true` */
164
167
  minor(msg: string): void;
168
+ /** Print to stdout if `verbose === true` */
165
169
  info(msg: string): void;
170
+ /** Print to stderr without formatting */
171
+ err(msg: string): void;
172
+ /** Print a bold red message, followed by a stack trace for each error (following `.cause` chains) */
173
+ prettyError(error: unknown, caller?: string): void;
166
174
  }
167
175
 
168
176
  export type MaybePromise<T> = T | Promise<T>;
@@ -21,24 +21,12 @@ const escape_html_dict = {
21
21
  '<': '&lt;'
22
22
  };
23
23
 
24
- const surrogates = // high surrogate without paired low surrogate
25
- '[\\ud800-\\udbff](?![\\udc00-\\udfff])|' +
26
- // a valid surrogate pair, the only match with 2 code units
27
- // we match it so that we can match unpaired low surrogates in the same pass
28
- // TODO: use lookbehind assertions once they are widely supported: (?<![\ud800-udbff])[\udc00-\udfff]
29
- '[\\ud800-\\udbff][\\udc00-\\udfff]|' +
30
- // unpaired low surrogate (see previous match)
31
- '[\\udc00-\\udfff]';
24
+ // `\p{Surrogate}` only matches unpaired surrogates with the `u` flag (a pair is one code point)
25
+ /** @param {Record<string, string>} dict */
26
+ const escape_regex = (dict) => new RegExp(`[${Object.keys(dict).join('')}]|\\p{Surrogate}`, 'gu');
32
27
 
33
- const escape_html_attr_regex = new RegExp(
34
- `[${Object.keys(escape_html_attr_dict).join('')}]|` + surrogates,
35
- 'g'
36
- );
37
-
38
- const escape_html_regex = new RegExp(
39
- `[${Object.keys(escape_html_dict).join('')}]|` + surrogates,
40
- 'g'
41
- );
28
+ const escape_html_attr_regex = escape_regex(escape_html_attr_dict);
29
+ const escape_html_regex = escape_regex(escape_html_dict);
42
30
 
43
31
  /**
44
32
  * Escapes unpaired surrogates (which are allowed in js strings but invalid in HTML) and
@@ -51,14 +39,10 @@ const escape_html_regex = new RegExp(
51
39
  */
52
40
  export function escape_html(str, is_attr) {
53
41
  const dict = is_attr ? escape_html_attr_dict : escape_html_dict;
54
- const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => {
55
- if (match.length === 2) {
56
- // valid surrogate pair
57
- return match;
58
- }
59
-
60
- return dict[match] ?? `&#${match.charCodeAt(0)};`;
61
- });
42
+ const escaped_str = str.replace(
43
+ is_attr ? escape_html_attr_regex : escape_html_regex,
44
+ (match) => dict[match] ?? `&#${match.charCodeAt(0)};`
45
+ );
62
46
 
63
47
  return escaped_str;
64
48
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @param {string} route_id
3
- * @param {any} config
3
+ * @param {Record<string, any>} config
4
4
  * @param {string} feature
5
5
  * @param {import('@sveltejs/kit').Adapter | undefined} adapter
6
6
  */
package/src/utils/fork.js CHANGED
@@ -38,7 +38,8 @@ export function forked(module, callback) {
38
38
  const worker = new Worker(fileURLToPath(module), {
39
39
  env: {
40
40
  ...process.env,
41
- SVELTEKIT_FORK: 'true'
41
+ SVELTEKIT_FORK: 'true',
42
+ FORCE_COLOR: '1'
42
43
  }
43
44
  });
44
45
 
@@ -60,9 +61,13 @@ export function forked(module, callback) {
60
61
  }
61
62
  );
62
63
 
64
+ worker.once('error', reject);
65
+
63
66
  worker.on('exit', (code) => {
64
67
  if (code) {
65
- reject(new Error(`Failed with code ${code}`));
68
+ const error = new Error(`Failed with code ${code}`);
69
+ error.stack = error.message;
70
+ reject(error);
66
71
  }
67
72
  });
68
73
  });
@@ -69,7 +69,7 @@ export class PageNodes {
69
69
  }
70
70
 
71
71
  get_config() {
72
- /** @type {any} */
72
+ /** @type {Record<string, any>} */
73
73
  let current = {};
74
74
 
75
75
  for (const node of this.data) {
@@ -77,13 +77,11 @@ export class PageNodes {
77
77
 
78
78
  current = {
79
79
  ...current,
80
- // TODO: should we override the server config value with the universal value similar to other page options?
81
- ...node?.universal?.config,
82
- ...node?.server?.config
80
+ ...node?.server?.config,
81
+ ...node?.universal?.config
83
82
  };
84
83
  }
85
84
 
86
- // TODO 3.0 always return `current`? then we can get rid of `?? {}` in other places
87
85
  return Object.keys(current).length ? current : undefined;
88
86
  }
89
87
 
package/src/utils/url.js CHANGED
@@ -27,6 +27,18 @@ export function is_root_relative(path) {
27
27
  return path[0] === '/' && path[1] !== '/';
28
28
  }
29
29
 
30
+ /**
31
+ * Relative reference from `from` to `to`, which must differ only by a trailing slash
32
+ * @param {string} from
33
+ * @param {string} to
34
+ * @returns {string}
35
+ */
36
+ export function relative_pathname(from, to) {
37
+ const segment = to.replace(/\/$/, '').split('/').at(-1);
38
+
39
+ return from.endsWith('/') ? `../${segment}` : `${segment}/`;
40
+ }
41
+
30
42
  /**
31
43
  * @param {string} location
32
44
  * @param {string} allowed
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // generated during release, do not modify
2
2
 
3
3
  /** @type {string} */
4
- export const VERSION = '3.0.0-next.10';
4
+ export const VERSION = '3.0.0-next.12';