@sveltejs/kit 1.0.0-next.520 → 1.0.0-next.522
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 +5 -5
- package/src/core/config/options.js +2 -2
- package/src/core/prerender/prerender.js +6 -45
- package/src/core/sync/create_manifest_data/index.js +2 -2
- package/src/runtime/app/forms.js +6 -3
- package/src/runtime/client/client.js +1 -1
- package/src/runtime/client/fetcher.js +1 -1
- package/src/runtime/server/fetch.js +0 -8
- package/src/runtime/server/page/load_data.js +9 -6
- package/src/runtime/server/page/render.js +1 -1
- package/src/runtime/server/utils.js +1 -1
- package/src/utils/routing.js +2 -1
- package/types/ambient.d.ts +6 -2
- package/types/index.d.ts +187 -0
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.522",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
"node": ">=16.14"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
|
-
"build": "
|
|
83
|
+
"build": "pnpm types",
|
|
84
84
|
"lint": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
|
|
85
85
|
"check": "tsc",
|
|
86
86
|
"check:all": "tsc && pnpm -r --filter=\"./**\" check",
|
|
87
|
-
"format": "
|
|
88
|
-
"test": "
|
|
89
|
-
"test:integration": "pnpm
|
|
87
|
+
"format": "pnpm lint --write",
|
|
88
|
+
"test": "pnpm test:unit && pnpm test:integration",
|
|
89
|
+
"test:integration": "pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test",
|
|
90
90
|
"test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\"",
|
|
91
91
|
"types": "node scripts/extract-types.js",
|
|
92
92
|
"postinstall": "node postinstall.js"
|
|
@@ -88,7 +88,7 @@ const options = object(
|
|
|
88
88
|
// TODO: remove this for the 1.0 release
|
|
89
89
|
amp: error(
|
|
90
90
|
(keypath) =>
|
|
91
|
-
`${keypath} has been removed. See https://kit.svelte.dev/docs/seo#amp for details on how to support AMP`
|
|
91
|
+
`${keypath} has been removed. See https://kit.svelte.dev/docs/seo#manual-setup-amp for details on how to support AMP`
|
|
92
92
|
),
|
|
93
93
|
|
|
94
94
|
appDir: validate('_app', (input, keypath) => {
|
|
@@ -321,7 +321,7 @@ const options = object(
|
|
|
321
321
|
// TODO remove this for 1.0
|
|
322
322
|
ssr: error(
|
|
323
323
|
(keypath) =>
|
|
324
|
-
`${keypath} has been removed — use the handle hook instead: https://kit.svelte.dev/docs/hooks#handle`
|
|
324
|
+
`${keypath} has been removed — use the handle hook instead: https://kit.svelte.dev/docs/hooks#server-hooks-handle`
|
|
325
325
|
),
|
|
326
326
|
|
|
327
327
|
// TODO remove this for 1.0
|
|
@@ -102,54 +102,15 @@ export async function prerender() {
|
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
installPolyfills();
|
|
105
|
+
|
|
106
|
+
// TODO remove this for 1.0
|
|
105
107
|
const { fetch } = globalThis;
|
|
106
108
|
globalThis.fetch = async (info, init) => {
|
|
107
|
-
|
|
108
|
-
let url;
|
|
109
|
-
|
|
110
|
-
/** @type {RequestInit} */
|
|
111
|
-
let opts = {};
|
|
112
|
-
|
|
113
|
-
if (info instanceof Request) {
|
|
114
|
-
url = info.url;
|
|
115
|
-
|
|
116
|
-
opts = {
|
|
117
|
-
method: info.method,
|
|
118
|
-
headers: info.headers,
|
|
119
|
-
body: info.body,
|
|
120
|
-
mode: info.mode,
|
|
121
|
-
credentials: info.credentials,
|
|
122
|
-
cache: info.cache,
|
|
123
|
-
redirect: info.redirect,
|
|
124
|
-
referrer: info.referrer,
|
|
125
|
-
integrity: info.integrity
|
|
126
|
-
};
|
|
127
|
-
} else {
|
|
128
|
-
url = info.toString();
|
|
129
|
-
}
|
|
109
|
+
const url = info instanceof Request ? info.url : info.toString();
|
|
130
110
|
|
|
131
111
|
if (url.startsWith(config.prerender.origin + '/')) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
getClientAddress,
|
|
135
|
-
prerendering: {
|
|
136
|
-
dependencies: new Map()
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
const decoded = new URL(url).pathname;
|
|
141
|
-
|
|
142
|
-
save(
|
|
143
|
-
'dependencies',
|
|
144
|
-
response,
|
|
145
|
-
Buffer.from(await response.clone().arrayBuffer()),
|
|
146
|
-
decoded,
|
|
147
|
-
encodeURI(decoded),
|
|
148
|
-
null,
|
|
149
|
-
'fetched'
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
return response;
|
|
112
|
+
const sliced = url.slice(config.prerender.origin.length);
|
|
113
|
+
throw new Error(`Use \`event.fetch('${sliced}')\` instead of the global \`fetch('${url}')\``);
|
|
153
114
|
}
|
|
154
115
|
|
|
155
116
|
return fetch(info, init);
|
|
@@ -409,7 +370,7 @@ export async function prerender() {
|
|
|
409
370
|
for (const [id, prerender] of prerender_map) {
|
|
410
371
|
if (prerender) {
|
|
411
372
|
if (id.includes('[')) continue;
|
|
412
|
-
const path =
|
|
373
|
+
const path = `${id.split('/').filter(affects_path).join('/')}`;
|
|
413
374
|
enqueue(null, config.paths.base + path);
|
|
414
375
|
}
|
|
415
376
|
}
|
|
@@ -207,7 +207,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
|
|
|
207
207
|
}
|
|
208
208
|
};
|
|
209
209
|
|
|
210
|
-
walk(0, '', '', null);
|
|
210
|
+
walk(0, '/', '', null);
|
|
211
211
|
|
|
212
212
|
if (routes.length === 1) {
|
|
213
213
|
const root = routes[0];
|
|
@@ -223,7 +223,7 @@ function create_routes_and_nodes(cwd, config, fallback) {
|
|
|
223
223
|
// If there's no routes directory, we'll just create a single empty route. This ensures the root layout and
|
|
224
224
|
// error components are included in the manifest, which is needed for subsequent build/dev commands to work
|
|
225
225
|
routes.push({
|
|
226
|
-
id: '',
|
|
226
|
+
id: '/',
|
|
227
227
|
segment: '',
|
|
228
228
|
pattern: /^$/,
|
|
229
229
|
names: [],
|
package/src/runtime/app/forms.js
CHANGED
|
@@ -21,11 +21,14 @@ export function enhance(form, submit = () => {}) {
|
|
|
21
21
|
* @param {{
|
|
22
22
|
* action: URL;
|
|
23
23
|
* result: import('types').ActionResult;
|
|
24
|
+
* reset?: boolean
|
|
24
25
|
* }} opts
|
|
25
26
|
*/
|
|
26
|
-
const fallback_callback = async ({ action, result }) => {
|
|
27
|
+
const fallback_callback = async ({ action, result, reset }) => {
|
|
27
28
|
if (result.type === 'success') {
|
|
28
|
-
|
|
29
|
+
if (reset !== false) {
|
|
30
|
+
form.reset();
|
|
31
|
+
}
|
|
29
32
|
await invalidateAll();
|
|
30
33
|
}
|
|
31
34
|
|
|
@@ -97,7 +100,7 @@ export function enhance(form, submit = () => {}) {
|
|
|
97
100
|
action,
|
|
98
101
|
data,
|
|
99
102
|
form,
|
|
100
|
-
update: () => fallback_callback({ action, result }),
|
|
103
|
+
update: (opts) => fallback_callback({ action, result, reset: opts?.reset }),
|
|
101
104
|
// @ts-expect-error generic constraints stuff we don't care about
|
|
102
105
|
result,
|
|
103
106
|
// TODO remove for 1.0
|
|
@@ -199,7 +199,7 @@ export function create_client({ target, base, trailing_slash }) {
|
|
|
199
199
|
const intent = get_navigation_intent(url, false);
|
|
200
200
|
|
|
201
201
|
if (!intent) {
|
|
202
|
-
throw new Error(
|
|
202
|
+
throw new Error(`Attempted to prefetch a URL that does not belong to this app: ${url}`);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
load_cache = { id: intent.id, promise: load_route(intent) };
|
|
@@ -29,7 +29,7 @@ if (import.meta.env.DEV) {
|
|
|
29
29
|
const heuristic = can_inspect_stack_trace ? stack.includes('load_node') : loading;
|
|
30
30
|
if (heuristic) {
|
|
31
31
|
console.warn(
|
|
32
|
-
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/load#
|
|
32
|
+
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/load#making-fetch-requests`
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -16,9 +16,6 @@ export function create_fetch({ event, options, state, get_cookie_header }) {
|
|
|
16
16
|
|
|
17
17
|
const request_body = init?.body;
|
|
18
18
|
|
|
19
|
-
/** @type {import('types').PrerenderDependency} */
|
|
20
|
-
let dependency;
|
|
21
|
-
|
|
22
19
|
return await options.hooks.handleFetch({
|
|
23
20
|
event,
|
|
24
21
|
request,
|
|
@@ -135,11 +132,6 @@ export function create_fetch({ event, options, state, get_cookie_header }) {
|
|
|
135
132
|
|
|
136
133
|
response = await respond(request, options, state);
|
|
137
134
|
|
|
138
|
-
if (state.prerendering) {
|
|
139
|
-
dependency = { response, body: null };
|
|
140
|
-
state.prerendering.dependencies.set(url.pathname, dependency);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
135
|
const set_cookie = response.headers.get('set-cookie');
|
|
144
136
|
if (set_cookie) {
|
|
145
137
|
for (const str of set_cookie_parser.splitCookiesString(set_cookie)) {
|
|
@@ -106,8 +106,13 @@ export async function load_data({
|
|
|
106
106
|
const url = new URL(input instanceof Request ? input.url : input, event.url);
|
|
107
107
|
const same_origin = url.origin === event.url.origin;
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
/** @type {import('types').PrerenderDependency} */
|
|
110
|
+
let dependency;
|
|
111
|
+
|
|
112
|
+
if (same_origin && state.prerendering) {
|
|
113
|
+
dependency = { response, body: null };
|
|
114
|
+
state.prerendering.dependencies.set(url.pathname, dependency);
|
|
115
|
+
}
|
|
111
116
|
|
|
112
117
|
const proxy = new Proxy(response, {
|
|
113
118
|
get(response, key, _receiver) {
|
|
@@ -127,7 +132,7 @@ export async function load_data({
|
|
|
127
132
|
fetched.push({
|
|
128
133
|
url: same_origin ? url.href.slice(event.url.origin.length) : url.href,
|
|
129
134
|
method: event.request.method,
|
|
130
|
-
request_body: /** @type {string | ArrayBufferView | undefined} */ (
|
|
135
|
+
request_body: /** @type {string | ArrayBufferView | undefined} */ (init?.body),
|
|
131
136
|
response_body: body,
|
|
132
137
|
response: response
|
|
133
138
|
});
|
|
@@ -165,8 +170,6 @@ export async function load_data({
|
|
|
165
170
|
};
|
|
166
171
|
}
|
|
167
172
|
|
|
168
|
-
// TODO arrayBuffer?
|
|
169
|
-
|
|
170
173
|
return Reflect.get(response, key, response);
|
|
171
174
|
}
|
|
172
175
|
});
|
|
@@ -181,7 +184,7 @@ export async function load_data({
|
|
|
181
184
|
const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
|
|
182
185
|
if (!included) {
|
|
183
186
|
throw new Error(
|
|
184
|
-
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://kit.svelte.dev/docs/hooks#handle (at ${event.routeId})`
|
|
187
|
+
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://kit.svelte.dev/docs/hooks#server-hooks-handle (at ${event.routeId})`
|
|
185
188
|
);
|
|
186
189
|
}
|
|
187
190
|
}
|
|
@@ -179,7 +179,7 @@ export async function render_response({
|
|
|
179
179
|
const match = /\[(\d+)\]\.data\.(.+)/.exec(error.path);
|
|
180
180
|
if (match) {
|
|
181
181
|
throw new Error(
|
|
182
|
-
`Data returned from \`load\` while rendering
|
|
182
|
+
`Data returned from \`load\` while rendering ${event.routeId} is not serializable: ${error.message} (data.${match[2]})`
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
185
|
throw error;
|
|
@@ -83,7 +83,7 @@ export function data_response(data, event) {
|
|
|
83
83
|
const error = /** @type {any} */ (e);
|
|
84
84
|
const match = /\[(\d+)\]\.data\.(.+)/.exec(error.path);
|
|
85
85
|
const message = match
|
|
86
|
-
? `Data returned from \`load\` while rendering
|
|
86
|
+
? `Data returned from \`load\` while rendering ${event.routeId} is not serializable: ${error.message} (data.${match[2]})`
|
|
87
87
|
: error.message;
|
|
88
88
|
return new Response(JSON.stringify(message), { headers, status: 500 });
|
|
89
89
|
}
|
package/src/utils/routing.js
CHANGED
|
@@ -13,11 +13,12 @@ export function parse_route_id(id) {
|
|
|
13
13
|
let add_trailing_slash = true;
|
|
14
14
|
|
|
15
15
|
const pattern =
|
|
16
|
-
id === ''
|
|
16
|
+
id === '/'
|
|
17
17
|
? /^\/$/
|
|
18
18
|
: new RegExp(
|
|
19
19
|
`^${id
|
|
20
20
|
.split(/(?:\/|$)/)
|
|
21
|
+
.slice(1)
|
|
21
22
|
.filter(affects_path)
|
|
22
23
|
.map((segment, i, segments) => {
|
|
23
24
|
const decoded_segment = decodeURIComponent(segment);
|
package/types/ambient.d.ts
CHANGED
|
@@ -110,7 +110,11 @@ declare module '$app/forms' {
|
|
|
110
110
|
form: HTMLFormElement;
|
|
111
111
|
action: URL;
|
|
112
112
|
result: ActionResult<Success, Invalid>;
|
|
113
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Call this to get the default behavior of a form submission response.
|
|
115
|
+
* @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission.
|
|
116
|
+
*/
|
|
117
|
+
update: (options?: { reset: boolean }) => Promise<void>;
|
|
114
118
|
}) => void);
|
|
115
119
|
|
|
116
120
|
/**
|
|
@@ -133,7 +137,7 @@ declare module '$app/forms' {
|
|
|
133
137
|
* If this function or its return value isn't set, it
|
|
134
138
|
* - falls back to updating the `form` prop with the returned data if the action is one same page as the form
|
|
135
139
|
* - updates `$page.status`
|
|
136
|
-
* - invalidates all data in case of successful submission with no redirect response
|
|
140
|
+
* - resets the `<form>` element and invalidates all data in case of successful submission with no redirect response
|
|
137
141
|
* - redirects in case of a redirect response
|
|
138
142
|
* - redirects to the nearest error page in case of an unexpected error
|
|
139
143
|
*
|
package/types/index.d.ts
CHANGED
|
@@ -271,18 +271,108 @@ export interface LoadEvent<
|
|
|
271
271
|
Data extends Record<string, unknown> | null = Record<string, any> | null,
|
|
272
272
|
ParentData extends Record<string, unknown> = Record<string, any>
|
|
273
273
|
> extends NavigationEvent<Params> {
|
|
274
|
+
/**
|
|
275
|
+
* `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features:
|
|
276
|
+
*
|
|
277
|
+
* - it can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request
|
|
278
|
+
* - it can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context)
|
|
279
|
+
* - internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call
|
|
280
|
+
* - during server-side rendering, the response will be captured and inlined into the rendered HTML. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](https://kit.svelte.dev/docs/hooks#server-hooks-handle)
|
|
281
|
+
* - during hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request
|
|
282
|
+
*
|
|
283
|
+
* > Cookies will only be passed through if the target host is the same as the SvelteKit application or a more specific subdomain of it.
|
|
284
|
+
*/
|
|
274
285
|
fetch: typeof fetch;
|
|
286
|
+
/**
|
|
287
|
+
* Contains the data returned by the route's server `load` function (in `+layout.server.js` or `+page.server.js`), if any.
|
|
288
|
+
*/
|
|
275
289
|
data: Data;
|
|
290
|
+
/**
|
|
291
|
+
* If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:
|
|
292
|
+
*
|
|
293
|
+
* ```js
|
|
294
|
+
* /// file: src/routes/blog/+page.js
|
|
295
|
+
* export async function load({ fetch, setHeaders }) {
|
|
296
|
+
* const url = `https://cms.example.com/articles.json`;
|
|
297
|
+
* const response = await fetch(url);
|
|
298
|
+
*
|
|
299
|
+
* setHeaders({
|
|
300
|
+
* age: response.headers.get('age'),
|
|
301
|
+
* 'cache-control': response.headers.get('cache-control')
|
|
302
|
+
* });
|
|
303
|
+
*
|
|
304
|
+
* return response.json();
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*
|
|
308
|
+
* Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once.
|
|
309
|
+
*
|
|
310
|
+
* You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://kit.svelte.dev/docs/types#sveltejs-kit-cookies) API in a server-only `load` function instead.
|
|
311
|
+
*
|
|
312
|
+
* `setHeaders` has no effect when a `load` function runs in the browser.
|
|
313
|
+
*/
|
|
276
314
|
setHeaders: (headers: Record<string, string>) => void;
|
|
315
|
+
/**
|
|
316
|
+
* `await parent()` returns data from parent `+layout.js` `load` functions.
|
|
317
|
+
* 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
|
+
*
|
|
319
|
+
* 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
|
+
*/
|
|
277
321
|
parent: () => Promise<ParentData>;
|
|
322
|
+
/**
|
|
323
|
+
* 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
|
+
*
|
|
325
|
+
* Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`.
|
|
326
|
+
*
|
|
327
|
+
* URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding).
|
|
328
|
+
*
|
|
329
|
+
* Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html).
|
|
330
|
+
*
|
|
331
|
+
* The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun.
|
|
332
|
+
*
|
|
333
|
+
* ```js
|
|
334
|
+
* /// file: src/routes/+page.js
|
|
335
|
+
* let count = 0;
|
|
336
|
+
* export async function load({ depends }) {
|
|
337
|
+
* depends('increase:count');
|
|
338
|
+
*
|
|
339
|
+
* return { count: count++ };
|
|
340
|
+
* }
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* ```html
|
|
344
|
+
* /// file: src/routes/+page.svelte
|
|
345
|
+
* <script>
|
|
346
|
+
* import { invalidate } from '$app/navigation';
|
|
347
|
+
*
|
|
348
|
+
* export let data;
|
|
349
|
+
*
|
|
350
|
+
* const increase = async () => {
|
|
351
|
+
* await invalidate('increase:count');
|
|
352
|
+
* }
|
|
353
|
+
* </script>
|
|
354
|
+
*
|
|
355
|
+
* <p>{data.count}<p>
|
|
356
|
+
* <button on:click={increase}>Increase Count</button>
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
278
359
|
depends: (...deps: string[]) => void;
|
|
279
360
|
}
|
|
280
361
|
|
|
281
362
|
export interface NavigationEvent<
|
|
282
363
|
Params extends Partial<Record<string, string>> = Partial<Record<string, string>>
|
|
283
364
|
> {
|
|
365
|
+
/**
|
|
366
|
+
* The parameters of the current page - e.g. for a route like `/blog/[slug]`, the `slug` parameter
|
|
367
|
+
*/
|
|
284
368
|
params: Params;
|
|
369
|
+
/**
|
|
370
|
+
* The route ID of the current page - e.g. for `src/routes/blog/[slug]`, it would be `blog/[slug]`
|
|
371
|
+
*/
|
|
285
372
|
routeId: string | null;
|
|
373
|
+
/**
|
|
374
|
+
* The URL of the current page
|
|
375
|
+
*/
|
|
286
376
|
url: URL;
|
|
287
377
|
}
|
|
288
378
|
|
|
@@ -342,15 +432,70 @@ export interface ParamMatcher {
|
|
|
342
432
|
export interface RequestEvent<
|
|
343
433
|
Params extends Partial<Record<string, string>> = Partial<Record<string, string>>
|
|
344
434
|
> {
|
|
435
|
+
/**
|
|
436
|
+
* Get or set cookies related to the current request
|
|
437
|
+
*/
|
|
345
438
|
cookies: Cookies;
|
|
439
|
+
/**
|
|
440
|
+
* `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features:
|
|
441
|
+
*
|
|
442
|
+
* - it can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request
|
|
443
|
+
* - it can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context)
|
|
444
|
+
* - internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call
|
|
445
|
+
*
|
|
446
|
+
* > Cookies will only be passed through if the target host is the same as the SvelteKit application or a more specific subdomain of it.
|
|
447
|
+
*/
|
|
346
448
|
fetch: typeof fetch;
|
|
449
|
+
/**
|
|
450
|
+
* The client's IP address, set by the adapter.
|
|
451
|
+
*/
|
|
347
452
|
getClientAddress: () => string;
|
|
453
|
+
/**
|
|
454
|
+
* Contains custom data that was added to the request within the [`handle hook`](https://kit.svelte.dev/docs/hooks#server-hooks-handle).
|
|
455
|
+
*/
|
|
348
456
|
locals: App.Locals;
|
|
457
|
+
/**
|
|
458
|
+
* The parameters of the current page or endpoint - e.g. for a route like `/blog/[slug]`, the `slug` parameter
|
|
459
|
+
*/
|
|
349
460
|
params: Params;
|
|
461
|
+
/**
|
|
462
|
+
* Additional data made available through the adapter.
|
|
463
|
+
*/
|
|
350
464
|
platform: Readonly<App.Platform>;
|
|
465
|
+
/**
|
|
466
|
+
* The original request object
|
|
467
|
+
*/
|
|
351
468
|
request: Request;
|
|
469
|
+
/**
|
|
470
|
+
* The route ID of the current page - e.g. for `src/routes/blog/[slug]`, it would be `blog/[slug]`
|
|
471
|
+
*/
|
|
352
472
|
routeId: string | null;
|
|
473
|
+
/**
|
|
474
|
+
* If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:
|
|
475
|
+
*
|
|
476
|
+
* ```js
|
|
477
|
+
* /// file: src/routes/blog/+page.js
|
|
478
|
+
* export async function load({ fetch, setHeaders }) {
|
|
479
|
+
* const url = `https://cms.example.com/articles.json`;
|
|
480
|
+
* const response = await fetch(url);
|
|
481
|
+
*
|
|
482
|
+
* setHeaders({
|
|
483
|
+
* age: response.headers.get('age'),
|
|
484
|
+
* 'cache-control': response.headers.get('cache-control')
|
|
485
|
+
* });
|
|
486
|
+
*
|
|
487
|
+
* return response.json();
|
|
488
|
+
* }
|
|
489
|
+
* ```
|
|
490
|
+
*
|
|
491
|
+
* Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once.
|
|
492
|
+
*
|
|
493
|
+
* You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](https://kit.svelte.dev/docs/types#sveltejs-kit-cookies) API instead.
|
|
494
|
+
*/
|
|
353
495
|
setHeaders: (headers: Record<string, string>) => void;
|
|
496
|
+
/**
|
|
497
|
+
* The URL of the current page or endpoint
|
|
498
|
+
*/
|
|
354
499
|
url: URL;
|
|
355
500
|
}
|
|
356
501
|
|
|
@@ -415,7 +560,49 @@ export interface ServerLoadEvent<
|
|
|
415
560
|
Params extends Partial<Record<string, string>> = Partial<Record<string, string>>,
|
|
416
561
|
ParentData extends Record<string, any> = Record<string, any>
|
|
417
562
|
> extends RequestEvent<Params> {
|
|
563
|
+
/**
|
|
564
|
+
* `await parent()` returns data from parent `+layout.server.js` `load` functions.
|
|
565
|
+
*
|
|
566
|
+
* 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
|
+
*/
|
|
418
568
|
parent: () => Promise<ParentData>;
|
|
569
|
+
/**
|
|
570
|
+
* 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
|
+
*
|
|
572
|
+
* Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`.
|
|
573
|
+
*
|
|
574
|
+
* URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding).
|
|
575
|
+
*
|
|
576
|
+
* Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html).
|
|
577
|
+
*
|
|
578
|
+
* The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun.
|
|
579
|
+
*
|
|
580
|
+
* ```js
|
|
581
|
+
* /// file: src/routes/+page.js
|
|
582
|
+
* let count = 0;
|
|
583
|
+
* export async function load({ depends }) {
|
|
584
|
+
* depends('increase:count');
|
|
585
|
+
*
|
|
586
|
+
* return { count: count++ };
|
|
587
|
+
* }
|
|
588
|
+
* ```
|
|
589
|
+
*
|
|
590
|
+
* ```html
|
|
591
|
+
* /// file: src/routes/+page.svelte
|
|
592
|
+
* <script>
|
|
593
|
+
* import { invalidate } from '$app/navigation';
|
|
594
|
+
*
|
|
595
|
+
* export let data;
|
|
596
|
+
*
|
|
597
|
+
* const increase = async () => {
|
|
598
|
+
* await invalidate('increase:count');
|
|
599
|
+
* }
|
|
600
|
+
* </script>
|
|
601
|
+
*
|
|
602
|
+
* <p>{data.count}<p>
|
|
603
|
+
* <button on:click={increase}>Increase Count</button>
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
419
606
|
depends: (...deps: string[]) => void;
|
|
420
607
|
}
|
|
421
608
|
|