@sveltejs/kit 1.0.0-next.525 → 1.0.0-next.527
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/generate_manifest/index.js +1 -0
- package/src/core/sync/create_manifest_data/index.js +3 -1
- package/src/core/sync/write_types/index.js +3 -1
- package/src/exports/node/index.js +2 -0
- package/src/exports/vite/dev/index.js +1 -0
- package/src/exports/vite/index.js +1 -1
- package/src/runtime/client/client.js +14 -4
- package/src/runtime/client/parse.js +2 -2
- package/src/runtime/client/types.d.ts +4 -4
- package/src/runtime/server/cookie.js +58 -12
- package/src/runtime/server/index.js +2 -2
- package/src/runtime/server/page/render.js +14 -0
- package/src/utils/routing.js +26 -22
- package/types/ambient.d.ts +28 -10
- package/types/index.d.ts +17 -15
- package/types/internal.d.ts +5 -3
- package/types/private.d.ts +5 -5
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.527",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://kit.svelte.dev",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@sveltejs/vite-plugin-svelte": "^1.0
|
|
13
|
+
"@sveltejs/vite-plugin-svelte": "^1.1.0",
|
|
14
14
|
"@types/cookie": "^0.5.1",
|
|
15
15
|
"cookie": "^0.5.0",
|
|
16
16
|
"devalue": "^4.0.0",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"set-cookie-parser": "^2.4.8",
|
|
22
22
|
"sirv": "^2.0.2",
|
|
23
23
|
"tiny-glob": "^0.2.9",
|
|
24
|
-
"undici": "
|
|
24
|
+
"undici": "5.12.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@playwright/test": "^1.25.0",
|
|
@@ -66,6 +66,7 @@ export function generate_manifest({ build_data, relative_path, routes, format =
|
|
|
66
66
|
pattern: ${route.pattern},
|
|
67
67
|
names: ${s(route.names)},
|
|
68
68
|
types: ${s(route.types)},
|
|
69
|
+
optional: ${s(route.optional)},
|
|
69
70
|
page: ${route.page ? `{ layouts: ${get_nodes(route.page.layouts)}, errors: ${get_nodes(route.page.errors)}, leaf: ${route.page.leaf} }` : 'null'},
|
|
70
71
|
endpoint: ${route.endpoint ? loader(`${relative_path}/${resolve_symlinks(build_data.server.vite_manifest, route.endpoint.file).chunk.file}`) : 'null'}
|
|
71
72
|
}`;
|
|
@@ -121,7 +121,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
|
|
|
121
121
|
);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
const { pattern, names, types } = parse_route_id(id);
|
|
124
|
+
const { pattern, names, types, optional } = parse_route_id(id);
|
|
125
125
|
|
|
126
126
|
/** @type {import('types').RouteData} */
|
|
127
127
|
const route = {
|
|
@@ -132,6 +132,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
|
|
|
132
132
|
pattern,
|
|
133
133
|
names,
|
|
134
134
|
types,
|
|
135
|
+
optional,
|
|
135
136
|
|
|
136
137
|
layout: null,
|
|
137
138
|
error: null,
|
|
@@ -228,6 +229,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
|
|
|
228
229
|
pattern: /^$/,
|
|
229
230
|
names: [],
|
|
230
231
|
types: [],
|
|
232
|
+
optional: [],
|
|
231
233
|
parent: null,
|
|
232
234
|
layout: null,
|
|
233
235
|
error: null,
|
|
@@ -195,7 +195,9 @@ function update_types(config, routes, route, to_delete = new Set()) {
|
|
|
195
195
|
// Makes sure a type is "repackaged" and therefore more readable
|
|
196
196
|
declarations.push('type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;');
|
|
197
197
|
declarations.push(
|
|
198
|
-
`type RouteParams = { ${route.names
|
|
198
|
+
`type RouteParams = { ${route.names
|
|
199
|
+
.map((param, idx) => `${param}${route.optional[idx] ? '?' : ''}: string`)
|
|
200
|
+
.join('; ')} }`
|
|
199
201
|
);
|
|
200
202
|
|
|
201
203
|
// These could also be placed in our public types, but it would bloat them unnecessarily and we may want to change these in the future
|
|
@@ -95,6 +95,8 @@ function get_raw_body(req, body_size_limit) {
|
|
|
95
95
|
/** @type {import('@sveltejs/kit/node').getRequest} */
|
|
96
96
|
export async function getRequest({ request, base, bodySizeLimit }) {
|
|
97
97
|
return new Request(base + request.url, {
|
|
98
|
+
// @ts-expect-error
|
|
99
|
+
duplex: 'half',
|
|
98
100
|
method: request.method,
|
|
99
101
|
headers: /** @type {Record<string, string>} */ (request.headers),
|
|
100
102
|
body: get_raw_body(request, bodySizeLimit)
|
|
@@ -164,13 +164,19 @@ export function create_client({ target, base, trailing_slash }) {
|
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* @param {string | URL} url
|
|
167
|
-
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any }} opts
|
|
167
|
+
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any; invalidateAll?: boolean }} opts
|
|
168
168
|
* @param {string[]} redirect_chain
|
|
169
169
|
* @param {{}} [nav_token]
|
|
170
170
|
*/
|
|
171
171
|
async function goto(
|
|
172
172
|
url,
|
|
173
|
-
{
|
|
173
|
+
{
|
|
174
|
+
noscroll = false,
|
|
175
|
+
replaceState = false,
|
|
176
|
+
keepfocus = false,
|
|
177
|
+
state = {},
|
|
178
|
+
invalidateAll = false
|
|
179
|
+
},
|
|
174
180
|
redirect_chain,
|
|
175
181
|
nav_token
|
|
176
182
|
) {
|
|
@@ -188,7 +194,11 @@ export function create_client({ target, base, trailing_slash }) {
|
|
|
188
194
|
replaceState
|
|
189
195
|
},
|
|
190
196
|
nav_token,
|
|
191
|
-
accepted: () => {
|
|
197
|
+
accepted: () => {
|
|
198
|
+
if (invalidateAll) {
|
|
199
|
+
force_invalidation = true;
|
|
200
|
+
}
|
|
201
|
+
},
|
|
192
202
|
blocked: () => {},
|
|
193
203
|
type: 'goto'
|
|
194
204
|
});
|
|
@@ -1212,7 +1222,7 @@ export function create_client({ target, base, trailing_slash }) {
|
|
|
1212
1222
|
post_update();
|
|
1213
1223
|
}
|
|
1214
1224
|
} else if (result.type === 'redirect') {
|
|
1215
|
-
goto(result.location, {}, []);
|
|
1225
|
+
goto(result.location, { invalidateAll: true }, []);
|
|
1216
1226
|
} else {
|
|
1217
1227
|
/** @type {Record<string, any>} */
|
|
1218
1228
|
const props = {
|
|
@@ -11,14 +11,14 @@ export function parse(nodes, server_loads, dictionary, matchers) {
|
|
|
11
11
|
const layouts_with_server_load = new Set(server_loads);
|
|
12
12
|
|
|
13
13
|
return Object.entries(dictionary).map(([id, [leaf, layouts, errors]]) => {
|
|
14
|
-
const { pattern, names, types } = parse_route_id(id);
|
|
14
|
+
const { pattern, names, types, optional } = parse_route_id(id);
|
|
15
15
|
|
|
16
16
|
const route = {
|
|
17
17
|
id,
|
|
18
18
|
/** @param {string} path */
|
|
19
19
|
exec: (path) => {
|
|
20
20
|
const match = pattern.exec(path);
|
|
21
|
-
if (match) return exec(match,
|
|
21
|
+
if (match) return exec(match, { names, types, optional }, matchers);
|
|
22
22
|
},
|
|
23
23
|
errors: [1, ...(errors || [])].map((n) => nodes[n]),
|
|
24
24
|
layouts: [0, ...(layouts || [])].map(create_layout_loader),
|
|
@@ -14,7 +14,7 @@ export interface Client {
|
|
|
14
14
|
// public API, exposed via $app/navigation
|
|
15
15
|
after_navigate: typeof afterNavigate;
|
|
16
16
|
before_navigate: typeof beforeNavigate;
|
|
17
|
-
disable_scroll_handling
|
|
17
|
+
disable_scroll_handling(): void;
|
|
18
18
|
goto: typeof goto;
|
|
19
19
|
invalidate: typeof invalidate;
|
|
20
20
|
invalidateAll: typeof invalidateAll;
|
|
@@ -23,7 +23,7 @@ export interface Client {
|
|
|
23
23
|
apply_action: typeof applyAction;
|
|
24
24
|
|
|
25
25
|
// private API
|
|
26
|
-
_hydrate
|
|
26
|
+
_hydrate(opts: {
|
|
27
27
|
status: number;
|
|
28
28
|
error: App.Error;
|
|
29
29
|
node_ids: number[];
|
|
@@ -31,8 +31,8 @@ export interface Client {
|
|
|
31
31
|
routeId: string | null;
|
|
32
32
|
data: Array<import('types').ServerDataNode | null>;
|
|
33
33
|
form: Record<string, any> | null;
|
|
34
|
-
})
|
|
35
|
-
_start_router
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
_start_router(): void;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export type NavigationIntent = {
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { parse, serialize } from 'cookie';
|
|
2
|
+
import { DATA_SUFFIX } from '../../constants.js';
|
|
3
|
+
import { normalize_path } from '../../utils/url.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tracks all cookies set during dev mode so we can emit warnings
|
|
7
|
+
* when we detect that there's likely cookie misusage due to wrong paths
|
|
8
|
+
*
|
|
9
|
+
* @type {Record<string, Set<string>>} */
|
|
10
|
+
const cookie_paths = {};
|
|
2
11
|
|
|
3
12
|
/**
|
|
4
13
|
* @param {Request} request
|
|
5
14
|
* @param {URL} url
|
|
15
|
+
* @param {Pick<import('types').SSROptions, 'dev' | 'trailing_slash'>} options
|
|
6
16
|
*/
|
|
7
|
-
export function get_cookies(request, url) {
|
|
17
|
+
export function get_cookies(request, url, options) {
|
|
8
18
|
const header = request.headers.get('cookie') ?? '';
|
|
9
19
|
|
|
10
20
|
const initial_cookies = parse(header);
|
|
@@ -42,7 +52,17 @@ export function get_cookies(request, url) {
|
|
|
42
52
|
|
|
43
53
|
const decode = opts?.decode || decodeURIComponent;
|
|
44
54
|
const req_cookies = parse(header, { decode });
|
|
45
|
-
|
|
55
|
+
const cookie = req_cookies[name]; // the decoded string or undefined
|
|
56
|
+
|
|
57
|
+
if (!options.dev || cookie) {
|
|
58
|
+
return cookie;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (c || cookie_paths[name]?.size > 0) {
|
|
62
|
+
console.warn(
|
|
63
|
+
`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 '/'?`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
46
66
|
},
|
|
47
67
|
|
|
48
68
|
/**
|
|
@@ -51,14 +71,45 @@ export function get_cookies(request, url) {
|
|
|
51
71
|
* @param {import('cookie').CookieSerializeOptions} opts
|
|
52
72
|
*/
|
|
53
73
|
set(name, value, opts = {}) {
|
|
74
|
+
let path = opts.path;
|
|
75
|
+
if (!path) {
|
|
76
|
+
const normalized = normalize_path(
|
|
77
|
+
// Remove suffix: 'foo/__data.json' would mean the cookie path is '/foo',
|
|
78
|
+
// whereas a direct hit of /foo would mean the cookie path is '/'
|
|
79
|
+
url.pathname.endsWith(DATA_SUFFIX)
|
|
80
|
+
? url.pathname.slice(0, -DATA_SUFFIX.length)
|
|
81
|
+
: url.pathname,
|
|
82
|
+
options.trailing_slash
|
|
83
|
+
);
|
|
84
|
+
// Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
|
|
85
|
+
path = normalized.split('/').slice(0, -1).join('/') || '/';
|
|
86
|
+
}
|
|
87
|
+
|
|
54
88
|
new_cookies[name] = {
|
|
55
89
|
name,
|
|
56
90
|
value,
|
|
57
91
|
options: {
|
|
58
92
|
...defaults,
|
|
59
|
-
...opts
|
|
93
|
+
...opts,
|
|
94
|
+
path
|
|
60
95
|
}
|
|
61
96
|
};
|
|
97
|
+
|
|
98
|
+
if (options.dev) {
|
|
99
|
+
cookie_paths[name] = cookie_paths[name] || new Set();
|
|
100
|
+
if (!value) {
|
|
101
|
+
if (!cookie_paths[name].has(path) && cookie_paths[name].size > 0) {
|
|
102
|
+
console.warn(
|
|
103
|
+
`Trying to delete cookie '${name}' at path '${path}', but a cookie with that name only exists at a different path.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
cookie_paths[name].delete(path);
|
|
107
|
+
} else {
|
|
108
|
+
// We could also emit a warning here if the cookie already exists at a different path,
|
|
109
|
+
// but that's more likely a false positive because it's valid to set the same name at different paths
|
|
110
|
+
cookie_paths[name].add(path);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
62
113
|
},
|
|
63
114
|
|
|
64
115
|
/**
|
|
@@ -66,15 +117,10 @@ export function get_cookies(request, url) {
|
|
|
66
117
|
* @param {import('cookie').CookieSerializeOptions} opts
|
|
67
118
|
*/
|
|
68
119
|
delete(name, opts = {}) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
...defaults,
|
|
74
|
-
...opts,
|
|
75
|
-
maxAge: 0
|
|
76
|
-
}
|
|
77
|
-
};
|
|
120
|
+
cookies.set(name, '', {
|
|
121
|
+
...opts,
|
|
122
|
+
maxAge: 0
|
|
123
|
+
});
|
|
78
124
|
},
|
|
79
125
|
|
|
80
126
|
/**
|
|
@@ -67,7 +67,7 @@ export async function respond(request, options, state) {
|
|
|
67
67
|
const match = candidate.pattern.exec(decoded);
|
|
68
68
|
if (!match) continue;
|
|
69
69
|
|
|
70
|
-
const matched = exec(match, candidate
|
|
70
|
+
const matched = exec(match, candidate, matchers);
|
|
71
71
|
if (matched) {
|
|
72
72
|
route = candidate;
|
|
73
73
|
params = decode_params(matched);
|
|
@@ -96,7 +96,7 @@ export async function respond(request, options, state) {
|
|
|
96
96
|
/** @type {Record<string, string>} */
|
|
97
97
|
const headers = {};
|
|
98
98
|
|
|
99
|
-
const { cookies, new_cookies, get_cookie_header } = get_cookies(request, url);
|
|
99
|
+
const { cookies, new_cookies, get_cookie_header } = get_cookies(request, url, options);
|
|
100
100
|
|
|
101
101
|
if (state.prerendering) disable_search(url);
|
|
102
102
|
|
|
@@ -182,6 +182,20 @@ export async function render_response({
|
|
|
182
182
|
`Data returned from \`load\` while rendering ${event.routeId} is not serializable: ${error.message} (data.${match[2]})`
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
|
+
|
|
186
|
+
const nonPojoError = /pojo/i.exec(error.message);
|
|
187
|
+
|
|
188
|
+
if (nonPojoError) {
|
|
189
|
+
const constructorName = branch.find(({ server_data }) => server_data?.data?.constructor?.name)
|
|
190
|
+
?.server_data?.data?.constructor?.name;
|
|
191
|
+
|
|
192
|
+
throw new Error(
|
|
193
|
+
`Data returned from \`load\` (while rendering ${event.routeId}) must be a plain object${
|
|
194
|
+
constructorName ? ` rather than an instance of ${constructorName}` : ''
|
|
195
|
+
}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
185
199
|
throw error;
|
|
186
200
|
}
|
|
187
201
|
|
package/src/utils/routing.js
CHANGED
|
@@ -8,6 +8,9 @@ export function parse_route_id(id) {
|
|
|
8
8
|
/** @type {string[]} */
|
|
9
9
|
const types = [];
|
|
10
10
|
|
|
11
|
+
/** @type {boolean[]} */
|
|
12
|
+
const optional = [];
|
|
13
|
+
|
|
11
14
|
// `/foo` should get an optional trailing slash, `/foo.json` should not
|
|
12
15
|
// const add_trailing_slash = !/\.[a-z]+$/.test(key);
|
|
13
16
|
let add_trailing_slash = true;
|
|
@@ -24,6 +27,7 @@ export function parse_route_id(id) {
|
|
|
24
27
|
if (rest_match) {
|
|
25
28
|
names.push(rest_match[1]);
|
|
26
29
|
types.push(rest_match[2]);
|
|
30
|
+
optional.push(false);
|
|
27
31
|
return '(?:/(.*))?';
|
|
28
32
|
}
|
|
29
33
|
// special case — /[[optional]]/ could contain zero segments
|
|
@@ -31,6 +35,7 @@ export function parse_route_id(id) {
|
|
|
31
35
|
if (optional_match) {
|
|
32
36
|
names.push(optional_match[1]);
|
|
33
37
|
types.push(optional_match[2]);
|
|
38
|
+
optional.push(true);
|
|
34
39
|
return '(?:/([^/]+))?';
|
|
35
40
|
}
|
|
36
41
|
|
|
@@ -51,14 +56,15 @@ export function parse_route_id(id) {
|
|
|
51
56
|
);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
const [,
|
|
59
|
+
const [, is_optional, is_rest, name, type] = match;
|
|
55
60
|
// It's assumed that the following invalid route id cases are already checked
|
|
56
61
|
// - unbalanced brackets
|
|
57
62
|
// - optional param following rest param
|
|
58
63
|
|
|
59
64
|
names.push(name);
|
|
60
65
|
types.push(type);
|
|
61
|
-
|
|
66
|
+
optional.push(!!is_optional);
|
|
67
|
+
return is_rest ? '(.*?)' : is_optional ? '([^/]*)?' : '([^/]+?)';
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
if (is_last && content.includes('.')) add_trailing_slash = false;
|
|
@@ -88,7 +94,7 @@ export function parse_route_id(id) {
|
|
|
88
94
|
.join('')}${add_trailing_slash ? '/?' : ''}$`
|
|
89
95
|
);
|
|
90
96
|
|
|
91
|
-
return { pattern, names, types };
|
|
97
|
+
return { pattern, names, types, optional };
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
/**
|
|
@@ -112,34 +118,32 @@ export function get_route_segments(route) {
|
|
|
112
118
|
|
|
113
119
|
/**
|
|
114
120
|
* @param {RegExpMatchArray} match
|
|
115
|
-
* @param {
|
|
116
|
-
*
|
|
117
|
-
*
|
|
121
|
+
* @param {{
|
|
122
|
+
* names: string[];
|
|
123
|
+
* types: string[];
|
|
124
|
+
* optional: boolean[];
|
|
125
|
+
* }} candidate
|
|
118
126
|
* @param {Record<string, import('types').ParamMatcher>} matchers
|
|
119
127
|
*/
|
|
120
|
-
export function exec(match,
|
|
128
|
+
export function exec(match, { names, types, optional }, matchers) {
|
|
121
129
|
/** @type {Record<string, string>} */
|
|
122
130
|
const params = {};
|
|
123
|
-
let last_type_idx = -1;
|
|
124
131
|
|
|
125
132
|
for (let i = 0; i < names.length; i += 1) {
|
|
126
133
|
const name = names[i];
|
|
127
134
|
const type = types[i];
|
|
128
|
-
let value = match[i + 1]
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
last_type_idx = routeId.indexOf(`=${type}`, last_type_idx + 1);
|
|
135
|
-
const is_empty_optional_param =
|
|
136
|
-
!value &&
|
|
137
|
-
// a param without a value can only be an optional or rest param
|
|
138
|
-
routeId.lastIndexOf('[[', last_type_idx) > routeId.lastIndexOf('[...', last_type_idx);
|
|
139
|
-
if (!is_empty_optional_param && !matcher(value)) return;
|
|
140
|
-
}
|
|
135
|
+
let value = match[i + 1];
|
|
136
|
+
|
|
137
|
+
if (value || !optional[i]) {
|
|
138
|
+
if (type) {
|
|
139
|
+
const matcher = matchers[type];
|
|
140
|
+
if (!matcher) throw new Error(`Missing "${type}" param matcher`); // TODO do this ahead of time?
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
if (!matcher(value)) return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
params[name] = value ?? '';
|
|
146
|
+
}
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
return params;
|
package/types/ambient.d.ts
CHANGED
|
@@ -103,7 +103,7 @@ declare module '$app/forms' {
|
|
|
103
103
|
data: FormData;
|
|
104
104
|
form: HTMLFormElement;
|
|
105
105
|
controller: AbortController;
|
|
106
|
-
cancel
|
|
106
|
+
cancel(): void;
|
|
107
107
|
}) =>
|
|
108
108
|
| void
|
|
109
109
|
| ((opts: {
|
|
@@ -114,7 +114,7 @@ declare module '$app/forms' {
|
|
|
114
114
|
* Call this to get the default behavior of a form submission response.
|
|
115
115
|
* @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission.
|
|
116
116
|
*/
|
|
117
|
-
update
|
|
117
|
+
update(options?: { reset: boolean }): Promise<void>;
|
|
118
118
|
}) => void);
|
|
119
119
|
|
|
120
120
|
/**
|
|
@@ -144,7 +144,7 @@ declare module '$app/forms' {
|
|
|
144
144
|
* If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback.
|
|
145
145
|
*/
|
|
146
146
|
submit?: SubmitFunction<Success, Invalid>
|
|
147
|
-
): { destroy
|
|
147
|
+
): { destroy(): void };
|
|
148
148
|
|
|
149
149
|
/**
|
|
150
150
|
* This action updates the `form` property of the current page with the given data and updates `$page.status`.
|
|
@@ -182,14 +182,32 @@ declare module '$app/navigation' {
|
|
|
182
182
|
* Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`.
|
|
183
183
|
*
|
|
184
184
|
* @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.
|
|
185
|
-
* @param opts
|
|
186
|
-
* @param opts.noscroll If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
|
|
187
|
-
* @param opts.keepfocus If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
|
|
188
|
-
* @param opts.state The state of the new/updated history entry
|
|
185
|
+
* @param opts Options related to the navigation
|
|
189
186
|
*/
|
|
190
187
|
export function goto(
|
|
191
188
|
url: string | URL,
|
|
192
|
-
opts?: {
|
|
189
|
+
opts?: {
|
|
190
|
+
/**
|
|
191
|
+
* If `true`, will replace the current `history` entry rather than creating a new one with `pushState`
|
|
192
|
+
*/
|
|
193
|
+
replaceState?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* If `true`, the browser will maintain its scroll position rather than scrolling to the top of the page after navigation
|
|
196
|
+
*/
|
|
197
|
+
noscroll?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* If `true`, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the body
|
|
200
|
+
*/
|
|
201
|
+
keepfocus?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* The state of the new/updated history entry
|
|
204
|
+
*/
|
|
205
|
+
state?: any;
|
|
206
|
+
/**
|
|
207
|
+
* If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#invalidation for more info on invalidation.
|
|
208
|
+
*/
|
|
209
|
+
invalidateAll?: boolean;
|
|
210
|
+
}
|
|
193
211
|
): Promise<void>;
|
|
194
212
|
/**
|
|
195
213
|
* Causes any `load` functions belonging to the currently active page to re-run if they depend on the `url` in question, via `fetch` or `depends`. Returns a `Promise` that resolves when the page is subsequently updated.
|
|
@@ -244,7 +262,7 @@ declare module '$app/navigation' {
|
|
|
244
262
|
* `beforeNavigate` must be called during a component initialization. It remains active as long as the component is mounted.
|
|
245
263
|
*/
|
|
246
264
|
export function beforeNavigate(
|
|
247
|
-
callback: (navigation: Navigation & { cancel
|
|
265
|
+
callback: (navigation: Navigation & { cancel(): void }) => void
|
|
248
266
|
): void;
|
|
249
267
|
|
|
250
268
|
/**
|
|
@@ -303,7 +321,7 @@ declare module '$app/stores' {
|
|
|
303
321
|
/**
|
|
304
322
|
* A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
|
|
305
323
|
*/
|
|
306
|
-
export const updated: Readable<boolean> & { check
|
|
324
|
+
export const updated: Readable<boolean> & { check(): boolean };
|
|
307
325
|
|
|
308
326
|
/**
|
|
309
327
|
* A function that returns all of the contextual stores. On the server, this must be called during component initialization.
|
package/types/index.d.ts
CHANGED
|
@@ -79,7 +79,7 @@ export interface Builder {
|
|
|
79
79
|
*/
|
|
80
80
|
createEntries(fn: (route: RouteDefinition) => AdapterEntry): Promise<void>;
|
|
81
81
|
|
|
82
|
-
generateManifest
|
|
82
|
+
generateManifest(opts: { relativePath: string; format?: 'esm' | 'cjs' }): string;
|
|
83
83
|
|
|
84
84
|
getBuildDirectory(name: string): string;
|
|
85
85
|
getClientDirectory(): string;
|
|
@@ -118,7 +118,7 @@ export interface Builder {
|
|
|
118
118
|
from: string,
|
|
119
119
|
to: string,
|
|
120
120
|
opts?: {
|
|
121
|
-
filter
|
|
121
|
+
filter?(basename: string): boolean;
|
|
122
122
|
replace?: Record<string, string>;
|
|
123
123
|
}
|
|
124
124
|
): string[];
|
|
@@ -137,8 +137,8 @@ export interface Config {
|
|
|
137
137
|
source?: string;
|
|
138
138
|
dir?: string;
|
|
139
139
|
emitTypes?: boolean;
|
|
140
|
-
exports
|
|
141
|
-
files
|
|
140
|
+
exports?(filepath: string): boolean;
|
|
141
|
+
files?(filepath: string): boolean;
|
|
142
142
|
};
|
|
143
143
|
preprocess?: any;
|
|
144
144
|
[key: string]: any;
|
|
@@ -161,6 +161,8 @@ export interface Cookies {
|
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
* Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
|
|
164
|
+
*
|
|
165
|
+
* 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.
|
|
164
166
|
*/
|
|
165
167
|
delete(name: string, opts?: import('cookie').CookieSerializeOptions): void;
|
|
166
168
|
|
|
@@ -225,7 +227,7 @@ export interface KitConfig {
|
|
|
225
227
|
};
|
|
226
228
|
serviceWorker?: {
|
|
227
229
|
register?: boolean;
|
|
228
|
-
files
|
|
230
|
+
files?(filepath: string): boolean;
|
|
229
231
|
};
|
|
230
232
|
trailingSlash?: TrailingSlash;
|
|
231
233
|
version?: {
|
|
@@ -311,14 +313,14 @@ export interface LoadEvent<
|
|
|
311
313
|
*
|
|
312
314
|
* `setHeaders` has no effect when a `load` function runs in the browser.
|
|
313
315
|
*/
|
|
314
|
-
setHeaders
|
|
316
|
+
setHeaders(headers: Record<string, string>): void;
|
|
315
317
|
/**
|
|
316
318
|
* `await parent()` returns data from parent `+layout.js` `load` functions.
|
|
317
319
|
* Implicitly, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will return and forward data from parent `+layout.server.js` files.
|
|
318
320
|
*
|
|
319
321
|
* Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
|
|
320
322
|
*/
|
|
321
|
-
parent
|
|
323
|
+
parent(): Promise<ParentData>;
|
|
322
324
|
/**
|
|
323
325
|
* This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/modules#$app-navigation-invalidate) to cause `load` to rerun.
|
|
324
326
|
*
|
|
@@ -356,7 +358,7 @@ export interface LoadEvent<
|
|
|
356
358
|
* <button on:click={increase}>Increase Count</button>
|
|
357
359
|
* ```
|
|
358
360
|
*/
|
|
359
|
-
depends
|
|
361
|
+
depends(...deps: string[]): void;
|
|
360
362
|
}
|
|
361
363
|
|
|
362
364
|
export interface NavigationEvent<
|
|
@@ -449,7 +451,7 @@ export interface RequestEvent<
|
|
|
449
451
|
/**
|
|
450
452
|
* The client's IP address, set by the adapter.
|
|
451
453
|
*/
|
|
452
|
-
getClientAddress
|
|
454
|
+
getClientAddress(): string;
|
|
453
455
|
/**
|
|
454
456
|
* Contains custom data that was added to the request within the [`handle hook`](https://kit.svelte.dev/docs/hooks#server-hooks-handle).
|
|
455
457
|
*/
|
|
@@ -492,7 +494,7 @@ export interface RequestEvent<
|
|
|
492
494
|
*
|
|
493
495
|
* You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://kit.svelte.dev/docs/types#sveltejs-kit-cookies) API instead.
|
|
494
496
|
*/
|
|
495
|
-
setHeaders
|
|
497
|
+
setHeaders(headers: Record<string, string>): void;
|
|
496
498
|
/**
|
|
497
499
|
* The URL of the current page or endpoint
|
|
498
500
|
*/
|
|
@@ -511,8 +513,8 @@ export interface RequestHandler<
|
|
|
511
513
|
}
|
|
512
514
|
|
|
513
515
|
export interface ResolveOptions {
|
|
514
|
-
transformPageChunk
|
|
515
|
-
filterSerializedResponseHeaders
|
|
516
|
+
transformPageChunk?(input: { html: string; done: boolean }): MaybePromise<string | undefined>;
|
|
517
|
+
filterSerializedResponseHeaders?(name: string, value: string): boolean;
|
|
516
518
|
}
|
|
517
519
|
|
|
518
520
|
export class Server {
|
|
@@ -540,7 +542,7 @@ export interface SSRManifest {
|
|
|
540
542
|
};
|
|
541
543
|
nodes: SSRNodeLoader[];
|
|
542
544
|
routes: SSRRoute[];
|
|
543
|
-
matchers
|
|
545
|
+
matchers(): Promise<Record<string, ParamMatcher>>;
|
|
544
546
|
};
|
|
545
547
|
}
|
|
546
548
|
|
|
@@ -565,7 +567,7 @@ export interface ServerLoadEvent<
|
|
|
565
567
|
*
|
|
566
568
|
* Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data.
|
|
567
569
|
*/
|
|
568
|
-
parent
|
|
570
|
+
parent(): Promise<ParentData>;
|
|
569
571
|
/**
|
|
570
572
|
* This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/modules#$app-navigation-invalidate) to cause `load` to rerun.
|
|
571
573
|
*
|
|
@@ -603,7 +605,7 @@ export interface ServerLoadEvent<
|
|
|
603
605
|
* <button on:click={increase}>Increase Count</button>
|
|
604
606
|
* ```
|
|
605
607
|
*/
|
|
606
|
-
depends
|
|
608
|
+
depends(...deps: string[]): void;
|
|
607
609
|
}
|
|
608
610
|
|
|
609
611
|
export interface Action<
|
package/types/internal.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ export type CSRPageNodeLoader = () => Promise<CSRPageNode>;
|
|
|
83
83
|
*/
|
|
84
84
|
export type CSRRoute = {
|
|
85
85
|
id: string;
|
|
86
|
-
exec
|
|
86
|
+
exec(path: string): undefined | Record<string, string>;
|
|
87
87
|
errors: Array<CSRPageNodeLoader | undefined>;
|
|
88
88
|
layouts: Array<[boolean, CSRPageNodeLoader] | undefined>;
|
|
89
89
|
leaf: [boolean, CSRPageNodeLoader];
|
|
@@ -169,6 +169,7 @@ export interface RouteData {
|
|
|
169
169
|
pattern: RegExp;
|
|
170
170
|
names: string[];
|
|
171
171
|
types: string[];
|
|
172
|
+
optional: boolean[];
|
|
172
173
|
|
|
173
174
|
layout: PageNode | null;
|
|
174
175
|
error: PageNode | null;
|
|
@@ -260,7 +261,7 @@ export interface SSRNode {
|
|
|
260
261
|
/** external CSS files */
|
|
261
262
|
stylesheets: string[];
|
|
262
263
|
/** inlined styles */
|
|
263
|
-
inline_styles
|
|
264
|
+
inline_styles?(): MaybePromise<Record<string, string>>;
|
|
264
265
|
|
|
265
266
|
shared: {
|
|
266
267
|
load?: Load;
|
|
@@ -335,6 +336,7 @@ export interface SSRRoute {
|
|
|
335
336
|
pattern: RegExp;
|
|
336
337
|
names: string[];
|
|
337
338
|
types: string[];
|
|
339
|
+
optional: boolean[];
|
|
338
340
|
|
|
339
341
|
page: PageNodeIndexes | null;
|
|
340
342
|
|
|
@@ -343,7 +345,7 @@ export interface SSRRoute {
|
|
|
343
345
|
|
|
344
346
|
export interface SSRState {
|
|
345
347
|
fallback?: string;
|
|
346
|
-
getClientAddress
|
|
348
|
+
getClientAddress(): string;
|
|
347
349
|
initiator?: SSRRoute | SSRErrorPage;
|
|
348
350
|
platform?: any;
|
|
349
351
|
prerendering?: PrerenderOptions;
|
package/types/private.d.ts
CHANGED
|
@@ -15,15 +15,15 @@ export interface AdapterEntry {
|
|
|
15
15
|
* if it should be treated as a fallback for the current route. For example, `/foo/[c]`
|
|
16
16
|
* is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes
|
|
17
17
|
*/
|
|
18
|
-
filter
|
|
18
|
+
filter(route: RouteDefinition): boolean;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* A function that is invoked once the entry has been created. This is where you
|
|
22
22
|
* should write the function to the filesystem and generate redirect manifests.
|
|
23
23
|
*/
|
|
24
|
-
complete
|
|
25
|
-
generateManifest
|
|
26
|
-
})
|
|
24
|
+
complete(entry: {
|
|
25
|
+
generateManifest(opts: { relativePath: string; format?: 'esm' | 'cjs' }): string;
|
|
26
|
+
}): MaybePromise<void>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// Based on https://github.com/josh-hemphill/csp-typed-directives/blob/latest/src/csp.types.ts
|
|
@@ -195,7 +195,7 @@ export type PrerenderOption = boolean | 'auto';
|
|
|
195
195
|
export type PrerenderMap = Map<string, PrerenderOption>;
|
|
196
196
|
|
|
197
197
|
export interface RequestOptions {
|
|
198
|
-
getClientAddress
|
|
198
|
+
getClientAddress(): string;
|
|
199
199
|
platform?: App.Platform;
|
|
200
200
|
}
|
|
201
201
|
|