@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.
Files changed (127) hide show
  1. package/package.json +33 -21
  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 +132 -71
  5. package/src/core/config/options.js +294 -244
  6. package/src/core/config/types.d.ts +1 -1
  7. package/src/core/env.js +121 -5
  8. package/src/core/generate_manifest/index.js +12 -15
  9. package/src/core/postbuild/analyse.js +7 -19
  10. package/src/core/postbuild/crawl.js +22 -6
  11. package/src/core/postbuild/prerender.js +42 -23
  12. package/src/core/sync/create_manifest_data/index.js +53 -50
  13. package/src/core/sync/sync.js +0 -2
  14. package/src/core/sync/write_client_manifest.js +8 -15
  15. package/src/core/sync/write_env.js +2 -1
  16. package/src/core/sync/write_non_ambient.js +12 -9
  17. package/src/core/sync/write_server.js +13 -14
  18. package/src/core/sync/write_tsconfig.js +16 -8
  19. package/src/core/sync/write_tsconfig_test/package.json +7 -0
  20. package/src/core/sync/write_types/index.js +28 -24
  21. package/src/core/utils.js +2 -2
  22. package/src/exports/env/index.js +12 -0
  23. package/src/exports/hooks/index.js +3 -9
  24. package/src/exports/hooks/sequence.js +3 -2
  25. package/src/exports/index.js +35 -13
  26. package/src/exports/internal/client.js +5 -0
  27. package/src/exports/internal/env.js +2 -2
  28. package/src/exports/internal/index.js +1 -90
  29. package/src/exports/internal/{event.js → server/event.js} +1 -2
  30. package/src/exports/internal/server/index.js +33 -0
  31. package/src/exports/internal/shared.js +89 -0
  32. package/src/exports/node/index.js +62 -15
  33. package/src/exports/params.js +63 -0
  34. package/src/exports/public.d.ts +323 -170
  35. package/src/exports/url.js +86 -0
  36. package/src/exports/vite/build/build_server.js +53 -59
  37. package/src/exports/vite/build/remote.js +18 -11
  38. package/src/exports/vite/build/utils.js +0 -8
  39. package/src/exports/vite/dev/index.js +42 -44
  40. package/src/exports/vite/index.js +810 -593
  41. package/src/exports/vite/preview/index.js +29 -22
  42. package/src/exports/vite/static_analysis/index.js +2 -4
  43. package/src/exports/vite/static_analysis/types.d.ts +14 -0
  44. package/src/exports/vite/utils.js +21 -36
  45. package/src/runtime/app/env/internal.js +4 -4
  46. package/src/runtime/app/env/types.d.ts +1 -1
  47. package/src/runtime/app/environment/index.js +6 -0
  48. package/src/runtime/app/forms.js +24 -7
  49. package/src/runtime/app/paths/client.js +4 -10
  50. package/src/runtime/app/paths/internal/client.js +4 -2
  51. package/src/runtime/app/paths/internal/server.js +2 -23
  52. package/src/runtime/app/paths/public.d.ts +0 -28
  53. package/src/runtime/app/paths/server.js +9 -5
  54. package/src/runtime/app/server/remote/command.js +0 -3
  55. package/src/runtime/app/server/remote/form.js +27 -15
  56. package/src/runtime/app/server/remote/prerender.js +29 -36
  57. package/src/runtime/app/server/remote/query.js +101 -99
  58. package/src/runtime/app/server/remote/requested.js +22 -14
  59. package/src/runtime/app/server/remote/shared.js +30 -26
  60. package/src/runtime/app/state/client.js +1 -2
  61. package/src/runtime/app/stores.js +13 -76
  62. package/src/runtime/client/bundle.js +1 -1
  63. package/src/runtime/client/client-entry.js +3 -0
  64. package/src/runtime/client/client.js +411 -318
  65. package/src/runtime/client/entry.js +24 -3
  66. package/src/runtime/client/fetcher.js +3 -2
  67. package/src/runtime/client/ndjson.js +6 -33
  68. package/src/runtime/client/payload.js +17 -0
  69. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  70. package/src/runtime/client/remote-functions/command.svelte.js +7 -32
  71. package/src/runtime/client/remote-functions/form.svelte.js +183 -112
  72. package/src/runtime/client/remote-functions/prerender.svelte.js +29 -8
  73. package/src/runtime/client/remote-functions/query/index.js +7 -14
  74. package/src/runtime/client/remote-functions/query/instance.svelte.js +63 -18
  75. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  76. package/src/runtime/client/remote-functions/query-batch.svelte.js +60 -68
  77. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +60 -18
  78. package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
  79. package/src/runtime/client/remote-functions/shared.svelte.js +88 -62
  80. package/src/runtime/client/sse.js +32 -0
  81. package/src/runtime/client/state.svelte.js +65 -49
  82. package/src/runtime/client/stream.js +38 -0
  83. package/src/runtime/client/types.d.ts +11 -7
  84. package/src/runtime/client/utils.js +0 -96
  85. package/src/runtime/components/root.svelte +66 -0
  86. package/src/runtime/env/dynamic/private.js +7 -0
  87. package/src/runtime/env/dynamic/public.js +7 -0
  88. package/src/runtime/env/static/private.js +6 -0
  89. package/src/runtime/env/static/public.js +6 -0
  90. package/src/runtime/form-utils.js +100 -22
  91. package/src/runtime/server/cookie.js +69 -52
  92. package/src/runtime/server/csrf.js +65 -0
  93. package/src/runtime/server/data/index.js +14 -18
  94. package/src/runtime/server/env_module.js +0 -5
  95. package/src/runtime/server/index.js +2 -2
  96. package/src/runtime/server/page/actions.js +41 -26
  97. package/src/runtime/server/page/index.js +9 -15
  98. package/src/runtime/server/page/load_data.js +1 -1
  99. package/src/runtime/server/page/render.js +112 -187
  100. package/src/runtime/server/page/respond_with_error.js +7 -8
  101. package/src/runtime/server/page/server_routing.js +27 -18
  102. package/src/runtime/server/remote.js +355 -216
  103. package/src/runtime/server/respond.js +97 -61
  104. package/src/runtime/server/utils.js +32 -9
  105. package/src/runtime/shared.js +83 -13
  106. package/src/runtime/telemetry/otel.js +1 -1
  107. package/src/runtime/types.d.ts +8 -0
  108. package/src/types/ambient.d.ts +10 -5
  109. package/src/types/global-private.d.ts +15 -22
  110. package/src/types/internal.d.ts +89 -74
  111. package/src/types/private.d.ts +33 -1
  112. package/src/utils/error.js +24 -4
  113. package/src/utils/import.js +6 -1
  114. package/src/utils/imports.js +83 -0
  115. package/src/utils/mime.js +9 -0
  116. package/src/utils/params.js +66 -0
  117. package/src/utils/routing.js +90 -44
  118. package/src/utils/shared-iterator.js +5 -0
  119. package/src/utils/streaming.js +14 -4
  120. package/src/utils/url.js +20 -2
  121. package/src/version.js +1 -1
  122. package/types/index.d.ts +467 -537
  123. package/types/index.d.ts.map +22 -39
  124. package/src/core/sync/write_root.js +0 -148
  125. package/src/exports/internal/server.js +0 -22
  126. package/src/types/synthetic/$lib.md +0 -5
  127. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -1,7 +1,6 @@
1
1
  import { BROWSER } from 'esm-env';
2
- import { decode_params } from './url.js';
3
2
 
4
- const param_pattern = /^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;
3
+ const param_pattern = /^(\[)?(\.\.\.)?([\w-]+)(?:=([\w-]+))?(\])?$/;
5
4
 
6
5
  const root_group_pattern = /^\/\((?:[^)]+)\)$/;
7
6
 
@@ -20,7 +19,7 @@ export function parse_route_id(id) {
20
19
  `^${get_route_segments(id)
21
20
  .map((segment) => {
22
21
  // special case — /[...rest]/ could contain zero segments
23
- const rest_match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment);
22
+ const rest_match = /^\[\.\.\.([\w-]+)(?:=([\w-]+))?\]$/.exec(segment);
24
23
  if (rest_match) {
25
24
  params.push({
26
25
  name: rest_match[1],
@@ -32,7 +31,7 @@ export function parse_route_id(id) {
32
31
  return '(?:/([^]*))?';
33
32
  }
34
33
  // special case — /[[optional]]/ could contain zero segments
35
- const optional_match = /^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(segment);
34
+ const optional_match = /^\[\[([\w-]+)(?:=([\w-]+))?\]\]$/.exec(segment);
36
35
  if (optional_match) {
37
36
  params.push({
38
37
  name: optional_match[1],
@@ -73,7 +72,7 @@ export function parse_route_id(id) {
73
72
  const match = /** @type {RegExpExecArray} */ (param_pattern.exec(content));
74
73
  if (!BROWSER && !match) {
75
74
  throw new Error(
76
- `Invalid param: ${content}. Params and matcher names can only have underscores and alphanumeric characters.`
75
+ `Invalid param: ${content}. Params and matcher names can only have underscores, hyphens, and alphanumeric characters.`
77
76
  );
78
77
  }
79
78
 
@@ -104,7 +103,7 @@ export function parse_route_id(id) {
104
103
  return { pattern, params };
105
104
  }
106
105
 
107
- const optional_param_regex = /\/\[\[\w+?(?:=\w+)?\]\]/;
106
+ const optional_param_regex = /\/\[\[[\w-]+?(?:=[\w-]+)?\]\]/;
108
107
 
109
108
  /**
110
109
  * Removes optional params from a route ID.
@@ -134,13 +133,43 @@ export function get_route_segments(route) {
134
133
  return route.slice(1).split('/').filter(affects_path);
135
134
  }
136
135
 
136
+ /**
137
+ * @param {import('@sveltejs/kit').ParamMatcher} matcher
138
+ * @param {string} value
139
+ * @returns {{ success: true, value: any } | { success: false }}
140
+ */
141
+ function run_matcher(matcher, value) {
142
+ const result = matcher['~standard'].validate(value);
143
+
144
+ if (result instanceof Promise) {
145
+ throw new Error('Async param matchers are not supported');
146
+ }
147
+
148
+ if (result.issues) {
149
+ return { success: false };
150
+ }
151
+
152
+ const parsed = result.value;
153
+
154
+ if (
155
+ typeof parsed !== 'string' &&
156
+ typeof parsed !== 'number' &&
157
+ typeof parsed !== 'boolean' &&
158
+ typeof parsed !== 'bigint'
159
+ ) {
160
+ throw new Error('Param matcher must return a string, number, boolean, or bigint');
161
+ }
162
+
163
+ return { success: true, value: parsed };
164
+ }
165
+
137
166
  /**
138
167
  * @param {RegExpMatchArray} match
139
168
  * @param {import('types').RouteParam[]} params
140
169
  * @param {Record<string, import('@sveltejs/kit').ParamMatcher>} matchers
141
170
  */
142
171
  export function exec(match, params, matchers) {
143
- /** @type {Record<string, string>} */
172
+ /** @type {Record<string, any>} */
144
173
  const result = {};
145
174
 
146
175
  const values = match.slice(1);
@@ -173,37 +202,41 @@ export function exec(match, params, matchers) {
173
202
  }
174
203
  }
175
204
 
176
- if (!param.matcher || matchers[param.matcher](value)) {
177
- result[param.name] = value;
205
+ const decoded = decodeURIComponent(value);
178
206
 
179
- // Now that the params match, reset the buffer if the next param isn't the [...rest]
180
- // and the next value is defined, otherwise the buffer will cause us to skip values
181
- const next_param = params[i + 1];
182
- const next_value = values[i + 1];
183
- if (next_param && !next_param.rest && next_param.optional && next_value && param.chained) {
184
- buffered = 0;
185
- }
207
+ if (param.matcher) {
208
+ const outcome = run_matcher(matchers[param.matcher], decoded);
209
+
210
+ if (!outcome.success) {
211
+ // in the `/[[a=b]]/...` case, if the value didn't satisfy the matcher,
212
+ // keep track of the number of skipped optional parameters and continue
213
+ if (param.optional && param.chained) {
214
+ buffered++;
215
+ continue;
216
+ }
186
217
 
187
- // There are no more params and no more values, but all non-empty values have been matched
188
- if (
189
- !next_param &&
190
- !next_value &&
191
- Object.keys(result).length === values_needing_match.length
192
- ) {
193
- buffered = 0;
218
+ // otherwise, if the matcher returns `false`, the route did not match
219
+ return;
194
220
  }
195
- continue;
221
+
222
+ result[param.name] = outcome.value;
223
+ } else {
224
+ result[param.name] = decoded;
196
225
  }
197
226
 
198
- // in the `/[[a=b]]/...` case, if the value didn't satisfy the matcher,
199
- // keep track of the number of skipped optional parameters and continue
200
- if (param.optional && param.chained) {
201
- buffered++;
202
- continue;
227
+ // Now that the params match, reset the buffer if the next param isn't the [...rest]
228
+ // and the next value is defined, otherwise the buffer will cause us to skip values
229
+ const next_param = params[i + 1];
230
+ const next_value = values[i + 1];
231
+ if (next_param && !next_param.rest && next_param.optional && next_value && param.chained) {
232
+ buffered = 0;
203
233
  }
204
234
 
205
- // otherwise, if the matcher returns `false`, the route did not match
206
- return;
235
+ // There are no more params and no more values, but all non-empty values have been matched
236
+ if (!next_param && !next_value && Object.keys(result).length === values_needing_match.length) {
237
+ buffered = 0;
238
+ }
239
+ continue;
207
240
  }
208
241
 
209
242
  if (buffered) return;
@@ -227,7 +260,7 @@ function escape(str) {
227
260
  );
228
261
  }
229
262
 
230
- const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
263
+ const basic_param_pattern = /\[(\[)?(\.\.\.)?([\w-]+?)(?:=([\w-]+))?\]\]?/g;
231
264
 
232
265
  /**
233
266
  * Populate a route ID with params to resolve a pathname.
@@ -242,7 +275,7 @@ const basic_param_pattern = /\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;
242
275
  * ); // `/blog/hello-world/something/else`
243
276
  * ```
244
277
  * @param {string} id
245
- * @param {Record<string, string | undefined>} params
278
+ * @param {Record<string, import('@sveltejs/kit').ParamValue | undefined>} params
246
279
  * @returns {string}
247
280
  */
248
281
  export function resolve_route(id, params) {
@@ -254,20 +287,33 @@ export function resolve_route(id, params) {
254
287
  segments
255
288
  .map((segment) =>
256
289
  segment.replace(basic_param_pattern, (_, optional, rest, name) => {
257
- const param_value = params[name];
290
+ const value = params[name];
258
291
 
259
- // This is nested so TS correctly narrows the type
260
- if (!param_value) {
292
+ if (value === undefined || value === '') {
261
293
  if (optional) return '';
262
- if (rest && param_value !== undefined) return '';
294
+ if (rest && value !== undefined) return '';
263
295
  throw new Error(`Missing parameter '${name}' in route ${id}`);
264
296
  }
265
297
 
266
- if (param_value.startsWith('/') || param_value.endsWith('/'))
267
- throw new Error(
268
- `Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
269
- );
270
- return param_value;
298
+ if (typeof value === 'string') {
299
+ if (value.startsWith('/') || value.endsWith('/')) {
300
+ throw new Error(
301
+ `Parameter '${name}' in route ${id} cannot start or end with a slash -- this would cause an invalid route like foo//bar`
302
+ );
303
+ }
304
+
305
+ return value;
306
+ }
307
+
308
+ if (
309
+ typeof value === 'number' ||
310
+ typeof value === 'boolean' ||
311
+ typeof value === 'bigint'
312
+ ) {
313
+ return String(value);
314
+ }
315
+
316
+ throw new Error('Parameter values must be a string, number, boolean, or bigint');
271
317
  })
272
318
  )
273
319
  .filter(Boolean)
@@ -290,7 +336,7 @@ export function has_server_load(node) {
290
336
  * @param {string} path - The decoded pathname to match
291
337
  * @param {Route[]} routes
292
338
  * @param {Record<string, import('@sveltejs/kit').ParamMatcher>} matchers
293
- * @returns {{ route: Route, params: Record<string, string> } | null}
339
+ * @returns {{ route: Route, params: Record<string, any> } | null}
294
340
  */
295
341
  export function find_route(path, routes, matchers) {
296
342
  for (const route of routes) {
@@ -301,7 +347,7 @@ export function find_route(path, routes, matchers) {
301
347
  if (matched) {
302
348
  return {
303
349
  route,
304
- params: decode_params(matched)
350
+ params: matched
305
351
  };
306
352
  }
307
353
  }
@@ -52,6 +52,11 @@ export class SharedIterator {
52
52
  /** @type {unknown} */
53
53
  #terminal_error = undefined;
54
54
 
55
+ /** Whether `done()` or `fail()` has been broadcast. */
56
+ get closed() {
57
+ return this.#closed;
58
+ }
59
+
55
60
  /**
56
61
  * @param {(instance: SharedIterator<T>) => (() => void)} [start]
57
62
  */
@@ -1,3 +1,5 @@
1
+ import { noop } from './functions.js';
2
+
1
3
  /**
2
4
  * Create an async iterator and a function to push values into it
3
5
  * @template T
@@ -30,10 +32,18 @@ export function create_async_iterator() {
30
32
  };
31
33
  },
32
34
  add: (promise) => {
33
- deferred.push(Promise.withResolvers());
34
- void promise.then((value) => {
35
- deferred[++resolved].resolve(value);
36
- });
35
+ const next = Promise.withResolvers();
36
+ void next.promise.catch(noop); // prevent unhandled rejection potentially crashing the process
37
+ deferred.push(next);
38
+
39
+ void promise.then(
40
+ (value) => {
41
+ deferred[++resolved].resolve(value);
42
+ },
43
+ (error) => {
44
+ deferred[++resolved].reject(error);
45
+ }
46
+ );
37
47
  }
38
48
  };
39
49
  }
package/src/utils/url.js CHANGED
@@ -4,7 +4,7 @@ import { BROWSER, DEV } from 'esm-env';
4
4
  * Matches a URI scheme. See https://www.rfc-editor.org/rfc/rfc3986#section-3.1
5
5
  * @type {RegExp}
6
6
  */
7
- export const SCHEME = /^[a-z][a-z\d+\-.]+:/i;
7
+ export const SCHEME = /^[a-z][a-z\d+\-.]*:/i;
8
8
 
9
9
  const internal = new URL('a://');
10
10
 
@@ -27,6 +27,24 @@ export function is_root_relative(path) {
27
27
  return path[0] === '/' && path[1] !== '/';
28
28
  }
29
29
 
30
+ /**
31
+ * @param {string} location
32
+ * @param {string} allowed
33
+ */
34
+ export function matches_external_allowlist_entry(location, allowed) {
35
+ if (location === allowed) return true;
36
+
37
+ try {
38
+ const allow = new URL(allowed);
39
+ const loc = new URL(location, allow);
40
+
41
+ // this is stricter than `loc.origin === allow.origin`, which can fail in `blob:` cases
42
+ return loc.protocol === allow.protocol && loc.host === allow.host;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+
30
48
  /**
31
49
  * @param {string} path
32
50
  * @param {import('types').TrailingSlash} trailing_slash
@@ -119,6 +137,7 @@ export function make_trackable(url, callback, search_params_callback, allow_hash
119
137
  /**
120
138
  * URL properties that could change during the lifetime of the page,
121
139
  * which excludes things like `origin`
140
+ * @type {(keyof URL)[]}
122
141
  */
123
142
  const tracked_url_properties = ['href', 'pathname', 'search', 'toString', 'toJSON'];
124
143
  if (allow_hash) tracked_url_properties.push('hash');
@@ -127,7 +146,6 @@ export function make_trackable(url, callback, search_params_callback, allow_hash
127
146
  Object.defineProperty(tracked, property, {
128
147
  get() {
129
148
  callback();
130
- // @ts-expect-error
131
149
  return url[property];
132
150
  },
133
151
 
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.0';
4
+ export const VERSION = '3.0.0-next.10';