Repository: sveltejs/kit
Pull request #4145 (2022-02-27 19:23:39)

Add Netlify Functions Context to Netlify Adapter
Netlify Functions' Handler type[1] has a `context` argument that the adapter currently drops.  The context contains useful information that Endpoints may want to have access to, namely auth information[2].  This PR passes that context down to Endpoints via app. Doing this has been discussed previously in https://github.com/sveltejs/kit/issues/1249, including one person patching something roughly equivalent to this change into their local repo.

[1] https://github.com/netlify/functions/blob/efcf21eb6c969c73d165e01b00f33b53f3e150b5/src/function/handler.ts#L11

[2] https://docs.netlify.com/functions/functions-and-identity/


### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpx changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


changeset-bot[bot]: ###  🦋  Changeset detected

Latest commit: c9ee636a3def533fb6e6565b4f66a8305f3a0e83

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 1 package</summary>

  | Name                      | Type  |
| ------------------------- | ----- |
| @sveltejs/adapter-netlify | Minor |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/jsandler18/kit/new/master?filename=.changeset/purple-ties-brake.md&value=---%0A%22%40sveltejs%2Fadapter-netlify%22%3A%20patch%0A---%0A%0AAdd%20Netlify%20Functions%20Context%20to%20Netlify%20Adapter%0A)


benmccann: I would expect some change to https://github.com/sveltejs/kit/blob/master/packages/adapter-netlify/README.md to document this
jsandler18: > I would expect some change to https://github.com/sveltejs/kit/blob/master/packages/adapter-netlify/README.md to document this

Done.

Patch:
diff --git a/.changeset/many-pigs-deliver.md b/.changeset/many-pigs-deliver.md
new file mode 100644
index 000000000..4617dfa1a
--- /dev/null
+++ b/.changeset/many-pigs-deliver.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/adapter-netlify': patch
+---
+
+Add Netlify Functions context as `event.platform.context`
diff --git a/.changeset/purple-readers-build.md b/.changeset/purple-readers-build.md
new file mode 100644
index 000000000..762698421
--- /dev/null
+++ b/.changeset/purple-readers-build.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+`RequestHandlerOutput` accepts body when it has or maybe is `undefined`
diff --git a/documentation/docs/03-loading.md b/documentation/docs/03-loading.md
index faca2bcc0..199cd5e78 100644
--- a/documentation/docs/03-loading.md
+++ b/documentation/docs/03-loading.md
@@ -26,7 +26,7 @@ If the data for a page comes from its endpoint, you may not need a `load` functi
 
 > Note the `<script context="module">` — this is necessary because `load` runs before the component is rendered. Code that is per-component instance should go into a second `<script>` tag.
 
-`load` is similar to `getStaticProps` or `getServerSideProps` in Next.js, except that it runs on both the server and the client. In the example above, if a user clicks on a link to this page the data will be fetched from `cms.example.com` without going via our server.
+`load` is similar to `getStaticProps` or `getServerSideProps` in Next.js, except that `load` runs on both the server and the client. In the example above, if a user clicks on a link to this page the data will be fetched from `cms.example.com` without going via our server.
 
 If `load` returns `{fallthrough: true}`, SvelteKit will [fall through](/docs/routing#advanced-routing-fallthrough-routes) to other routes until something responds, or will respond with a generic 404.
 
diff --git a/documentation/docs/13-configuration.md b/documentation/docs/13-configuration.md
index 54f77a5ef..0bc7ff71b 100644
--- a/documentation/docs/13-configuration.md
+++ b/documentation/docs/13-configuration.md
@@ -132,7 +132,7 @@ export default config;
 
 When pages are prerendered, the CSP header is added via a `<meta http-equiv>` tag (note that in this case, `frame-ancestors`, `report-uri` and `sandbox` directives will be ignored).
 
-> When `mode` is `'auto'`, SvelteKit will use nonces for dynamically rendered pages and hashes for prerendered pages. Using nonces with prerendered pages is insecure and therefore forbiddem.
+> When `mode` is `'auto'`, SvelteKit will use nonces for dynamically rendered pages and hashes for prerendered pages. Using nonces with prerendered pages is insecure and therefore forbidden.
 
 ### files
 
diff --git a/packages/adapter-netlify/README.md b/packages/adapter-netlify/README.md
index 52979b7bc..8ba42157d 100644
--- a/packages/adapter-netlify/README.md
+++ b/packages/adapter-netlify/README.md
@@ -57,7 +57,9 @@ During compilation, redirect rules are automatically appended to your `_redirect
 
 ### Using Netlify Functions
 
-[Netlify Functions](https://docs.netlify.com/functions/overview/) can be used alongside your SvelteKit routes. If you would like to add them to your site, you should create a directory for them and add the configuration to your `netlify.toml` file. For example:
+With this adapter, SvelteKit endpoints are hosted as [Netlify Functions](https://docs.netlify.com/functions/overview/). Netlify function handlers have additional context, including [Netlify Identity](https://docs.netlify.com/visitor-access/identity/) information. You can access this context via the `event.platform.context` field inside your hooks and endpoints.
+
+Additionally, you can add your own Netlify functions by creating a directory for them and adding the configuration to your `netlify.toml` file. For example:
 
 ```toml
 [build]
diff --git a/packages/adapter-netlify/src/handler.js b/packages/adapter-netlify/src/handler.js
index 13eb9175c..160706c1b 100644
--- a/packages/adapter-netlify/src/handler.js
+++ b/packages/adapter-netlify/src/handler.js
@@ -9,8 +9,8 @@ import { split_headers } from './headers';
 export function init(manifest) {
 	const server = new Server(manifest);
 
-	return async (event) => {
-		const rendered = await server.respond(to_request(event));
+	return async (event, context) => {
+		const rendered = await server.respond(to_request(event), { platform: { context } });
 
 		const partial_response = {
 			statusCode: rendered.status,
diff --git a/packages/kit/types/ambient.d.ts b/packages/kit/types/ambient.d.ts
index 885c960f3..ff8f0fd7f 100644
--- a/packages/kit/types/ambient.d.ts
+++ b/packages/kit/types/ambient.d.ts
@@ -125,7 +125,7 @@ declare module '$app/navigation' {
 	 * If no argument is given, all routes will be fetched, otherwise you can specify routes by any matching pathname
 	 * such as `/about` (to match `src/routes/about.svelte`) or `/blog/*` (to match `src/routes/blog/[slug].svelte`).
 	 *
-	 * Unlike prefetch, this won't call preload for individual pages.
+	 * Unlike prefetch, this won't call load for individual pages.
 	 * Returns a Promise that resolves when the routes have been prefetched.
 	 */
 	export function prefetchRoutes(routes?: string[]): Promise<void>;
diff --git a/packages/kit/types/private.d.ts b/packages/kit/types/private.d.ts
index d51d7864e..33b8d487f 100644
--- a/packages/kit/types/private.d.ts
+++ b/packages/kit/types/private.d.ts
@@ -208,7 +208,15 @@ export type HttpMethod = 'get' | 'head' | 'post' | 'put' | 'delete' | 'patch';
 
 export type JSONObject = { [key: string]: JSONValue };
 
-export type JSONValue = string | number | boolean | null | ToJSON | JSONValue[] | JSONObject;
+export type JSONValue =
+	| string
+	| number
+	| boolean
+	| null
+	| undefined
+	| ToJSON
+	| JSONValue[]
+	| JSONObject;
 
 export interface LoadInput<Params = Record<string, string>> {
 	url: URL;


Test patch:
diff --git a/packages/kit/test/typings/endpoint.test.ts b/packages/kit/test/typings/endpoint.test.ts
index f805a811d..9f5af8ec3 100644
--- a/packages/kit/test/typings/endpoint.test.ts
+++ b/packages/kit/test/typings/endpoint.test.ts
@@ -5,10 +5,11 @@ const valid_body = {
 	num: 12345,
 	bool: true,
 	null: null,
+	maybe: Math.random() < 0.5 ? undefined : true,
 	custom: {
 		toJSON: () => 'custom toJSON function'
 	},
-	list: ['string', 12345, false, null],
+	list: ['string', 12345, false, null, undefined],
 	nested: {
 		another: 'string',
 		big_num: 98765,
@@ -84,13 +85,6 @@ export const differential_headers_assignment: RequestHandler = () => {
 
 // --- invalid cases ---
 
-// @ts-expect-error - should not have undefined (should it not?)
-export const error_no_undefined: RequestHandler = () => {
-	return {
-		body: { no: Math.random() < 0.5 ? undefined : 'something' }
-	};
-};
-
 // @ts-expect-error - body must be JSON serializable
 export const error_body_must_be_serializable: RequestHandler = () => {
 	return {