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

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 (144) hide show
  1. package/package.json +33 -21
  2. package/src/constants.js +2 -0
  3. package/src/core/adapt/builder.js +32 -49
  4. package/src/core/adapt/index.js +1 -4
  5. package/src/core/config/index.js +137 -71
  6. package/src/core/config/options.js +236 -244
  7. package/src/core/config/types.d.ts +1 -1
  8. package/src/core/env.js +121 -5
  9. package/src/core/generate_manifest/index.js +12 -15
  10. package/src/core/postbuild/analyse.js +7 -19
  11. package/src/core/postbuild/crawl.js +22 -6
  12. package/src/core/postbuild/fallback.js +2 -1
  13. package/src/core/postbuild/prerender.js +114 -48
  14. package/src/core/postbuild/queue.js +2 -1
  15. package/src/core/sync/create_manifest_data/index.js +53 -50
  16. package/src/core/sync/sync.js +0 -2
  17. package/src/core/sync/write_client_manifest.js +8 -15
  18. package/src/core/sync/write_env.js +2 -1
  19. package/src/core/sync/write_non_ambient.js +12 -9
  20. package/src/core/sync/write_server.js +14 -15
  21. package/src/core/sync/write_tsconfig.js +16 -8
  22. package/src/core/sync/write_tsconfig_test/package.json +7 -0
  23. package/src/core/sync/write_types/index.js +28 -24
  24. package/src/core/utils.js +30 -5
  25. package/src/exports/env/index.js +77 -0
  26. package/src/exports/hooks/index.js +3 -9
  27. package/src/exports/hooks/sequence.js +3 -2
  28. package/src/exports/index.js +35 -13
  29. package/src/exports/internal/client.js +5 -0
  30. package/src/exports/internal/env.js +8 -5
  31. package/src/exports/internal/index.js +1 -90
  32. package/src/exports/internal/{event.js → server/event.js} +1 -2
  33. package/src/exports/internal/server/index.js +33 -0
  34. package/src/exports/internal/shared.js +89 -0
  35. package/src/exports/node/index.js +62 -15
  36. package/src/exports/params.js +68 -0
  37. package/src/exports/public.d.ts +363 -189
  38. package/src/exports/url.js +86 -0
  39. package/src/exports/vite/build/build_server.js +53 -59
  40. package/src/exports/vite/build/remote.js +18 -11
  41. package/src/exports/vite/build/utils.js +0 -8
  42. package/src/exports/vite/dev/index.js +92 -50
  43. package/src/exports/vite/index.js +903 -681
  44. package/src/exports/vite/module_ids.js +0 -2
  45. package/src/exports/vite/preview/index.js +32 -24
  46. package/src/exports/vite/static_analysis/index.js +2 -4
  47. package/src/exports/vite/static_analysis/types.d.ts +14 -0
  48. package/src/exports/vite/utils.js +40 -35
  49. package/src/runtime/app/env/internal.js +4 -4
  50. package/src/runtime/app/env/types.d.ts +1 -1
  51. package/src/runtime/app/environment/index.js +3 -3
  52. package/src/runtime/app/forms.js +24 -7
  53. package/src/runtime/app/paths/client.js +4 -10
  54. package/src/runtime/app/paths/internal/client.js +4 -2
  55. package/src/runtime/app/paths/internal/server.js +2 -23
  56. package/src/runtime/app/paths/public.d.ts +0 -28
  57. package/src/runtime/app/paths/server.js +10 -6
  58. package/src/runtime/app/server/index.js +1 -1
  59. package/src/runtime/app/server/remote/command.js +0 -3
  60. package/src/runtime/app/server/remote/form.js +27 -15
  61. package/src/runtime/app/server/remote/prerender.js +29 -36
  62. package/src/runtime/app/server/remote/query.js +101 -99
  63. package/src/runtime/app/server/remote/requested.js +22 -14
  64. package/src/runtime/app/server/remote/shared.js +30 -26
  65. package/src/runtime/app/state/client.js +1 -2
  66. package/src/runtime/app/stores.js +13 -76
  67. package/src/runtime/client/bundle.js +1 -1
  68. package/src/runtime/client/client-entry.js +3 -0
  69. package/src/runtime/client/client.js +411 -318
  70. package/src/runtime/client/entry.js +24 -3
  71. package/src/runtime/client/fetcher.js +3 -2
  72. package/src/runtime/client/ndjson.js +6 -33
  73. package/src/runtime/client/payload.js +17 -0
  74. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  75. package/src/runtime/client/remote-functions/command.svelte.js +7 -32
  76. package/src/runtime/client/remote-functions/form.svelte.js +183 -112
  77. package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
  78. package/src/runtime/client/remote-functions/query/index.js +7 -14
  79. package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
  80. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  81. package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
  82. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
  83. package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
  84. package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
  85. package/src/runtime/client/sse.js +32 -0
  86. package/src/runtime/client/state.svelte.js +65 -49
  87. package/src/runtime/client/stream.js +39 -0
  88. package/src/runtime/client/types.d.ts +11 -7
  89. package/src/runtime/client/utils.js +0 -96
  90. package/src/runtime/components/root.svelte +66 -0
  91. package/src/runtime/env/dynamic/private.js +7 -0
  92. package/src/runtime/env/dynamic/public.js +7 -0
  93. package/src/runtime/env/static/private.js +6 -0
  94. package/src/runtime/env/static/public.js +6 -0
  95. package/src/runtime/form-utils.js +100 -22
  96. package/src/runtime/server/cookie.js +69 -52
  97. package/src/runtime/server/csrf.js +65 -0
  98. package/src/runtime/server/data/index.js +15 -19
  99. package/src/runtime/server/env_module.js +0 -5
  100. package/src/runtime/server/errors.js +135 -0
  101. package/src/runtime/server/fetch.js +1 -1
  102. package/src/runtime/server/index.js +22 -12
  103. package/src/runtime/server/internal.js +25 -0
  104. package/src/runtime/server/page/actions.js +43 -27
  105. package/src/runtime/server/page/data_serializer.js +10 -10
  106. package/src/runtime/server/page/index.js +12 -17
  107. package/src/runtime/server/page/load_data.js +2 -2
  108. package/src/runtime/server/page/render.js +114 -193
  109. package/src/runtime/server/page/respond_with_error.js +11 -11
  110. package/src/runtime/server/page/server_routing.js +27 -18
  111. package/src/runtime/server/remote-functions.js +596 -0
  112. package/src/runtime/server/respond.js +100 -68
  113. package/src/runtime/server/sourcemaps.js +183 -0
  114. package/src/runtime/server/utils.js +2 -134
  115. package/src/runtime/shared.js +83 -13
  116. package/src/runtime/telemetry/otel.js +1 -1
  117. package/src/runtime/types.d.ts +8 -0
  118. package/src/types/ambient-private.d.ts +2 -0
  119. package/src/types/ambient.d.ts +10 -5
  120. package/src/types/global-private.d.ts +13 -25
  121. package/src/types/internal.d.ts +95 -80
  122. package/src/types/private.d.ts +41 -1
  123. package/src/utils/error.js +24 -4
  124. package/src/utils/escape.js +9 -25
  125. package/src/utils/features.js +1 -1
  126. package/src/utils/fork.js +7 -2
  127. package/src/utils/import.js +6 -1
  128. package/src/utils/imports.js +83 -0
  129. package/src/utils/mime.js +9 -0
  130. package/src/utils/page_nodes.js +3 -5
  131. package/src/utils/params.js +66 -0
  132. package/src/utils/routing.js +90 -44
  133. package/src/utils/shared-iterator.js +5 -0
  134. package/src/utils/streaming.js +14 -4
  135. package/src/utils/url.js +20 -2
  136. package/src/version.js +1 -1
  137. package/types/index.d.ts +537 -557
  138. package/types/index.d.ts.map +24 -39
  139. package/src/core/sync/write_root.js +0 -148
  140. package/src/exports/internal/server.js +0 -22
  141. package/src/runtime/server/remote.js +0 -457
  142. package/src/runtime/shared-server.js +0 -7
  143. package/src/types/synthetic/$lib.md +0 -5
  144. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -1,90 +1 @@
1
- /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
-
3
- export class HttpError {
4
- /**
5
- * @param {number} status
6
- * @param {{message: string} extends App.Error ? (App.Error | string | undefined) : App.Error} body
7
- */
8
- constructor(status, body) {
9
- this.status = status;
10
- if (typeof body === 'string') {
11
- this.body = { message: body };
12
- } else if (body) {
13
- this.body = body;
14
- } else {
15
- this.body = { message: `Error: ${status}` };
16
- }
17
- }
18
-
19
- toString() {
20
- return JSON.stringify(this.body);
21
- }
22
- }
23
-
24
- export class Redirect {
25
- /**
26
- * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
27
- * @param {string} location
28
- */
29
- constructor(status, location) {
30
- try {
31
- new Headers({ location });
32
- } catch {
33
- throw new Error(
34
- `Invalid redirect location ${JSON.stringify(location)}: ` +
35
- 'this string contains characters that cannot be used in HTTP headers'
36
- );
37
- }
38
-
39
- this.status = status;
40
- this.location = location;
41
- }
42
- }
43
-
44
- /**
45
- * An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
46
- * `SvelteKitError` goes through `handleError`.
47
- * @extends Error
48
- */
49
- export class SvelteKitError extends Error {
50
- /**
51
- * @param {number} status
52
- * @param {string} text
53
- * @param {string} message
54
- */
55
- constructor(status, text, message) {
56
- super(message);
57
- this.status = status;
58
- this.text = text;
59
- }
60
- }
61
-
62
- /**
63
- * @template [T=undefined]
64
- */
65
- export class ActionFailure {
66
- /**
67
- * @param {number} status
68
- * @param {T} data
69
- */
70
- constructor(status, data) {
71
- this.status = status;
72
- this.data = data;
73
- }
74
- }
75
-
76
- /**
77
- * Error thrown when form validation fails imperatively
78
- */
79
- export class ValidationError extends Error {
80
- /**
81
- * @param {StandardSchemaV1.Issue[]} issues
82
- */
83
- constructor(issues) {
84
- super('Validation failed');
85
- this.name = 'ValidationError';
86
- this.issues = issues;
87
- }
88
- }
89
-
90
- export { init_remote_functions } from './remote-functions.js';
1
+ export * from '#internal';
@@ -1,8 +1,7 @@
1
1
  /** @import { RequestEvent } from '@sveltejs/kit' */
2
2
  /** @import { RequestStore } from 'types' */
3
3
  /** @import { AsyncLocalStorage } from 'node:async_hooks' */
4
-
5
- import { IN_WEBCONTAINER } from '../../runtime/server/constants.js';
4
+ import { IN_WEBCONTAINER } from '../../../runtime/server/constants.js';
6
5
 
7
6
  /** @type {RequestStore | null} */
8
7
  let sync_store = null;
@@ -0,0 +1,33 @@
1
+ /** @import { Span } from '@opentelemetry/api' */
2
+ import { try_get_request_store } from './event.js';
3
+
4
+ export function get_origin() {
5
+ return try_get_request_store()?.event.url.origin;
6
+ }
7
+
8
+ /**
9
+ * @template {{ tracing: { enabled: boolean, root: Span, current: Span } }} T
10
+ * @param {T} event_like
11
+ * @param {Span} current
12
+ * @returns {T}
13
+ */
14
+ export function merge_tracing(event_like, current) {
15
+ return {
16
+ ...event_like,
17
+ tracing: {
18
+ ...event_like.tracing,
19
+ current
20
+ }
21
+ };
22
+ }
23
+
24
+ export {
25
+ with_request_store,
26
+ getRequestEvent,
27
+ get_request_store,
28
+ try_get_request_store
29
+ } from './event.js';
30
+
31
+ export { init_remote_functions } from './remote-functions.js';
32
+
33
+ export * from '../shared.js';
@@ -0,0 +1,89 @@
1
+ /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
2
+
3
+ export class HttpError {
4
+ /**
5
+ * @param {number} status
6
+ * @param {Omit<App.Error, 'status'> | string | undefined} body
7
+ * @param {Omit<App.Error, 'status' | 'message'>} [properties]
8
+ */
9
+ constructor(status, body, properties) {
10
+ this.status = status;
11
+ if (typeof body === 'string') {
12
+ this.body = { ...properties, message: body, status };
13
+ } else if (body) {
14
+ this.body = { ...body, status };
15
+ } else {
16
+ this.body = { message: `Error: ${status}`, status };
17
+ }
18
+ }
19
+
20
+ toString() {
21
+ return JSON.stringify(this.body);
22
+ }
23
+ }
24
+
25
+ export class Redirect {
26
+ /**
27
+ * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
28
+ * @param {string} location
29
+ */
30
+ constructor(status, location) {
31
+ try {
32
+ new Headers({ location });
33
+ } catch {
34
+ throw new Error(
35
+ `Invalid redirect location ${JSON.stringify(location)}: ` +
36
+ 'this string contains characters that cannot be used in HTTP headers'
37
+ );
38
+ }
39
+
40
+ this.status = status;
41
+ this.location = location;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
47
+ * `SvelteKitError` goes through `handleError`.
48
+ * @extends Error
49
+ */
50
+ export class SvelteKitError extends Error {
51
+ /**
52
+ * @param {number} status
53
+ * @param {string} text
54
+ * @param {string} message
55
+ */
56
+ constructor(status, text, message) {
57
+ super(message);
58
+ this.status = status;
59
+ this.text = text;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @template [T=undefined]
65
+ */
66
+ export class ActionFailure {
67
+ /**
68
+ * @param {number} status
69
+ * @param {T} data
70
+ */
71
+ constructor(status, data) {
72
+ this.status = status;
73
+ this.data = data;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Error thrown when form validation fails imperatively
79
+ */
80
+ export class ValidationError extends Error {
81
+ /**
82
+ * @param {StandardSchemaV1.Issue[]} issues
83
+ */
84
+ constructor(issues) {
85
+ super('Validation failed');
86
+ this.name = 'ValidationError';
87
+ this.issues = issues;
88
+ }
89
+ }
@@ -1,8 +1,11 @@
1
1
  import { createReadStream } from 'node:fs';
2
2
  import { Readable } from 'node:stream';
3
- import { SvelteKitError } from '../internal/index.js';
3
+ import { SvelteKitError } from '../internal/shared.js';
4
4
  import { noop } from '../../utils/functions.js';
5
5
 
6
+ /** @type {WeakMap<import('http').IncomingMessage, (chunk: Buffer) => void>} */
7
+ const body_data_listeners = new WeakMap();
8
+
6
9
  /**
7
10
  * @param {import('http').IncomingMessage} req
8
11
  * @param {number} [body_size_limit]
@@ -47,17 +50,19 @@ function get_raw_body(req, body_size_limit) {
47
50
  return;
48
51
  }
49
52
 
50
- req.on('error', (error) => {
53
+ /** @param {Error} error */
54
+ const on_error = (error) => {
51
55
  cancelled = true;
52
56
  controller.error(error);
53
- });
57
+ };
54
58
 
55
- req.on('end', () => {
59
+ const on_end = () => {
56
60
  if (cancelled) return;
57
61
  controller.close();
58
- });
62
+ };
59
63
 
60
- req.on('data', (chunk) => {
64
+ /** @param {Buffer} chunk */
65
+ const on_data = (chunk) => {
61
66
  if (cancelled) return;
62
67
 
63
68
  size += chunk.length;
@@ -89,7 +94,12 @@ function get_raw_body(req, body_size_limit) {
89
94
  if (controller.desiredSize === null || controller.desiredSize <= 0) {
90
95
  req.pause();
91
96
  }
92
- });
97
+ };
98
+
99
+ req.on('error', on_error);
100
+ req.on('end', on_end);
101
+ req.on('data', on_data);
102
+ body_data_listeners.set(req, on_data);
93
103
  },
94
104
 
95
105
  pull() {
@@ -109,11 +119,9 @@ function get_raw_body(req, body_size_limit) {
109
119
  * base: string;
110
120
  * bodySizeLimit?: number;
111
121
  * }} options
112
- * @returns {Promise<Request>}
122
+ * @returns {Request}
113
123
  */
114
- // TODO 3.0 make the signature synchronous?
115
- // eslint-disable-next-line @typescript-eslint/require-await
116
- export async function getRequest({ request, base, bodySizeLimit }) {
124
+ export function getRequest({ request, base, bodySizeLimit }) {
117
125
  let headers = /** @type {Record<string, string>} */ (request.headers);
118
126
  if (request.httpVersionMajor >= 2) {
119
127
  // the Request constructor rejects headers with ':' in the name
@@ -154,14 +162,53 @@ export async function getRequest({ request, base, bodySizeLimit }) {
154
162
  });
155
163
  }
156
164
 
165
+ /**
166
+ * Drains any unconsumed request body once the response has been sent. When a
167
+ * route doesn't read the request body (for example a page route receiving a
168
+ * POST), the unread bytes remain buffered in the socket. On keep-alive
169
+ * connections Node's HTTP parser then reads those leftover bytes as the next
170
+ * request, fails to parse them, and resets the connection — losing any
171
+ * pipelined request. Resuming the request discards the bytes so the connection
172
+ * stays usable.
173
+ *
174
+ * Because `get_raw_body` attaches a `data` listener, Node marks the request as
175
+ * being consumed (`req._consuming`) and skips its own automatic drain, so we
176
+ * have to do it ourselves. The whole remaining body is read and discarded; this
177
+ * is the intended trade-off (keeping the connection reusable) over destroying it.
178
+ * @see https://github.com/sveltejs/kit/issues/14916
179
+ * @see https://github.com/sveltejs/kit/issues/15526
180
+ * @param {import('http').ServerResponse} res
181
+ */
182
+ function drain_request(res) {
183
+ const req = res.req;
184
+ if (!req || req.readableEnded || req.destroyed) return;
185
+
186
+ // When the body went unread, get_raw_body's `data` listener is still attached
187
+ // and enqueues into a ReadableStream nobody consumes; it pauses the request at
188
+ // the high water mark, so one chunk sits in memory and the rest stays buffered
189
+ // in the socket. Remove only that `data` listener so the resumed stream drops
190
+ // the remaining bytes instead of re-buffering them. The `end` and `error`
191
+ // listeners stay attached so the body's ReadableStream is still closed (or
192
+ // errored) once draining completes, and a consumer that stopped reading
193
+ // mid-body sees a clean end instead of hanging.
194
+ const on_data = body_data_listeners.get(req);
195
+ if (on_data) {
196
+ req.removeListener('data', on_data);
197
+ body_data_listeners.delete(req);
198
+ }
199
+
200
+ req.resume();
201
+ }
202
+
157
203
  /**
158
204
  * @param {import('http').ServerResponse} res
159
205
  * @param {Response} response
160
- * @returns {Promise<void>}
206
+ * @returns {void}
161
207
  */
162
- // TODO 3.0 make the signature synchronous?
163
- // eslint-disable-next-line @typescript-eslint/require-await
164
- export async function setResponse(res, response) {
208
+ export function setResponse(res, response) {
209
+ res.once('finish', () => drain_request(res));
210
+ res.once('close', () => drain_request(res));
211
+
165
212
  for (const [key, value] of response.headers) {
166
213
  try {
167
214
  res.setHeader(key, key === 'set-cookie' ? response.headers.getSetCookie() : value);
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Define [parameter matchers](https://svelte.dev/docs/kit/advanced-routing#Matching) for your app.
3
+ *
4
+ * @example
5
+ * ```js
6
+ * import { defineParams } from '@sveltejs/kit';
7
+ * import * as v from 'valibot';
8
+ *
9
+ * export const params = defineParams({
10
+ * locale: (param) => {
11
+ * if (param !== 'de' && param !== 'en') return;
12
+ * return param;
13
+ * },
14
+ * number: v.pipe(v.string(), v.toNumber())
15
+ * });
16
+ * ```
17
+ *
18
+ * @template {Record<string, import('./public.js').ParamDefinition>} T
19
+ * @param {T} definitions
20
+ * @returns {import('./public.js').DefinedParams<T>}
21
+ */
22
+ export function defineParams(definitions) {
23
+ /** @type {Record<string, import('./public.js').ParamMatcher>} */
24
+ const matchers = {};
25
+
26
+ for (const [key, definition] of Object.entries(definitions)) {
27
+ matchers[key] = normalize_param_definition(definition);
28
+ }
29
+
30
+ return /** @type {import('./public.js').DefinedParams<T>} */ (matchers);
31
+ }
32
+
33
+ /**
34
+ * @param {import('@sveltejs/kit').ParamDefinition} definition
35
+ * @returns {import('@sveltejs/kit').ParamMatcher}
36
+ */
37
+ export function normalize_param_definition(definition) {
38
+ // standard schemas can be callable (e.g. ArkType), so this must be checked before the function case
39
+ if (
40
+ definition &&
41
+ (typeof definition === 'object' || typeof definition === 'function') &&
42
+ '~standard' in definition
43
+ ) {
44
+ return definition;
45
+ }
46
+
47
+ if (typeof definition === 'function') {
48
+ return /** @type {import('@sveltejs/kit').ParamMatcher} */ (
49
+ /** @type {unknown} */ ({
50
+ '~standard': {
51
+ validate(/** @type {unknown} */ value) {
52
+ const result = definition(/** @type {string} */ (value));
53
+
54
+ if (result === undefined) {
55
+ return { issues: [{ message: 'Invalid param' }] };
56
+ }
57
+
58
+ if (/** @type {any} */ (result) instanceof Promise) return result; // will be validated and rejected upstream
59
+
60
+ return { value: result };
61
+ }
62
+ }
63
+ })
64
+ );
65
+ }
66
+
67
+ throw new Error('Invalid param definition');
68
+ }