@sveltejs/kit 1.0.0-next.482 → 1.0.0-next.484
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 +3 -3
- package/src/core/sync/write_types/index.js +1 -1
- package/src/runtime/server/cookie.js +65 -27
- package/src/runtime/server/index.js +2 -8
- package/src/runtime/server/page/fetch.js +8 -6
- package/src/runtime/server/page/index.js +1 -1
- package/src/runtime/server/page/render.js +3 -7
- package/src/runtime/server/page/types.d.ts +7 -1
- package/src/runtime/server/utils.js +6 -2
- package/types/index.d.ts +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.484",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@sveltejs/vite-plugin-svelte": "^1.0.5",
|
|
14
|
+
"@types/cookie": "^0.5.1",
|
|
14
15
|
"cookie": "^0.5.0",
|
|
15
16
|
"devalue": "^3.1.2",
|
|
16
17
|
"kleur": "^4.1.4",
|
|
@@ -26,7 +27,6 @@
|
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@playwright/test": "^1.25.0",
|
|
28
29
|
"@types/connect": "^3.4.35",
|
|
29
|
-
"@types/cookie": "^0.5.1",
|
|
30
30
|
"@types/marked": "^4.0.3",
|
|
31
31
|
"@types/mime": "^3.0.0",
|
|
32
32
|
"@types/node": "^16.11.36",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"svelte-preprocess": "^4.10.6",
|
|
39
39
|
"typescript": "^4.8.2",
|
|
40
40
|
"uvu": "^0.5.3",
|
|
41
|
-
"vite": "^3.1.
|
|
41
|
+
"vite": "^3.1.1"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"svelte": "^3.44.0",
|
|
@@ -68,7 +68,7 @@ export async function write_types(config, manifest_data, file) {
|
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const id = path.relative(config.kit.files.routes, path.dirname(file));
|
|
71
|
+
const id = path.posix.relative(config.kit.files.routes, path.dirname(file));
|
|
72
72
|
|
|
73
73
|
const route = manifest_data.routes.find((route) => route.id === id);
|
|
74
74
|
if (!route) return; // this shouldn't ever happen
|
|
@@ -1,49 +1,76 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { parse, serialize } from 'cookie';
|
|
2
|
+
|
|
3
|
+
/** @type {import('cookie').CookieSerializeOptions} */
|
|
4
|
+
const DEFAULT_SERIALIZE_OPTIONS = {
|
|
5
|
+
httpOnly: true,
|
|
6
|
+
secure: true,
|
|
7
|
+
sameSite: 'lax'
|
|
8
|
+
};
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* @param {Request} request
|
|
5
12
|
* @param {URL} url
|
|
6
13
|
*/
|
|
7
14
|
export function get_cookies(request, url) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/** @type {Array<{ name: string, value: string, options: import('cookie').CookieSerializeOptions }>} */
|
|
11
|
-
const new_cookies = [];
|
|
15
|
+
/** @type {Map<string, import('./page/types').Cookie>} */
|
|
16
|
+
const new_cookies = new Map();
|
|
12
17
|
|
|
13
18
|
/** @type {import('types').Cookies} */
|
|
14
19
|
const cookies = {
|
|
15
|
-
get
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
while (i--) {
|
|
20
|
-
const cookie = new_cookies[i];
|
|
20
|
+
// The JSDoc param annotations appearing below for get, set and delete
|
|
21
|
+
// are necessary to expose the `cookie` library types to
|
|
22
|
+
// typescript users. `@type {import('types').Cookies}` above is not
|
|
23
|
+
// sufficient to do so.
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} name
|
|
27
|
+
* @param {import('cookie').CookieParseOptions} opts
|
|
28
|
+
*/
|
|
29
|
+
get(name, opts) {
|
|
30
|
+
const c = new_cookies.get(name);
|
|
31
|
+
if (
|
|
32
|
+
c &&
|
|
33
|
+
domain_matches(url.hostname, c.options.domain) &&
|
|
34
|
+
path_matches(url.pathname, c.options.path)
|
|
35
|
+
) {
|
|
36
|
+
return c.value;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
const decode = opts?.decode || decodeURIComponent;
|
|
40
|
+
const req_cookies = parse(request.headers.get('cookie') ?? '', { decode });
|
|
41
|
+
return req_cookies[name]; // the decoded string or undefined
|
|
32
42
|
},
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} name
|
|
46
|
+
* @param {string} value
|
|
47
|
+
* @param {import('cookie').CookieSerializeOptions} opts
|
|
48
|
+
*/
|
|
49
|
+
set(name, value, opts = {}) {
|
|
50
|
+
new_cookies.set(name, {
|
|
35
51
|
name,
|
|
36
52
|
value,
|
|
37
53
|
options: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
...options
|
|
54
|
+
...DEFAULT_SERIALIZE_OPTIONS,
|
|
55
|
+
...opts
|
|
41
56
|
}
|
|
42
57
|
});
|
|
43
58
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} name
|
|
62
|
+
* @param {import('cookie').CookieSerializeOptions} opts
|
|
63
|
+
*/
|
|
64
|
+
delete(name, opts = {}) {
|
|
65
|
+
new_cookies.set(name, {
|
|
66
|
+
name,
|
|
67
|
+
value: '',
|
|
68
|
+
options: {
|
|
69
|
+
...DEFAULT_SERIALIZE_OPTIONS,
|
|
70
|
+
...opts,
|
|
71
|
+
maxAge: 0
|
|
72
|
+
}
|
|
73
|
+
});
|
|
47
74
|
}
|
|
48
75
|
};
|
|
49
76
|
|
|
@@ -75,3 +102,14 @@ export function path_matches(path, constraint) {
|
|
|
75
102
|
if (path === normalized) return true;
|
|
76
103
|
return path.startsWith(normalized + '/');
|
|
77
104
|
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {Headers} headers
|
|
108
|
+
* @param {import('./page/types').Cookie[]} cookies
|
|
109
|
+
*/
|
|
110
|
+
export function add_cookies_to_headers(headers, cookies) {
|
|
111
|
+
for (const new_cookie of cookies) {
|
|
112
|
+
const { name, value, options } = new_cookie;
|
|
113
|
+
headers.append('set-cookie', serialize(name, value, options));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as cookie from 'cookie';
|
|
2
1
|
import { render_endpoint } from './endpoint.js';
|
|
3
2
|
import { render_page } from './page/index.js';
|
|
4
3
|
import { render_response } from './page/render.js';
|
|
@@ -9,7 +8,7 @@ import { decode_params, disable_search, normalize_path } from '../../utils/url.j
|
|
|
9
8
|
import { exec } from '../../utils/routing.js';
|
|
10
9
|
import { render_data } from './data/index.js';
|
|
11
10
|
import { DATA_SUFFIX } from '../../constants.js';
|
|
12
|
-
import { get_cookies } from './cookie.js';
|
|
11
|
+
import { add_cookies_to_headers, get_cookies } from './cookie.js';
|
|
13
12
|
import { HttpError } from '../control.js';
|
|
14
13
|
|
|
15
14
|
/* global __SVELTEKIT_ADAPTER_NAME__ */
|
|
@@ -246,12 +245,7 @@ export async function respond(request, options, state) {
|
|
|
246
245
|
}
|
|
247
246
|
}
|
|
248
247
|
|
|
249
|
-
|
|
250
|
-
response.headers.append(
|
|
251
|
-
'set-cookie',
|
|
252
|
-
cookie.serialize(new_cookie.name, new_cookie.value, new_cookie.options)
|
|
253
|
-
);
|
|
254
|
-
}
|
|
248
|
+
add_cookies_to_headers(response.headers, Array.from(new_cookies.values()));
|
|
255
249
|
|
|
256
250
|
return response;
|
|
257
251
|
}
|
|
@@ -19,7 +19,7 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
19
19
|
|
|
20
20
|
const initial_cookies = cookie.parse(event.request.headers.get('cookie') || '');
|
|
21
21
|
|
|
22
|
-
/** @type {import('
|
|
22
|
+
/** @type {import('./types').Cookie[]} */
|
|
23
23
|
const set_cookies = [];
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -31,8 +31,8 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
31
31
|
const new_cookies = {};
|
|
32
32
|
|
|
33
33
|
for (const cookie of set_cookies) {
|
|
34
|
-
if (!domain_matches(url.hostname, cookie.domain)) continue;
|
|
35
|
-
if (!path_matches(url.pathname, cookie.path)) continue;
|
|
34
|
+
if (!domain_matches(url.hostname, cookie.options.domain)) continue;
|
|
35
|
+
if (!path_matches(url.pathname, cookie.options.path)) continue;
|
|
36
36
|
|
|
37
37
|
new_cookies[cookie.name] = cookie.value;
|
|
38
38
|
}
|
|
@@ -179,9 +179,11 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
179
179
|
const set_cookie = response.headers.get('set-cookie');
|
|
180
180
|
if (set_cookie) {
|
|
181
181
|
set_cookies.push(
|
|
182
|
-
...set_cookie_parser
|
|
183
|
-
.
|
|
184
|
-
.
|
|
182
|
+
...set_cookie_parser.splitCookiesString(set_cookie).map((str) => {
|
|
183
|
+
const { name, value, ...options } = set_cookie_parser.parseString(str);
|
|
184
|
+
// options.sameSite is string, something more specific is required - type cast is safe
|
|
185
|
+
return /** @type{import('./types').Cookie} */ ({ name, value, options });
|
|
186
|
+
})
|
|
185
187
|
);
|
|
186
188
|
}
|
|
187
189
|
|
|
@@ -217,7 +217,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
return redirect_response(err.status, err.location);
|
|
220
|
+
return redirect_response(err.status, err.location, cookies);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
const status = err instanceof HttpError ? err.status : 500;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { devalue } from 'devalue';
|
|
2
2
|
import { readable, writable } from 'svelte/store';
|
|
3
|
-
import * as cookie from 'cookie';
|
|
4
3
|
import { hash } from '../../hash.js';
|
|
5
4
|
import { serialize_data } from './serialize_data.js';
|
|
6
5
|
import { s } from '../../../utils/misc.js';
|
|
7
6
|
import { Csp } from './csp.js';
|
|
7
|
+
import { add_cookies_to_headers } from '../cookie.js';
|
|
8
8
|
|
|
9
9
|
// TODO rename this function/module
|
|
10
10
|
|
|
@@ -18,7 +18,7 @@ const updated = {
|
|
|
18
18
|
* @param {{
|
|
19
19
|
* branch: Array<import('./types').Loaded>;
|
|
20
20
|
* fetched: Array<import('./types').Fetched>;
|
|
21
|
-
* cookies: import('
|
|
21
|
+
* cookies: import('./types').Cookie[];
|
|
22
22
|
* options: import('types').SSROptions;
|
|
23
23
|
* state: import('types').SSRState;
|
|
24
24
|
* page_config: { ssr: boolean; csr: boolean };
|
|
@@ -328,11 +328,7 @@ export async function render_response({
|
|
|
328
328
|
headers.set('content-security-policy-report-only', report_only_header);
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
-
|
|
332
|
-
const { name, value, ...options } = new_cookie;
|
|
333
|
-
// @ts-expect-error
|
|
334
|
-
headers.append('set-cookie', cookie.serialize(name, value, options));
|
|
335
|
-
}
|
|
331
|
+
add_cookies_to_headers(headers, cookies);
|
|
336
332
|
|
|
337
333
|
if (link_header_preloads.size) {
|
|
338
334
|
headers.set('link', Array.from(link_header_preloads).join(', '));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { CookieSerializeOptions } from 'cookie';
|
|
1
2
|
import { SSRNode, CspDirectives } from 'types';
|
|
2
|
-
import { HttpError } from '../../control.js';
|
|
3
3
|
|
|
4
4
|
export interface Fetched {
|
|
5
5
|
url: string;
|
|
@@ -33,3 +33,9 @@ export interface CspOpts {
|
|
|
33
33
|
dev: boolean;
|
|
34
34
|
prerender: boolean;
|
|
35
35
|
}
|
|
36
|
+
|
|
37
|
+
export interface Cookie {
|
|
38
|
+
name: string;
|
|
39
|
+
value: string;
|
|
40
|
+
options: CookieSerializeOptions;
|
|
41
|
+
}
|
|
@@ -2,6 +2,7 @@ import { devalue } from 'devalue';
|
|
|
2
2
|
import { DATA_SUFFIX } from '../../constants.js';
|
|
3
3
|
import { negotiate } from '../../utils/http.js';
|
|
4
4
|
import { HttpError } from '../control.js';
|
|
5
|
+
import { add_cookies_to_headers } from './cookie.js';
|
|
5
6
|
|
|
6
7
|
/** @param {any} body */
|
|
7
8
|
export function is_pojo(body) {
|
|
@@ -169,10 +170,13 @@ export function handle_error_and_jsonify(event, options, error) {
|
|
|
169
170
|
/**
|
|
170
171
|
* @param {number} status
|
|
171
172
|
* @param {string} location
|
|
173
|
+
* @param {import('./page/types.js').Cookie[]} [cookies]
|
|
172
174
|
*/
|
|
173
|
-
export function redirect_response(status, location) {
|
|
174
|
-
|
|
175
|
+
export function redirect_response(status, location, cookies = []) {
|
|
176
|
+
const response = new Response(undefined, {
|
|
175
177
|
status,
|
|
176
178
|
headers: { location }
|
|
177
179
|
});
|
|
180
|
+
add_cookies_to_headers(response.headers, cookies);
|
|
181
|
+
return response;
|
|
178
182
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -128,21 +128,21 @@ export interface Cookies {
|
|
|
128
128
|
/**
|
|
129
129
|
* Gets a cookie that was previously set with `cookies.set`, or from the request headers.
|
|
130
130
|
*/
|
|
131
|
-
get(name: string, opts?: import('cookie').CookieParseOptions): string |
|
|
131
|
+
get(name: string, opts?: import('cookie').CookieParseOptions): string | void;
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
|
-
* Sets a cookie. This will add a `set-cookie` header to the response, but also make
|
|
135
|
-
* the cookie available via `cookies.get` during the current request.
|
|
134
|
+
* 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.
|
|
136
135
|
*
|
|
137
|
-
* The `httpOnly` and `secure` options are `true` by default, and must be explicitly
|
|
138
|
-
*
|
|
136
|
+
* 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`.
|
|
137
|
+
*
|
|
138
|
+
* 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.
|
|
139
139
|
*/
|
|
140
140
|
set(name: string, value: string, opts?: import('cookie').CookieSerializeOptions): void;
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
|
|
144
144
|
*/
|
|
145
|
-
delete(name: string): void;
|
|
145
|
+
delete(name: string, opts?: import('cookie').CookieSerializeOptions): void;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export interface KitConfig {
|