@sveltejs/kit 1.15.9 → 1.15.11

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.15.9",
3
+ "version": "1.15.11",
4
4
  "description": "The fastest way to build Svelte apps",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "magic-string": "^0.30.0",
21
21
  "mime": "^3.0.0",
22
22
  "sade": "^1.8.1",
23
- "set-cookie-parser": "^2.5.1",
23
+ "set-cookie-parser": "^2.6.0",
24
24
  "sirv": "^2.0.2",
25
25
  "tiny-glob": "^0.2.9",
26
26
  "undici": "~5.22.0"
@@ -36,7 +36,7 @@
36
36
  "marked": "^4.2.3",
37
37
  "rollup": "^3.7.0",
38
38
  "svelte": "^3.56.0",
39
- "svelte-preprocess": "^5.0.0",
39
+ "svelte-preprocess": "^5.0.3",
40
40
  "typescript": "^4.9.4",
41
41
  "uvu": "^0.5.6",
42
42
  "vite": "^4.3.0"
@@ -43,17 +43,6 @@ export function generate_manifest({ build_data, relative_path, routes }) {
43
43
  })
44
44
  );
45
45
 
46
- /** @typedef {{ index: number, path: string }} LookupEntry */
47
- /** @type {Map<import('types').PageNode, LookupEntry>} */
48
- const bundled_nodes = new Map();
49
-
50
- build_data.manifest_data.nodes.forEach((node, i) => {
51
- bundled_nodes.set(node, {
52
- path: join_relative(relative_path, `/nodes/${i}.js`),
53
- index: i
54
- });
55
- });
56
-
57
46
  /** @type {(path: string) => string} */
58
47
  const loader = (path) => `() => import('${path}')`;
59
48
 
@@ -68,14 +57,10 @@ export function generate_manifest({ build_data, relative_path, routes }) {
68
57
  function get_nodes(indexes) {
69
58
  let string = indexes.map((n) => reindexed.get(n) ?? '').join(',');
70
59
 
71
- if (indexes.at(-1) === undefined) {
72
- // since JavaScript ignores trailing commas, we need to insert a dummy
73
- // comma so that the array has the correct length if the last item
74
- // is undefined
75
- string += ',';
76
- }
77
-
78
- return `[${string}]`;
60
+ // since JavaScript ignores trailing commas, we need to insert a dummy
61
+ // comma so that the array has the correct length if the last item
62
+ // is undefined
63
+ return `[${string},]`;
79
64
  }
80
65
 
81
66
  // prettier-ignore
@@ -94,12 +79,12 @@ export function generate_manifest({ build_data, relative_path, routes }) {
94
79
  ],
95
80
  routes: [
96
81
  ${routes.map(route => {
82
+ if (!route.page && !route.endpoint) return;
83
+
97
84
  route.params.forEach(param => {
98
85
  if (param.matcher) matchers.add(param.matcher);
99
86
  });
100
87
 
101
- if (!route.page && !route.endpoint) return;
102
-
103
88
  return dedent`
104
89
  {
105
90
  id: ${s(route.id)},
@@ -21,7 +21,7 @@ export function sequence(...handlers) {
21
21
  return handle({
22
22
  event,
23
23
  resolve: (event, options) => {
24
- /** @param {{ html: string, done: boolean }} opts */
24
+ /** @type {import('types').ResolveOptions['transformPageChunk']} */
25
25
  const transformPageChunk = async ({ html, done }) => {
26
26
  if (options?.transformPageChunk) {
27
27
  html = (await options.transformPageChunk({ html, done })) ?? '';
@@ -34,9 +34,21 @@ export function sequence(...handlers) {
34
34
  return html;
35
35
  };
36
36
 
37
+ /** @type {import('types').ResolveOptions['filterSerializedResponseHeaders']} */
38
+ const filterSerializedResponseHeaders =
39
+ parent_options?.filterSerializedResponseHeaders ??
40
+ options?.filterSerializedResponseHeaders;
41
+
42
+ /** @type {import('types').ResolveOptions['preload']} */
43
+ const preload = parent_options?.preload ?? options?.preload;
44
+
37
45
  return i < length - 1
38
- ? apply_handle(i + 1, event, { transformPageChunk })
39
- : resolve(event, { transformPageChunk });
46
+ ? apply_handle(i + 1, event, {
47
+ transformPageChunk,
48
+ filterSerializedResponseHeaders,
49
+ preload
50
+ })
51
+ : resolve(event, { transformPageChunk, filterSerializedResponseHeaders, preload });
40
52
  }
41
53
  });
42
54
  }
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import { mkdirp } from '../../../utils/filesystem.js';
3
3
  import { find_deps, resolve_symlinks } from './utils.js';
4
4
  import { s } from '../../../utils/misc.js';
5
+ import { normalizePath } from 'vite';
5
6
 
6
7
  /**
7
8
  * @param {string} out
@@ -48,12 +49,6 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
48
49
  const fonts = [];
49
50
 
50
51
  if (node.component && client_manifest) {
51
- const entry = find_deps(client_manifest, node.component, true);
52
-
53
- imported.push(...entry.imports);
54
- stylesheets.push(...entry.stylesheets);
55
- fonts.push(...entry.fonts);
56
-
57
52
  exports.push(
58
53
  `export const component = async () => (await import('../${
59
54
  resolve_symlinks(server_manifest, node.component).chunk.file
@@ -62,14 +57,6 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
62
57
  }
63
58
 
64
59
  if (node.universal) {
65
- if (client_manifest) {
66
- const entry = find_deps(client_manifest, node.universal, true);
67
-
68
- imported.push(...entry.imports);
69
- stylesheets.push(...entry.stylesheets);
70
- fonts.push(...entry.fonts);
71
- }
72
-
73
60
  imports.push(`import * as universal from '../${server_manifest[node.universal].file}';`);
74
61
  exports.push(`export { universal };`);
75
62
  exports.push(`export const universal_id = ${s(node.universal)};`);
@@ -81,6 +68,18 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
81
68
  exports.push(`export const server_id = ${s(node.server)};`);
82
69
  }
83
70
 
71
+ if (client_manifest && (node.universal || node.component)) {
72
+ const entry = find_deps(
73
+ client_manifest,
74
+ `${normalizePath(kit.outDir)}/generated/client-optimized/nodes/${i}.js`,
75
+ true
76
+ );
77
+
78
+ imported.push(...entry.imports);
79
+ stylesheets.push(...entry.stylesheets);
80
+ fonts.push(...entry.fonts);
81
+ }
82
+
84
83
  exports.push(
85
84
  `export const imports = ${s(imported)};`,
86
85
  `export const stylesheets = ${s(stylesheets)};`,
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { normalizePath } from 'vite';
3
4
 
4
5
  /**
5
6
  * Adds transitive JS and CSS dependencies to the js and css inputs.
@@ -72,7 +73,7 @@ export function find_deps(manifest, entry, add_dynamic_css) {
72
73
  */
73
74
  export function resolve_symlinks(manifest, file) {
74
75
  while (!manifest[file]) {
75
- const next = path.relative('.', fs.realpathSync(file));
76
+ const next = normalizePath(path.relative('.', fs.realpathSync(file)));
76
77
  if (next === file) throw new Error(`Could not find file "${file}" in Vite manifest`);
77
78
  file = next;
78
79
  }
@@ -116,7 +116,7 @@ export async function dev(vite, vite_config, svelte_config) {
116
116
  _: {
117
117
  client: {
118
118
  start: `${runtime_base}/client/start.js`,
119
- app: `${svelte_config.kit.outDir}/generated/client/app.js`,
119
+ app: `${to_fs(svelte_config.kit.outDir)}/generated/client/app.js`,
120
120
  imports: [],
121
121
  stylesheets: [],
122
122
  fonts: []
@@ -525,27 +525,6 @@ function kit({ svelte_config }) {
525
525
  } else {
526
526
  input['entry/start'] = `${runtime_directory}/client/start.js`;
527
527
  input['entry/app'] = `${kit.outDir}/generated/client-optimized/app.js`;
528
-
529
- /**
530
- * @param {string | undefined} file
531
- */
532
- function add_input(file) {
533
- if (!file) return;
534
-
535
- const resolved = path.resolve(file);
536
- const relative = decodeURIComponent(path.relative(kit.files.routes, resolved));
537
-
538
- const name = relative.startsWith('..')
539
- ? path.basename(file).replace(/^\+/, '')
540
- : relative.replace(/(\\|\/)\+/g, '-').replace(/[\\/]/g, '-');
541
-
542
- input[`entry/${name}`] = resolved;
543
- }
544
-
545
- for (const node of manifest_data.nodes) {
546
- add_input(node.component);
547
- add_input(node.universal);
548
- }
549
528
  }
550
529
 
551
530
  // see the kit.output.preloadStrategy option for details on why we have multiple options here
@@ -1,19 +1,9 @@
1
1
  import * as devalue from 'devalue';
2
- import { client } from '../client/singletons.js';
2
+ import { DEV } from 'esm-env';
3
+ import { client_method } from '../client/singletons.js';
3
4
  import { invalidateAll } from './navigation.js';
4
- import { BROWSER, DEV } from 'esm-env';
5
-
6
- /**
7
- * @param {string} name
8
- */
9
- function guard(name) {
10
- return () => {
11
- throw new Error(`Cannot call ${name}(...) on the server`);
12
- };
13
- }
14
5
 
15
- /** @type {import('$app/forms').applyAction} */
16
- export const applyAction = BROWSER ? client.apply_action : guard('applyAction');
6
+ export const applyAction = client_method('apply_action');
17
7
 
18
8
  /** @type {import('$app/forms').deserialize} */
19
9
  export function deserialize(result) {
@@ -1,22 +1,17 @@
1
- import { BROWSER } from 'esm-env';
2
- import { client } from '../client/singletons.js';
3
-
4
- /**
5
- * @param {string} name
6
- */
7
- function guard(name) {
8
- return () => {
9
- throw new Error(`Cannot call ${name}(...) on the server`);
10
- };
11
- }
12
-
13
- export const disableScrollHandling = BROWSER
14
- ? client.disable_scroll_handling
15
- : guard('disableScrollHandling');
16
- export const goto = BROWSER ? client.goto : guard('goto');
17
- export const invalidate = BROWSER ? client.invalidate : guard('invalidate');
18
- export const invalidateAll = BROWSER ? client.invalidateAll : guard('invalidateAll');
19
- export const preloadData = BROWSER ? client.preload_data : guard('preloadData');
20
- export const preloadCode = BROWSER ? client.preload_code : guard('preloadCode');
21
- export const beforeNavigate = BROWSER ? client.before_navigate : () => {};
22
- export const afterNavigate = BROWSER ? client.after_navigate : () => {};
1
+ import { client_method } from '../client/singletons.js';
2
+
3
+ export const disableScrollHandling = /* @__PURE__ */ client_method('disable_scroll_handling');
4
+
5
+ export const goto = /* @__PURE__ */ client_method('goto');
6
+
7
+ export const invalidate = /* @__PURE__ */ client_method('invalidate');
8
+
9
+ export const invalidateAll = /* @__PURE__ */ client_method('invalidate_all');
10
+
11
+ export const preloadData = /* @__PURE__ */ client_method('preload_data');
12
+
13
+ export const preloadCode = /* @__PURE__ */ client_method('preload_code');
14
+
15
+ export const beforeNavigate = /* @__PURE__ */ client_method('before_navigate');
16
+
17
+ export const afterNavigate = /* @__PURE__ */ client_method('after_navigate');
@@ -33,7 +33,7 @@ import * as devalue from 'devalue';
33
33
  import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js';
34
34
  import { validate_common_exports } from '../../utils/exports.js';
35
35
  import { compact } from '../../utils/array.js';
36
- import { validate_depends } from '../shared.js';
36
+ import { INVALIDATED_PARAM, validate_depends } from '../shared.js';
37
37
 
38
38
  let errored = false;
39
39
 
@@ -1354,7 +1354,7 @@ export function create_client(app, target) {
1354
1354
  return invalidate();
1355
1355
  },
1356
1356
 
1357
- invalidateAll: () => {
1357
+ invalidate_all: () => {
1358
1358
  force_invalidation = true;
1359
1359
  return invalidate();
1360
1360
  },
@@ -1775,13 +1775,10 @@ export function create_client(app, target) {
1775
1775
  async function load_data(url, invalid) {
1776
1776
  const data_url = new URL(url);
1777
1777
  data_url.pathname = add_data_suffix(url.pathname);
1778
- if (DEV && url.searchParams.has('x-sveltekit-invalidated')) {
1779
- throw new Error('Cannot used reserved query parameter "x-sveltekit-invalidated"');
1778
+ if (DEV && url.searchParams.has(INVALIDATED_PARAM)) {
1779
+ throw new Error(`Cannot used reserved query parameter "${INVALIDATED_PARAM}"`);
1780
1780
  }
1781
- data_url.searchParams.append(
1782
- 'x-sveltekit-invalidated',
1783
- invalid.map((x) => (x ? '1' : '')).join('_')
1784
- );
1781
+ data_url.searchParams.append(INVALIDATED_PARAM, invalid.map((i) => (i ? '1' : '0')).join(''));
1785
1782
 
1786
1783
  const res = await native_fetch(data_url.href);
1787
1784
 
@@ -1,5 +1,6 @@
1
1
  import { writable } from 'svelte/store';
2
2
  import { create_updated_store, notifiable_store } from './utils.js';
3
+ import { BROWSER } from 'esm-env';
3
4
 
4
5
  /** @type {import('./types').Client} */
5
6
  export let client;
@@ -13,6 +14,35 @@ export function init(opts) {
13
14
  client = opts.client;
14
15
  }
15
16
 
17
+ /**
18
+ * @template {keyof typeof client} T
19
+ * @param {T} key
20
+ * @returns {typeof client[T]}
21
+ */
22
+ export function client_method(key) {
23
+ if (!BROWSER) {
24
+ if (key === 'before_navigate' || key === 'after_navigate') {
25
+ // @ts-expect-error doesn't recognize that both keys here return void so expects a async function
26
+ return () => {};
27
+ } else {
28
+ /** @type {Record<string, string>} */
29
+ const name_lookup = {
30
+ disable_scroll_handling: 'disableScrollHandling',
31
+ preload_data: 'preloadData',
32
+ preload_code: 'preloadCode',
33
+ invalidate_all: 'invalidateAll'
34
+ };
35
+
36
+ return () => {
37
+ throw new Error(`Cannot call ${name_lookup[key] ?? key}(...) on the server`);
38
+ };
39
+ }
40
+ } else {
41
+ // @ts-expect-error
42
+ return (...args) => client[key](...args);
43
+ }
44
+ }
45
+
16
46
  export const stores = {
17
47
  url: notifiable_store({}),
18
48
  page: notifiable_store({}),
@@ -54,7 +54,7 @@ export interface Client {
54
54
  disable_scroll_handling(): void;
55
55
  goto: typeof goto;
56
56
  invalidate: typeof invalidate;
57
- invalidateAll: typeof invalidateAll;
57
+ invalidate_all: typeof invalidateAll;
58
58
  preload_code: typeof preloadCode;
59
59
  preload_data: typeof preloadData;
60
60
  apply_action: typeof applyAction;
@@ -8,8 +8,6 @@ import { text } from '../../../exports/index.js';
8
8
  import * as devalue from 'devalue';
9
9
  import { create_async_iterator } from '../../../utils/streaming.js';
10
10
 
11
- export const INVALIDATED_PARAM = 'x-sveltekit-invalidated';
12
-
13
11
  const encoder = new TextEncoder();
14
12
 
15
13
  /**
@@ -16,8 +16,6 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
16
16
  return async (info, init) => {
17
17
  const original_request = normalize_fetch_input(info, init, event.url);
18
18
 
19
- const request_body = init?.body;
20
-
21
19
  // some runtimes (e.g. Cloudflare) error if you access `request.mode`,
22
20
  // annoyingly, so we need to read the value from the `init` object instead
23
21
  let mode = (info instanceof Request ? info.mode : init?.mode) ?? 'cors';
@@ -111,15 +109,6 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
111
109
  }
112
110
  }
113
111
 
114
- if (request_body && typeof request_body !== 'string' && !ArrayBuffer.isView(request_body)) {
115
- // TODO is this still necessary? we just bail out below
116
- // per https://developer.mozilla.org/en-US/docs/Web/API/Request/Request, this can be a
117
- // Blob, BufferSource, FormData, URLSearchParams, USVString, or ReadableStream object.
118
- // non-string bodies are irksome to deal with, but luckily aren't particularly useful
119
- // in this context anyway, so we take the easy route and ban them
120
- throw new Error('Request body must be a string or TypedArray');
121
- }
122
-
123
112
  if (!request.headers.has('accept')) {
124
113
  request.headers.set('accept', '*/*');
125
114
  }
@@ -41,8 +41,7 @@ export class Server {
41
41
 
42
42
  this.#options.hooks = {
43
43
  handle: module.handle || (({ event, resolve }) => resolve(event)),
44
- // @ts-expect-error
45
- handleError: module.handleError || (({ error }) => console.error(error?.stack)),
44
+ handleError: module.handleError || (({ error }) => console.error(error)),
46
45
  handleFetch: module.handleFetch || (({ request, fetch }) => fetch(request))
47
46
  };
48
47
  } catch (error) {
@@ -51,8 +50,7 @@ export class Server {
51
50
  handle: () => {
52
51
  throw error;
53
52
  },
54
- // @ts-expect-error
55
- handleError: ({ error }) => console.error(error?.stack),
53
+ handleError: ({ error }) => console.error(error),
56
54
  handleFetch: ({ request, fetch }) => fetch(request)
57
55
  };
58
56
  } else {
@@ -15,7 +15,7 @@ import {
15
15
  strip_data_suffix
16
16
  } from '../../utils/url.js';
17
17
  import { exec } from '../../utils/routing.js';
18
- import { INVALIDATED_PARAM, redirect_json_response, render_data } from './data/index.js';
18
+ import { redirect_json_response, render_data } from './data/index.js';
19
19
  import { add_cookies_to_headers, get_cookies } from './cookie.js';
20
20
  import { create_fetch } from './fetch.js';
21
21
  import { Redirect } from '../control.js';
@@ -27,6 +27,7 @@ import {
27
27
  import { get_option } from '../../utils/options.js';
28
28
  import { error, json, text } from '../../exports/index.js';
29
29
  import { action_json_redirect, is_action_json_request } from './page/actions.js';
30
+ import { INVALIDATED_PARAM } from '../shared.js';
30
31
 
31
32
  /* global __SVELTEKIT_ADAPTER_NAME__ */
32
33
 
@@ -94,7 +95,10 @@ export async function respond(request, options, manifest, state) {
94
95
  if (is_data_request) {
95
96
  decoded = strip_data_suffix(decoded) || '/';
96
97
  url.pathname = strip_data_suffix(url.pathname) || '/';
97
- invalidated_data_nodes = url.searchParams.get(INVALIDATED_PARAM)?.split('_').map(Boolean);
98
+ invalidated_data_nodes = url.searchParams
99
+ .get(INVALIDATED_PARAM)
100
+ ?.split('')
101
+ .map((node) => node === '1');
98
102
  url.searchParams.delete(INVALIDATED_PARAM);
99
103
  }
100
104
 
@@ -10,3 +10,5 @@ export function validate_depends(route_id, dep) {
10
10
  );
11
11
  }
12
12
  }
13
+
14
+ export const INVALIDATED_PARAM = 'x-sveltekit-invalidated';
@@ -359,6 +359,10 @@ declare module '@sveltejs/kit/hooks' {
359
359
 
360
360
  /**
361
361
  * A helper function for sequencing multiple `handle` calls in a middleware-like manner.
362
+ * The behavior for the `handle` options is as follows:
363
+ * - `transformPageChunk` is applied in reverse order and merged
364
+ * - `preload` is applied in forward order, the first option "wins" and no `preload` options after it are called
365
+ * - `filterSerializedResponseHeaders` behaves the same as `preload`
362
366
  *
363
367
  * ```js
364
368
  * /// file: src/hooks.server.js
@@ -372,6 +376,10 @@ declare module '@sveltejs/kit/hooks' {
372
376
  * // transforms are applied in reverse order
373
377
  * console.log('first transform');
374
378
  * return html;
379
+ * },
380
+ * preload: () => {
381
+ * // this one wins as it's the first defined in the chain
382
+ * console.log('first preload');
375
383
  * }
376
384
  * });
377
385
  * console.log('first post-processing');
@@ -385,6 +393,13 @@ declare module '@sveltejs/kit/hooks' {
385
393
  * transformPageChunk: ({ html }) => {
386
394
  * console.log('second transform');
387
395
  * return html;
396
+ * },
397
+ * preload: () => {
398
+ * console.log('second preload');
399
+ * },
400
+ * filterSerializedResponseHeaders: () => {
401
+ * // this one wins as it's the first defined in the chain
402
+ * console.log('second filterSerializedResponseHeaders');
388
403
  * }
389
404
  * });
390
405
  * console.log('second post-processing');
@@ -398,7 +413,9 @@ declare module '@sveltejs/kit/hooks' {
398
413
  *
399
414
  * ```
400
415
  * first pre-processing
416
+ * first preload
401
417
  * second pre-processing
418
+ * second filterSerializedResponseHeaders
402
419
  * second transform
403
420
  * first transform
404
421
  * second post-processing
package/types/index.d.ts CHANGED
@@ -557,16 +557,16 @@ export interface KitConfig {
557
557
  * If SvelteKit encounters an error while loading the page and detects that a new version has been deployed (using the `name` specified here, which defaults to a timestamp of the build) it will fall back to traditional full-page navigation.
558
558
  * Not all navigations will result in an error though, for example if the JavaScript for the next page is already loaded. If you still want to force a full-page navigation in these cases, use techniques such as setting the `pollInterval` and then using `beforeNavigate`:
559
559
  * ```html
560
- * /// +layout.svelte
560
+ * /// file: +layout.svelte
561
561
  * <script>
562
- * import { beforeNavigate } from '$app/navigation';
563
- * import { updated } from '$app/stores';
562
+ * import { beforeNavigate } from '$app/navigation';
563
+ * import { updated } from '$app/stores';
564
564
  *
565
- * beforeNavigate(({ willUnload, to }) => {
566
- * if ($updated && !willUnload && to?.url) {
567
- * location.href = to.url.href;
568
- * }
569
- * });
565
+ * beforeNavigate(({ willUnload, to }) => {
566
+ * if ($updated && !willUnload && to?.url) {
567
+ * location.href = to.url.href;
568
+ * }
569
+ * });
570
570
  * </script>
571
571
  * ```
572
572
  *