@sveltejs/kit 1.0.0-next.574 → 1.0.0-next.575

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.574",
3
+ "version": "1.0.0-next.575",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -21,7 +21,7 @@
21
21
  "set-cookie-parser": "^2.5.1",
22
22
  "sirv": "^2.0.2",
23
23
  "tiny-glob": "^0.2.9",
24
- "undici": "5.13.0"
24
+ "undici": "5.14.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@playwright/test": "^1.28.1",
@@ -27,6 +27,10 @@ export function deserialize(result) {
27
27
 
28
28
  /** @type {import('$app/forms').enhance} */
29
29
  export function enhance(form, submit = () => {}) {
30
+ if (__SVELTEKIT_DEV__ && form.method !== 'post') {
31
+ throw new Error('use:enhance can only be used on <form> fields with method="POST"');
32
+ }
33
+
30
34
  /**
31
35
  * @param {{
32
36
  * action: URL;
@@ -1,5 +1,5 @@
1
1
  import { parse, serialize } from 'cookie';
2
- import { has_data_suffix, normalize_path, strip_data_suffix } from '../../utils/url.js';
2
+ import { normalize_path } from '../../utils/url.js';
3
3
 
4
4
  /**
5
5
  * Tracks all cookies set during dev mode so we can emit warnings
@@ -22,12 +22,7 @@ export function get_cookies(request, url, dev, trailing_slash) {
22
22
  const header = request.headers.get('cookie') ?? '';
23
23
  const initial_cookies = parse(header, { decode });
24
24
 
25
- const normalized_url = normalize_path(
26
- // Remove suffix: 'foo/__data.json' would mean the cookie path is '/foo',
27
- // whereas a direct hit of /foo would mean the cookie path is '/'
28
- has_data_suffix(url.pathname) ? strip_data_suffix(url.pathname) : url.pathname,
29
- trailing_slash
30
- );
25
+ const normalized_url = normalize_path(url.pathname, trailing_slash);
31
26
  // Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
32
27
  const default_path = normalized_url.split('/').slice(0, -1).join('/') || '/';
33
28
 
@@ -3,19 +3,27 @@ import { normalize_error } from '../../../utils/error.js';
3
3
  import { once } from '../../../utils/functions.js';
4
4
  import { load_server_data } from '../page/load_data.js';
5
5
  import { clarify_devalue_error, handle_error_and_jsonify, serialize_data_node } from '../utils.js';
6
- import { normalize_path, strip_data_suffix } from '../../../utils/url.js';
6
+ import { normalize_path } from '../../../utils/url.js';
7
7
 
8
- export const INVALIDATED_HEADER = 'x-sveltekit-invalidated';
8
+ export const INVALIDATED_PARAM = 'x-sveltekit-invalidated';
9
9
 
10
10
  /**
11
11
  * @param {import('types').RequestEvent} event
12
12
  * @param {import('types').SSRRoute} route
13
13
  * @param {import('types').SSROptions} options
14
14
  * @param {import('types').SSRState} state
15
+ * @param {boolean[] | undefined} invalidated_data_nodes
15
16
  * @param {import('types').TrailingSlash} trailing_slash
16
17
  * @returns {Promise<Response>}
17
18
  */
18
- export async function render_data(event, route, options, state, trailing_slash) {
19
+ export async function render_data(
20
+ event,
21
+ route,
22
+ options,
23
+ state,
24
+ invalidated_data_nodes,
25
+ trailing_slash
26
+ ) {
19
27
  if (!route.page) {
20
28
  // requesting /__data.json should fail for a +server.js
21
29
  return new Response(undefined, {
@@ -25,16 +33,12 @@ export async function render_data(event, route, options, state, trailing_slash)
25
33
 
26
34
  try {
27
35
  const node_ids = [...route.page.layouts, route.page.leaf];
28
-
29
- const invalidated =
30
- event.url.searchParams.get(INVALIDATED_HEADER)?.split('_').map(Boolean) ??
31
- node_ids.map(() => true);
32
- event.url.searchParams.delete(INVALIDATED_HEADER);
36
+ const invalidated = invalidated_data_nodes ?? node_ids.map(() => true);
33
37
 
34
38
  let aborted = false;
35
39
 
36
40
  const url = new URL(event.url);
37
- url.pathname = normalize_path(strip_data_suffix(url.pathname), trailing_slash);
41
+ url.pathname = normalize_path(url.pathname, trailing_slash);
38
42
 
39
43
  const new_event = { ...event, url };
40
44
 
@@ -13,7 +13,7 @@ import {
13
13
  strip_data_suffix
14
14
  } from '../../utils/url.js';
15
15
  import { exec } from '../../utils/routing.js';
16
- import { redirect_json_response, render_data } from './data/index.js';
16
+ import { INVALIDATED_PARAM, redirect_json_response, render_data } from './data/index.js';
17
17
  import { add_cookies_to_headers, get_cookies } from './cookie.js';
18
18
  import { create_fetch } from './fetch.js';
19
19
  import { Redirect } from '../control.js';
@@ -37,6 +37,7 @@ const default_preload = ({ type }) => type === 'js' || type === 'css';
37
37
 
38
38
  /** @type {import('types').Respond} */
39
39
  export async function respond(request, options, state) {
40
+ /** URL but stripped from the potential `/__data.json` suffix and its search param */
40
41
  let url = new URL(request.url);
41
42
 
42
43
  if (options.csrf.check_origin) {
@@ -75,7 +76,14 @@ export async function respond(request, options, state) {
75
76
  }
76
77
 
77
78
  const is_data_request = has_data_suffix(decoded);
78
- if (is_data_request) decoded = strip_data_suffix(decoded) || '/';
79
+ /** @type {boolean[] | undefined} */
80
+ let invalidated_data_nodes;
81
+ if (is_data_request) {
82
+ decoded = strip_data_suffix(decoded) || '/';
83
+ url.pathname = strip_data_suffix(url.pathname) || '/';
84
+ invalidated_data_nodes = url.searchParams.get(INVALIDATED_PARAM)?.split('_').map(Boolean);
85
+ url.searchParams.delete(INVALIDATED_PARAM);
86
+ }
79
87
 
80
88
  if (!state.prerendering?.fallback) {
81
89
  // TODO this could theoretically break — should probably be inside a try-catch
@@ -138,7 +146,8 @@ export async function respond(request, options, state) {
138
146
  }
139
147
  }
140
148
  },
141
- url
149
+ url,
150
+ isDataRequest: is_data_request
142
151
  };
143
152
 
144
153
  // TODO remove this for 1.0
@@ -376,7 +385,14 @@ export async function respond(request, options, state) {
376
385
  let response;
377
386
 
378
387
  if (is_data_request) {
379
- response = await render_data(event, route, options, state, trailing_slash ?? 'never');
388
+ response = await render_data(
389
+ event,
390
+ route,
391
+ options,
392
+ state,
393
+ invalidated_data_nodes,
394
+ trailing_slash ?? 'never'
395
+ );
380
396
  } else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
381
397
  response = await render_endpoint(event, await route.endpoint(), state);
382
398
  } else if (route.page) {
@@ -124,7 +124,7 @@ export async function handle_fatal_error(event, options, error) {
124
124
  'text/html'
125
125
  ]);
126
126
 
127
- if (has_data_suffix(event.url.pathname) || type === 'application/json') {
127
+ if (has_data_suffix(new URL(event.request.url).pathname) || type === 'application/json') {
128
128
  return new Response(JSON.stringify(body), {
129
129
  status,
130
130
  headers: { 'content-type': 'application/json; charset=utf-8' }
package/types/index.d.ts CHANGED
@@ -900,9 +900,14 @@ export interface RequestEvent<
900
900
  */
901
901
  setHeaders(headers: Record<string, string>): void;
902
902
  /**
903
- * The URL of the current page or endpoint
903
+ * The URL of the current page or endpoint.
904
904
  */
905
905
  url: URL;
906
+ /**
907
+ * `true` if the request comes from the client asking for `+page/layout.server.js` data. The `url` property will be stripped of the internal information
908
+ * related to the data request in this case. Use this property instead if the distinction is important to you.
909
+ */
910
+ isDataRequest: boolean;
906
911
  }
907
912
 
908
913
  /**