@sveltejs/kit 1.0.0-next.576 → 1.0.0-next.578

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.576",
3
+ "version": "1.0.0-next.578",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -1,11 +1,14 @@
1
+ import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';
2
+ import { pipeline } from 'node:stream';
3
+ import { promisify } from 'node:util';
4
+ import { fork } from 'node:child_process';
5
+ import { fileURLToPath } from 'node:url';
1
6
  import glob from 'tiny-glob';
2
7
  import zlib from 'zlib';
3
- import { existsSync, statSync, createReadStream, createWriteStream } from 'fs';
4
- import { pipeline } from 'stream';
5
- import { promisify } from 'util';
6
8
  import { copy, rimraf, mkdirp } from '../../utils/filesystem.js';
7
9
  import { generate_manifest } from '../generate_manifest/index.js';
8
10
  import { get_route_segments } from '../../utils/routing.js';
11
+ import { get_env } from '../../exports/vite/utils.js';
9
12
 
10
13
  const pipe = promisify(pipeline);
11
14
 
@@ -104,6 +107,33 @@ export function create_builder({ config, build_data, routes, prerendered, log })
104
107
  }
105
108
  },
106
109
 
110
+ generateFallback(dest) {
111
+ // do prerendering in a subprocess so any dangling stuff gets killed upon completion
112
+ const script = fileURLToPath(new URL('../prerender/fallback.js', import.meta.url));
113
+
114
+ const manifest_path = `${config.kit.outDir}/output/server/manifest-full.js`;
115
+
116
+ const env = get_env(config.kit.env, 'production');
117
+
118
+ return new Promise((fulfil, reject) => {
119
+ const child = fork(
120
+ script,
121
+ [dest, manifest_path, JSON.stringify({ ...env.private, ...env.public })],
122
+ {
123
+ stdio: 'inherit'
124
+ }
125
+ );
126
+
127
+ child.on('exit', (code) => {
128
+ if (code) {
129
+ reject(new Error(`Could not create a fallback page — failed with code ${code}`));
130
+ } else {
131
+ fulfil(undefined);
132
+ }
133
+ });
134
+ });
135
+ },
136
+
107
137
  generateManifest: ({ relativePath }) => {
108
138
  return generate_manifest({
109
139
  build_data,
@@ -132,16 +162,17 @@ export function create_builder({ config, build_data, routes, prerendered, log })
132
162
  return [...copy(`${config.kit.outDir}/output/client`, dest)];
133
163
  },
134
164
 
135
- writePrerendered(dest, { fallback } = {}) {
136
- const source = `${config.kit.outDir}/output/prerendered`;
137
- const files = [...copy(`${source}/pages`, dest), ...copy(`${source}/dependencies`, dest)];
138
-
139
- if (fallback) {
140
- files.push(fallback);
141
- copy(`${source}/fallback.html`, `${dest}/${fallback}`);
165
+ // @ts-expect-error
166
+ writePrerendered(dest, opts) {
167
+ // TODO remove for 1.0
168
+ if (opts?.fallback) {
169
+ throw new Error(
170
+ 'The fallback option no longer exists — use builder.generateFallback(fallback) instead'
171
+ );
142
172
  }
143
173
 
144
- return files;
174
+ const source = `${config.kit.outDir}/output/prerendered`;
175
+ return [...copy(`${source}/pages`, dest), ...copy(`${source}/dependencies`, dest)];
145
176
  },
146
177
 
147
178
  writeServer(dest) {
@@ -129,6 +129,8 @@ const options = object(
129
129
  checkOrigin: boolean(true)
130
130
  }),
131
131
 
132
+ embedded: boolean(false),
133
+
132
134
  // TODO: remove this for the 1.0 release
133
135
  endpointExtensions: error(
134
136
  (keypath) => `${keypath} has been renamed to config.kit.moduleExtensions`
@@ -0,0 +1,43 @@
1
+ import { readFileSync, writeFileSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+ import { pathToFileURL } from 'url';
4
+ import { mkdirp } from '../../utils/filesystem.js';
5
+ import { installPolyfills } from '../../exports/node/polyfills.js';
6
+ import { load_config } from '../config/index.js';
7
+
8
+ const [, , dest, manifest_path, env] = process.argv;
9
+
10
+ /** @type {import('types').ValidatedKitConfig} */
11
+ const config = (await load_config()).kit;
12
+
13
+ installPolyfills();
14
+
15
+ const server_root = join(config.outDir, 'output');
16
+
17
+ /** @type {import('types').ServerModule} */
18
+ const { Server, override } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
19
+
20
+ /** @type {import('types').SSRManifest} */
21
+ const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
22
+
23
+ override({
24
+ building: true,
25
+ paths: config.paths,
26
+ read: (file) => readFileSync(join(config.files.assets, file))
27
+ });
28
+
29
+ const server = new Server(manifest);
30
+ await server.init({ env: JSON.parse(env) });
31
+
32
+ const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
33
+ getClientAddress: () => {
34
+ throw new Error('Cannot read clientAddress during prerendering');
35
+ },
36
+ prerendering: {
37
+ fallback: true,
38
+ dependencies: new Map()
39
+ }
40
+ });
41
+
42
+ mkdirp(dirname(dest));
43
+ writeFileSync(dest, await rendered.text());
@@ -453,18 +453,6 @@ export async function prerender() {
453
453
  );
454
454
  }
455
455
 
456
- const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
457
- getClientAddress,
458
- prerendering: {
459
- fallback: true,
460
- dependencies: new Map()
461
- }
462
- });
463
-
464
- const file = `${config.outDir}/output/prerendered/fallback.html`;
465
- mkdirp(dirname(file));
466
- writeFileSync(file, await rendered.text());
467
-
468
456
  output_and_exit({ prerendered, prerender_map });
469
457
  }
470
458
 
@@ -1,4 +1,4 @@
1
- import { HttpError, Redirect, ValidationError } from '../runtime/control.js';
1
+ import { HttpError, Redirect, ActionFailure } from '../runtime/control.js';
2
2
 
3
3
  // For some reason we need to type the params as well here,
4
4
  // JSdoc doesn't seem to like @type with function overloads
@@ -46,10 +46,15 @@ export function json(data, init) {
46
46
  }
47
47
 
48
48
  /**
49
- * Generates a `ValidationError` object.
49
+ * Generates an `ActionFailure` object.
50
50
  * @param {number} status
51
51
  * @param {Record<string, any> | undefined} [data]
52
52
  */
53
- export function invalid(status, data) {
54
- return new ValidationError(status, data);
53
+ export function fail(status, data) {
54
+ return new ActionFailure(status, data);
55
+ }
56
+
57
+ // TODO remove for 1.0
58
+ export function invalid() {
59
+ throw new Error('invalid(...) is now fail(...)');
55
60
  }
@@ -66,6 +66,7 @@ export class Server {
66
66
  check_origin: ${s(config.kit.csrf.checkOrigin)},
67
67
  },
68
68
  dev: false,
69
+ embedded: ${config.kit.embedded},
69
70
  handle_error: (error, event) => {
70
71
  return this.options.hooks.handleError({
71
72
  error,
@@ -147,7 +147,8 @@ export function get_default_build_config({ config, input, ssr, outDir }) {
147
147
  __SVELTEKIT_APP_VERSION_FILE__: JSON.stringify(`${config.kit.appDir}/version.json`),
148
148
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: JSON.stringify(config.kit.version.pollInterval),
149
149
  __SVELTEKIT_BROWSER__: ssr ? 'false' : 'true',
150
- __SVELTEKIT_DEV__: 'false'
150
+ __SVELTEKIT_DEV__: 'false',
151
+ __SVELTEKIT_EMBEDDED__: config.kit.embedded ? 'true' : 'false'
151
152
  },
152
153
  publicDir: ssr ? false : config.kit.files.assets,
153
154
  resolve: {
@@ -449,6 +449,7 @@ export async function dev(vite, vite_config, svelte_config) {
449
449
  check_origin: svelte_config.kit.csrf.checkOrigin
450
450
  },
451
451
  dev: true,
452
+ embedded: svelte_config.kit.embedded,
452
453
  handle_error: async (error, event) => {
453
454
  const error_object = await hooks.handleError({
454
455
  error: new Proxy(error, {
@@ -262,7 +262,8 @@ function kit({ svelte_config }) {
262
262
  define: {
263
263
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0',
264
264
  __SVELTEKIT_BROWSER__: config_env.ssrBuild ? 'false' : 'true',
265
- __SVELTEKIT_DEV__: 'true'
265
+ __SVELTEKIT_DEV__: 'true',
266
+ __SVELTEKIT_EMBEDDED__: svelte_config.kit.embedded ? 'true' : 'false'
266
267
  },
267
268
  publicDir: svelte_config.kit.files.assets,
268
269
  resolve: {
@@ -47,7 +47,7 @@ export function enhance(form, submit = () => {}) {
47
47
  await invalidateAll();
48
48
  }
49
49
 
50
- // For success/invalid results, only apply action if it belongs to the
50
+ // For success/failure results, only apply action if it belongs to the
51
51
  // current page, otherwise `form` will be updated erroneously
52
52
  if (
53
53
  location.origin + location.pathname === action.origin + action.pathname ||
@@ -89,6 +89,7 @@ function check_for_removed_attributes() {
89
89
  * @returns {import('./types').Client}
90
90
  */
91
91
  export function create_client({ target, base }) {
92
+ const container = __SVELTEKIT_EMBEDDED__ ? target : document.documentElement;
92
93
  /** @type {Array<((url: URL) => boolean)>} */
93
94
  const invalidated = [];
94
95
 
@@ -591,6 +592,7 @@ export function create_client({ target, base }) {
591
592
  uses.url = true;
592
593
  }),
593
594
  async fetch(resource, init) {
595
+ /** @type {URL | string} */
594
596
  let requested;
595
597
 
596
598
  if (resource instanceof Request) {
@@ -1199,7 +1201,7 @@ export function create_client({ target, base }) {
1199
1201
  /** @type {NodeJS.Timeout} */
1200
1202
  let mousemove_timeout;
1201
1203
 
1202
- target.addEventListener('mousemove', (event) => {
1204
+ container.addEventListener('mousemove', (event) => {
1203
1205
  const target = /** @type {Element} */ (event.target);
1204
1206
 
1205
1207
  clearTimeout(mousemove_timeout);
@@ -1213,8 +1215,8 @@ export function create_client({ target, base }) {
1213
1215
  preload(/** @type {Element} */ (event.composedPath()[0]), 1);
1214
1216
  }
1215
1217
 
1216
- target.addEventListener('mousedown', tap);
1217
- target.addEventListener('touchstart', tap, { passive: true });
1218
+ container.addEventListener('mousedown', tap);
1219
+ container.addEventListener('touchstart', tap, { passive: true });
1218
1220
 
1219
1221
  const observer = new IntersectionObserver(
1220
1222
  (entries) => {
@@ -1233,7 +1235,7 @@ export function create_client({ target, base }) {
1233
1235
  * @param {number} priority
1234
1236
  */
1235
1237
  function preload(element, priority) {
1236
- const a = find_anchor(element, target);
1238
+ const a = find_anchor(element, container);
1237
1239
  if (!a) return;
1238
1240
 
1239
1241
  const { url, external } = get_link_info(a, base);
@@ -1253,7 +1255,7 @@ export function create_client({ target, base }) {
1253
1255
  function after_navigate() {
1254
1256
  observer.disconnect();
1255
1257
 
1256
- for (const a of target.querySelectorAll('a')) {
1258
+ for (const a of container.querySelectorAll('a')) {
1257
1259
  const { url, external } = get_link_info(a, base);
1258
1260
  if (external) continue;
1259
1261
 
@@ -1457,14 +1459,14 @@ export function create_client({ target, base }) {
1457
1459
  }
1458
1460
 
1459
1461
  /** @param {MouseEvent} event */
1460
- target.addEventListener('click', (event) => {
1462
+ container.addEventListener('click', (event) => {
1461
1463
  // Adapted from https://github.com/visionmedia/page.js
1462
1464
  // MIT license https://github.com/visionmedia/page.js#license
1463
1465
  if (event.button || event.which !== 1) return;
1464
1466
  if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
1465
1467
  if (event.defaultPrevented) return;
1466
1468
 
1467
- const a = find_anchor(/** @type {Element} */ (event.composedPath()[0]), target);
1469
+ const a = find_anchor(/** @type {Element} */ (event.composedPath()[0]), container);
1468
1470
  if (!a) return;
1469
1471
 
1470
1472
  const { url, external, has } = get_link_info(a, base);
@@ -1534,7 +1536,7 @@ export function create_client({ target, base }) {
1534
1536
  });
1535
1537
  });
1536
1538
 
1537
- target.addEventListener('submit', (event) => {
1539
+ container.addEventListener('submit', (event) => {
1538
1540
  if (event.defaultPrevented) return;
1539
1541
 
1540
1542
  const form = /** @type {HTMLFormElement} */ (
@@ -1639,11 +1641,25 @@ export function create_client({ target, base }) {
1639
1641
  });
1640
1642
  },
1641
1643
 
1642
- _hydrate: async ({ status, error, node_ids, params, route, data: server_data_nodes, form }) => {
1644
+ _hydrate: async ({
1645
+ status = 200,
1646
+ error,
1647
+ node_ids,
1648
+ params,
1649
+ route,
1650
+ data: server_data_nodes,
1651
+ form
1652
+ }) => {
1643
1653
  hydrated = true;
1644
1654
 
1645
1655
  const url = new URL(location.href);
1646
1656
 
1657
+ if (!__SVELTEKIT_EMBEDDED__) {
1658
+ // See https://github.com/sveltejs/kit/pull/4935#issuecomment-1328093358 for one motivation
1659
+ // of determining the params on the client side.
1660
+ ({ params = {}, route = { id: null } } = get_navigation_intent(url, false) || {});
1661
+ }
1662
+
1647
1663
  /** @type {import('./types').NavigationFinished | undefined} */
1648
1664
  let result;
1649
1665
 
@@ -41,9 +41,7 @@ if (import.meta.env.DEV) {
41
41
  const method = input instanceof Request ? input.method : init?.method || 'GET';
42
42
 
43
43
  if (method !== 'GET') {
44
- const url = new URL(input instanceof Request ? input.url : input.toString(), document.baseURI)
45
- .href;
46
- cache.delete(url);
44
+ cache.delete(build_selector(input));
47
45
  }
48
46
 
49
47
  return native_fetch(input, init);
@@ -53,9 +51,7 @@ if (import.meta.env.DEV) {
53
51
  const method = input instanceof Request ? input.method : init?.method || 'GET';
54
52
 
55
53
  if (method !== 'GET') {
56
- const url = new URL(input instanceof Request ? input.url : input.toString(), document.baseURI)
57
- .href;
58
- cache.delete(url);
54
+ cache.delete(build_selector(input));
59
55
  }
60
56
 
61
57
  return native_fetch(input, init);
@@ -67,7 +63,7 @@ const cache = new Map();
67
63
  /**
68
64
  * Should be called on the initial run of load functions that hydrate the page.
69
65
  * Saves any requests with cache-control max-age to the cache.
70
- * @param {RequestInfo | URL} resource
66
+ * @param {URL | string} resource
71
67
  * @param {RequestInit} [opts]
72
68
  */
73
69
  export function initial_fetch(resource, opts) {
@@ -88,7 +84,7 @@ export function initial_fetch(resource, opts) {
88
84
 
89
85
  /**
90
86
  * Tries to get the response from the cache, if max-age allows it, else does a fetch.
91
- * @param {RequestInfo | URL} resource
87
+ * @param {URL | string} resource
92
88
  * @param {string} resolved
93
89
  * @param {RequestInit} [opts]
94
90
  */
@@ -97,7 +93,11 @@ export function subsequent_fetch(resource, resolved, opts) {
97
93
  const selector = build_selector(resource, opts);
98
94
  const cached = cache.get(selector);
99
95
  if (cached) {
100
- if (performance.now() < cached.ttl) {
96
+ // https://developer.mozilla.org/en-US/docs/Web/API/Request/cache#value
97
+ if (
98
+ performance.now() < cached.ttl &&
99
+ ['default', 'force-cache', 'only-if-cached', undefined].includes(opts?.cache)
100
+ ) {
101
101
  return new Response(cached.body, cached.init);
102
102
  }
103
103
 
@@ -110,7 +110,7 @@ export function subsequent_fetch(resource, resolved, opts) {
110
110
 
111
111
  /**
112
112
  * Build the cache key for a given request
113
- * @param {RequestInfo | URL} resource
113
+ * @param {URL | RequestInfo} resource
114
114
  * @param {RequestInit} [opts]
115
115
  */
116
116
  function build_selector(resource, opts) {
@@ -33,7 +33,7 @@ export class Redirect {
33
33
  /**
34
34
  * @template {Record<string, unknown> | undefined} [T=undefined]
35
35
  */
36
- export class ValidationError {
36
+ export class ActionFailure {
37
37
  /**
38
38
  * @param {number} status
39
39
  * @param {T} [data]
@@ -2,7 +2,7 @@ import * as devalue from 'devalue';
2
2
  import { error, json } from '../../../exports/index.js';
3
3
  import { normalize_error } from '../../../utils/error.js';
4
4
  import { is_form_content_type, negotiate } from '../../../utils/http.js';
5
- import { HttpError, Redirect, ValidationError } from '../../control.js';
5
+ import { HttpError, Redirect, ActionFailure } from '../../control.js';
6
6
  import { handle_error_and_jsonify } from '../utils.js';
7
7
 
8
8
  /** @param {import('types').RequestEvent} event */
@@ -50,9 +50,9 @@ export async function handle_action_json_request(event, options, server) {
50
50
  try {
51
51
  const data = await call_action(event, actions);
52
52
 
53
- if (data instanceof ValidationError) {
53
+ if (data instanceof ActionFailure) {
54
54
  return action_json({
55
- type: 'invalid',
55
+ type: 'failure',
56
56
  status: data.status,
57
57
  // @ts-expect-error we assign a string to what is supposed to be an object. That's ok
58
58
  // because we don't use the object outside, and this way we have better code navigation
@@ -81,7 +81,7 @@ export async function handle_action_json_request(event, options, server) {
81
81
  return action_json(
82
82
  {
83
83
  type: 'error',
84
- error: await handle_error_and_jsonify(event, options, check_incorrect_invalid_use(error))
84
+ error: await handle_error_and_jsonify(event, options, check_incorrect_fail_use(error))
85
85
  },
86
86
  {
87
87
  status: error instanceof HttpError ? error.status : 500
@@ -93,9 +93,9 @@ export async function handle_action_json_request(event, options, server) {
93
93
  /**
94
94
  * @param {HttpError | Error} error
95
95
  */
96
- function check_incorrect_invalid_use(error) {
97
- return error instanceof ValidationError
98
- ? new Error(`Cannot "throw invalid()". Use "return invalid()"`)
96
+ function check_incorrect_fail_use(error) {
97
+ return error instanceof ActionFailure
98
+ ? new Error(`Cannot "throw fail()". Use "return fail()"`)
99
99
  : error;
100
100
  }
101
101
 
@@ -142,8 +142,8 @@ export async function handle_action_request(event, server) {
142
142
  try {
143
143
  const data = await call_action(event, actions);
144
144
 
145
- if (data instanceof ValidationError) {
146
- return { type: 'invalid', status: data.status, data: data.data };
145
+ if (data instanceof ActionFailure) {
146
+ return { type: 'failure', status: data.status, data: data.data };
147
147
  } else {
148
148
  return {
149
149
  type: 'success',
@@ -164,7 +164,7 @@ export async function handle_action_request(event, server) {
164
164
 
165
165
  return {
166
166
  type: 'error',
167
- error: check_incorrect_invalid_use(error)
167
+ error: check_incorrect_fail_use(error)
168
168
  };
169
169
  }
170
170
  }
@@ -183,7 +183,7 @@ function check_named_default_separate(actions) {
183
183
  /**
184
184
  * @param {import('types').RequestEvent} event
185
185
  * @param {NonNullable<import('types').SSRNode['server']['actions']>} actions
186
- * @throws {Redirect | ValidationError | HttpError | Error}
186
+ * @throws {Redirect | ActionFailure | HttpError | Error}
187
187
  */
188
188
  export async function call_action(event, actions) {
189
189
  const url = new URL(event.request.url);
@@ -68,7 +68,7 @@ export async function render_page(event, route, page, options, state, resolve_op
68
68
  const error = action_result.error;
69
69
  status = error instanceof HttpError ? error.status : 500;
70
70
  }
71
- if (action_result?.type === 'invalid') {
71
+ if (action_result?.type === 'failure') {
72
72
  status = action_result.status;
73
73
  }
74
74
  }
@@ -67,7 +67,7 @@ export async function render_response({
67
67
  let rendered;
68
68
 
69
69
  const form_value =
70
- action_result?.type === 'success' || action_result?.type === 'invalid'
70
+ action_result?.type === 'success' || action_result?.type === 'failure'
71
71
  ? action_result.data ?? null
72
72
  : null;
73
73
 
@@ -266,24 +266,41 @@ export async function render_response({
266
266
  }
267
267
 
268
268
  if (page_config.csr) {
269
+ const opts = [
270
+ `env: ${s(options.public_env)}`,
271
+ `paths: ${s(options.paths)}`,
272
+ `target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode`,
273
+ `version: ${s(options.version)}`
274
+ ];
275
+
276
+ if (page_config.ssr) {
277
+ const hydrate = [
278
+ `node_ids: [${branch.map(({ node }) => node.index).join(', ')}]`,
279
+ `data: ${serialized.data}`,
280
+ `form: ${serialized.form}`
281
+ ];
282
+
283
+ if (status !== 200) {
284
+ hydrate.push(`status: ${status}`);
285
+ }
286
+
287
+ if (error) {
288
+ hydrate.push(`error: ${devalue.uneval(error)}`);
289
+ }
290
+
291
+ if (options.embedded) {
292
+ hydrate.push(`params: ${devalue.uneval(event.params)}`, `route: ${s(event.route)}`);
293
+ }
294
+
295
+ opts.push(`hydrate: {\n\t\t\t\t\t${hydrate.join(',\n\t\t\t\t\t')}\n\t\t\t\t}`);
296
+ }
297
+
269
298
  // prettier-ignore
270
299
  const init_app = `
271
300
  import { start } from ${s(prefixed(entry.file))};
272
301
 
273
302
  start({
274
- env: ${s(options.public_env)},
275
- hydrate: ${page_config.ssr ? `{
276
- status: ${status},
277
- error: ${devalue.uneval(error)},
278
- node_ids: [${branch.map(({ node }) => node.index).join(', ')}],
279
- params: ${devalue.uneval(event.params)},
280
- route: ${s(event.route)},
281
- data: ${serialized.data},
282
- form: ${serialized.form}
283
- }` : 'null'},
284
- paths: ${s(options.paths)},
285
- target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode,
286
- version: ${s(options.version)}
303
+ ${opts.join(',\n\t\t\t\t')}
287
304
  });
288
305
  `;
289
306
 
package/types/index.d.ts CHANGED
@@ -61,7 +61,7 @@ type OptionalUnion<
61
61
  A extends keyof U = U extends U ? keyof U : never
62
62
  > = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
63
63
 
64
- type UnpackValidationError<T> = T extends ValidationError<infer X>
64
+ type UnpackValidationError<T> = T extends ActionFailure<infer X>
65
65
  ? X
66
66
  : T extends void
67
67
  ? undefined // needs to be undefined, because void will corrupt union type
@@ -90,6 +90,11 @@ export interface Builder {
90
90
  */
91
91
  createEntries(fn: (route: RouteDefinition) => AdapterEntry): Promise<void>;
92
92
 
93
+ /**
94
+ * Generate a fallback page for a static webserver to use when no route is matched. Useful for single-page apps.
95
+ */
96
+ generateFallback(dest: string): Promise<void>;
97
+
93
98
  /**
94
99
  * Generate a server-side manifest to initialise the SvelteKit [server](https://kit.svelte.dev/docs/types#public-types-server) with.
95
100
  * @param opts a relative path to the base directory of the app and optionally in which format (esm or cjs) the manifest should be generated
@@ -117,15 +122,9 @@ export interface Builder {
117
122
  /**
118
123
  * Write prerendered files to `dest`.
119
124
  * @param dest the destination folder
120
- * @param opts.fallback the name of a file for fallback responses, like `200.html` or `404.html` depending on where the app is deployed
121
125
  * @returns an array of files written to `dest`
122
126
  */
123
- writePrerendered(
124
- dest: string,
125
- opts?: {
126
- fallback?: string;
127
- }
128
- ): string[];
127
+ writePrerendered(dest: string): string[];
129
128
  /**
130
129
  * Write server-side code to `dest`.
131
130
  * @param dest the destination folder
@@ -325,6 +324,11 @@ export interface KitConfig {
325
324
  */
326
325
  checkOrigin?: boolean;
327
326
  };
327
+ /**
328
+ * Whether or not the app is embedded inside a larger app. If `true`, SvelteKit will add its event listeners related to navigation etc on the parent of `%sveltekit.body%` instead of `window`, and will pass `params` from the server rather than inferring them from `location.pathname`.
329
+ * @default false
330
+ */
331
+ embedded?: boolean;
328
332
  /**
329
333
  * Environment variable configuration
330
334
  */
@@ -1069,7 +1073,7 @@ export type ActionResult<
1069
1073
  Invalid extends Record<string, unknown> | undefined = Record<string, any>
1070
1074
  > =
1071
1075
  | { type: 'success'; status: number; data?: Success }
1072
- | { type: 'invalid'; status: number; data?: Invalid }
1076
+ | { type: 'failure'; status: number; data?: Invalid }
1073
1077
  | { type: 'redirect'; status: number; location: string }
1074
1078
  | { type: 'error'; error: any };
1075
1079
 
@@ -1124,17 +1128,17 @@ export interface Redirect {
1124
1128
  export function json(data: any, init?: ResponseInit): Response;
1125
1129
 
1126
1130
  /**
1127
- * Create a `ValidationError` object.
1131
+ * Create an `ActionFailure` object.
1128
1132
  */
1129
- export function invalid<T extends Record<string, unknown> | undefined>(
1133
+ export function fail<T extends Record<string, unknown> | undefined>(
1130
1134
  status: number,
1131
1135
  data?: T
1132
- ): ValidationError<T>;
1136
+ ): ActionFailure<T>;
1133
1137
 
1134
1138
  /**
1135
- * The object returned by the [`invalid`](https://kit.svelte.dev/docs/modules#sveltejs-kit-invalid) function
1139
+ * The object returned by the [`fail`](https://kit.svelte.dev/docs/modules#sveltejs-kit-fail) function
1136
1140
  */
1137
- export interface ValidationError<T extends Record<string, unknown> | undefined = undefined>
1141
+ export interface ActionFailure<T extends Record<string, unknown> | undefined = undefined>
1138
1142
  extends UniqueInterface {
1139
1143
  status: number;
1140
1144
  data: T;
@@ -299,6 +299,7 @@ export interface SSROptions {
299
299
  check_origin: boolean;
300
300
  };
301
301
  dev: boolean;
302
+ embedded: boolean;
302
303
  handle_error(error: Error & { frame?: string }, event: RequestEvent): MaybePromise<App.Error>;
303
304
  hooks: ServerHooks;
304
305
  manifest: SSRManifest;
@@ -387,4 +388,5 @@ declare global {
387
388
  const __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: number;
388
389
  const __SVELTEKIT_BROWSER__: boolean;
389
390
  const __SVELTEKIT_DEV__: boolean;
391
+ const __SVELTEKIT_EMBEDDED__: boolean;
390
392
  }