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

Allow passing platform context from adapters #3429

Merged
merged 45 commits into from
Jan 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d574cb6
Can pass locals at app.render
fezproof Jan 20, 2022
33d4737
Updated cloudflare workers to pass in env to locals
fezproof Jan 20, 2022
56bfe37
Fixed other adapters for new API
fezproof Jan 20, 2022
8309cd7
Fixed naming in app types to be more consistent
fezproof Jan 20, 2022
bb67019
Merge branch 'master' into locals-from-adapter
Rich-Harris Jan 20, 2022
9f95150
Updated to use meta in stead of polluting locals
fezproof Jan 21, 2022
4f4247c
updated adapter cloudflare to use meta
fezproof Jan 21, 2022
fd9a6f5
Added changesets
fezproof Jan 21, 2022
df36652
Formated and linted
fezproof Jan 21, 2022
6d34a4c
Updated types to include Meta consistently
fezproof Jan 21, 2022
2d887a3
Updated documentation to include information about the meta object
fezproof Jan 21, 2022
bcd3c8d
Fixed type issue in hooks
fezproof Jan 21, 2022
36b139a
Merge branch 'master' of https://github.com/sveltejs/kit into locals-…
fezproof Jan 21, 2022
eb977ea
Updated naming to platform
fezproof Jan 21, 2022
a9d3fa9
Added a way to get the original request from the node adapter
fezproof Jan 21, 2022
8745a71
Made platform Readonly in RequestEvent
fezproof Jan 21, 2022
40f8cd7
Fixed typo in docs
fezproof Jan 21, 2022
201e595
Update documentation/docs/01-routing.md
fezproof Jan 22, 2022
0bce46d
Fixed bad spaces
fezproof Jan 22, 2022
e95e1b3
Merge branch 'master' into locals-from-adapter
fezproof Jan 22, 2022
741eda4
Fixed merge issues
fezproof Jan 22, 2022
19d5039
Merge branch 'master' into locals-from-adapter
ignatiusmb Jan 25, 2022
2f6cb31
rerun flakey tests
fezproof Jan 25, 2022
c7b10a1
rerun flakey tests 2
fezproof Jan 25, 2022
e4a1047
Update documentation/docs/10-adapters.md grammer
fezproof Jan 25, 2022
d91beaf
rerun flakey tests 3
fezproof Jan 25, 2022
22c2e6f
Merge branch 'locals-from-adapter' of https://github.com/fezproof/kit…
fezproof Jan 25, 2022
492809d
rerun flakey tests 4
fezproof Jan 25, 2022
e4c7be7
Changed node handler to pass in `req`
fezproof Jan 26, 2022
bb2ddaa
Updated cloudflare readme
fezproof Jan 26, 2022
e5fd336
Renamed to request
fezproof Jan 26, 2022
4e96cf1
Use Record<string, any>
fezproof Jan 26, 2022
9fc934b
rerun flakey tests 5
fezproof Jan 26, 2022
72459fe
change API to app.render(request, opts)
Rich-Harris Jan 27, 2022
54de5bf
update adapters
Rich-Harris Jan 27, 2022
d417d00
use platform.req instead of platform.request — more idiomatic
Rich-Harris Jan 27, 2022
e68d469
remove changesets for unaffected adapters
Rich-Harris Jan 27, 2022
358c747
tweak changesets
Rich-Harris Jan 27, 2022
2a4b54b
remove platform stuff from routing section
Rich-Harris Jan 27, 2022
9d57b6c
tweak adapter docs
Rich-Harris Jan 27, 2022
a3121b8
Merge branch 'master' into locals-from-adapter
Rich-Harris Jan 27, 2022
6e90095
Fix documentation/docs/04-hooks.md spaces
fezproof Jan 27, 2022
9ca9144
remove changes to adapter-node
Rich-Harris Jan 27, 2022
5d3c3ae
create-svelte is unchanged
Rich-Harris Jan 27, 2022
983ec4f
simplify docs
Rich-Harris Jan 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cyan-numbers-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-cloudflare': patch
---

Pass `env` object to SvelteKit via `platform`
5 changes: 5 additions & 0 deletions .changeset/many-mayflies-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Allow adapters to pass in `platform` object
12 changes: 9 additions & 3 deletions documentation/docs/01-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ Endpoints are modules written in `.js` (or `.ts`) files that export functions co
// Declaration types for Endpoints
// * declarations that are not exported are for internal use

export interface RequestEvent<Locals = Record<string, any>> {
export interface RequestEvent<Locals = Record<string, any>, Platform = Record<string, any>> {
request: Request;
url: URL;
params: Record<string, string>;
locals: Locals;
platform: Platform;
}

type Body = JSONString | Uint8Array | ReadableStream | stream.Readable;
Expand All @@ -69,8 +70,13 @@ type MaybePromise<T> = T | Promise<T>;
interface Fallthrough {
fallthrough: true;
}
export interface RequestHandler<Locals = Record<string, any>, Output extends Body = Body> {
(event: RequestEvent<Locals>): MaybePromise<

export interface RequestHandler<
Locals = Record<string, any>,
Platform = Record<string, any>,
Output extends Body = Body
> {
(event: RequestEvent<Locals, Platform>): MaybePromise<
Either<Response | EndpointOutput<Output>, Fallthrough>
>;
}
Expand Down
21 changes: 13 additions & 8 deletions documentation/docs/04-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,22 @@ If unimplemented, defaults to `({ event, resolve }) => resolve(event)`.
// everything else must be a type of string
type ResponseHeaders = Record<string, string | string[]>;

export interface RequestEvent<Locals = Record<string, any>> {
export interface RequestEvent<Locals = Record<string, any>, Platform = Record<string, any>> {
request: Request;
url: URL;
params: Record<string, string>;
locals: Locals;
platform: Platform;
}

export interface ResolveOpts {
ssr?: boolean;
}

export interface Handle<Locals = Record<string, any>> {
export interface Handle<Locals = Record<string, any>, Platform = Record<string, any>> {
(input: {
event: RequestEvent<Locals>;
resolve(event: RequestEvent<Locals>, opts?: ResolveOpts): MaybePromise<Response>;
event: RequestEvent<Locals, Platform>;
resolve(event: RequestEvent<Locals, Platform>, opts?: ResolveOpts): MaybePromise<Response>;
}): MaybePromise<Response>;
}
```
Expand Down Expand Up @@ -84,8 +85,8 @@ If unimplemented, SvelteKit will log the error with default formatting.

```ts
// Declaration types for handleError hook
export interface HandleError<Locals = Record<string, any>> {
(input: { error: Error & { frame?: string }; event: RequestEvent<Locals> }): void;
export interface HandleError<Locals = Record<string, any>, Platform = Record<string, any>> {
(input: { error: Error & { frame?: string }; event: RequestEvent<Locals, Platform> }): void;
}
```

Expand All @@ -107,8 +108,12 @@ If unimplemented, session is `{}`.

```ts
// Declaration types for getSession hook
export interface GetSession<Locals = Record<string, any>, Session = any> {
(event: RequestEvent<Locals>): Session | Promise<Session>;
export interface GetSession<
Locals = Record<string, any>,
Platform = Record<string, any>,
Session = any
> {
(event: RequestEvent<Locals, Platform>): MaybePromise<Session>;
}
```

Expand Down
5 changes: 5 additions & 0 deletions documentation/docs/10-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ Most adapters will generate static HTML for any [prerenderable](#page-options-pr

You can also use `adapter-static` to generate single-page apps (SPAs) by specifying a [fallback page](https://github.com/sveltejs/kit/tree/master/packages/adapter-static#spa-mode).

#### Platform-specific context

Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an `env` object containing KV namespaces etc. This can be passed to the `RequestEvent` used in [hooks](#hooks) and [endpoints](#routing-endpoints) as the `platform` property — consult each adapter's documentation to learn more.

### Community adapters

Additional [community-provided adapters](https://sveltesociety.dev/components#adapters) exist for other platforms. After installing the relevant adapter with your package manager, update your `svelte.config.js`:
Expand Down Expand Up @@ -93,6 +97,7 @@ Within the `adapt` method, there are a number of things that an adapter should d
- Imports `App` from `${builder.getServerDirectory()}/app.js`
- Instantiates the app with a manifest generated with `builder.generateManifest({ relativePath })`
- Listens for requests from the platform, converts them to a standard [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) if necessary, calls the `render` function to generate a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) and responds with it
- expose any platform-specific information to SvelteKit via the `platform` option passed to `app.render`
- Globally shims `fetch` to work on the target platform, if necessary. SvelteKit provides a `@sveltejs/kit/install-fetch` helper for platforms that can use `node-fetch`
- Bundle the output to avoid needing to install dependencies on the target platform, if necessary
- Put the user's static files and the generated JS/CSS in the correct location for the target platform
Expand Down
20 changes: 20 additions & 0 deletions packages/adapter-cloudflare/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,26 @@ When configuring your project settings, you must use the following settings:

> **Important:** You need to add a `NODE_VERSION` environment variable to both the "production" and "preview" environments. You can add this during project setup or later in the Pages project settings. SvelteKit requires Node `14.13` or later, so you should use `14` or `16` as the `NODE_VERSION` value.

## Environment variables

The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object, containing KV namespaces etc, is passed to SvelteKit via the `platform` property, meaning you can access it in hooks and endpoints:

```ts
interface Locals {}

interface Platform {
env: {
COUNTER: DurableObjectNamespace;
};
}

export async function post<Locals, Platform>({ request, platform }) {
const counter = platform.env.COUNTER.idFromName('A');
}
```

> `platform.env` is only available in the production build. Use [wrangler](https://developers.cloudflare.com/workers/cli-wrangler) to test it locally

## Changelog

[The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/master/packages/adapter-cloudflare/CHANGELOG.md).
2 changes: 1 addition & 1 deletion packages/adapter-cloudflare/files/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default {

// dynamically-generated pages
try {
return await app.render(req);
return await app.render(req, { platform: { env } });
} catch (e) {
return new Response('Error rendering route: ' + (e.message || e.toString()), { status: 500 });
}
Expand Down
7 changes: 2 additions & 5 deletions packages/kit/src/core/build/build_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,12 @@ export class App {
};
}

render(request, {
prerender
} = {}) {
render(request, options = {}) {
if (!(request instanceof Request)) {
throw new Error('The first argument to app.render must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details');
}

return respond(request, this.options, { prerender });
return respond(request, this.options, options);
}
}
`;
Expand Down Expand Up @@ -172,7 +170,6 @@ export async function build_server(
return relative_file[0] === '.' ? relative_file : `./${relative_file}`;
};

// prettier-ignore
fs.writeFileSync(
input.app,
app_template({
Expand Down
3 changes: 2 additions & 1 deletion packages/kit/src/runtime/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export async function respond(request, options, state = {}) {
request,
url,
params: {},
locals: {}
locals: {},
platform: state.platform
};

// TODO remove this for 1.0
Expand Down
10 changes: 7 additions & 3 deletions packages/kit/types/app.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { PrerenderOptions, SSRNodeLoader, SSRRoute } from './internal';

export interface RequestOptions<Platform = Record<string, any>> {
platform?: Platform;
}

export class App {
constructor(manifest: SSRManifest);
render(request: Request): Promise<Response>;
render(request: Request, options?: RequestOptions): Promise<Response>;
}

export class InternalApp extends App {
render(
request: Request,
options?: {
prerender: PrerenderOptions;
options?: RequestOptions & {
prerender?: PrerenderOptions;
}
): Promise<Response>;
}
Expand Down
8 changes: 6 additions & 2 deletions packages/kit/types/endpoint.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ export interface Fallthrough {
fallthrough: true;
}

export interface RequestHandler<Locals = Record<string, any>, Output extends Body = Body> {
(event: RequestEvent<Locals>): MaybePromise<
export interface RequestHandler<
Locals = Record<string, any>,
Platform = Record<string, any>,
Output extends Body = Body
> {
(event: RequestEvent<Locals, Platform>): MaybePromise<
Either<Response | EndpointOutput<Output>, Fallthrough>
>;
}
17 changes: 11 additions & 6 deletions packages/kit/types/hooks.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@ import { MaybePromise } from './helper';

export type StrictBody = string | Uint8Array;

export interface RequestEvent<Locals = Record<string, any>> {
export interface RequestEvent<Locals = Record<string, any>, Platform = Record<string, any>> {
request: Request;
url: URL;
params: Record<string, string>;
locals: Locals;
platform: Readonly<Platform>;
}

export interface GetSession<Locals = Record<string, any>, Session = any> {
(event: RequestEvent<Locals>): MaybePromise<Session>;
export interface GetSession<
Locals = Record<string, any>,
Platform = Record<string, any>,
Session = any
> {
(event: RequestEvent<Locals, Platform>): MaybePromise<Session>;
}

export interface ResolveOpts {
ssr?: boolean;
}

export interface Handle<Locals = Record<string, any>> {
export interface Handle<Locals = Record<string, any>, Platform = Record<string, any>> {
(input: {
event: RequestEvent<Locals>;
resolve(event: RequestEvent<Locals>, opts?: ResolveOpts): MaybePromise<Response>;
event: RequestEvent<Locals, Platform>;
resolve(event: RequestEvent<Locals, Platform>, opts?: ResolveOpts): MaybePromise<Response>;
}): MaybePromise<Response>;
}

Expand Down
1 change: 1 addition & 0 deletions packages/kit/types/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export interface SSRRenderOptions {
export interface SSRRenderState {
fetched?: string;
initiator?: SSRPage | null;
platform?: any;
prerender?: PrerenderOptions;
fallback?: string;
}
Expand Down