@sveltejs/kit 3.0.0-next.4 → 3.0.0-next.7

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 (91) hide show
  1. package/package.json +23 -18
  2. package/src/core/adapt/builder.js +29 -43
  3. package/src/core/adapt/index.js +1 -4
  4. package/src/core/config/index.js +135 -71
  5. package/src/core/config/options.js +291 -244
  6. package/src/core/config/types.d.ts +1 -1
  7. package/src/core/env.js +120 -5
  8. package/src/core/generate_manifest/index.js +12 -15
  9. package/src/core/postbuild/analyse.js +8 -12
  10. package/src/core/postbuild/crawl.js +22 -6
  11. package/src/core/postbuild/prerender.js +40 -23
  12. package/src/core/sync/create_manifest_data/index.js +29 -49
  13. package/src/core/sync/write_client_manifest.js +14 -14
  14. package/src/core/sync/write_non_ambient.js +10 -7
  15. package/src/core/sync/write_root.js +9 -30
  16. package/src/core/sync/write_server.js +13 -11
  17. package/src/core/sync/write_tsconfig.js +2 -4
  18. package/src/core/sync/write_types/index.js +11 -10
  19. package/src/exports/index.js +34 -12
  20. package/src/exports/internal/client.js +5 -0
  21. package/src/exports/internal/env.js +1 -1
  22. package/src/exports/internal/index.js +1 -90
  23. package/src/exports/internal/{event.js → server/event.js} +1 -2
  24. package/src/exports/internal/server/index.js +33 -0
  25. package/src/exports/internal/shared.js +89 -0
  26. package/src/exports/node/index.js +58 -7
  27. package/src/exports/params.js +63 -0
  28. package/src/exports/public.d.ts +299 -145
  29. package/src/exports/url.js +84 -0
  30. package/src/exports/vite/build/build_server.js +6 -1
  31. package/src/exports/vite/dev/index.js +38 -37
  32. package/src/exports/vite/index.js +498 -353
  33. package/src/exports/vite/preview/index.js +16 -8
  34. package/src/exports/vite/utils.js +7 -11
  35. package/src/runtime/app/env/types.d.ts +1 -1
  36. package/src/runtime/app/forms.js +22 -5
  37. package/src/runtime/app/paths/client.js +4 -10
  38. package/src/runtime/app/paths/public.d.ts +0 -28
  39. package/src/runtime/app/paths/server.js +8 -4
  40. package/src/runtime/app/server/remote/form.js +10 -3
  41. package/src/runtime/app/server/remote/query.js +9 -18
  42. package/src/runtime/app/server/remote/requested.js +8 -4
  43. package/src/runtime/app/server/remote/shared.js +5 -7
  44. package/src/runtime/app/state/client.js +1 -2
  45. package/src/runtime/app/stores.js +13 -76
  46. package/src/runtime/client/client.js +205 -167
  47. package/src/runtime/client/fetcher.js +3 -2
  48. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  49. package/src/runtime/client/remote-functions/form.svelte.js +122 -31
  50. package/src/runtime/client/remote-functions/prerender.svelte.js +17 -4
  51. package/src/runtime/client/remote-functions/query/index.js +3 -2
  52. package/src/runtime/client/remote-functions/query/instance.svelte.js +27 -11
  53. package/src/runtime/client/remote-functions/query-batch.svelte.js +4 -3
  54. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +42 -15
  55. package/src/runtime/client/remote-functions/shared.svelte.js +18 -9
  56. package/src/runtime/client/state.svelte.js +66 -49
  57. package/src/runtime/client/types.d.ts +10 -2
  58. package/src/runtime/client/utils.js +0 -96
  59. package/src/runtime/form-utils.js +99 -18
  60. package/src/runtime/server/cookie.js +22 -33
  61. package/src/runtime/server/csrf.js +65 -0
  62. package/src/runtime/server/data/index.js +7 -7
  63. package/src/runtime/server/env_module.js +0 -5
  64. package/src/runtime/server/index.js +2 -2
  65. package/src/runtime/server/page/actions.js +41 -26
  66. package/src/runtime/server/page/index.js +2 -1
  67. package/src/runtime/server/page/load_data.js +1 -1
  68. package/src/runtime/server/page/render.js +36 -47
  69. package/src/runtime/server/page/respond_with_error.js +7 -8
  70. package/src/runtime/server/page/server_routing.js +13 -9
  71. package/src/runtime/server/remote.js +85 -39
  72. package/src/runtime/server/respond.js +92 -58
  73. package/src/runtime/server/utils.js +7 -7
  74. package/src/runtime/telemetry/otel.js +1 -1
  75. package/src/types/ambient.d.ts +10 -5
  76. package/src/types/global-private.d.ts +4 -4
  77. package/src/types/internal.d.ts +17 -20
  78. package/src/types/private.d.ts +33 -1
  79. package/src/types/synthetic/$lib.md +1 -1
  80. package/src/utils/error.js +12 -4
  81. package/src/utils/mime.js +9 -0
  82. package/src/utils/params.js +66 -0
  83. package/src/utils/routing.js +84 -38
  84. package/src/utils/shared-iterator.js +5 -0
  85. package/src/utils/streaming.js +14 -4
  86. package/src/utils/url.js +20 -2
  87. package/src/version.js +1 -1
  88. package/types/index.d.ts +434 -269
  89. package/types/index.d.ts.map +19 -15
  90. package/src/exports/internal/server.js +0 -22
  91. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -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() {
@@ -154,6 +164,44 @@ export async function getRequest({ request, base, bodySizeLimit }) {
154
164
  });
155
165
  }
156
166
 
167
+ /**
168
+ * Drains any unconsumed request body once the response has been sent. When a
169
+ * route doesn't read the request body (for example a page route receiving a
170
+ * POST), the unread bytes remain buffered in the socket. On keep-alive
171
+ * connections Node's HTTP parser then reads those leftover bytes as the next
172
+ * request, fails to parse them, and resets the connection — losing any
173
+ * pipelined request. Resuming the request discards the bytes so the connection
174
+ * stays usable.
175
+ *
176
+ * Because `get_raw_body` attaches a `data` listener, Node marks the request as
177
+ * being consumed (`req._consuming`) and skips its own automatic drain, so we
178
+ * have to do it ourselves. The whole remaining body is read and discarded; this
179
+ * is the intended trade-off (keeping the connection reusable) over destroying it.
180
+ * @see https://github.com/sveltejs/kit/issues/14916
181
+ * @see https://github.com/sveltejs/kit/issues/15526
182
+ * @param {import('http').ServerResponse} res
183
+ */
184
+ function drain_request(res) {
185
+ const req = res.req;
186
+ if (!req || req.readableEnded || req.destroyed) return;
187
+
188
+ // When the body went unread, get_raw_body's `data` listener is still attached
189
+ // and enqueues into a ReadableStream nobody consumes; it pauses the request at
190
+ // the high water mark, so one chunk sits in memory and the rest stays buffered
191
+ // in the socket. Remove only that `data` listener so the resumed stream drops
192
+ // the remaining bytes instead of re-buffering them. The `end` and `error`
193
+ // listeners stay attached so the body's ReadableStream is still closed (or
194
+ // errored) once draining completes, and a consumer that stopped reading
195
+ // mid-body sees a clean end instead of hanging.
196
+ const on_data = body_data_listeners.get(req);
197
+ if (on_data) {
198
+ req.removeListener('data', on_data);
199
+ body_data_listeners.delete(req);
200
+ }
201
+
202
+ req.resume();
203
+ }
204
+
157
205
  /**
158
206
  * @param {import('http').ServerResponse} res
159
207
  * @param {Response} response
@@ -162,6 +210,9 @@ export async function getRequest({ request, base, bodySizeLimit }) {
162
210
  // TODO 3.0 make the signature synchronous?
163
211
  // eslint-disable-next-line @typescript-eslint/require-await
164
212
  export async function setResponse(res, response) {
213
+ res.once('finish', () => drain_request(res));
214
+ res.once('close', () => drain_request(res));
215
+
165
216
  for (const [key, value] of response.headers) {
166
217
  try {
167
218
  res.setHeader(key, key === 'set-cookie' ? response.headers.getSetCookie() : value);
@@ -0,0 +1,63 @@
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
+ if (typeof definition === 'function') {
39
+ return /** @type {import('@sveltejs/kit').ParamMatcher} */ (
40
+ /** @type {unknown} */ ({
41
+ '~standard': {
42
+ validate(/** @type {unknown} */ value) {
43
+ const result = definition(/** @type {string} */ (value));
44
+
45
+ if (result === undefined) {
46
+ return { issues: [{ message: 'Invalid param' }] };
47
+ }
48
+
49
+ if (/** @type {any} */ (result) instanceof Promise) return result; // will be validated and rejected upstream
50
+
51
+ return { value: result };
52
+ }
53
+ }
54
+ })
55
+ );
56
+ }
57
+
58
+ if (definition && typeof definition === 'object' && '~standard' in definition) {
59
+ return definition;
60
+ }
61
+
62
+ throw new Error('Invalid param definition');
63
+ }