@sveltejs/kit 1.0.0-next.525 → 1.0.0-next.527

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.525",
3
+ "version": "1.0.0-next.527",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -10,7 +10,7 @@
10
10
  "homepage": "https://kit.svelte.dev",
11
11
  "type": "module",
12
12
  "dependencies": {
13
- "@sveltejs/vite-plugin-svelte": "^1.0.5",
13
+ "@sveltejs/vite-plugin-svelte": "^1.1.0",
14
14
  "@types/cookie": "^0.5.1",
15
15
  "cookie": "^0.5.0",
16
16
  "devalue": "^4.0.0",
@@ -21,7 +21,7 @@
21
21
  "set-cookie-parser": "^2.4.8",
22
22
  "sirv": "^2.0.2",
23
23
  "tiny-glob": "^0.2.9",
24
- "undici": "^5.11.0"
24
+ "undici": "5.12.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@playwright/test": "^1.25.0",
@@ -66,6 +66,7 @@ export function generate_manifest({ build_data, relative_path, routes, format =
66
66
  pattern: ${route.pattern},
67
67
  names: ${s(route.names)},
68
68
  types: ${s(route.types)},
69
+ optional: ${s(route.optional)},
69
70
  page: ${route.page ? `{ layouts: ${get_nodes(route.page.layouts)}, errors: ${get_nodes(route.page.errors)}, leaf: ${route.page.leaf} }` : 'null'},
70
71
  endpoint: ${route.endpoint ? loader(`${relative_path}/${resolve_symlinks(build_data.server.vite_manifest, route.endpoint.file).chunk.file}`) : 'null'}
71
72
  }`;
@@ -121,7 +121,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
121
121
  );
122
122
  }
123
123
 
124
- const { pattern, names, types } = parse_route_id(id);
124
+ const { pattern, names, types, optional } = parse_route_id(id);
125
125
 
126
126
  /** @type {import('types').RouteData} */
127
127
  const route = {
@@ -132,6 +132,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
132
132
  pattern,
133
133
  names,
134
134
  types,
135
+ optional,
135
136
 
136
137
  layout: null,
137
138
  error: null,
@@ -228,6 +229,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
228
229
  pattern: /^$/,
229
230
  names: [],
230
231
  types: [],
232
+ optional: [],
231
233
  parent: null,
232
234
  layout: null,
233
235
  error: null,
@@ -195,7 +195,9 @@ function update_types(config, routes, route, to_delete = new Set()) {
195
195
  // Makes sure a type is "repackaged" and therefore more readable
196
196
  declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
197
197
  declarations.push(
198
- `type RouteParams = { ${route.names.map((param) => `${param}: string`).join('; ')} }`
198
+ `type RouteParams = { ${route.names
199
+ .map((param, idx) => `${param}${route.optional[idx] ? '?' : ''}: string`)
200
+ .join('; ')} }`
199
201
  );
200
202
 
201
203
  // These could also be placed in our public types, but it would bloat them unnecessarily and we may want to change these in the future
@@ -95,6 +95,8 @@ function get_raw_body(req, body_size_limit) {
95
95
  /** @type {import('@sveltejs/kit/node').getRequest} */
96
96
  export async function getRequest({ request, base, bodySizeLimit }) {
97
97
  return new Request(base + request.url, {
98
+ // @ts-expect-error
99
+ duplex: 'half',
98
100
  method: request.method,
99
101
  headers: /** @type {Record<string, string>} */ (request.headers),
100
102
  body: get_raw_body(request, bodySizeLimit)
@@ -172,6 +172,7 @@ export async function dev(vite, vite_config, svelte_config) {
172
172
  pattern: route.pattern,
173
173
  names: route.names,
174
174
  types: route.types,
175
+ optional: route.optional,
175
176
  page: route.page,
176
177
  endpoint: endpoint
177
178
  ? async () => {
@@ -61,7 +61,7 @@ const enforced_config = {
61
61
 
62
62
  /** @return {import('vite').Plugin[]} */
63
63
  export function sveltekit() {
64
- return [...svelte(), kit()];
64
+ return [...svelte({ prebundleSvelteLibraries: true }), kit()];
65
65
  }
66
66
 
67
67
  /**
@@ -164,13 +164,19 @@ export function create_client({ target, base, trailing_slash }) {
164
164
 
165
165
  /**
166
166
  * @param {string | URL} url
167
- * @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any }} opts
167
+ * @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any; invalidateAll?: boolean }} opts
168
168
  * @param {string[]} redirect_chain
169
169
  * @param {{}} [nav_token]
170
170
  */
171
171
  async function goto(
172
172
  url,
173
- { noscroll = false, replaceState = false, keepfocus = false, state = {} },
173
+ {
174
+ noscroll = false,
175
+ replaceState = false,
176
+ keepfocus = false,
177
+ state = {},
178
+ invalidateAll = false
179
+ },
174
180
  redirect_chain,
175
181
  nav_token
176
182
  ) {
@@ -188,7 +194,11 @@ export function create_client({ target, base, trailing_slash }) {
188
194
  replaceState
189
195
  },
190
196
  nav_token,
191
- accepted: () => {},
197
+ accepted: () => {
198
+ if (invalidateAll) {
199
+ force_invalidation = true;
200
+ }
201
+ },
192
202
  blocked: () => {},
193
203
  type: 'goto'
194
204
  });
@@ -1212,7 +1222,7 @@ export function create_client({ target, base, trailing_slash }) {
1212
1222
  post_update();
1213
1223
  }
1214
1224
  } else if (result.type === 'redirect') {
1215
- goto(result.location, {}, []);
1225
+ goto(result.location, { invalidateAll: true }, []);
1216
1226
  } else {
1217
1227
  /** @type {Record<string, any>} */
1218
1228
  const props = {
@@ -11,14 +11,14 @@ export function parse(nodes, server_loads, dictionary, matchers) {
11
11
  const layouts_with_server_load = new Set(server_loads);
12
12
 
13
13
  return Object.entries(dictionary).map(([id, [leaf, layouts, errors]]) => {
14
- const { pattern, names, types } = parse_route_id(id);
14
+ const { pattern, names, types, optional } = parse_route_id(id);
15
15
 
16
16
  const route = {
17
17
  id,
18
18
  /** @param {string} path */
19
19
  exec: (path) => {
20
20
  const match = pattern.exec(path);
21
- if (match) return exec(match, id, names, types, matchers);
21
+ if (match) return exec(match, { names, types, optional }, matchers);
22
22
  },
23
23
  errors: [1, ...(errors || [])].map((n) => nodes[n]),
24
24
  layouts: [0, ...(layouts || [])].map(create_layout_loader),
@@ -14,7 +14,7 @@ export interface Client {
14
14
  // public API, exposed via $app/navigation
15
15
  after_navigate: typeof afterNavigate;
16
16
  before_navigate: typeof beforeNavigate;
17
- disable_scroll_handling: () => void;
17
+ disable_scroll_handling(): void;
18
18
  goto: typeof goto;
19
19
  invalidate: typeof invalidate;
20
20
  invalidateAll: typeof invalidateAll;
@@ -23,7 +23,7 @@ export interface Client {
23
23
  apply_action: typeof applyAction;
24
24
 
25
25
  // private API
26
- _hydrate: (opts: {
26
+ _hydrate(opts: {
27
27
  status: number;
28
28
  error: App.Error;
29
29
  node_ids: number[];
@@ -31,8 +31,8 @@ export interface Client {
31
31
  routeId: string | null;
32
32
  data: Array<import('types').ServerDataNode | null>;
33
33
  form: Record<string, any> | null;
34
- }) => Promise<void>;
35
- _start_router: () => void;
34
+ }): Promise<void>;
35
+ _start_router(): void;
36
36
  }
37
37
 
38
38
  export type NavigationIntent = {
@@ -1,10 +1,20 @@
1
1
  import { parse, serialize } from 'cookie';
2
+ import { DATA_SUFFIX } from '../../constants.js';
3
+ import { normalize_path } from '../../utils/url.js';
4
+
5
+ /**
6
+ * Tracks all cookies set during dev mode so we can emit warnings
7
+ * when we detect that there's likely cookie misusage due to wrong paths
8
+ *
9
+ * @type {Record<string, Set<string>>} */
10
+ const cookie_paths = {};
2
11
 
3
12
  /**
4
13
  * @param {Request} request
5
14
  * @param {URL} url
15
+ * @param {Pick<import('types').SSROptions, 'dev' | 'trailing_slash'>} options
6
16
  */
7
- export function get_cookies(request, url) {
17
+ export function get_cookies(request, url, options) {
8
18
  const header = request.headers.get('cookie') ?? '';
9
19
 
10
20
  const initial_cookies = parse(header);
@@ -42,7 +52,17 @@ export function get_cookies(request, url) {
42
52
 
43
53
  const decode = opts?.decode || decodeURIComponent;
44
54
  const req_cookies = parse(header, { decode });
45
- return req_cookies[name]; // the decoded string or undefined
55
+ const cookie = req_cookies[name]; // the decoded string or undefined
56
+
57
+ if (!options.dev || cookie) {
58
+ return cookie;
59
+ }
60
+
61
+ if (c || cookie_paths[name]?.size > 0) {
62
+ console.warn(
63
+ `Cookie with name '${name}' was not found, but a cookie with that name exists at a sub path. Did you mean to set its 'path' to '/'?`
64
+ );
65
+ }
46
66
  },
47
67
 
48
68
  /**
@@ -51,14 +71,45 @@ export function get_cookies(request, url) {
51
71
  * @param {import('cookie').CookieSerializeOptions} opts
52
72
  */
53
73
  set(name, value, opts = {}) {
74
+ let path = opts.path;
75
+ if (!path) {
76
+ const normalized = normalize_path(
77
+ // Remove suffix: 'foo/__data.json' would mean the cookie path is '/foo',
78
+ // whereas a direct hit of /foo would mean the cookie path is '/'
79
+ url.pathname.endsWith(DATA_SUFFIX)
80
+ ? url.pathname.slice(0, -DATA_SUFFIX.length)
81
+ : url.pathname,
82
+ options.trailing_slash
83
+ );
84
+ // Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
85
+ path = normalized.split('/').slice(0, -1).join('/') || '/';
86
+ }
87
+
54
88
  new_cookies[name] = {
55
89
  name,
56
90
  value,
57
91
  options: {
58
92
  ...defaults,
59
- ...opts
93
+ ...opts,
94
+ path
60
95
  }
61
96
  };
97
+
98
+ if (options.dev) {
99
+ cookie_paths[name] = cookie_paths[name] || new Set();
100
+ if (!value) {
101
+ if (!cookie_paths[name].has(path) && cookie_paths[name].size > 0) {
102
+ console.warn(
103
+ `Trying to delete cookie '${name}' at path '${path}', but a cookie with that name only exists at a different path.`
104
+ );
105
+ }
106
+ cookie_paths[name].delete(path);
107
+ } else {
108
+ // We could also emit a warning here if the cookie already exists at a different path,
109
+ // but that's more likely a false positive because it's valid to set the same name at different paths
110
+ cookie_paths[name].add(path);
111
+ }
112
+ }
62
113
  },
63
114
 
64
115
  /**
@@ -66,15 +117,10 @@ export function get_cookies(request, url) {
66
117
  * @param {import('cookie').CookieSerializeOptions} opts
67
118
  */
68
119
  delete(name, opts = {}) {
69
- new_cookies[name] = {
70
- name,
71
- value: '',
72
- options: {
73
- ...defaults,
74
- ...opts,
75
- maxAge: 0
76
- }
77
- };
120
+ cookies.set(name, '', {
121
+ ...opts,
122
+ maxAge: 0
123
+ });
78
124
  },
79
125
 
80
126
  /**
@@ -67,7 +67,7 @@ export async function respond(request, options, state) {
67
67
  const match = candidate.pattern.exec(decoded);
68
68
  if (!match) continue;
69
69
 
70
- const matched = exec(match, candidate.id, candidate.names, candidate.types, matchers);
70
+ const matched = exec(match, candidate, matchers);
71
71
  if (matched) {
72
72
  route = candidate;
73
73
  params = decode_params(matched);
@@ -96,7 +96,7 @@ export async function respond(request, options, state) {
96
96
  /** @type {Record<string, string>} */
97
97
  const headers = {};
98
98
 
99
- const { cookies, new_cookies, get_cookie_header } = get_cookies(request, url);
99
+ const { cookies, new_cookies, get_cookie_header } = get_cookies(request, url, options);
100
100
 
101
101
  if (state.prerendering) disable_search(url);
102
102
 
@@ -182,6 +182,20 @@ export async function render_response({
182
182
  `Data returned from \`load\` while rendering ${event.routeId} is not serializable: ${error.message} (data.${match[2]})`
183
183
  );
184
184
  }
185
+
186
+ const nonPojoError = /pojo/i.exec(error.message);
187
+
188
+ if (nonPojoError) {
189
+ const constructorName = branch.find(({ server_data }) => server_data?.data?.constructor?.name)
190
+ ?.server_data?.data?.constructor?.name;
191
+
192
+ throw new Error(
193
+ `Data returned from \`load\` (while rendering ${event.routeId}) must be a plain object${
194
+ constructorName ? ` rather than an instance of ${constructorName}` : ''
195
+ }`
196
+ );
197
+ }
198
+
185
199
  throw error;
186
200
  }
187
201
 
@@ -8,6 +8,9 @@ export function parse_route_id(id) {
8
8
  /** @type {string[]} */
9
9
  const types = [];
10
10
 
11
+ /** @type {boolean[]} */
12
+ const optional = [];
13
+
11
14
  // `/foo` should get an optional trailing slash, `/foo.json` should not
12
15
  // const add_trailing_slash = !/\.[a-z]+$/.test(key);
13
16
  let add_trailing_slash = true;
@@ -24,6 +27,7 @@ export function parse_route_id(id) {
24
27
  if (rest_match) {
25
28
  names.push(rest_match[1]);
26
29
  types.push(rest_match[2]);
30
+ optional.push(false);
27
31
  return '(?:/(.*))?';
28
32
  }
29
33
  // special case — /[[optional]]/ could contain zero segments
@@ -31,6 +35,7 @@ export function parse_route_id(id) {
31
35
  if (optional_match) {
32
36
  names.push(optional_match[1]);
33
37
  types.push(optional_match[2]);
38
+ optional.push(true);
34
39
  return '(?:/([^/]+))?';
35
40
  }
36
41
 
@@ -51,14 +56,15 @@ export function parse_route_id(id) {
51
56
  );
52
57
  }
53
58
 
54
- const [, optional, rest, name, type] = match;
59
+ const [, is_optional, is_rest, name, type] = match;
55
60
  // It's assumed that the following invalid route id cases are already checked
56
61
  // - unbalanced brackets
57
62
  // - optional param following rest param
58
63
 
59
64
  names.push(name);
60
65
  types.push(type);
61
- return rest ? '(.*?)' : optional ? '([^/]*)?' : '([^/]+?)';
66
+ optional.push(!!is_optional);
67
+ return is_rest ? '(.*?)' : is_optional ? '([^/]*)?' : '([^/]+?)';
62
68
  }
63
69
 
64
70
  if (is_last && content.includes('.')) add_trailing_slash = false;
@@ -88,7 +94,7 @@ export function parse_route_id(id) {
88
94
  .join('')}${add_trailing_slash ? '/?' : ''}$`
89
95
  );
90
96
 
91
- return { pattern, names, types };
97
+ return { pattern, names, types, optional };
92
98
  }
93
99
 
94
100
  /**
@@ -112,34 +118,32 @@ export function get_route_segments(route) {
112
118
 
113
119
  /**
114
120
  * @param {RegExpMatchArray} match
115
- * @param {string} routeId
116
- * @param {string[]} names
117
- * @param {string[]} types
121
+ * @param {{
122
+ * names: string[];
123
+ * types: string[];
124
+ * optional: boolean[];
125
+ * }} candidate
118
126
  * @param {Record<string, import('types').ParamMatcher>} matchers
119
127
  */
120
- export function exec(match, routeId, names, types, matchers) {
128
+ export function exec(match, { names, types, optional }, matchers) {
121
129
  /** @type {Record<string, string>} */
122
130
  const params = {};
123
- let last_type_idx = -1;
124
131
 
125
132
  for (let i = 0; i < names.length; i += 1) {
126
133
  const name = names[i];
127
134
  const type = types[i];
128
- let value = match[i + 1] || '';
129
-
130
- if (type) {
131
- const matcher = matchers[type];
132
- if (!matcher) throw new Error(`Missing "${type}" param matcher`); // TODO do this ahead of time?
133
-
134
- last_type_idx = routeId.indexOf(`=${type}`, last_type_idx + 1);
135
- const is_empty_optional_param =
136
- !value &&
137
- // a param without a value can only be an optional or rest param
138
- routeId.lastIndexOf('[[', last_type_idx) > routeId.lastIndexOf('[...', last_type_idx);
139
- if (!is_empty_optional_param && !matcher(value)) return;
140
- }
135
+ let value = match[i + 1];
136
+
137
+ if (value || !optional[i]) {
138
+ if (type) {
139
+ const matcher = matchers[type];
140
+ if (!matcher) throw new Error(`Missing "${type}" param matcher`); // TODO do this ahead of time?
141
141
 
142
- params[name] = value;
142
+ if (!matcher(value)) return;
143
+ }
144
+
145
+ params[name] = value ?? '';
146
+ }
143
147
  }
144
148
 
145
149
  return params;
@@ -103,7 +103,7 @@ declare module '$app/forms' {
103
103
  data: FormData;
104
104
  form: HTMLFormElement;
105
105
  controller: AbortController;
106
- cancel: () => void;
106
+ cancel(): void;
107
107
  }) =>
108
108
  | void
109
109
  | ((opts: {
@@ -114,7 +114,7 @@ declare module '$app/forms' {
114
114
  * Call this to get the default behavior of a form submission response.
115
115
  * @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission.
116
116
  */
117
- update: (options?: { reset: boolean }) => Promise<void>;
117
+ update(options?: { reset: boolean }): Promise<void>;
118
118
  }) => void);
119
119
 
120
120
  /**
@@ -144,7 +144,7 @@ declare module '$app/forms' {
144
144
  * If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback.
145
145
  */
146
146
  submit?: SubmitFunction<Success, Invalid>
147
- ): { destroy: () => void };
147
+ ): { destroy(): void };
148
148
 
149
149
  /**
150
150
  * This action updates the `form` property of the current page with the given data and updates `$page.status`.
@@ -182,14 +182,32 @@ declare module '$app/navigation' {
182
182
  * Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`.
183
183
  *
184
184
  * @param url Where to navigate to. Note that if you've set [`config.kit.paths.base`](https://kit.svelte.dev/docs/configuration#paths) and the URL is root-relative, you need to prepend the base path if you want to navigate within the app.
185
- * @param opts.replaceState If `true`, will replace the current `history` entry rather than creating a new one with `pushState`
186
- * @param opts.noscroll If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
187
- * @param opts.keepfocus If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
188
- * @param opts.state The state of the new/updated history entry
185
+ * @param opts Options related to the navigation
189
186
  */
190
187
  export function goto(
191
188
  url: string | URL,
192
- opts?: { replaceState?: boolean; noscroll?: boolean; keepfocus?: boolean; state?: any }
189
+ opts?: {
190
+ /**
191
+ * If `true`, will replace the current `history` entry rather than creating a new one with `pushState`
192
+ */
193
+ replaceState?: boolean;
194
+ /**
195
+ * If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
196
+ */
197
+ noscroll?: boolean;
198
+ /**
199
+ * If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
200
+ */
201
+ keepfocus?: boolean;
202
+ /**
203
+ * The state of the new/updated history entry
204
+ */
205
+ state?: any;
206
+ /**
207
+ * If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#invalidation for more info on invalidation.
208
+ */
209
+ invalidateAll?: boolean;
210
+ }
193
211
  ): Promise<void>;
194
212
  /**
195
213
  * Causes any `load` functions belonging to the currently active page to re-run if they depend on the `url` in question, via `fetch` or `depends`. Returns a `Promise` that resolves when the page is subsequently updated.
@@ -244,7 +262,7 @@ declare module '$app/navigation' {
244
262
  * `beforeNavigate` must be called during a component initialization. It remains active as long as the component is mounted.
245
263
  */
246
264
  export function beforeNavigate(
247
- callback: (navigation: Navigation & { cancel: () => void }) => void
265
+ callback: (navigation: Navigation & { cancel(): void }) => void
248
266
  ): void;
249
267
 
250
268
  /**
@@ -303,7 +321,7 @@ declare module '$app/stores' {
303
321
  /**
304
322
  * A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
305
323
  */
306
- export const updated: Readable<boolean> & { check: () => boolean };
324
+ export const updated: Readable<boolean> & { check(): boolean };
307
325
 
308
326
  /**
309
327
  * A function that returns all of the contextual stores. On the server, this must be called during component initialization.
package/types/index.d.ts CHANGED
@@ -79,7 +79,7 @@ export interface Builder {
79
79
  */
80
80
  createEntries(fn: (route: RouteDefinition) => AdapterEntry): Promise<void>;
81
81
 
82
- generateManifest: (opts: { relativePath: string; format?: 'esm' | 'cjs' }) => string;
82
+ generateManifest(opts: { relativePath: string; format?: 'esm' | 'cjs' }): string;
83
83
 
84
84
  getBuildDirectory(name: string): string;
85
85
  getClientDirectory(): string;
@@ -118,7 +118,7 @@ export interface Builder {
118
118
  from: string,
119
119
  to: string,
120
120
  opts?: {
121
- filter?: (basename: string) => boolean;
121
+ filter?(basename: string): boolean;
122
122
  replace?: Record<string, string>;
123
123
  }
124
124
  ): string[];
@@ -137,8 +137,8 @@ export interface Config {
137
137
  source?: string;
138
138
  dir?: string;
139
139
  emitTypes?: boolean;
140
- exports?: (filepath: string) => boolean;
141
- files?: (filepath: string) => boolean;
140
+ exports?(filepath: string): boolean;
141
+ files?(filepath: string): boolean;
142
142
  };
143
143
  preprocess?: any;
144
144
  [key: string]: any;
@@ -161,6 +161,8 @@ export interface Cookies {
161
161
 
162
162
  /**
163
163
  * Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
164
+ *
165
+ * By default, the `path` of a cookie is the 'directory' of the current pathname. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app.
164
166
  */
165
167
  delete(name: string, opts?: import('cookie').CookieSerializeOptions): void;
166
168
 
@@ -225,7 +227,7 @@ export interface KitConfig {
225
227
  };
226
228
  serviceWorker?: {
227
229
  register?: boolean;
228
- files?: (filepath: string) => boolean;
230
+ files?(filepath: string): boolean;
229
231
  };
230
232
  trailingSlash?: TrailingSlash;
231
233
  version?: {
@@ -311,14 +313,14 @@ export interface LoadEvent<
311
313
  *
312
314
  * `setHeaders` has no effect when a `load` function runs in the browser.
313
315
  */
314
- setHeaders: (headers: Record<string, string>) => void;
316
+ setHeaders(headers: Record<string, string>): void;
315
317
  /**
316
318
  * `await parent()` returns data from parent `+layout.js` `load` functions.
317
319
  * Implicitly, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will return and forward data from parent `+layout.server.js` files.
318
320
  *
319
321
  * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
320
322
  */
321
- parent: () => Promise<ParentData>;
323
+ parent(): Promise<ParentData>;
322
324
  /**
323
325
  * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/modules#$app-navigation-invalidate) to cause `load` to rerun.
324
326
  *
@@ -356,7 +358,7 @@ export interface LoadEvent<
356
358
  * <button on:click={increase}>Increase Count</button>
357
359
  * ```
358
360
  */
359
- depends: (...deps: string[]) => void;
361
+ depends(...deps: string[]): void;
360
362
  }
361
363
 
362
364
  export interface NavigationEvent<
@@ -449,7 +451,7 @@ export interface RequestEvent<
449
451
  /**
450
452
  * The client's IP address, set by the adapter.
451
453
  */
452
- getClientAddress: () => string;
454
+ getClientAddress(): string;
453
455
  /**
454
456
  * Contains custom data that was added to the request within the [`handle hook`](https://kit.svelte.dev/docs/hooks#server-hooks-handle).
455
457
  */
@@ -492,7 +494,7 @@ export interface RequestEvent<
492
494
  *
493
495
  * You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://kit.svelte.dev/docs/types#sveltejs-kit-cookies) API instead.
494
496
  */
495
- setHeaders: (headers: Record<string, string>) => void;
497
+ setHeaders(headers: Record<string, string>): void;
496
498
  /**
497
499
  * The URL of the current page or endpoint
498
500
  */
@@ -511,8 +513,8 @@ export interface RequestHandler<
511
513
  }
512
514
 
513
515
  export interface ResolveOptions {
514
- transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise<string | undefined>;
515
- filterSerializedResponseHeaders?: (name: string, value: string) => boolean;
516
+ transformPageChunk?(input: { html: string; done: boolean }): MaybePromise<string | undefined>;
517
+ filterSerializedResponseHeaders?(name: string, value: string): boolean;
516
518
  }
517
519
 
518
520
  export class Server {
@@ -540,7 +542,7 @@ export interface SSRManifest {
540
542
  };
541
543
  nodes: SSRNodeLoader[];
542
544
  routes: SSRRoute[];
543
- matchers: () => Promise<Record<string, ParamMatcher>>;
545
+ matchers(): Promise<Record<string, ParamMatcher>>;
544
546
  };
545
547
  }
546
548
 
@@ -565,7 +567,7 @@ export interface ServerLoadEvent<
565
567
  *
566
568
  * Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
567
569
  */
568
- parent: () => Promise<ParentData>;
570
+ parent(): Promise<ParentData>;
569
571
  /**
570
572
  * This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/modules#$app-navigation-invalidate) to cause `load` to rerun.
571
573
  *
@@ -603,7 +605,7 @@ export interface ServerLoadEvent<
603
605
  * <button on:click={increase}>Increase Count</button>
604
606
  * ```
605
607
  */
606
- depends: (...deps: string[]) => void;
608
+ depends(...deps: string[]): void;
607
609
  }
608
610
 
609
611
  export interface Action<
@@ -83,7 +83,7 @@ export type CSRPageNodeLoader = () => Promise<CSRPageNode>;
83
83
  */
84
84
  export type CSRRoute = {
85
85
  id: string;
86
- exec: (path: string) => undefined | Record<string, string>;
86
+ exec(path: string): undefined | Record<string, string>;
87
87
  errors: Array<CSRPageNodeLoader | undefined>;
88
88
  layouts: Array<[boolean, CSRPageNodeLoader] | undefined>;
89
89
  leaf: [boolean, CSRPageNodeLoader];
@@ -169,6 +169,7 @@ export interface RouteData {
169
169
  pattern: RegExp;
170
170
  names: string[];
171
171
  types: string[];
172
+ optional: boolean[];
172
173
 
173
174
  layout: PageNode | null;
174
175
  error: PageNode | null;
@@ -260,7 +261,7 @@ export interface SSRNode {
260
261
  /** external CSS files */
261
262
  stylesheets: string[];
262
263
  /** inlined styles */
263
- inline_styles?: () => MaybePromise<Record<string, string>>;
264
+ inline_styles?(): MaybePromise<Record<string, string>>;
264
265
 
265
266
  shared: {
266
267
  load?: Load;
@@ -335,6 +336,7 @@ export interface SSRRoute {
335
336
  pattern: RegExp;
336
337
  names: string[];
337
338
  types: string[];
339
+ optional: boolean[];
338
340
 
339
341
  page: PageNodeIndexes | null;
340
342
 
@@ -343,7 +345,7 @@ export interface SSRRoute {
343
345
 
344
346
  export interface SSRState {
345
347
  fallback?: string;
346
- getClientAddress: () => string;
348
+ getClientAddress(): string;
347
349
  initiator?: SSRRoute | SSRErrorPage;
348
350
  platform?: any;
349
351
  prerendering?: PrerenderOptions;
@@ -15,15 +15,15 @@ export interface AdapterEntry {
15
15
  * if it should be treated as a fallback for the current route. For example, `/foo/[c]`
16
16
  * is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes
17
17
  */
18
- filter: (route: RouteDefinition) => boolean;
18
+ filter(route: RouteDefinition): boolean;
19
19
 
20
20
  /**
21
21
  * A function that is invoked once the entry has been created. This is where you
22
22
  * should write the function to the filesystem and generate redirect manifests.
23
23
  */
24
- complete: (entry: {
25
- generateManifest: (opts: { relativePath: string; format?: 'esm' | 'cjs' }) => string;
26
- }) => MaybePromise<void>;
24
+ complete(entry: {
25
+ generateManifest(opts: { relativePath: string; format?: 'esm' | 'cjs' }): string;
26
+ }): MaybePromise<void>;
27
27
  }
28
28
 
29
29
  // Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts
@@ -195,7 +195,7 @@ export type PrerenderOption = boolean | 'auto';
195
195
  export type PrerenderMap = Map<string, PrerenderOption>;
196
196
 
197
197
  export interface RequestOptions {
198
- getClientAddress: () => string;
198
+ getClientAddress(): string;
199
199
  platform?: App.Platform;
200
200
  }
201
201