@sveltejs/kit 3.0.0-next.13 → 3.0.0-next.16

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 (86) hide show
  1. package/package.json +7 -4
  2. package/src/cli.js +8 -5
  3. package/src/core/adapt/builder.js +20 -10
  4. package/src/core/config/index.js +4 -5
  5. package/src/core/env.js +3 -3
  6. package/src/core/generate_manifest/index.js +6 -0
  7. package/src/core/postbuild/entities.js +8 -2
  8. package/src/core/postbuild/fallback.js +2 -1
  9. package/src/core/postbuild/prerender.js +18 -13
  10. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  11. package/src/core/sync/create_manifest_data/index.js +33 -2
  12. package/src/core/sync/sync.js +3 -2
  13. package/src/core/sync/utils.js +2 -2
  14. package/src/core/sync/write_app_types.js +72 -27
  15. package/src/core/sync/write_tsconfig/index.js +73 -54
  16. package/src/core/sync/write_tsconfig/utils.js +0 -61
  17. package/src/core/sync/write_tsconfig/validate.js +128 -0
  18. package/src/core/sync/write_types/index.js +7 -4
  19. package/src/exports/node/index.js +2 -7
  20. package/src/exports/public.d.ts +25 -18
  21. package/src/exports/vite/build/build_server.js +2 -3
  22. package/src/exports/vite/dev/index.js +44 -36
  23. package/src/exports/vite/index.js +91 -16
  24. package/src/exports/vite/utils.js +62 -15
  25. package/src/runner.js +4 -2
  26. package/src/runtime/app/forms.js +4 -7
  27. package/src/runtime/app/internal/transport.js +53 -0
  28. package/src/runtime/app/paths/client.js +2 -2
  29. package/src/runtime/app/paths/internal/client.js +2 -2
  30. package/src/runtime/app/server/remote/prerender.js +6 -10
  31. package/src/runtime/app/server/remote/query.js +3 -9
  32. package/src/runtime/app/server/remote/requested.js +2 -2
  33. package/src/runtime/app/server/remote/shared.js +1 -16
  34. package/src/runtime/client/client.js +177 -63
  35. package/src/runtime/client/fetcher.js +2 -13
  36. package/src/runtime/client/parse.js +1 -1
  37. package/src/runtime/client/remote-functions/command.svelte.js +1 -2
  38. package/src/runtime/client/remote-functions/form.svelte.js +3 -7
  39. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  40. package/src/runtime/client/remote-functions/query/index.js +1 -1
  41. package/src/runtime/client/remote-functions/query/proxy.js +2 -2
  42. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  43. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  44. package/src/runtime/client/remote-functions/shared.svelte.js +1 -1
  45. package/src/runtime/client/utils.js +1 -0
  46. package/src/runtime/form-utils.js +4 -6
  47. package/src/runtime/pathname.js +44 -1
  48. package/src/runtime/server/data/index.js +5 -8
  49. package/src/runtime/server/dev.js +22 -0
  50. package/src/runtime/server/endpoint.js +3 -4
  51. package/src/runtime/server/fetch.js +25 -30
  52. package/src/runtime/server/index.js +64 -46
  53. package/src/runtime/server/internal.js +12 -5
  54. package/src/runtime/server/page/actions.js +18 -43
  55. package/src/runtime/server/page/crypto.js +2 -2
  56. package/src/runtime/server/page/csp.js +2 -1
  57. package/src/runtime/server/page/data_serializer.js +12 -13
  58. package/src/runtime/server/page/index.js +16 -32
  59. package/src/runtime/server/page/load_data.js +28 -44
  60. package/src/runtime/server/page/render.js +28 -12
  61. package/src/runtime/server/page/respond_with_error.js +8 -20
  62. package/src/runtime/server/page/serialize_data.js +2 -13
  63. package/src/runtime/server/page/server_routing.js +58 -9
  64. package/src/runtime/server/remote-functions.js +11 -15
  65. package/src/runtime/server/respond.js +44 -56
  66. package/src/runtime/server/state.js +60 -0
  67. package/src/runtime/server/utils.js +0 -20
  68. package/src/runtime/shared.js +20 -40
  69. package/src/runtime/utils.js +3 -0
  70. package/src/types/ambient-private.d.ts +1 -1
  71. package/src/types/ambient.d.ts +58 -7
  72. package/src/types/global-private.d.ts +1 -1
  73. package/src/types/internal.d.ts +47 -53
  74. package/src/utils/filesystem.js +1 -23
  75. package/src/utils/hash.js +21 -0
  76. package/src/utils/http.js +8 -7
  77. package/src/utils/import.js +2 -1
  78. package/src/utils/params.js +1 -1
  79. package/src/utils/regex.js +9 -0
  80. package/src/utils/routing.js +52 -27
  81. package/src/utils/url.js +1 -0
  82. package/src/version.js +1 -1
  83. package/types/index.d.ts +98 -28
  84. package/types/index.d.ts.map +1 -1
  85. package/src/exports/node/polyfills.js +0 -30
  86. package/src/runtime/server/app.js +0 -9
@@ -11,16 +11,21 @@ import { uneval_action_response } from './actions.js';
11
11
  import { SVELTE_KIT_ASSETS } from '../../../constants.js';
12
12
  import { SCHEME } from '../../../utils/url.js';
13
13
  import { create_server_routing_response, generate_route_object } from './server_routing.js';
14
- import { add_data_suffix, add_resolution_suffix } from '../../pathname.js';
14
+ import {
15
+ add_data_suffix,
16
+ add_resolution_suffix,
17
+ route_id_resolution_pathname
18
+ } from '../../pathname.js';
15
19
  import { try_get_request_store, with_request_store } from '@sveltejs/kit/internal/server';
16
20
  import { text_encoder } from '../../utils.js';
17
- import { count_non_ssi_comments, create_replacer, get_global_name } from '../utils.js';
21
+ import { count_non_ssi_comments, get_global_name } from '../utils.js';
18
22
  import { handle_error_and_jsonify } from '../errors.js';
19
23
  import * as env from '__sveltekit/env';
20
24
  import { collect_remote_data } from '../remote-functions.js';
21
25
  import Root from '../../components/root.svelte';
22
26
  import { render } from 'svelte/server';
23
27
  import { Props, RenderNode } from '../../props.svelte.js';
28
+ import { has_custom_transporters, uneval } from '#app/internal/transport';
24
29
 
25
30
  // TODO rename this function/module
26
31
 
@@ -31,12 +36,11 @@ import { Props, RenderNode } from '../../props.svelte.js';
31
36
  * fetched: Array<import('./types.js').Fetched>;
32
37
  * options: import('types').SSROptions;
33
38
  * manifest: import('@sveltejs/kit').SSRManifest;
34
- * state: import('types').SSRState;
35
39
  * page_config: { ssr: boolean; csr: boolean };
36
40
  * status: number;
37
41
  * error: App.Error | null;
38
42
  * event: import('@sveltejs/kit').RequestEvent;
39
- * event_state: import('types').RequestState;
43
+ * state: import('types').RequestState;
40
44
  * resolve_opts: import('types').RequiredResolveOptions;
41
45
  * action_result?: import('@sveltejs/kit').ActionResult;
42
46
  * data_serializer: import('./types.js').ServerDataSerializer;
@@ -48,12 +52,11 @@ export async function render_response({
48
52
  fetched,
49
53
  options,
50
54
  manifest,
51
- state,
52
55
  page_config,
53
56
  status,
54
57
  error = null,
55
58
  event,
56
- event_state,
59
+ state,
57
60
  resolve_opts,
58
61
  action_result,
59
62
  data_serializer,
@@ -179,7 +182,7 @@ export async function render_response({
179
182
 
180
183
  props.page.data = data;
181
184
 
182
- const render_state = { ...event_state, is_in_render: true };
185
+ const render_state = { ...state, is_in_render: true };
183
186
 
184
187
  const render_opts = {
185
188
  context: new Map([
@@ -390,6 +393,20 @@ export async function render_response({
390
393
  pathname,
391
394
  create_server_routing_response(route, event.params, new URL(pathname, event.url), client)
392
395
  );
396
+
397
+ // Prerender a route-ID-keyed `/_app/routes/<id>/__route.js` module alongside the
398
+ // pathname-keyed one above, so that `preloadCode(id)` can resolve a route ID without
399
+ // hitting the server.
400
+ if (route && !state.prerendering.resolved_route_ids.has(route.id)) {
401
+ state.prerendering.resolved_route_ids.add(route.id);
402
+
403
+ const id_pathname = paths.base + route_id_resolution_pathname(paths.app_dir, route.id);
404
+
405
+ state.prerendering.dependencies.set(
406
+ id_pathname,
407
+ create_server_routing_response(route, null, new URL(id_pathname, event.url), client)
408
+ );
409
+ }
393
410
  }
394
411
 
395
412
  const blocks = [];
@@ -413,7 +430,7 @@ export async function render_response({
413
430
 
414
431
  let app_declaration = '';
415
432
 
416
- if (Object.keys(options.hooks.transport).length > 0) {
433
+ if (has_custom_transporters) {
417
434
  if (client.inline) {
418
435
  app_declaration = `const app = ${global}.app.app;`;
419
436
  } else if (client.app) {
@@ -464,8 +481,7 @@ export async function render_response({
464
481
  if (form_value) {
465
482
  serialized.form = uneval_action_response(
466
483
  form_value,
467
- /** @type {string} */ (event.route.id),
468
- options.hooks.transport
484
+ /** @type {string} */ (event.route.id)
469
485
  );
470
486
  }
471
487
 
@@ -500,11 +516,11 @@ export async function render_response({
500
516
  args.push(`{\n${indent}\t${hydrate.join(`,\n${indent}\t`)}\n${indent}}`);
501
517
  }
502
518
 
503
- const remote_data = await collect_remote_data({}, event, event_state, options);
519
+ const remote_data = await collect_remote_data({}, event, state, options);
504
520
 
505
521
  const serialized_data =
506
522
  Object.keys(remote_data).length > 0
507
- ? `${global}.data = ${devalue.uneval(remote_data, create_replacer(options.hooks.transport))};\n\n\t\t\t\t\t\t`
523
+ ? `${global}.data = ${uneval(remote_data)};\n\n\t\t\t\t\t\t`
508
524
  : '';
509
525
 
510
526
  // `client.app` is a proxy for `bundleStrategy === 'split'`
@@ -13,26 +13,17 @@ import { server_data_serializer } from './data_serializer.js';
13
13
  /**
14
14
  * @param {{
15
15
  * event: import('@sveltejs/kit').RequestEvent;
16
- * event_state: import('types').RequestState;
16
+ * state: import('types').RequestState;
17
17
  * options: import('types').SSROptions;
18
18
  * manifest: import('@sveltejs/kit').SSRManifest;
19
- * state: import('types').SSRState;
20
19
  * error: unknown;
21
20
  * resolve_opts: import('types').RequiredResolveOptions;
22
21
  * }} opts
23
22
  */
24
- export async function respond_with_error({
25
- event,
26
- event_state,
27
- options,
28
- manifest,
29
- state,
30
- error,
31
- resolve_opts
32
- }) {
23
+ export async function respond_with_error({ event, state, options, manifest, error, resolve_opts }) {
33
24
  // reroute to the fallback page to prevent an infinite chain of requests.
34
25
  if (event.request.headers.get('x-sveltekit-error')) {
35
- const transformed = await handle_error_and_jsonify(event, event_state, options, error);
26
+ const transformed = await handle_error_and_jsonify(event, state, options, error);
36
27
  return static_error_page(options, transformed.status, transformed.message);
37
28
  }
38
29
 
@@ -44,16 +35,15 @@ export async function respond_with_error({
44
35
  const nodes = new PageNodes([default_layout]);
45
36
  const ssr = nodes.ssr();
46
37
  const csr = nodes.csr();
47
- const data_serializer = server_data_serializer(event, event_state, options);
38
+ const data_serializer = server_data_serializer(event, state, options);
48
39
  // Do this here first in case the awaits below before rendering themselves error
49
- const transformed = await handle_error_and_jsonify(event, event_state, options, error);
40
+ const transformed = await handle_error_and_jsonify(event, state, options, error);
50
41
 
51
42
  if (ssr) {
52
43
  state.error = true;
53
44
 
54
45
  const server_data_promise = load_server_data({
55
46
  event,
56
- event_state,
57
47
  state,
58
48
  node: default_layout,
59
49
  // eslint-disable-next-line @typescript-eslint/require-await
@@ -65,14 +55,13 @@ export async function respond_with_error({
65
55
 
66
56
  const data = await load_data({
67
57
  event,
68
- event_state,
58
+ state,
69
59
  fetched,
70
60
  node: default_layout,
71
61
  // eslint-disable-next-line @typescript-eslint/require-await
72
62
  parent: async () => ({}),
73
63
  resolve_opts,
74
64
  server_data_promise,
75
- state,
76
65
  csr
77
66
  });
78
67
 
@@ -93,7 +82,6 @@ export async function respond_with_error({
93
82
  return await render_response({
94
83
  options,
95
84
  manifest,
96
- state,
97
85
  page_config: {
98
86
  ssr,
99
87
  csr
@@ -104,7 +92,7 @@ export async function respond_with_error({
104
92
  error_components: [],
105
93
  fetched,
106
94
  event,
107
- event_state,
95
+ state,
108
96
  resolve_opts,
109
97
  data_serializer
110
98
  });
@@ -115,7 +103,7 @@ export async function respond_with_error({
115
103
  return redirect_response(e.status, e.location);
116
104
  }
117
105
 
118
- const transformed = await handle_error_and_jsonify(event, event_state, options, e);
106
+ const transformed = await handle_error_and_jsonify(event, state, options, e);
119
107
 
120
108
  return static_error_page(options, transformed.status, transformed.message);
121
109
  }
@@ -1,5 +1,5 @@
1
1
  import { escape_html } from '../../../utils/escape.js';
2
- import { hash } from '../../../utils/hash.js';
2
+ import { hash_request } from '../../../utils/hash.js';
3
3
 
4
4
  /**
5
5
  * Inside a script element, only `</script` and `<!--` hold special meaning to the HTML parser.
@@ -78,18 +78,7 @@ export function serialize_data(fetched, filter, prerendering = false) {
78
78
  }
79
79
 
80
80
  if (fetched.request_headers || fetched.request_body) {
81
- /** @type {import('types').StrictBody[]} */
82
- const values = [];
83
-
84
- if (fetched.request_headers) {
85
- values.push([...new Headers(fetched.request_headers)].join(','));
86
- }
87
-
88
- if (fetched.request_body) {
89
- values.push(fetched.request_body);
90
- }
91
-
92
- attrs.push(`data-hash="${hash(...values)}"`);
81
+ attrs.push(`data-hash="${hash_request(fetched.request_headers, fetched.request_body)}"`);
93
82
  }
94
83
 
95
84
  // Compute the time the response should be cached, taking into account max-age and age.
@@ -84,26 +84,75 @@ export async function resolve_route(resolved_path, url, manifest) {
84
84
  }
85
85
  }
86
86
 
87
+ /**
88
+ * Resolve a route-ID resolution request (`/_app/routes/<id>/__route.js`) to a
89
+ * JS module containing the route's node loaders. Params are always `{}` since
90
+ * this endpoint exists to support `preloadCode(routeId)`, which doesn't need them.
91
+ *
92
+ * The module has one of three shapes, which the client uses to tell three cases apart:
93
+ *
94
+ * - `export const route = {...}` — a page route, with loaders to import
95
+ * - `export const endpoint_only = true` — a real route with no `+page`, so there is
96
+ * nothing to preload, but the client can cache that fact and stop asking
97
+ * - an empty module — no such route
98
+ *
99
+ * @param {string} route_id
100
+ * @param {URL} url
101
+ * @param {SSRManifest} manifest
102
+ * @returns {Response}
103
+ */
104
+ export function resolve_route_by_id(route_id, url, manifest) {
105
+ if (!manifest._.client?.routes) {
106
+ return text('Server-side route resolution disabled', { status: 400 });
107
+ }
108
+
109
+ try {
110
+ const route = manifest._.client.routes.find((r) => r.id === route_id);
111
+
112
+ if (route) {
113
+ return create_server_routing_response(route, null, url, manifest._.client).response;
114
+ }
115
+
116
+ // `client.routes` only contains routes with a `+page`, so a miss above doesn't mean the
117
+ // route doesn't exist — it might be a `+server.js`-only route. `_.routes` includes those
118
+ // (with `page: null`), so we can distinguish "exists but has no code" from "unknown".
119
+ if (manifest._.routes.some((r) => r.id === route_id && !r.page)) {
120
+ return text('export const endpoint_only = true;', { headers: js_headers() });
121
+ }
122
+
123
+ return create_server_routing_response(null, null, url, manifest._.client).response;
124
+ } catch {
125
+ return text('Error resolving route', { status: 500 });
126
+ }
127
+ }
128
+
129
+ function js_headers() {
130
+ return new Headers({
131
+ 'content-type': 'application/javascript; charset=utf-8'
132
+ });
133
+ }
134
+
87
135
  /**
88
136
  * @param {import('types').SSRClientRoute | null} route
89
- * @param {Partial<Record<string, string>>} params
137
+ * @param {Partial<Record<string, string>> | null} params
90
138
  * @param {URL} url
91
139
  * @param {NonNullable<SSRManifest['_']['client']>} client
92
140
  * @returns {{response: Response, body: string}}
93
141
  */
94
142
  export function create_server_routing_response(route, params, url, client) {
95
- const headers = new Headers({
96
- 'content-type': 'application/javascript; charset=utf-8'
97
- });
143
+ const headers = js_headers();
144
+ let body = '';
98
145
 
99
146
  if (route) {
100
147
  const csr_route = generate_route_object(route, url, client);
101
- const body = `${create_css_import(route, url, client)}\nexport const route = ${csr_route}; export const params = ${JSON.stringify(params)};`;
148
+ body = `${create_css_import(route, url, client)}export const route = ${csr_route};`;
102
149
 
103
- return { response: text(body, { headers }), body };
104
- } else {
105
- return { response: text('', { headers }), body: '' };
150
+ if (params !== null) {
151
+ body += `\nexport const params = ${JSON.stringify(params)}`;
152
+ }
106
153
  }
154
+
155
+ return { response: text(body, { headers }), body };
107
156
  }
108
157
 
109
158
  /**
@@ -132,5 +181,5 @@ function create_css_import(route, url, client) {
132
181
 
133
182
  if (!css) return '';
134
183
 
135
- return `${create_client_import(client.start, url)}.then(x => x.load_css([${css}]));`;
184
+ return `${create_client_import(client.start, url)}.then(x => x.load_css([${css}]));\n`;
136
185
  }
@@ -6,7 +6,8 @@ import { Redirect, SvelteKitError } from '@sveltejs/kit/internal';
6
6
  import { with_request_store, merge_tracing } from '@sveltejs/kit/internal/server';
7
7
  import { app_dir, base } from '$app/paths/internal/server';
8
8
  import { is_form_content_type } from '../../utils/http.js';
9
- import { create_remote_key, parse_remote_arg, split_remote_key, stringify } from '../shared.js';
9
+ import { create_remote_key, parse_remote_arg, split_remote_key } from '../shared.js';
10
+ import { stringify } from '#app/internal/transport';
10
11
  import { handle_error_and_jsonify } from './errors.js';
11
12
  import { normalize_error } from '../../utils/error.js';
12
13
  import { check_incorrect_fail_use } from './page/actions.js';
@@ -59,7 +60,6 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
59
60
 
60
61
  /** @type {RemoteInternals} */
61
62
  const internals = fn.__;
62
- const transport = options.hooks.transport;
63
63
 
64
64
  event.tracing.current.setAttributes({
65
65
  'sveltekit.remote.call.type': internals.type,
@@ -87,7 +87,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
87
87
  new URL(event.request.url).searchParams.get('payload')
88
88
  );
89
89
 
90
- const generator = internals.run(event, state, parse_remote_arg(payload, transport));
90
+ const generator = internals.run(event, state, parse_remote_arg(payload));
91
91
 
92
92
  const encoder = new TextEncoder();
93
93
 
@@ -156,7 +156,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
156
156
  }
157
157
 
158
158
  // only send changed data
159
- if (result !== (result = stringify(value, transport))) {
159
+ if (result !== (result = stringify(value))) {
160
160
  send(controller, {
161
161
  type: 'result',
162
162
  result
@@ -214,9 +214,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
214
214
  /** @type {{ payloads: string[] }} */
215
215
  const { payloads } = await event.request.json();
216
216
 
217
- const args = await Promise.all(
218
- payloads.map((payload) => parse_remote_arg(payload, transport))
219
- );
217
+ const args = await Promise.all(payloads.map((payload) => parse_remote_arg(payload)));
220
218
 
221
219
  data._ = await with_request_store({ event, state }, () => internals.run(args, options));
222
220
 
@@ -266,7 +264,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
266
264
  return json(
267
265
  /** @type {RemoteFunctionResponse} */ ({
268
266
  type: 'result',
269
- data: stringify(data, transport)
267
+ data: stringify(data)
270
268
  }),
271
269
  { headers }
272
270
  );
@@ -279,7 +277,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
279
277
  /** @type {{ payload: string, refreshes?: string[] }} */
280
278
  const { payload, refreshes } = await event.request.json();
281
279
  state.remote.requested = create_requested_map(refreshes);
282
- const arg = parse_remote_arg(payload, transport);
280
+ const arg = parse_remote_arg(payload);
283
281
 
284
282
  data._ = await with_request_store(
285
283
  { event, state: { ...state, is_in_remote_form_or_command: true } },
@@ -291,7 +289,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
291
289
 
292
290
  case 'prerender': {
293
291
  data._ = await with_request_store({ event, state }, () =>
294
- fn(parse_remote_arg(additional_args, transport))
292
+ fn(parse_remote_arg(additional_args))
295
293
  );
296
294
 
297
295
  break;
@@ -303,9 +301,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
303
301
  new URL(event.request.url).searchParams.get('payload')
304
302
  );
305
303
 
306
- data._ = await with_request_store({ event, state }, () =>
307
- fn(parse_remote_arg(payload, transport))
308
- );
304
+ data._ = await with_request_store({ event, state }, () => fn(parse_remote_arg(payload)));
309
305
 
310
306
  break;
311
307
  }
@@ -316,7 +312,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
316
312
  return json(
317
313
  /** @type {RemoteFunctionResponse} */ ({
318
314
  type: 'result',
319
- data: stringify(data, transport)
315
+ data: stringify(data)
320
316
  }),
321
317
  { headers }
322
318
  );
@@ -327,7 +323,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
327
323
  return json(
328
324
  /** @type {RemoteFunctionResponse} */ ({
329
325
  type: 'result',
330
- data: stringify(data, transport)
326
+ data: stringify(data)
331
327
  }),
332
328
  { headers }
333
329
  );