@sveltejs/kit 2.16.0 → 2.17.0

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 (36) hide show
  1. package/package.json +5 -3
  2. package/src/core/adapt/builder.js +2 -0
  3. package/src/core/config/index.js +16 -1
  4. package/src/core/config/options.js +2 -1
  5. package/src/core/generate_manifest/index.js +14 -5
  6. package/src/core/postbuild/analyse.js +2 -2
  7. package/src/core/sync/write_client_manifest.js +33 -17
  8. package/src/core/sync/write_server.js +2 -1
  9. package/src/exports/public.d.ts +29 -6
  10. package/src/exports/vite/build/build_server.js +5 -0
  11. package/src/exports/vite/dev/index.js +29 -1
  12. package/src/exports/vite/index.js +51 -5
  13. package/src/runtime/app/state/index.js +11 -0
  14. package/src/runtime/client/client.js +80 -46
  15. package/src/runtime/client/parse.js +20 -0
  16. package/src/runtime/client/types.d.ts +16 -1
  17. package/src/runtime/client/utils.js +6 -0
  18. package/src/runtime/pathname.js +54 -0
  19. package/src/runtime/server/cookie.js +2 -1
  20. package/src/runtime/server/endpoint.js +0 -5
  21. package/src/runtime/server/fetch.js +12 -0
  22. package/src/runtime/server/page/index.js +1 -1
  23. package/src/runtime/server/page/render.js +25 -3
  24. package/src/runtime/server/page/server_routing.js +110 -0
  25. package/src/runtime/server/respond.js +45 -26
  26. package/src/runtime/server/validate-headers.js +64 -0
  27. package/src/runtime/utils.js +21 -0
  28. package/src/types/ambient-private.d.ts +1 -0
  29. package/src/types/global-private.d.ts +2 -0
  30. package/src/types/internal.d.ts +47 -9
  31. package/src/utils/filesystem.js +4 -3
  32. package/src/utils/routing.js +8 -0
  33. package/src/utils/url.js +0 -23
  34. package/src/version.js +1 -1
  35. package/types/index.d.ts +72 -13
  36. package/types/index.d.ts.map +2 -1
@@ -1,19 +1,12 @@
1
1
  import { DEV } from 'esm-env';
2
- import { base } from '__sveltekit/paths';
2
+ import { base, app_dir } from '__sveltekit/paths';
3
3
  import { is_endpoint_request, render_endpoint } from './endpoint.js';
4
4
  import { render_page } from './page/index.js';
5
5
  import { render_response } from './page/render.js';
6
6
  import { respond_with_error } from './page/respond_with_error.js';
7
7
  import { is_form_content_type } from '../../utils/http.js';
8
8
  import { handle_fatal_error, method_not_allowed, redirect_response } from './utils.js';
9
- import {
10
- decode_pathname,
11
- decode_params,
12
- disable_search,
13
- has_data_suffix,
14
- normalize_path,
15
- strip_data_suffix
16
- } from '../../utils/url.js';
9
+ import { decode_pathname, decode_params, disable_search, normalize_path } from '../../utils/url.js';
17
10
  import { exec } from '../../utils/routing.js';
18
11
  import { redirect_json_response, render_data } from './data/index.js';
19
12
  import { add_cookies_to_headers, get_cookies } from './cookie.js';
@@ -33,8 +26,17 @@ import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM } from '../shared.js';
33
26
  import { get_public_env } from './env_module.js';
34
27
  import { load_page_nodes } from './page/load_page_nodes.js';
35
28
  import { get_page_config } from '../../utils/route_config.js';
29
+ import { resolve_route } from './page/server_routing.js';
30
+ import { validateHeaders } from './validate-headers.js';
31
+ import {
32
+ has_data_suffix,
33
+ has_resolution_prefix,
34
+ strip_data_suffix,
35
+ strip_resolution_prefix
36
+ } from '../pathname.js';
36
37
 
37
38
  /* global __SVELTEKIT_ADAPTER_NAME__ */
39
+ /* global __SVELTEKIT_DEV__ */
38
40
 
39
41
  /** @type {import('types').RequiredResolveOptions['transformPageChunk']} */
40
42
  const default_transform = ({ html }) => html;
@@ -85,10 +87,19 @@ export async function respond(request, options, manifest, state) {
85
87
  return text('Not found', { status: 404 });
86
88
  }
87
89
 
88
- const is_data_request = has_data_suffix(url.pathname);
89
90
  /** @type {boolean[] | undefined} */
90
91
  let invalidated_data_nodes;
91
- if (is_data_request) {
92
+
93
+ /**
94
+ * If the request is for a route resolution, first modify the URL, then continue as normal
95
+ * for path resolution, then return the route object as a JS file.
96
+ */
97
+ const is_route_resolution_request = has_resolution_prefix(url.pathname);
98
+ const is_data_request = has_data_suffix(url.pathname);
99
+
100
+ if (is_route_resolution_request) {
101
+ url.pathname = strip_resolution_prefix(url.pathname);
102
+ } else if (is_data_request) {
92
103
  url.pathname =
93
104
  strip_data_suffix(url.pathname) +
94
105
  (url.searchParams.get(TRAILING_SLASH_PARAM) === '1' ? '/' : '') || '/';
@@ -100,19 +111,19 @@ export async function respond(request, options, manifest, state) {
100
111
  url.searchParams.delete(INVALIDATED_PARAM);
101
112
  }
102
113
 
103
- // reroute could alter the given URL, so we pass a copy
104
- let rerouted_path;
114
+ let resolved_path;
115
+
105
116
  try {
106
- rerouted_path = options.hooks.reroute({ url: new URL(url) }) ?? url.pathname;
117
+ // reroute could alter the given URL, so we pass a copy
118
+ resolved_path = options.hooks.reroute({ url: new URL(url) }) ?? url.pathname;
107
119
  } catch {
108
120
  return text('Internal Server Error', {
109
121
  status: 500
110
122
  });
111
123
  }
112
124
 
113
- let decoded;
114
125
  try {
115
- decoded = decode_pathname(rerouted_path);
126
+ resolved_path = decode_pathname(resolved_path);
116
127
  } catch {
117
128
  return text('Malformed URI', { status: 400 });
118
129
  }
@@ -124,17 +135,21 @@ export async function respond(request, options, manifest, state) {
124
135
  let params = {};
125
136
 
126
137
  if (base && !state.prerendering?.fallback) {
127
- if (!decoded.startsWith(base)) {
138
+ if (!resolved_path.startsWith(base)) {
128
139
  return text('Not found', { status: 404 });
129
140
  }
130
- decoded = decoded.slice(base.length) || '/';
141
+ resolved_path = resolved_path.slice(base.length) || '/';
142
+ }
143
+
144
+ if (is_route_resolution_request) {
145
+ return resolve_route(resolved_path, new URL(request.url), manifest);
131
146
  }
132
147
 
133
- if (decoded === `/${options.app_dir}/env.js`) {
148
+ if (resolved_path === `/${app_dir}/env.js`) {
134
149
  return get_public_env(request);
135
150
  }
136
151
 
137
- if (decoded.startsWith(`/${options.app_dir}`)) {
152
+ if (resolved_path.startsWith(`/${app_dir}`)) {
138
153
  // Ensure that 404'd static assets are not cached - some adapters might apply caching by default
139
154
  const headers = new Headers();
140
155
  headers.set('cache-control', 'public, max-age=0, must-revalidate');
@@ -146,7 +161,7 @@ export async function respond(request, options, manifest, state) {
146
161
  const matchers = await manifest._.matchers();
147
162
 
148
163
  for (const candidate of manifest._.routes) {
149
- const match = candidate.pattern.exec(decoded);
164
+ const match = candidate.pattern.exec(resolved_path);
150
165
  if (!match) continue;
151
166
 
152
167
  const matched = exec(match, candidate.params, matchers);
@@ -186,6 +201,10 @@ export async function respond(request, options, manifest, state) {
186
201
  request,
187
202
  route: { id: route?.id ?? null },
188
203
  setHeaders: (new_headers) => {
204
+ if (__SVELTEKIT_DEV__) {
205
+ validateHeaders(new_headers);
206
+ }
207
+
189
208
  for (const key in new_headers) {
190
209
  const lower = key.toLowerCase();
191
210
  const value = new_headers[key];
@@ -508,11 +527,11 @@ export async function respond(request, options, manifest, state) {
508
527
  }
509
528
 
510
529
  if (state.error && event.isSubRequest) {
511
- return await fetch(request, {
512
- headers: {
513
- 'x-sveltekit-error': 'true'
514
- }
515
- });
530
+ // avoid overwriting the headers. This could be a same origin fetch request
531
+ // to an external service from the root layout while rendering an error page
532
+ const headers = new Headers(request.headers);
533
+ headers.set('x-sveltekit-error', 'true');
534
+ return await fetch(request, { headers });
516
535
  }
517
536
 
518
537
  if (state.error) {
@@ -0,0 +1,64 @@
1
+ /** @type {Set<string>} */
2
+ const VALID_CACHE_CONTROL_DIRECTIVES = new Set([
3
+ 'max-age',
4
+ 'public',
5
+ 'private',
6
+ 'no-cache',
7
+ 'no-store',
8
+ 'must-revalidate',
9
+ 'proxy-revalidate',
10
+ 's-maxage',
11
+ 'immutable',
12
+ 'stale-while-revalidate',
13
+ 'stale-if-error',
14
+ 'no-transform',
15
+ 'only-if-cached',
16
+ 'max-stale',
17
+ 'min-fresh'
18
+ ]);
19
+
20
+ const CONTENT_TYPE_PATTERN =
21
+ /^(application|audio|example|font|haptics|image|message|model|multipart|text|video|x-[a-z]+)\/[-+.\w]+$/i;
22
+
23
+ /** @type {Record<string, (value: string) => void>} */
24
+ const HEADER_VALIDATORS = {
25
+ 'cache-control': (value) => {
26
+ const error_suffix = `(While parsing "${value}".)`;
27
+ const parts = value.split(',').map((part) => part.trim());
28
+ if (parts.some((part) => !part)) {
29
+ throw new Error(`\`cache-control\` header contains empty directives. ${error_suffix}`);
30
+ }
31
+
32
+ const directives = parts.map((part) => part.split('=')[0].toLowerCase());
33
+ const invalid = directives.find((directive) => !VALID_CACHE_CONTROL_DIRECTIVES.has(directive));
34
+ if (invalid) {
35
+ throw new Error(
36
+ `Invalid cache-control directive "${invalid}". Did you mean one of: ${[...VALID_CACHE_CONTROL_DIRECTIVES].join(', ')}? ${error_suffix}`
37
+ );
38
+ }
39
+ },
40
+
41
+ 'content-type': (value) => {
42
+ const type = value.split(';')[0].trim();
43
+ const error_suffix = `(While parsing "${value}".)`;
44
+ if (!CONTENT_TYPE_PATTERN.test(type)) {
45
+ throw new Error(`Invalid content-type value "${type}". ${error_suffix}`);
46
+ }
47
+ }
48
+ };
49
+
50
+ /**
51
+ * @param {Record<string, string>} headers
52
+ */
53
+ export function validateHeaders(headers) {
54
+ for (const [key, value] of Object.entries(headers)) {
55
+ const validator = HEADER_VALIDATORS[key.toLowerCase()];
56
+ try {
57
+ validator?.(value);
58
+ } catch (error) {
59
+ if (error instanceof Error) {
60
+ console.warn(`[SvelteKit] ${error.message}`);
61
+ }
62
+ }
63
+ }
64
+ }
@@ -32,3 +32,24 @@ export function b64_encode(buffer) {
32
32
  )
33
33
  );
34
34
  }
35
+
36
+ /**
37
+ * Like node's path.relative, but without using node
38
+ * @param {string} from
39
+ * @param {string} to
40
+ */
41
+ export function get_relative_path(from, to) {
42
+ const from_parts = from.split(/[/\\]/);
43
+ const to_parts = to.split(/[/\\]/);
44
+ from_parts.pop(); // get dirname
45
+
46
+ while (from_parts[0] === to_parts[0]) {
47
+ from_parts.shift();
48
+ to_parts.shift();
49
+ }
50
+
51
+ let i = from_parts.length;
52
+ while (i--) from_parts[i] = '..';
53
+
54
+ return from_parts.concat(to_parts).join('/');
55
+ }
@@ -11,6 +11,7 @@ declare module '__sveltekit/environment' {
11
11
  declare module '__sveltekit/paths' {
12
12
  export let base: '' | `/${string}`;
13
13
  export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets';
14
+ export let app_dir: string;
14
15
  export let relative: boolean;
15
16
  export function reset(): void;
16
17
  export function override(paths: { base: string; assets: string }): void;
@@ -4,6 +4,8 @@ declare global {
4
4
  const __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: number;
5
5
  const __SVELTEKIT_DEV__: boolean;
6
6
  const __SVELTEKIT_EMBEDDED__: boolean;
7
+ /** True if `config.kit.router.resolution === 'client'` */
8
+ const __SVELTEKIT_CLIENT_ROUTING__: boolean;
7
9
  /**
8
10
  * This makes the use of specific features visible at both dev and build time, in such a
9
11
  * way that we can error when they are not supported by the target platform.
@@ -68,12 +68,28 @@ export interface BuildData {
68
68
  out_dir: string;
69
69
  service_worker: string | null;
70
70
  client: {
71
+ /** Path to the client entry point */
71
72
  start: string;
73
+ /** Path to the generated `app.js` file that contains the client manifest. Only set in case of `bundleStrategy === 'split'` */
72
74
  app?: string;
75
+ /** JS files that the client entry point relies on */
73
76
  imports: string[];
77
+ /**
78
+ * JS files that represent the entry points of the layouts/pages.
79
+ * An entry is undefined if the layout/page has no component or universal file (i.e. only has a `.server.js` file).
80
+ * Only set in case of `router.resolution === 'server'`.
81
+ */
82
+ nodes?: (string | undefined)[];
83
+ /**
84
+ * Contains the client route manifest in a form suitable for the server which is used for server side route resolution.
85
+ * Notably, it contains all routes, regardless of whether they are prerendered or not (those are missing in the optimized server route manifest).
86
+ * Only set in case of `router.resolution === 'server'`.
87
+ */
88
+ routes?: SSRClientRoute[];
74
89
  stylesheets: string[];
75
90
  fonts: string[];
76
91
  uses_env_dynamic_public: boolean;
92
+ /** Only set in case of `bundleStrategy === 'inline'` */
77
93
  inline?: {
78
94
  script: string;
79
95
  style: string | undefined;
@@ -104,6 +120,17 @@ export type CSRRoute = {
104
120
  leaf: [has_server_load: boolean, node_loader: CSRPageNodeLoader];
105
121
  };
106
122
 
123
+ /**
124
+ * Definition of a client side route as transported via `_app/route/...` when using server-side route resolution.
125
+ */
126
+ export type CSRRouteServer = {
127
+ id: string;
128
+ errors: Array<number | undefined>;
129
+ layouts: Array<[has_server_load: boolean, node_id: number] | undefined>;
130
+ leaf: [has_server_load: boolean, node_id: number];
131
+ nodes: Record<string, CSRPageNodeLoader>;
132
+ };
133
+
107
134
  export interface Deferred {
108
135
  fulfil: (value: any) => void;
109
136
  reject: (error: Error) => void;
@@ -160,11 +187,11 @@ export interface ManifestData {
160
187
 
161
188
  export interface PageNode {
162
189
  depth: number;
163
- /** The +page.svelte */
190
+ /** The +page/layout.svelte */
164
191
  component?: string; // TODO supply default component if it's missing (bit of an edge case)
165
- /** The +page.js/.ts */
192
+ /** The +page/layout.js/.ts */
166
193
  universal?: string;
167
- /** The +page.server.js/ts */
194
+ /** The +page/layout.server.js/ts */
168
195
  server?: string;
169
196
  parent_id?: string;
170
197
  parent?: PageNode;
@@ -304,7 +331,10 @@ export interface ServerMetadataRoute {
304
331
  }
305
332
 
306
333
  export interface ServerMetadata {
307
- nodes: Array<{ has_server_load: boolean }>;
334
+ nodes: Array<{
335
+ /** Also `true` when using `trailingSlash`, because we need to do a server request in that case to get its value */
336
+ has_server_load: boolean;
337
+ }>;
308
338
  routes: Map<string, ServerMetadataRoute>;
309
339
  }
310
340
 
@@ -328,13 +358,13 @@ export type SSRComponentLoader = () => Promise<SSRComponent>;
328
358
 
329
359
  export interface SSRNode {
330
360
  component: SSRComponentLoader;
331
- /** index into the `components` array in client/manifest.js */
361
+ /** index into the `nodes` array in the generated `client/app.js` */
332
362
  index: number;
333
- /** external JS files */
363
+ /** external JS files that are loaded on the client. `imports[0]` is the entry point (e.g. `client/nodes/0.js`) */
334
364
  imports: string[];
335
- /** external CSS files */
365
+ /** external CSS files that are loaded on the client */
336
366
  stylesheets: string[];
337
- /** external font files */
367
+ /** external font files that are loaded on the client */
338
368
  fonts: string[];
339
369
  /** inlined styles */
340
370
  inline_styles?(): MaybePromise<Record<string, string>>;
@@ -367,7 +397,6 @@ export interface SSRNode {
367
397
  export type SSRNodeLoader = () => Promise<SSRNode>;
368
398
 
369
399
  export interface SSROptions {
370
- app_dir: string;
371
400
  app_template_contains_nonce: boolean;
372
401
  csp: ValidatedConfig['kit']['csp'];
373
402
  csrf_check_origin: boolean;
@@ -417,6 +446,15 @@ export interface SSRRoute {
417
446
  endpoint_id?: string;
418
447
  }
419
448
 
449
+ export interface SSRClientRoute {
450
+ id: string;
451
+ pattern: RegExp;
452
+ params: RouteParam[];
453
+ errors: Array<number | undefined>;
454
+ layouts: Array<[has_server_load: boolean, node_id: number] | undefined>;
455
+ leaf: [has_server_load: boolean, node_id: number];
456
+ }
457
+
420
458
  export interface SSRState {
421
459
  fallback?: string;
422
460
  getClientAddress(): string;
@@ -169,11 +169,12 @@ export function from_fs(str) {
169
169
  export function resolve_entry(entry) {
170
170
  if (fs.existsSync(entry)) {
171
171
  const stats = fs.statSync(entry);
172
- const index = path.join(entry, 'index');
173
-
174
172
  if (stats.isFile()) {
175
173
  return entry;
176
- } else if (fs.existsSync(index)) {
174
+ }
175
+
176
+ const index = path.join(entry, 'index');
177
+ if (fs.existsSync(index + '.js') || fs.existsSync(index + '.ts')) {
177
178
  return resolve_entry(index);
178
179
  }
179
180
  }
@@ -265,3 +265,11 @@ export function resolve_route(id, params) {
265
265
  .join('/')
266
266
  );
267
267
  }
268
+
269
+ /**
270
+ * @param {import('types').SSRNode} node
271
+ * @returns {boolean}
272
+ */
273
+ export function has_server_load(node) {
274
+ return node.server?.load !== undefined || node.server?.trailingSlash !== undefined;
275
+ }
package/src/utils/url.js CHANGED
@@ -199,26 +199,3 @@ function allow_nodejs_console_log(url) {
199
199
  };
200
200
  }
201
201
  }
202
-
203
- const DATA_SUFFIX = '/__data.json';
204
- const HTML_DATA_SUFFIX = '.html__data.json';
205
-
206
- /** @param {string} pathname */
207
- export function has_data_suffix(pathname) {
208
- return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX);
209
- }
210
-
211
- /** @param {string} pathname */
212
- export function add_data_suffix(pathname) {
213
- if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX);
214
- return pathname.replace(/\/$/, '') + DATA_SUFFIX;
215
- }
216
-
217
- /** @param {string} pathname */
218
- export function strip_data_suffix(pathname) {
219
- if (pathname.endsWith(HTML_DATA_SUFFIX)) {
220
- return pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';
221
- }
222
-
223
- return pathname.slice(0, -DATA_SUFFIX.length);
224
- }
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 = '2.16.0';
4
+ export const VERSION = '2.17.0';
package/types/index.d.ts CHANGED
@@ -641,6 +641,28 @@ declare module '@sveltejs/kit' {
641
641
  * @since 2.14.0
642
642
  */
643
643
  type?: 'pathname' | 'hash';
644
+ /**
645
+ * How to determine which route to load when navigating to a new page.
646
+ *
647
+ * By default, SvelteKit will serve a route manifest to the browser.
648
+ * When navigating, this manifest is used (along with the `reroute` hook, if it exists) to determine which components to load and which `load` functions to run.
649
+ * Because everything happens on the client, this decision can be made immediately. The drawback is that the manifest needs to be
650
+ * loaded and parsed before the first navigation can happen, which may have an impact if your app contains many routes.
651
+ *
652
+ * Alternatively, SvelteKit can determine the route on the server. This means that for every navigation to a path that has not yet been visited, the server will be asked to determine the route.
653
+ * This has several advantages:
654
+ * - The client does not need to load the routing manifest upfront, which can lead to faster initial page loads
655
+ * - The list of routes is hidden from public view
656
+ * - The server has an opportunity to intercept each navigation (for example through a middleware), enabling (for example) A/B testing opaque to SvelteKit
657
+
658
+ * The drawback is that for unvisited paths, resolution will take slightly longer (though this is mitigated by [preloading](https://svelte.dev/docs/kit/link-options#data-sveltekit-preload-data)).
659
+ *
660
+ * > [!NOTE] When using server-side route resolution and prerendering, the resolution is prerendered along with the route itself.
661
+ *
662
+ * @default "client"
663
+ * @since 2.17.0
664
+ */
665
+ resolution?: 'client' | 'server';
644
666
  };
645
667
  serviceWorker?: {
646
668
  /**
@@ -1070,31 +1092,31 @@ declare module '@sveltejs/kit' {
1070
1092
  }
1071
1093
 
1072
1094
  /**
1073
- * The shape of the `$page` store
1095
+ * The shape of the [`page`](https://svelte.dev/docs/kit/$app-state#page) reactive object and the [`$page`](https://svelte.dev/docs/kit/$app-stores) store.
1074
1096
  */
1075
1097
  export interface Page<
1076
1098
  Params extends Record<string, string> = Record<string, string>,
1077
1099
  RouteId extends string | null = string | null
1078
1100
  > {
1079
1101
  /**
1080
- * The URL of the current page
1102
+ * The URL of the current page.
1081
1103
  */
1082
1104
  url: URL;
1083
1105
  /**
1084
- * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object
1106
+ * The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object.
1085
1107
  */
1086
1108
  params: Params;
1087
1109
  /**
1088
- * Info about the current route
1110
+ * Info about the current route.
1089
1111
  */
1090
1112
  route: {
1091
1113
  /**
1092
- * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`
1114
+ * The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`.
1093
1115
  */
1094
1116
  id: RouteId;
1095
1117
  };
1096
1118
  /**
1097
- * Http status code of the current page
1119
+ * HTTP status code of the current page.
1098
1120
  */
1099
1121
  status: number;
1100
1122
  /**
@@ -1279,6 +1301,7 @@ declare module '@sveltejs/kit' {
1279
1301
  client: NonNullable<BuildData['client']>;
1280
1302
  nodes: SSRNodeLoader[];
1281
1303
  routes: SSRRoute[];
1304
+ prerendered_routes: Set<string>;
1282
1305
  matchers: () => Promise<Record<string, ParamMatcher>>;
1283
1306
  /** A `[file]: size` map of all assets imported by server code */
1284
1307
  server_assets: Record<string, number>;
@@ -1692,12 +1715,28 @@ declare module '@sveltejs/kit' {
1692
1715
  out_dir: string;
1693
1716
  service_worker: string | null;
1694
1717
  client: {
1718
+ /** Path to the client entry point */
1695
1719
  start: string;
1720
+ /** Path to the generated `app.js` file that contains the client manifest. Only set in case of `bundleStrategy === 'split'` */
1696
1721
  app?: string;
1722
+ /** JS files that the client entry point relies on */
1697
1723
  imports: string[];
1724
+ /**
1725
+ * JS files that represent the entry points of the layouts/pages.
1726
+ * An entry is undefined if the layout/page has no component or universal file (i.e. only has a `.server.js` file).
1727
+ * Only set in case of `router.resolution === 'server'`.
1728
+ */
1729
+ nodes?: (string | undefined)[];
1730
+ /**
1731
+ * Contains the client route manifest in a form suitable for the server which is used for server side route resolution.
1732
+ * Notably, it contains all routes, regardless of whether they are prerendered or not (those are missing in the optimized server route manifest).
1733
+ * Only set in case of `router.resolution === 'server'`.
1734
+ */
1735
+ routes?: SSRClientRoute[];
1698
1736
  stylesheets: string[];
1699
1737
  fonts: string[];
1700
1738
  uses_env_dynamic_public: boolean;
1739
+ /** Only set in case of `bundleStrategy === 'inline'` */
1701
1740
  inline?: {
1702
1741
  script: string;
1703
1742
  style: string | undefined;
@@ -1720,11 +1759,11 @@ declare module '@sveltejs/kit' {
1720
1759
 
1721
1760
  interface PageNode {
1722
1761
  depth: number;
1723
- /** The +page.svelte */
1762
+ /** The +page/layout.svelte */
1724
1763
  component?: string; // TODO supply default component if it's missing (bit of an edge case)
1725
- /** The +page.js/.ts */
1764
+ /** The +page/layout.js/.ts */
1726
1765
  universal?: string;
1727
- /** The +page.server.js/ts */
1766
+ /** The +page/layout.server.js/ts */
1728
1767
  server?: string;
1729
1768
  parent_id?: string;
1730
1769
  parent?: PageNode;
@@ -1796,13 +1835,13 @@ declare module '@sveltejs/kit' {
1796
1835
 
1797
1836
  interface SSRNode {
1798
1837
  component: SSRComponentLoader;
1799
- /** index into the `components` array in client/manifest.js */
1838
+ /** index into the `nodes` array in the generated `client/app.js` */
1800
1839
  index: number;
1801
- /** external JS files */
1840
+ /** external JS files that are loaded on the client. `imports[0]` is the entry point (e.g. `client/nodes/0.js`) */
1802
1841
  imports: string[];
1803
- /** external CSS files */
1842
+ /** external CSS files that are loaded on the client */
1804
1843
  stylesheets: string[];
1805
- /** external font files */
1844
+ /** external font files that are loaded on the client */
1806
1845
  fonts: string[];
1807
1846
  /** inlined styles */
1808
1847
  inline_styles?(): MaybePromise<Record<string, string>>;
@@ -1859,6 +1898,15 @@ declare module '@sveltejs/kit' {
1859
1898
  endpoint_id?: string;
1860
1899
  }
1861
1900
 
1901
+ interface SSRClientRoute {
1902
+ id: string;
1903
+ pattern: RegExp;
1904
+ params: RouteParam[];
1905
+ errors: Array<number | undefined>;
1906
+ layouts: Array<[has_server_load: boolean, node_id: number] | undefined>;
1907
+ leaf: [has_server_load: boolean, node_id: number];
1908
+ }
1909
+
1862
1910
  type ValidatedConfig = Config & {
1863
1911
  kit: ValidatedKitConfig;
1864
1912
  extensions: string[];
@@ -2356,6 +2404,17 @@ declare module '$app/state' {
2356
2404
  * {/if}
2357
2405
  * ```
2358
2406
  *
2407
+ * Changes to `page` are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes)
2408
+ *
2409
+ * ```svelte
2410
+ * <!--- file: +page.svelte --->
2411
+ * <script>
2412
+ * import { page } from '$app/state';
2413
+ * const id = $derived(page.params.id); // This will correctly update id for usage on this page
2414
+ * $: badId = page.params.id; // Do not use; will never update after initial load
2415
+ * </script>
2416
+ * ```
2417
+ *
2359
2418
  * On the server, values can only be read during rendering (in other words _not_ in e.g. `load` functions). In the browser, the values can be read at any time.
2360
2419
  *
2361
2420
  * */
@@ -79,6 +79,7 @@
79
79
  "PrerenderEntryGenerator",
80
80
  "SSREndpoint",
81
81
  "SSRRoute",
82
+ "SSRClientRoute",
82
83
  "ValidatedConfig",
83
84
  "ValidatedKitConfig",
84
85
  "isHttpError",
@@ -159,6 +160,6 @@
159
160
  null,
160
161
  null
161
162
  ],
162
- "mappings": "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",
163
+ "mappings": "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",
163
164
  "ignoreList": []
164
165
  }