@sveltejs/kit 1.0.0-next.505 → 1.0.0-next.507

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.505",
3
+ "version": "1.0.0-next.507",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -28,7 +28,7 @@ prerender();
28
28
  function format_error({ status, path, referrer, referenceType }, config) {
29
29
  const message =
30
30
  status === 404 && !path.startsWith(config.paths.base)
31
- ? `${path} does not begin with \`base\`, which is configured in \`paths.base\` and can be imported from \`$app/paths\``
31
+ ? `${path} does not begin with \`base\`, which is configured in \`paths.base\` and can be imported from \`$app/paths\` - see https://kit.svelte.dev/docs/configuration#paths for more info`
32
32
  : path;
33
33
 
34
34
  return `${status} ${message}${referrer ? ` (${referenceType} from ${referrer})` : ''}`;
@@ -244,10 +244,13 @@ export async function prerender() {
244
244
 
245
245
  const prerender = headers['x-sveltekit-prerender'];
246
246
  if (prerender) {
247
- const route_id = headers['x-sveltekit-routeid'];
248
- const existing_value = prerender_map.get(route_id);
249
- if (existing_value !== 'auto') {
250
- prerender_map.set(route_id, prerender === 'true' ? true : 'auto');
247
+ const encoded_route_id = headers['x-sveltekit-routeid'];
248
+ if (encoded_route_id != null) {
249
+ const route_id = decodeURI(encoded_route_id);
250
+ const existing_value = prerender_map.get(route_id);
251
+ if (existing_value !== 'auto') {
252
+ prerender_map.set(route_id, prerender === 'true' ? true : 'auto');
253
+ }
251
254
  }
252
255
  }
253
256
 
@@ -305,7 +308,8 @@ export async function prerender() {
305
308
 
306
309
  if (written.has(file)) return;
307
310
 
308
- const route_id = response.headers.get('x-sveltekit-routeid');
311
+ const encoded_route_id = response.headers.get('x-sveltekit-routeid');
312
+ const route_id = encoded_route_id != null ? decodeURI(encoded_route_id) : null;
309
313
  if (route_id !== null) prerendered_routes.add(route_id);
310
314
 
311
315
  if (response_type === REDIRECT) {
@@ -1,7 +1,7 @@
1
- import { fetch, Response, Request, Headers } from 'undici';
1
+ import { fetch, Response, Request, Headers, FormData } from 'undici';
2
2
  import { ReadableStream, TransformStream, WritableStream } from 'stream/web';
3
3
  import { Readable } from 'stream';
4
- import { Request as NodeFetchRequest, FormData } from 'node-fetch';
4
+ import { Request as NodeFetchRequest } from 'node-fetch';
5
5
  import { webcrypto as crypto } from 'crypto';
6
6
 
7
7
  /** @type {Record<string, any>} */
@@ -13,12 +13,18 @@ const globals = {
13
13
  // https://github.com/nodejs/undici/issues/974
14
14
  Request: class extends Request {
15
15
  // @ts-expect-error
16
- formData() {
17
- return new NodeFetchRequest(this.url, {
16
+ async formData() {
17
+ const nodeFetchFormData = await new NodeFetchRequest(this.url, {
18
18
  method: this.method,
19
19
  headers: this.headers,
20
20
  body: this.body && Readable.from(this.body)
21
21
  }).formData();
22
+
23
+ const formData = new FormData();
24
+ for (const [name, value] of nodeFetchFormData.entries()) {
25
+ formData.append(name, value);
26
+ }
27
+ return formData;
22
28
  }
23
29
  },
24
30
  Headers,
@@ -96,6 +96,7 @@ export function enhance(form, submit = () => {}) {
96
96
  action,
97
97
  data,
98
98
  form,
99
+ update: () => fallback_callback({ action, result }),
99
100
  // @ts-expect-error generic constraints stuff we don't care about
100
101
  result,
101
102
  // TODO remove for 1.0
@@ -71,7 +71,7 @@ export function initial_fetch(resource, resolved, opts) {
71
71
 
72
72
  let selector = `script[data-sveltekit-fetched][data-url=${url}]`;
73
73
 
74
- if (opts && typeof opts.body === 'string') {
74
+ if (opts?.body && (typeof opts.body === 'string' || ArrayBuffer.isView(opts.body))) {
75
75
  selector += `[data-hash="${hash(opts.body)}"]`;
76
76
  }
77
77
 
@@ -4,12 +4,16 @@
4
4
  */
5
5
  export function hash(value) {
6
6
  let hash = 5381;
7
- let i = value.length;
8
7
 
9
8
  if (typeof value === 'string') {
9
+ let i = value.length;
10
10
  while (i) hash = (hash * 33) ^ value.charCodeAt(--i);
11
+ } else if (ArrayBuffer.isView(value)) {
12
+ const buffer = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
13
+ let i = buffer.length;
14
+ while (i) hash = (hash * 33) ^ buffer[--i];
11
15
  } else {
12
- while (i) hash = (hash * 33) ^ value[--i];
16
+ throw new TypeError('value must be a string or TypedArray');
13
17
  }
14
18
 
15
19
  return (hash >>> 0).toString(36);
@@ -1,12 +1,5 @@
1
1
  import { parse, serialize } from 'cookie';
2
2
 
3
- /** @type {import('cookie').CookieSerializeOptions} */
4
- const DEFAULT_SERIALIZE_OPTIONS = {
5
- httpOnly: true,
6
- secure: true,
7
- sameSite: 'lax'
8
- };
9
-
10
3
  /**
11
4
  * @param {Request} request
12
5
  * @param {URL} url
@@ -15,6 +8,13 @@ export function get_cookies(request, url) {
15
8
  /** @type {Map<string, import('./page/types').Cookie>} */
16
9
  const new_cookies = new Map();
17
10
 
11
+ /** @type {import('cookie').CookieSerializeOptions} */
12
+ const defaults = {
13
+ httpOnly: true,
14
+ sameSite: 'lax',
15
+ secure: url.hostname === 'localhost' && url.protocol === 'http:' ? false : true
16
+ };
17
+
18
18
  /** @type {import('types').Cookies} */
19
19
  const cookies = {
20
20
  // The JSDoc param annotations appearing below for get, set and delete
@@ -51,7 +51,7 @@ export function get_cookies(request, url) {
51
51
  name,
52
52
  value,
53
53
  options: {
54
- ...DEFAULT_SERIALIZE_OPTIONS,
54
+ ...defaults,
55
55
  ...opts
56
56
  }
57
57
  });
@@ -66,7 +66,7 @@ export function get_cookies(request, url) {
66
66
  name,
67
67
  value: '',
68
68
  options: {
69
- ...DEFAULT_SERIALIZE_OPTIONS,
69
+ ...defaults,
70
70
  ...opts,
71
71
  maxAge: 0
72
72
  }
@@ -80,7 +80,7 @@ export function get_cookies(request, url) {
80
80
  */
81
81
  serialize(name, value, opts) {
82
82
  return serialize(name, value, {
83
- ...DEFAULT_SERIALIZE_OPTIONS,
83
+ ...defaults,
84
84
  ...opts
85
85
  });
86
86
  }
@@ -298,7 +298,7 @@ export async function respond(request, options, state) {
298
298
  add_cookies_to_headers(response.headers, Array.from(new_cookies.values()));
299
299
 
300
300
  if (state.prerendering && event.routeId !== null) {
301
- response.headers.set('x-sveltekit-routeid', event.routeId);
301
+ response.headers.set('x-sveltekit-routeid', encodeURI(event.routeId));
302
302
  }
303
303
 
304
304
  return response;
@@ -165,13 +165,13 @@ export function create_fetch({ event, options, state, route, prerender_default,
165
165
  }
166
166
  }
167
167
 
168
- if (request_body && typeof request_body !== 'string') {
168
+ if (request_body && typeof request_body !== 'string' && !ArrayBuffer.isView(request_body)) {
169
169
  // TODO is this still necessary? we just bail out below
170
170
  // per https://developer.mozilla.org/en-US/docs/Web/API/Request/Request, this can be a
171
171
  // Blob, BufferSource, FormData, URLSearchParams, USVString, or ReadableStream object.
172
172
  // non-string bodies are irksome to deal with, but luckily aren't particularly useful
173
173
  // in this context anyway, so we take the easy route and ban them
174
- throw new Error('Request body must be a string');
174
+ throw new Error('Request body must be a string or TypedArray');
175
175
  }
176
176
 
177
177
  response = await respond(request, options, {
@@ -220,7 +220,7 @@ export function create_fetch({ event, options, state, route, prerender_default,
220
220
  ? request.url.slice(event.url.origin.length)
221
221
  : request.url,
222
222
  method: request.method,
223
- request_body: /** @type {string | undefined} */ (request_body),
223
+ request_body: /** @type {string | ArrayBufferView | undefined} */ (request_body),
224
224
  response_body: body,
225
225
  response: response
226
226
  });
@@ -4,7 +4,7 @@ import { SSRNode, CspDirectives } from 'types';
4
4
  export interface Fetched {
5
5
  url: string;
6
6
  method: string;
7
- request_body?: string | null;
7
+ request_body?: string | ArrayBufferView | null;
8
8
  response_body: string;
9
9
  response: Response;
10
10
  }
@@ -110,6 +110,7 @@ declare module '$app/forms' {
110
110
  form: HTMLFormElement;
111
111
  action: URL;
112
112
  result: ActionResult<Success, Invalid>;
113
+ update: () => Promise<void>;
113
114
  }) => void);
114
115
 
115
116
  /**
@@ -135,6 +136,8 @@ declare module '$app/forms' {
135
136
  * - invalidates all data in case of successful submission with no redirect response
136
137
  * - redirects in case of a redirect response
137
138
  * - redirects to the nearest error page in case of an unexpected error
139
+ *
140
+ * If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback.
138
141
  */
139
142
  submit?: SubmitFunction<Success, Invalid>
140
143
  ): { destroy: () => void };
@@ -174,7 +177,7 @@ declare module '$app/navigation' {
174
177
  /**
175
178
  * Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`.
176
179
  *
177
- * @param url Where to navigate to
180
+ * @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.
178
181
  * @param opts.replaceState If `true`, will replace the current `history` entry rather than creating a new one with `pushState`
179
182
  * @param opts.noscroll If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
180
183
  * @param opts.keepfocus If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
@@ -255,7 +258,9 @@ declare module '$app/navigation' {
255
258
  */
256
259
  declare module '$app/paths' {
257
260
  /**
258
- * A string that matches [`config.kit.paths.base`](https://kit.svelte.dev/docs/configuration#paths). It must start, but not end with `/` (e.g. `/base-path`), unless it is the empty string.
261
+ * A string that matches [`config.kit.paths.base`](https://kit.svelte.dev/docs/configuration#paths).
262
+ *
263
+ * Example usage: `<a href="{base}/your-page">Link</a>`
259
264
  */
260
265
  export const base: `/${string}`;
261
266
  /**
package/types/index.d.ts CHANGED
@@ -151,7 +151,7 @@ export interface Cookies {
151
151
  /**
152
152
  * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` during the current request.
153
153
  *
154
- * The `httpOnly` and `secure` options are `true` by default, and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`.
154
+ * The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`.
155
155
  *
156
156
  * 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.
157
157
  */
@@ -165,7 +165,7 @@ export interface Cookies {
165
165
  /**
166
166
  * Serialize a cookie name-value pair into a Set-Cookie header string.
167
167
  *
168
- * The `httpOnly` and `secure` options are `true` by default, and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`.
168
+ * The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`.
169
169
  *
170
170
  * By default, the `path` of a cookie is the current pathname. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app.
171
171
  *
@@ -353,7 +353,7 @@ export interface SSRState {
353
353
  prerender_default?: PrerenderOption;
354
354
  }
355
355
 
356
- export type StrictBody = string | Uint8Array;
356
+ export type StrictBody = string | ArrayBufferView;
357
357
 
358
358
  export interface Uses {
359
359
  dependencies: Set<string>;