Repository: sveltejs/kit
Pull request #8652 (2023-01-21 19:48:26)

docs: add satisfies for actions
Changes the Form actions documentation section TS examples to use `satisfies`.
They are currently using the old `export const actions: Actions = {`
https://kit.svelte.dev/docs/form-actions

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [ ] 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
- [ ] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.


changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: d551a491336027dce1787b299da0d0e3f75cb7c7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/s3812497/kit/new/satisfies-actions?filename=.changeset/chilly-keys-raise.md&value=---%0A%22kit.svelte.dev%22%3A%20patch%0A---%0A%0Adocs%3A%20add%20satisfies%20for%20actions%0A)



Patch:
diff --git a/documentation/docs/20-core-concepts/30-form-actions.md b/documentation/docs/20-core-concepts/30-form-actions.md
index 71be240cf..f135a5043 100644
--- a/documentation/docs/20-core-concepts/30-form-actions.md
+++ b/documentation/docs/20-core-concepts/30-form-actions.md
@@ -56,7 +56,6 @@ Instead of one `default` action, a page can have as many named actions as it nee
 
 ```diff
 /// file: src/routes/login/+page.server.js
-
 /** @type {import('./$types').Actions} */
 export const actions = {
 -	default: async (event) => {
@@ -107,7 +106,7 @@ As well as the `action` attribute, we can use the `formaction` attribute on a bu
 Each action receives a `RequestEvent` object, allowing you to read the data with `request.formData()`. After processing the request (for example, logging the user in by setting a cookie), the action can respond with data that will be available through the `form` property on the corresponding page and through `$page.form` app-wide until the next update.
 
 ```js
-// @errors: 2339 2304
+// @errors: 2304
 /// file: src/routes/login/+page.server.js
 /** @type {import('./$types').PageServerLoad} */
 export async function load({ cookies }) {
@@ -155,7 +154,6 @@ export const actions = {
 If the request couldn't be processed because of invalid data, you can return validation errors — along with the previously submitted form values — back to the user so that they can try again. The `fail` function lets you return an HTTP status code (typically 400 or 422, in the case of validation errors) along with the data. The status code is available through `$page.status` and the data through `form`:
 
 ```diff
-// @errors: 2339 2304
 /// file: src/routes/login/+page.server.js
 +import { fail } from '@sveltejs/kit';
 
@@ -214,7 +212,6 @@ The returned data must be serializable as JSON. Beyond that, the structure is en
 Redirects (and errors) work exactly the same as in [`load`](/docs/load#redirects):
 
 ```diff
-// @errors: 2339 2304
 /// file: src/routes/login/+page.server.js
 +import { fail, redirect } from '@sveltejs/kit';
 
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index 9e95ed92a..3ed29909a 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/kit
 
+## 1.2.3
+
+### Patch Changes
+
+- fix: set environment variables before postbuild analysis ([#8647](https://github.com/sveltejs/kit/pull/8647))
+
 ## 1.2.2
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index 690ff40c3..259d246a7 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.2.2",
+	"version": "1.2.3",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
@@ -22,7 +22,7 @@
 		"set-cookie-parser": "^2.5.1",
 		"sirv": "^2.0.2",
 		"tiny-glob": "^0.2.9",
-		"undici": "5.15.1"
+		"undici": "5.15.2"
 	},
 	"devDependencies": {
 		"@playwright/test": "^1.29.2",
diff --git a/packages/kit/src/core/env.js b/packages/kit/src/core/env.js
index 9dc66f55a..5b2c56bbb 100644
--- a/packages/kit/src/core/env.js
+++ b/packages/kit/src/core/env.js
@@ -44,7 +44,7 @@ export function create_dynamic_module(type, dev_values) {
 		);
 		return `export const env = {\n${keys.join(',\n')}\n}`;
 	}
-	return `export { env } from '${runtime_base}/env-${type}.js';`;
+	return `export { ${type}_env as env } from '${runtime_base}/shared.js';`;
 }
 
 /**
diff --git a/packages/kit/src/core/postbuild/index.js b/packages/kit/src/core/postbuild/index.js
index d62bcdae9..05424a242 100644
--- a/packages/kit/src/core/postbuild/index.js
+++ b/packages/kit/src/core/postbuild/index.js
@@ -10,7 +10,8 @@ import {
 import { load_config } from '../config/index.js';
 import { prerender } from './prerender.js';
 
-const [, , client_out_dir, manifest_path, results_path, verbose, env] = process.argv;
+const [, , client_out_dir, manifest_path, results_path, verbose, env_json] = process.argv;
+const env = JSON.parse(env_json);
 
 /** @type {import('types').SSRManifest} */
 const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
@@ -33,6 +34,12 @@ const { Server } = await import(pathToFileURL(`${server_root}/server/index.js`).
 // essential we do this before analysing the code
 internal.set_building(true);
 
+// set env, in case it's used in initialisation
+const entries = Object.entries(env);
+const prefix = config.env.publicPrefix;
+internal.set_private_env(Object.fromEntries(entries.filter(([k]) => !k.startsWith(prefix))));
+internal.set_public_env(Object.fromEntries(entries.filter(([k]) => k.startsWith(prefix))));
+
 // analyse routes
 for (const route of manifest._.routes) {
 	if (route.endpoint) {
diff --git a/packages/kit/src/core/postbuild/prerender.js b/packages/kit/src/core/postbuild/prerender.js
index fb65f48b3..4af035800 100644
--- a/packages/kit/src/core/postbuild/prerender.js
+++ b/packages/kit/src/core/postbuild/prerender.js
@@ -50,7 +50,7 @@ const REDIRECT = 3;
  *   prerender_map: import('types').PrerenderMap;
  *   client_out_dir: string;
  *   verbose: string;
- *   env: string;
+ *   env: Record<string, string>;
  * }} opts
  * @returns
  */
@@ -92,7 +92,7 @@ export async function prerender({
 	internal.set_paths(config.paths);
 
 	const server = new Server(manifest);
-	await server.init({ env: JSON.parse(env) });
+	await server.init({ env });
 
 	const handle_http_error = normalise_error_handler(
 		log,
diff --git a/packages/kit/src/core/sync/write_server.js b/packages/kit/src/core/sync/write_server.js
index 6cb05a8ee..1b80f7a5a 100644
--- a/packages/kit/src/core/sync/write_server.js
+++ b/packages/kit/src/core/sync/write_server.js
@@ -24,7 +24,7 @@ const server_template = ({
 	error_page
 }) => `
 import root from './root.svelte';
-import { set_building, set_paths, set_version } from '${runtime_directory}/shared.js';
+import { set_building, set_paths, set_private_env, set_public_env, set_version } from '${runtime_directory}/shared.js';
 
 set_paths(${s(config.kit.paths)});
 set_version(${s(config.kit.version.name)});
@@ -57,7 +57,7 @@ export function get_hooks() {
 	return ${hooks ? `import(${s(hooks)})` : '{}'};
 }
 
-export { set_building, set_paths };
+export { set_building, set_paths, set_private_env, set_public_env };
 `;
 
 // TODO need to re-run this whenever src/app.html or src/error.html are
diff --git a/packages/kit/src/runtime/client/start.js b/packages/kit/src/runtime/client/start.js
index b9f3e4d75..1083898a9 100644
--- a/packages/kit/src/runtime/client/start.js
+++ b/packages/kit/src/runtime/client/start.js
@@ -1,8 +1,7 @@
 import { DEV } from 'esm-env';
 import { create_client } from './client.js';
 import { init } from './singletons.js';
-import { set_paths, set_version } from '../shared.js';
-import { set_public_env } from '../env-public.js';
+import { set_paths, set_version, set_public_env } from '../shared.js';
 
 /**
  * @param {{
diff --git a/packages/kit/src/runtime/env-private.js b/packages/kit/src/runtime/env-private.js
deleted file mode 100644
index 7352ceb17..000000000
--- a/packages/kit/src/runtime/env-private.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export let env = {};
-
-/** @type {(environment: Record<string, string>) => void} */
-export function set_private_env(environment) {
-	env = environment;
-}
diff --git a/packages/kit/src/runtime/env-public.js b/packages/kit/src/runtime/env-public.js
deleted file mode 100644
index 800f6262a..000000000
--- a/packages/kit/src/runtime/env-public.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/** @type {Record<string, string>} */
-export let env = {};
-
-/** @type {(environment: Record<string, string>) => void} */
-export function set_public_env(environment) {
-	env = environment;
-}
diff --git a/packages/kit/src/runtime/env/dynamic/private.js b/packages/kit/src/runtime/env/dynamic/private.js
index 971d61ed5..d05b2fd8b 100644
--- a/packages/kit/src/runtime/env/dynamic/private.js
+++ b/packages/kit/src/runtime/env/dynamic/private.js
@@ -1,1 +1,1 @@
-export { env } from '../../env-private.js';
+export { private_env as env } from '../../shared.js';
diff --git a/packages/kit/src/runtime/env/dynamic/public.js b/packages/kit/src/runtime/env/dynamic/public.js
index 34dc1950b..ba6c33230 100644
--- a/packages/kit/src/runtime/env/dynamic/public.js
+++ b/packages/kit/src/runtime/env/dynamic/public.js
@@ -1,1 +1,1 @@
-export { env } from '../../env-public.js';
+export { public_env as env } from '../../shared.js';
diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js
index 7290beaf3..cd2db2db8 100644
--- a/packages/kit/src/runtime/server/index.js
+++ b/packages/kit/src/runtime/server/index.js
@@ -1,6 +1,5 @@
 import { respond } from './respond.js';
-import { set_private_env } from '../env-private.js';
-import { set_public_env } from '../env-public.js';
+import { set_private_env, set_public_env } from '../shared.js';
 import { options, get_hooks } from '__GENERATED__/server-internal.js';
 
 export class Server {
diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js
index 55bba9a9d..9c911ebb1 100644
--- a/packages/kit/src/runtime/server/page/render.js
+++ b/packages/kit/src/runtime/server/page/render.js
@@ -7,8 +7,7 @@ import { s } from '../../../utils/misc.js';
 import { Csp } from './csp.js';
 import { uneval_action_response } from './actions.js';
 import { clarify_devalue_error } from '../utils.js';
-import { assets, base, version } from '../../shared.js';
-import { env } from '../../env-public.js';
+import { assets, base, version, public_env } from '../../shared.js';
 import { text } from '../../../exports/index.js';
 
 // TODO rename this function/module
@@ -258,7 +257,7 @@ export async function render_response({
 
 	if (page_config.csr) {
 		const opts = [
-			`env: ${s(env)}`,
+			`env: ${s(public_env)}`,
 			`paths: ${s({ assets, base })}`,
 			`target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode`,
 			`version: ${s(version)}`
@@ -368,7 +367,7 @@ export async function render_response({
 		body,
 		assets: resolved_assets,
 		nonce: /** @type {string} */ (csp.nonce),
-		env
+		env: public_env
 	});
 
 	// TODO flush chunks as early as we can
diff --git a/packages/kit/src/runtime/shared.js b/packages/kit/src/runtime/shared.js
index 277ab3656..0cb8fd91d 100644
--- a/packages/kit/src/runtime/shared.js
+++ b/packages/kit/src/runtime/shared.js
@@ -3,6 +3,12 @@ export let base = '';
 export let building = false;
 export let version = '';
 
+/** @type {Record<string, string>} */
+export let private_env = {};
+
+/** @type {Record<string, string>} */
+export let public_env = {};
+
 /** @param {string} stack */
 export let fix_stack_trace = (stack) => stack;
 
@@ -17,6 +23,16 @@ export function set_building(value) {
 	building = value;
 }
 
+/** @type {(environment: Record<string, string>) => void} */
+export function set_private_env(environment) {
+	private_env = environment;
+}
+
+/** @type {(environment: Record<string, string>) => void} */
+export function set_public_env(environment) {
+	public_env = environment;
+}
+
 /** @param {string} value */
 export function set_version(value) {
 	version = value;
diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts
index 85734650f..267b400a6 100644
--- a/packages/kit/types/internal.d.ts
+++ b/packages/kit/types/internal.d.ts
@@ -32,6 +32,8 @@ export interface ServerModule {
 export interface ServerInternalModule {
 	set_building(building: boolean): void;
 	set_paths(paths: { base: string; assets: string }): void;
+	set_private_env(environment: Record<string, string>): void;
+	set_public_env(environment: Record<string, string>): void;
 	set_version(version: string): void;
 	set_fix_stack_trace(fix_stack_trace: (stack: string) => string): void;
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a9be598b3..4abb7a860 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -281,7 +281,7 @@ importers:
       svelte-preprocess: ^5.0.0
       tiny-glob: ^0.2.9
       typescript: ^4.9.4
-      undici: 5.15.1
+      undici: 5.15.2
       uvu: ^0.5.6
       vite: ^4.0.4
     dependencies:
@@ -297,7 +297,7 @@ importers:
       set-cookie-parser: 2.5.1
       sirv: 2.0.2
       tiny-glob: 0.2.9
-      undici: 5.15.1
+      undici: 5.15.2
     devDependencies:
       '@playwright/test': 1.29.2
       '@types/connect': 3.4.35
@@ -4485,8 +4485,8 @@ packages:
       which-boxed-primitive: 1.0.2
     dev: true
 
-  /undici/5.15.1:
-    resolution: {integrity: sha512-XLk8g0WAngdvFqTI+VKfBtM4YWXgdxkf1WezC771Es0Dd+Pm1KmNx8t93WTC+Hh9tnghmVxkclU1HN+j+CvIUA==}
+  /undici/5.15.2:
+    resolution: {integrity: sha512-JsN6meyJESMJaLqOuozstwrolSkLWlTIT4qpGoKepNdnZy7HJMPKB0v0Td/CepGgoiPpUSvVO9Nh/5N9QrmDgQ==}
     engines: {node: '>=12.18'}
     dependencies:
       busboy: 1.6.0
diff --git a/sites/kit.svelte.dev/src/lib/docs/server/index.js b/sites/kit.svelte.dev/src/lib/docs/server/index.js
index f93b217f2..e1530cb13 100644
--- a/sites/kit.svelte.dev/src/lib/docs/server/index.js
+++ b/sites/kit.svelte.dev/src/lib/docs/server/index.js
@@ -504,7 +504,13 @@ function convert_to_ts(js_code, indent = '', offset = '') {
 							ts.isVariableStatement(node) &&
 							node.declarationList.declarations.length === 1
 						) {
-							code.appendLeft(node.declarationList.declarations[0].name.getEnd(), `: ${name}`);
+							const variable_statement = node.declarationList.declarations[0];
+
+							if (variable_statement.name.getText() === 'actions') {
+								code.appendLeft(variable_statement.getEnd(), ` satisfies ${name}`);
+							} else {
+								code.appendLeft(variable_statement.name.getEnd(), `: ${name}`);
+							}
 
 							modified = true;
 						} else {


Test patch:
diff --git a/packages/kit/test/apps/basics/.env b/packages/kit/test/apps/basics/.env
index a406fc245..9bfc91723 100644
--- a/packages/kit/test/apps/basics/.env
+++ b/packages/kit/test/apps/basics/.env
@@ -5,3 +5,5 @@ PUBLIC_STATIC="accessible anywhere/replaced at build time"
 PUBLIC_DYNAMIC="accessible anywhere/evaluated at run time"
 
 PUBLIC_THEME="groovy"
+
+SOME_JSON='{"answer":42}'
\ No newline at end of file
diff --git a/packages/kit/test/apps/basics/src/routes/+layout.server.js b/packages/kit/test/apps/basics/src/routes/+layout.server.js
index d30920705..f6d2446b6 100644
--- a/packages/kit/test/apps/basics/src/routes/+layout.server.js
+++ b/packages/kit/test/apps/basics/src/routes/+layout.server.js
@@ -1,4 +1,15 @@
 import { error, redirect } from '@sveltejs/kit';
+import { env } from '$env/dynamic/private';
+import { SOME_JSON } from '$env/static/private';
+
+// https://github.com/sveltejs/kit/issues/8646
+if (JSON.parse(SOME_JSON).answer !== 42) {
+	throw new Error('failed to parse env var');
+}
+
+if (JSON.parse(env.SOME_JSON).answer !== 42) {
+	throw new Error('failed to parse env var');
+}
 
 /** @type {import('./$types').LayoutServerLoad} */
 export async function load({ cookies }) {