Skip to content

Commit 49b5171

Browse files
committed
merge
2 parents b111acd + 004e81b commit 49b5171

File tree

48 files changed

+314
-158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+314
-158
lines changed

.changeset/eighty-turkeys-exercise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
[fix] harmonize cookie path and add dev time warnings

.changeset/lucky-moles-count.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sveltejs/kit": patch
3+
---
4+
5+
Restore `req.url` to `req.originalUrl` in dev and preview

.changeset/pre.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@
274274
"eighty-candles-grow",
275275
"eighty-carrots-heal",
276276
"eighty-parrots-cry",
277+
"eighty-turkeys-exercise",
277278
"eighty-waves-obey",
278279
"eleven-buckets-deny",
279280
"eleven-bugs-fail",
@@ -648,6 +649,7 @@
648649
"lucky-bottles-kick",
649650
"lucky-glasses-sell",
650651
"lucky-guests-act",
652+
"lucky-moles-count",
651653
"lucky-phones-march",
652654
"lucky-plums-listen",
653655
"many-cups-report",
@@ -1292,6 +1294,7 @@
12921294
"tidy-rocks-beg",
12931295
"tidy-turkeys-rule",
12941296
"tidy-wasps-shave",
1297+
"tidy-wombats-repeat",
12951298
"tiny-badgers-love",
12961299
"tiny-candles-repeat",
12971300
"tiny-eels-hear",

.changeset/tidy-wombats-repeat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
[feat] add invalidateAll option to goto

documentation/docs/20-core-concepts/20-load.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ export async function load({ cookies }) {
266266
}
267267
```
268268

269+
> When setting cookies, be aware of the `path` property. By default, the `path` of a cookie is the current pathname. If you for example set a cookie at page `admin/user`, the cookie will only be available within the `admin` pages by default. In most cases you likely want to set `path` to `'/'` to make the cookie available throughout your app.
270+
269271
Both server-only and shared `load` functions have access to a `setHeaders` function that, when running on the server, can set headers for the response. (When running in the browser, `setHeaders` has no effect.) This is useful if you want the page to be cached, for example:
270272

271273
```js

documentation/docs/30-advanced/70-packaging.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ You can use SvelteKit to build apps as well as component libraries, using the `@
88

99
When you're creating an app, the contents of `src/routes` is the public-facing stuff; [`src/lib`](/docs/modules#$lib) contains your app's internal library.
1010

11-
A SvelteKit component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
11+
A component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
1212

1313
Running the `svelte-package` command from `@sveltejs/package` will take the contents of `src/lib` and generate a `package` directory (which can be [configured](/docs/configuration#package)) containing the following:
1414

@@ -38,6 +38,8 @@ declare module 'your-library/Foo.svelte';
3838
import Foo from 'your-library/Foo.svelte';
3939
```
4040

41+
> You should avoid using [SvelteKit-specific modules](/docs/modules) like `$app` in your packages unless you intend for them to only be consumable by other SvelteKit projects. E.g. rather than using `import { browser } from '$app/environment'` you could use [`import.meta.env.SSR`](https://vitejs.dev/guide/env-and-mode.html#env-variables) to make the library available to all Vite-based projects or better yet use [Node conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to make it work for all bundlers. You may also wish to pass in things like the current URL or a navigation action as a prop rather than relying directly on `$app/stores`, `$app/navigation`, etc. Writing your app in this more generic fashion will also make it easier to setup tools for testing, UI demos and so on.
42+
4143
### Options
4244

4345
`svelte-package` accepts the following options:

packages/adapter-static/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
"svelte": "^3.52.0",
3232
"typescript": "^4.8.4",
3333
"uvu": "^0.5.6",
34-
"vite": "^3.1.8"
34+
"vite": "^3.2.1"
3535
}
3636
}

packages/adapter-static/test/apps/prerendered/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"devDependencies": {
1111
"@sveltejs/kit": "workspace:*",
1212
"svelte": "^3.52.0",
13-
"vite": "^3.1.8"
13+
"vite": "^3.2.1"
1414
},
1515
"type": "module"
1616
}

packages/adapter-static/test/apps/spa/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@sveltejs/kit": "workspace:*",
1313
"sirv-cli": "^2.0.2",
1414
"svelte": "^3.52.0",
15-
"vite": "^3.1.8"
15+
"vite": "^3.2.1"
1616
},
1717
"type": "module"
1818
}

packages/create-svelte/templates/default/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"svelte": "^3.52.0",
1515
"svelte-preprocess": "^4.10.7",
1616
"typescript": "^4.8.4",
17-
"vite": "^3.1.8"
17+
"vite": "^3.2.1"
1818
},
1919
"type": "module",
2020
"dependencies": {

packages/kit/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# @sveltejs/kit
22

3+
## 1.0.0-next.528
4+
5+
### Patch Changes
6+
7+
- Restore `req.url` to `req.originalUrl` in dev and preview ([#7343](https://github.com/sveltejs/kit/pull/7343))
8+
9+
## 1.0.0-next.527
10+
11+
### Patch Changes
12+
13+
- [fix] harmonize cookie path and add dev time warnings ([#7416](https://github.com/sveltejs/kit/pull/7416))
14+
15+
* [feat] add invalidateAll option to goto ([#7407](https://github.com/sveltejs/kit/pull/7407))
16+
317
## 1.0.0-next.526
418

519
### Patch Changes

packages/kit/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sveltejs/kit",
3-
"version": "1.0.0-next.526",
3+
"version": "1.0.0-next.528",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/sveltejs/kit",
@@ -37,7 +37,7 @@
3737
"svelte-preprocess": "^4.10.7",
3838
"typescript": "^4.8.4",
3939
"uvu": "^0.5.6",
40-
"vite": "^3.1.8"
40+
"vite": "^3.2.1"
4141
},
4242
"peerDependencies": {
4343
"svelte": "^3.44.0",

packages/kit/src/constants.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,3 @@
33
export const SVELTE_KIT_ASSETS = '/_svelte_kit_assets';
44

55
export const GENERATED_COMMENT = '// this file is generated — do not edit it\n';
6-
7-
export const DATA_SUFFIX = '/__data.json';

packages/kit/src/exports/vite/dev/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ export async function dev(vite, vite_config, svelte_config) {
291291
remove_static_middlewares(vite.middlewares);
292292

293293
vite.middlewares.use(async (req, res) => {
294+
// Vite's base middleware strips out the base path. Restore it
295+
req.url = req.originalUrl;
294296
try {
295297
const base = `${vite.config.server.https ? 'https' : 'http'}://${
296298
req.headers[':authority'] || req.headers.host

packages/kit/src/runtime/client/client.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { onMount, tick } from 'svelte';
2-
import { make_trackable, decode_params, normalize_path } from '../../utils/url.js';
2+
import { make_trackable, decode_params, normalize_path, add_data_suffix } from '../../utils/url.js';
33
import { find_anchor, get_base_uri, scroll_state } from './utils.js';
44
import {
55
lock_fetch,
@@ -14,7 +14,6 @@ import Root from '__GENERATED__/root.svelte';
1414
import { nodes, server_loads, dictionary, matchers, hooks } from '__GENERATED__/client-manifest.js';
1515
import { HttpError, Redirect } from '../control.js';
1616
import { stores } from './singletons.js';
17-
import { DATA_SUFFIX } from '../../constants.js';
1817
import { unwrap_promises } from '../../utils/promises.js';
1918
import * as devalue from 'devalue';
2019

@@ -164,13 +163,19 @@ export function create_client({ target, base, trailing_slash }) {
164163

165164
/**
166165
* @param {string | URL} url
167-
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any }} opts
166+
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any; invalidateAll?: boolean }} opts
168167
* @param {string[]} redirect_chain
169168
* @param {{}} [nav_token]
170169
*/
171170
async function goto(
172171
url,
173-
{ noscroll = false, replaceState = false, keepfocus = false, state = {} },
172+
{
173+
noscroll = false,
174+
replaceState = false,
175+
keepfocus = false,
176+
state = {},
177+
invalidateAll = false
178+
},
174179
redirect_chain,
175180
nav_token
176181
) {
@@ -188,7 +193,11 @@ export function create_client({ target, base, trailing_slash }) {
188193
replaceState
189194
},
190195
nav_token,
191-
accepted: () => {},
196+
accepted: () => {
197+
if (invalidateAll) {
198+
force_invalidation = true;
199+
}
200+
},
192201
blocked: () => {},
193202
type: 'goto'
194203
});
@@ -1212,7 +1221,7 @@ export function create_client({ target, base, trailing_slash }) {
12121221
post_update();
12131222
}
12141223
} else if (result.type === 'redirect') {
1215-
goto(result.location, {}, []);
1224+
goto(result.location, { invalidateAll: true }, []);
12161225
} else {
12171226
/** @type {Record<string, any>} */
12181227
const props = {
@@ -1501,7 +1510,7 @@ export function create_client({ target, base, trailing_slash }) {
15011510
*/
15021511
async function load_data(url, invalid) {
15031512
const data_url = new URL(url);
1504-
data_url.pathname = url.pathname.replace(/\/$/, '') + DATA_SUFFIX;
1513+
data_url.pathname = add_data_suffix(url.pathname);
15051514

15061515
const res = await native_fetch(data_url.href, {
15071516
headers: {

packages/kit/src/runtime/server/cookie.js

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import { parse, serialize } from 'cookie';
2+
import { has_data_suffix, normalize_path, strip_data_suffix } from '../../utils/url.js';
3+
4+
/**
5+
* Tracks all cookies set during dev mode so we can emit warnings
6+
* when we detect that there's likely cookie misusage due to wrong paths
7+
*
8+
* @type {Record<string, Set<string>>} */
9+
const cookie_paths = {};
210

311
/**
412
* @param {Request} request
513
* @param {URL} url
14+
* @param {Pick<import('types').SSROptions, 'dev' | 'trailing_slash'>} options
615
*/
7-
export function get_cookies(request, url) {
16+
export function get_cookies(request, url, options) {
817
const header = request.headers.get('cookie') ?? '';
918

1019
const initial_cookies = parse(header);
@@ -42,7 +51,17 @@ export function get_cookies(request, url) {
4251

4352
const decode = opts?.decode || decodeURIComponent;
4453
const req_cookies = parse(header, { decode });
45-
return req_cookies[name]; // the decoded string or undefined
54+
const cookie = req_cookies[name]; // the decoded string or undefined
55+
56+
if (!options.dev || cookie) {
57+
return cookie;
58+
}
59+
60+
if (c || cookie_paths[name]?.size > 0) {
61+
console.warn(
62+
`Cookie with name '${name}' was not found, but a cookie with that name exists at a sub path. Did you mean to set its 'path' to '/'?`
63+
);
64+
}
4665
},
4766

4867
/**
@@ -51,30 +70,54 @@ export function get_cookies(request, url) {
5170
* @param {import('cookie').CookieSerializeOptions} opts
5271
*/
5372
set(name, value, opts = {}) {
73+
let path = opts.path;
74+
if (!path) {
75+
const normalized = normalize_path(
76+
// Remove suffix: 'foo/__data.json' would mean the cookie path is '/foo',
77+
// whereas a direct hit of /foo would mean the cookie path is '/'
78+
has_data_suffix(url.pathname) ? strip_data_suffix(url.pathname) : url.pathname,
79+
options.trailing_slash
80+
);
81+
// Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
82+
path = normalized.split('/').slice(0, -1).join('/') || '/';
83+
}
84+
5485
new_cookies[name] = {
5586
name,
5687
value,
5788
options: {
5889
...defaults,
59-
...opts
90+
...opts,
91+
path
6092
}
6193
};
94+
95+
if (options.dev) {
96+
cookie_paths[name] = cookie_paths[name] || new Set();
97+
if (!value) {
98+
if (!cookie_paths[name].has(path) && cookie_paths[name].size > 0) {
99+
console.warn(
100+
`Trying to delete cookie '${name}' at path '${path}', but a cookie with that name only exists at a different path.`
101+
);
102+
}
103+
cookie_paths[name].delete(path);
104+
} else {
105+
// We could also emit a warning here if the cookie already exists at a different path,
106+
// but that's more likely a false positive because it's valid to set the same name at different paths
107+
cookie_paths[name].add(path);
108+
}
109+
}
62110
},
63111

64112
/**
65113
* @param {string} name
66114
* @param {import('cookie').CookieSerializeOptions} opts
67115
*/
68116
delete(name, opts = {}) {
69-
new_cookies[name] = {
70-
name,
71-
value: '',
72-
options: {
73-
...defaults,
74-
...opts,
75-
maxAge: 0
76-
}
77-
};
117+
cookies.set(name, '', {
118+
...opts,
119+
maxAge: 0
120+
});
78121
},
79122

80123
/**

packages/kit/src/runtime/server/cookie.spec.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ paths.negative.forEach(([path, constraint]) => {
4242
});
4343
});
4444

45-
/** @param {boolean} localhost */
46-
const cookies_setup = (localhost = false) => {
47-
const url = new URL(localhost ? 'http://localhost:1234' : 'https://example.com');
45+
/** @param {string} href */
46+
const cookies_setup = (href = 'https://example.com') => {
47+
const url = new URL(href);
4848
const request = new Request(url, {
4949
headers: new Headers({
5050
cookie: 'a=b;'
5151
})
5252
});
53-
return get_cookies(request, url);
53+
return get_cookies(request, url, { dev: false, trailing_slash: 'ignore' });
5454
};
5555

5656
test('a cookie should not be present after it is deleted', () => {
@@ -67,12 +67,22 @@ test('default values when set is called', () => {
6767
const opts = new_cookies['a']?.options;
6868
assert.equal(opts?.secure, true);
6969
assert.equal(opts?.httpOnly, true);
70-
assert.equal(opts?.path, undefined);
70+
assert.equal(opts?.path, '/');
71+
assert.equal(opts?.sameSite, 'lax');
72+
});
73+
74+
test('default values when set is called on sub path', () => {
75+
const { cookies, new_cookies } = cookies_setup('https://example.com/foo/bar');
76+
cookies.set('a', 'b');
77+
const opts = new_cookies['a']?.options;
78+
assert.equal(opts?.secure, true);
79+
assert.equal(opts?.httpOnly, true);
80+
assert.equal(opts?.path, '/foo');
7181
assert.equal(opts?.sameSite, 'lax');
7282
});
7383

7484
test('default values when on localhost', () => {
75-
const { cookies, new_cookies } = cookies_setup(true);
85+
const { cookies, new_cookies } = cookies_setup('http://localhost:1234');
7686
cookies.set('a', 'b');
7787
const opts = new_cookies['a']?.options;
7888
assert.equal(opts?.secure, false);
@@ -94,7 +104,7 @@ test('default values when delete is called', () => {
94104
const opts = new_cookies['a']?.options;
95105
assert.equal(opts?.secure, true);
96106
assert.equal(opts?.httpOnly, true);
97-
assert.equal(opts?.path, undefined);
107+
assert.equal(opts?.path, '/');
98108
assert.equal(opts?.sameSite, 'lax');
99109
assert.equal(opts?.maxAge, 0);
100110
});

0 commit comments

Comments
 (0)