Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Merge ErrorLoad and Load, make Input and Output typings public #4515

Merged
5 changes: 5 additions & 0 deletions .changeset/moody-rabbits-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Made LoadInput and LoadOutput types public, merged ErrorLoad and Load declarations
10 changes: 9 additions & 1 deletion documentation/docs/03-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ It is recommended that you not store pre-request state in global variables, but

### Input

The `load` function receives an object containing six fields — `url`, `params`, `props`, `fetch`, `session` and `stuff`. The `load` function is reactive, and will re-run when its parameters change, but only if they are used in the function. Specifically, if `url`, `session` or `stuff` are used in the function, they will be re-run whenever their value changes, and likewise for the individual properties of `params`.
The `load` function receives an object containing eight fields — `url`, `params`, `props`, `fetch`, `session`, `stuff`, `status`, and `error`. The `load` function is reactive, and will re-run when its parameters change, but only if they are used in the function. Specifically, if `url`, `session` or `stuff` are used in the function, they will be re-run whenever their value changes, and likewise for the individual properties of `params`.

> Note that destructuring parameters in the function declaration is enough to count as using them.

Expand Down Expand Up @@ -93,6 +93,14 @@ If the page you're loading has an endpoint, the data returned from it is accessi

`stuff` is passed from layouts to descendant layouts and pages, and can be filled with anything else you need to make available. For the root `__layout.svelte` component, it is equal to `{}`, but if that component's `load` function returns an object with a `stuff` property, it will be available to subsequent `load` functions.

#### status

`status` is the HTTP status code when rendering an error page, or `null` otherwise.

#### error

`error` is the error that was thrown (or returned from a previous `load`) when rendering an error page, or `null` otherwise.

### Output

If you return a Promise from `load`, SvelteKit will delay rendering until the promise resolves. The return value has several properties, all optional:
Expand Down
11 changes: 4 additions & 7 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ export function create_client({ target, session, base, trailing_slash }) {
const session = $session;

if (module.load) {
/** @type {import('types').LoadInput | import('types').ErrorLoadInput} */
/** @type {import('types').LoadInput} */
const load_input = {
routeId,
params: uses_params,
Expand All @@ -520,7 +520,9 @@ export function create_client({ target, session, base, trailing_slash }) {
node.uses.dependencies.add(href);

return started ? fetch(resource, info) : initial_fetch(resource, info);
}
},
status: status ?? null,
error: error ?? null
};

if (import.meta.env.DEV) {
Expand All @@ -532,11 +534,6 @@ export function create_client({ target, session, base, trailing_slash }) {
});
}

if (error) {
/** @type {import('types').ErrorLoadInput} */ (load_input).status = status;
/** @type {import('types').ErrorLoadInput} */ (load_input).error = error;
}

const loaded = await module.load.call(null, load_input);

if (!loaded) {
Expand Down
11 changes: 4 additions & 7 deletions packages/kit/src/runtime/server/page/load_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export async function load_node({
redirect: shadow.redirect
};
} else if (module.load) {
/** @type {import('types').LoadInput | import('types').ErrorLoadInput} */
/** @type {import('types').LoadInput} */
const load_input = {
url: state.prerender ? create_prerendering_url_proxy(event.url) : event.url,
params: event.params,
Expand Down Expand Up @@ -308,7 +308,9 @@ export async function load_node({

return proxy;
},
stuff: { ...stuff }
stuff: { ...stuff },
status: is_error ? status ?? null : null,
error: is_error ? error ?? null : null
};

if (options.dev) {
Expand All @@ -320,11 +322,6 @@ export async function load_node({
});
}

if (is_error) {
/** @type {import('types').ErrorLoadInput} */ (load_input).status = status;
/** @type {import('types').ErrorLoadInput} */ (load_input).error = error;
}

loaded = await module.load.call(null, load_input);

if (!loaded) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script context="module">
/** @type {import('@sveltejs/kit').ErrorLoad} */
/** @type {import('@sveltejs/kit').Load} */
export async function load({ status, error }) {
return {
props: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script context="module">
/** @type {import('@sveltejs/kit').ErrorLoad} */
/** @type {import('@sveltejs/kit').Load} */
export async function load({ status, error }) {
return {
props: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script context="module">
/** @type {import('@sveltejs/kit').ErrorLoad} */
/** @type {import('@sveltejs/kit').Load} */
export function load({ error }) {
return {
stuff: {
Expand Down
34 changes: 24 additions & 10 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import { CompileOptions } from 'svelte/types/compiler/interfaces';
import {
AdapterEntry,
CspDirectives,
ErrorLoadInput,
JSONValue,
LoadInput,
LoadOutput,
Logger,
MaybePromise,
Prerendered,
Expand Down Expand Up @@ -157,13 +154,6 @@ export interface Config {
preprocess?: any;
}

export interface ErrorLoad<
Params extends Record<string, string> = Record<string, string>,
Props extends Record<string, any> = Record<string, any>
> {
(input: ErrorLoadInput<Params>): MaybePromise<LoadOutput<Props>>;
}

export interface ExternalFetch {
(req: Request): Promise<Response>;
}
Expand Down Expand Up @@ -196,6 +186,30 @@ export interface Load<
(input: LoadInput<Params, InputProps>): MaybePromise<LoadOutput<OutputProps>>;
}

export interface LoadInput<
Params extends Record<string, string> = Record<string, string>,
Props extends Record<string, any> = Record<string, any>
> {
fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
params: Params;
props: Props;
routeId: string | null;
session: App.Session;
stuff: Partial<App.Stuff>;
url: URL;
status: number | null;
error: Error | null;
}

export interface LoadOutput<Props extends Record<string, any> = Record<string, any>> {
status?: number;
error?: string | Error;
redirect?: string;
props?: Props;
stuff?: Partial<App.Stuff>;
maxage?: number;
}

export interface Navigation {
from: URL;
to: URL;
Expand Down
28 changes: 0 additions & 28 deletions packages/kit/types/private.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,6 @@ export interface CspDirectives {
>;
}

export interface ErrorLoadInput<Params extends Record<string, string> = Record<string, string>>
extends LoadInput<Params> {
status?: number;
error?: Error;
}

export type HttpMethod = 'get' | 'head' | 'post' | 'put' | 'delete' | 'patch';

export interface JSONObject {
Expand All @@ -156,28 +150,6 @@ export type JSONValue =
| JSONValue[]
| JSONObject;

export interface LoadInput<
Params extends Record<string, string> = Record<string, string>,
Props extends Record<string, any> = Record<string, any>
> {
fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
params: Params;
props: Props;
routeId: string | null;
session: App.Session;
stuff: Partial<App.Stuff>;
url: URL;
}

export interface LoadOutput<Props extends Record<string, any> = Record<string, any>> {
status?: number;
error?: string | Error;
redirect?: string;
props?: Props;
stuff?: Partial<App.Stuff>;
maxage?: number;
}

export interface Logger {
(msg: string): void;
success(msg: string): void;
Expand Down