Repository: sveltejs/kit
Pull request #6220 (2022-08-24 14:45:53)

reuse compact utility
Another minor follow-up to #6174, I knew I've read "compact" somewhere before in the codebase

### 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. All changesets should be `patch` until SvelteKit 1.0


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

Latest commit: 86afa2318d9aaa9bd4b880e96f2aaded0995ef5c

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/sveltejs/kit/new/reuse-util?filename=.changeset/swift-feet-impress.md&value=---%0A%22%40sveltejs%2Fkit%22%3A%20patch%0A---%0A%0Areuse%20compact%20utility%0A)



Patch:
diff --git a/.changeset/curvy-students-march.md b/.changeset/curvy-students-march.md
new file mode 100644
index 000000000..f413cf8e5
--- /dev/null
+++ b/.changeset/curvy-students-march.md
@@ -0,0 +1,10 @@
+---
+'@sveltejs/adapter-cloudflare': patch
+'@sveltejs/adapter-cloudflare-workers': patch
+'@sveltejs/adapter-netlify': patch
+'@sveltejs/adapter-node': patch
+'@sveltejs/adapter-vercel': patch
+'@sveltejs/kit': patch
+---
+
+[feat] Moved hooks.js initialization from Server.respond into Server.init
diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js
index 0646c7acc..fe1c45a24 100644
--- a/packages/adapter-cloudflare-workers/files/entry.js
+++ b/packages/adapter-cloudflare-workers/files/entry.js
@@ -15,7 +15,7 @@ export default {
 	 * @param {any} context
 	 */
 	async fetch(req, env, context) {
-		server.init({ env });
+		await server.init({ env });
 
 		const url = new URL(req.url);
 
diff --git a/packages/adapter-cloudflare/src/worker.js b/packages/adapter-cloudflare/src/worker.js
index 20993ee11..a31267aef 100644
--- a/packages/adapter-cloudflare/src/worker.js
+++ b/packages/adapter-cloudflare/src/worker.js
@@ -9,7 +9,7 @@ const prefix = `/${manifest.appDir}/`;
 /** @type {import('worktop/cfw').Module.Worker<{ ASSETS: import('worktop/cfw.durable').Durable.Object }>} */
 const worker = {
 	async fetch(req, env, context) {
-		server.init({ env });
+		await server.init({ env });
 		// skip cache if "cache-control: no-cache" in request
 		let pragma = req.headers.get('cache-control') || '';
 		let res = !pragma.includes('no-cache') && (await Cache.lookup(req));
diff --git a/packages/adapter-netlify/src/serverless.js b/packages/adapter-netlify/src/serverless.js
index aec29eef5..f898796b8 100644
--- a/packages/adapter-netlify/src/serverless.js
+++ b/packages/adapter-netlify/src/serverless.js
@@ -9,11 +9,16 @@ import { split_headers } from './headers';
 export function init(manifest) {
 	const server = new Server(manifest);
 
-	server.init({
+	let init_promise = server.init({
 		env: process.env
 	});
 
 	return async (event, context) => {
+		if (init_promise !== null) {
+			await init_promise;
+			init_promise = null;
+		}
+
 		const response = await server.respond(to_request(event), {
 			platform: { context },
 			getClientAddress() {
diff --git a/packages/adapter-node/src/handler.js b/packages/adapter-node/src/handler.js
index e5e67bfa3..d90bce52d 100644
--- a/packages/adapter-node/src/handler.js
+++ b/packages/adapter-node/src/handler.js
@@ -11,7 +11,7 @@ import { env } from './env.js';
 /* global ENV_PREFIX */
 
 const server = new Server(manifest);
-server.init({ env: process.env });
+await server.init({ env: process.env });
 const origin = env('ORIGIN', undefined);
 const xff_depth = parseInt(env('XFF_DEPTH', '1'));
 
diff --git a/packages/adapter-node/tsconfig.json b/packages/adapter-node/tsconfig.json
index 89ca95cf9..63ea97316 100644
--- a/packages/adapter-node/tsconfig.json
+++ b/packages/adapter-node/tsconfig.json
@@ -6,7 +6,8 @@
 		"noImplicitAny": true,
 		"allowSyntheticDefaultImports": true,
 		"moduleResolution": "node",
-		"module": "es2020",
+		"module": "es2022",
+		"target": "es2017",
 		"baseUrl": ".",
 		"paths": {
 			"@sveltejs/kit": ["../kit/types/index"]
diff --git a/packages/adapter-vercel/files/serverless.js b/packages/adapter-vercel/files/serverless.js
index 639275b9b..c647fd8b1 100644
--- a/packages/adapter-vercel/files/serverless.js
+++ b/packages/adapter-vercel/files/serverless.js
@@ -7,7 +7,7 @@ installPolyfills();
 
 const server = new Server(manifest);
 
-server.init({
+await server.init({
 	env: process.env
 });
 
diff --git a/packages/kit/src/core/prerender/prerender.js b/packages/kit/src/core/prerender/prerender.js
index a2cfbd79c..410aa0e5b 100644
--- a/packages/kit/src/core/prerender/prerender.js
+++ b/packages/kit/src/core/prerender/prerender.js
@@ -15,7 +15,7 @@ import { load_config } from '../config/index.js';
  * @typedef {import('types').Logger} Logger
  */
 
-const [, , client_out_dir, results_path, manifest_path, verbose] = process.argv;
+const [, , client_out_dir, results_path, manifest_path, verbose, env] = process.argv;
 
 prerender();
 
@@ -159,6 +159,7 @@ export async function prerender() {
 	});
 
 	const server = new Server(manifest);
+	await server.init({ env: JSON.parse(env) });
 
 	const error = normalise_error_handler(log, config);
 
diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js
index d0df231da..ebe1f005d 100644
--- a/packages/kit/src/runtime/server/page/index.js
+++ b/packages/kit/src/runtime/server/page/index.js
@@ -5,6 +5,7 @@ import { method_not_allowed, error_to_pojo, allowed_methods } from '../utils.js'
 import { create_fetch } from './fetch.js';
 import { HttpError, Redirect } from '../../../index/private.js';
 import { error, json } from '../../../index/index.js';
+import { compact } from '../../../utils/array.js';
 import { normalize_error } from '../../../utils/error.js';
 import { load_data, load_server_data } from './load_data.js';
 
@@ -401,18 +402,3 @@ function redirect_response(status, location) {
 		headers: { location }
 	});
 }
-
-/**
- * @template T
- * @param {Array<T | null>} array
- * @returns {T[]}
- */
-function compact(array) {
-	const compacted = [];
-	for (const item of array) {
-		if (item) {
-			compacted.push(item);
-		}
-	}
-	return compacted;
-}
diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js
index 793179b1c..d2124e4f8 100644
--- a/packages/kit/src/vite/build/build_server.js
+++ b/packages/kit/src/vite/build/build_server.js
@@ -84,7 +84,12 @@ export class Server {
 		};
 	}
 
-	init({ env }) {
+	/**
+	 * Take care: Some adapters may have to call \`Server.init\` per-request to set env vars,
+	 * so anything that shouldn't be rerun should be wrapped in an \`if\` block to make sure it hasn't
+	 * been done already.
+	 */
+	async init({ env }) {
 		const entries = Object.entries(env);
 
 		const prv = Object.fromEntries(entries.filter(([k]) => !k.startsWith('${
@@ -99,12 +104,6 @@ export class Server {
 		set_public_env(pub);
 
 		this.options.public_env = pub;
-	}
-
-	async respond(request, options = {}) {
-		if (!(request instanceof Request)) {
-			throw new Error('The first argument to server.respond must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details');
-		}
 
 		if (!this.options.hooks) {
 			const module = await import(${s(hooks)});
@@ -114,6 +113,12 @@ export class Server {
 				externalFetch: module.externalFetch || fetch
 			};
 		}
+	}
+
+	async respond(request, options = {}) {
+		if (!(request instanceof Request)) {
+			throw new Error('The first argument to server.respond must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details');
+		}
 
 		return respond(request, this.options, options);
 	}
diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js
index 7f6e74bc3..c6ecdb9ef 100644
--- a/packages/kit/src/vite/index.js
+++ b/packages/kit/src/vite/index.js
@@ -411,7 +411,13 @@ function kit() {
 
 				const child = fork(
 					script,
-					[vite_config.build.outDir, results_path, manifest_path, '' + verbose],
+					[
+						vite_config.build.outDir,
+						results_path,
+						manifest_path,
+						'' + verbose,
+						JSON.stringify({ ...env.private, ...env.public })
+					],
 					{
 						stdio: 'inherit'
 					}
diff --git a/packages/kit/src/vite/preview/index.js b/packages/kit/src/vite/preview/index.js
index 56c471913..561d22cb1 100644
--- a/packages/kit/src/vite/preview/index.js
+++ b/packages/kit/src/vite/preview/index.js
@@ -45,7 +45,7 @@ export async function preview(vite, vite_config, svelte_config) {
 	});
 
 	const server = new Server(manifest);
-	server.init({
+	await server.init({
 		env: loadEnv(vite_config.mode, process.cwd(), '')
 	});
 
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index a38968f52..260cdfc00 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -264,7 +264,7 @@ export interface ResolveOptions {
 
 export class Server {
 	constructor(manifest: SSRManifest);
-	init(options: ServerInitOptions): void;
+	init(options: ServerInitOptions): Promise<void>;
 	respond(request: Request, options: RequestOptions): Promise<Response>;
 }
 
diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts
index 1d870c4ba..5e8376edb 100644
--- a/packages/kit/types/internal.d.ts
+++ b/packages/kit/types/internal.d.ts
@@ -94,7 +94,7 @@ export interface ImportNode {
 }
 
 export class InternalServer extends Server {
-	init(options: ServerInitOptions): void;
+	init(options: ServerInitOptions): Promise<void>;
 	respond(
 		request: Request,
 		options: RequestOptions & {


Test patch:
diff --git a/packages/kit/test/apps/basics/src/hooks.js b/packages/kit/test/apps/basics/src/hooks.js
index d6b9caa9d..fe4b94752 100644
--- a/packages/kit/test/apps/basics/src/hooks.js
+++ b/packages/kit/test/apps/basics/src/hooks.js
@@ -1,6 +1,6 @@
 import fs from 'fs';
 import cookie from 'cookie';
-import { sequence } from '../../../../src/hooks';
+import { sequence } from '@sveltejs/kit/hooks';
 
 /** @type {import('@sveltejs/kit').HandleError} */
 export const handleError = ({ event, error }) => {
diff --git a/packages/kit/test/prerendering/basics/.env b/packages/kit/test/prerendering/basics/.env
new file mode 100644
index 000000000..1597af124
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/.env
@@ -0,0 +1,5 @@
+PRIVATE_STATIC="accessible to server-side code/replaced at build time"
+PRIVATE_DYNAMIC="accessible to server-side code/evaluated at run time"
+
+PUBLIC_STATIC="accessible anywhere/replaced at build time"
+PUBLIC_DYNAMIC="accessible anywhere/evaluated at run time"
diff --git a/packages/kit/test/prerendering/basics/.gitignore b/packages/kit/test/prerendering/basics/.gitignore
new file mode 100644
index 000000000..1e18f275e
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/.gitignore
@@ -0,0 +1,1 @@
+!.env
\ No newline at end of file
diff --git a/packages/kit/test/prerendering/basics/src/routes/env/+page.server.js b/packages/kit/test/prerendering/basics/src/routes/env/+page.server.js
new file mode 100644
index 000000000..617a8542f
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/src/routes/env/+page.server.js
@@ -0,0 +1,9 @@
+import { PRIVATE_STATIC } from '$env/static/private';
+import { env } from '$env/dynamic/private';
+
+export function load() {
+	return {
+		PRIVATE_STATIC,
+		PRIVATE_DYNAMIC: env.PRIVATE_DYNAMIC
+	};
+}
diff --git a/packages/kit/test/prerendering/basics/src/routes/env/+page.svelte b/packages/kit/test/prerendering/basics/src/routes/env/+page.svelte
new file mode 100644
index 000000000..4ee2f424d
--- /dev/null
+++ b/packages/kit/test/prerendering/basics/src/routes/env/+page.svelte
@@ -0,0 +1,13 @@
+<script>
+	import { PUBLIC_STATIC } from '$env/static/public';
+	import { env } from '$env/dynamic/public';
+
+	/** @type {import('./$types').PageData} */
+	export let data;
+</script>
+
+<p id="static-private">PRIVATE_STATIC: {data.PRIVATE_STATIC}</p>
+<p id="dynamic-private">PRIVATE_DYNAMIC: {data.PRIVATE_DYNAMIC}</p>
+
+<p id="static-public">PUBLIC_STATIC: {PUBLIC_STATIC}</p>
+<p id="dynamic-public">PUBLIC_DYNAMIC: {env.PUBLIC_DYNAMIC}</p>
diff --git a/packages/kit/test/prerendering/basics/test/test.js b/packages/kit/test/prerendering/basics/test/test.js
index 280a86286..b38c6ab65 100644
--- a/packages/kit/test/prerendering/basics/test/test.js
+++ b/packages/kit/test/prerendering/basics/test/test.js
@@ -190,4 +190,19 @@ test('respects config.prerender.origin', () => {
 	assert.ok(content.includes('<h2>http://example.com</h2>'));
 });
 
+test('$env - includes environment variables', () => {
+	const content = read('env.html');
+
+	assert.match(
+		content,
+		/.*PRIVATE_STATIC: accessible to server-side code\/replaced at build time.*/gs
+	);
+	assert.match(
+		content,
+		/.*PRIVATE_DYNAMIC: accessible to server-side code\/evaluated at run time.*/gs
+	);
+	assert.match(content, /.*PUBLIC_STATIC: accessible anywhere\/replaced at build time.*/gs);
+	assert.match(content, /.*PUBLIC_DYNAMIC: accessible anywhere\/evaluated at run time.*/gs);
+});
+
 test.run();