From c8a0bfabd41f5b7ba38bf24f4c3a1b4712aa26c0 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 18:59:18 +0800 Subject: [PATCH 01/18] it works? --- packages/kit/src/cli.js | 2 +- packages/kit/src/core/sync/sync.js | 17 +++++--- packages/kit/src/core/sync/write_env.js | 22 +++++++++++ packages/kit/src/core/sync/write_root.js | 1 + packages/kit/src/core/sync/write_tsconfig.js | 1 + packages/kit/src/exports/vite/dev/index.js | 5 ++- packages/kit/src/exports/vite/index.js | 39 +++++++------------ packages/kit/src/exports/vite/types.d.ts | 5 +++ packages/kit/src/exports/vite/utils.js | 1 + .../basics/test/cross-platform/server.test.js | 22 +++++++++++ 10 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 packages/kit/src/core/sync/write_env.js diff --git a/packages/kit/src/cli.js b/packages/kit/src/cli.js index 9f56e2e17814..db2413e86b5a 100755 --- a/packages/kit/src/cli.js +++ b/packages/kit/src/cli.js @@ -24,7 +24,7 @@ const prog = sade('svelte-kit').version(pkg.version); prog .command('sync') - .describe('Synchronise generated type definitions') + .describe('Synchronise generated type definitions and $env modules') .option('--mode', 'Specify a mode for loading environment variables', 'development') .action(async ({ mode }) => { const config_files = ['js', 'ts'] diff --git a/packages/kit/src/core/sync/sync.js b/packages/kit/src/core/sync/sync.js index c77bbca30f27..1d86642abc92 100644 --- a/packages/kit/src/core/sync/sync.js +++ b/packages/kit/src/core/sync/sync.js @@ -7,13 +7,17 @@ import { write_types, write_all_types } from './write_types/index.js'; import { write_ambient } from './write_ambient.js'; import { write_non_ambient } from './write_non_ambient.js'; import { write_server } from './write_server.js'; +import { write_env } from './write_env.js'; +import { get_env } from '../../exports/vite/utils.js'; /** * Initialize SvelteKit's generated files that only depend on the config and mode. * @param {import('types').ValidatedConfig} config * @param {string} mode + * @param {import('../../exports/vite/types.js').Env} env */ -export function init(config, mode) { +export function init(config, mode, env) { + write_env(config.kit, env); write_tsconfig(config.kit); write_ambient(config.kit, mode); } @@ -52,19 +56,22 @@ export function update(config, manifest_data, file) { * Run sync.init and sync.create in series, returning the result from sync.create. * @param {import('types').ValidatedConfig} config * @param {string} mode The Vite mode + * @param {import('../../exports/vite/types.js').Env} env */ -export function all(config, mode) { - init(config, mode); +export function all(config, mode, env) { + init(config, mode, env); return create(config); } /** - * Run sync.init and then generate all type files. + * Run sync.init and then generate all type files and $env modules. * @param {import('types').ValidatedConfig} config * @param {string} mode The Vite mode */ export function all_types(config, mode) { - init(config, mode); + const env = get_env(config.kit.env, mode); + + init(config, mode, env); const manifest_data = create_manifest_data({ config }); write_all_types(config, manifest_data); write_non_ambient(config.kit, manifest_data); diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js new file mode 100644 index 000000000000..a107a00d9ca4 --- /dev/null +++ b/packages/kit/src/core/sync/write_env.js @@ -0,0 +1,22 @@ +import path from 'node:path'; +import { write_if_changed } from './utils.js'; +import { create_dynamic_module, create_static_module } from '../env.js'; + +/** + * Writes env variable modules to the output directory + * @param {import('types').ValidatedKitConfig} config + * @param {import('../../exports/vite/types.js').Env} env + */ +export function write_env(config, env) { + const env_static_private = create_static_module('$env/static/private', env.private); + write_if_changed(path.join(config.outDir, 'env', 'static', 'private.js'), env_static_private); + + const env_static_public = create_static_module('$env/static/public', env.public); + write_if_changed(path.join(config.outDir, 'env', 'static', 'public.js'), env_static_public); + + const env_dynamic_private = create_dynamic_module('private', env.private); + write_if_changed(path.join(config.outDir, 'env', 'dynamic', 'private.js'), env_dynamic_private); + + const env_dynamic_public = create_dynamic_module('public', env.public); + write_if_changed(path.join(config.outDir, 'env', 'dynamic', 'public.js'), env_dynamic_public); +} diff --git a/packages/kit/src/core/sync/write_root.js b/packages/kit/src/core/sync/write_root.js index 5866b3d8e783..c5a2be5ca39b 100644 --- a/packages/kit/src/core/sync/write_root.js +++ b/packages/kit/src/core/sync/write_root.js @@ -1,6 +1,7 @@ import { dedent, isSvelte5Plus, write_if_changed } from './utils.js'; /** + * Creates the "App.svelte" root component used to mount the user's layouts and pages * @param {import('types').ManifestData} manifest_data * @param {string} output */ diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index 6bca8214bdb1..fd0754aa1127 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -100,6 +100,7 @@ export function get_tsconfig(kit) { // generated options paths: { ...get_tsconfig_paths(kit), + '$env/*': ['./env/*'], '$app/types': ['./types/index.d.ts'] }, rootDirs: [config_relative('.'), './types'], diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index 31c13c1ead8b..2dc5a373995c 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -30,9 +30,10 @@ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/; * @param {import('vite').ResolvedConfig} vite_config * @param {import('types').ValidatedConfig} svelte_config * @param {() => Array<{ hash: string, file: string }>} get_remotes + * @param {import('../types.js').Env} kit_env * @return {Promise void>>} */ -export async function dev(vite, vite_config, svelte_config, get_remotes) { +export async function dev(vite, vite_config, svelte_config, get_remotes, kit_env) { installPolyfills(); const async_local_storage = new AsyncLocalStorage(); @@ -55,7 +56,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) { return fetch(info, init); }; - sync.init(svelte_config, vite_config.mode); + sync.init(svelte_config, vite_config.mode, kit_env); /** @type {import('types').ManifestData} */ let manifest_data; diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 445001139726..c6c80390e2b9 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -5,7 +5,7 @@ import process from 'node:process'; import colors from 'kleur'; import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js'; -import { create_static_module, create_dynamic_module } from '../../core/env.js'; +import { create_dynamic_module } from '../../core/env.js'; import * as sync from '../../core/sync/sync.js'; import { create_assets } from '../../core/sync/create_manifest_data/index.js'; import { runtime_directory, logger } from '../../core/utils.js'; @@ -32,8 +32,6 @@ import { dedent, isSvelte5Plus } from '../../core/sync/utils.js'; import { env_dynamic_private, env_dynamic_public, - env_static_private, - env_static_public, service_worker, sveltekit_environment, sveltekit_server @@ -209,7 +207,7 @@ async function kit({ svelte_config }) { /** @type {boolean} */ let is_build; - /** @type {{ public: Record; private: Record }} */ + /** @type {import('./types.js').Env} */ let env; /** @type {() => Promise} */ @@ -370,7 +368,7 @@ async function kit({ svelte_config }) { }; if (!secondary_build_started) { - manifest_data = sync.all(svelte_config, config_env.mode).manifest_data; + manifest_data = sync.all(svelte_config, config_env.mode, env).manifest_data; // During the initial server build we don't know yet new_config.define.__SVELTEKIT_HAS_SERVER_LOAD__ = 'true'; new_config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ = 'true'; @@ -423,7 +421,7 @@ async function kit({ svelte_config }) { const plugin_virtual_modules = { name: 'vite-plugin-sveltekit-virtual-modules', - resolveId(id, importer) { + resolveId(id, importer, options) { if (id === '__sveltekit/manifest') { return `${kit.outDir}/generated/client-optimized/app.js`; } @@ -450,8 +448,14 @@ async function kit({ svelte_config }) { } } + const browser = !options?.ssr; + // treat $env/static/[public|private] as virtual - if (id.startsWith('$env/') || id === '$service-worker') { + if ( + (id.startsWith('$env/dynamic') && vite_config_env.command !== 'serve') || + (id === '$env/dynamic/public' && browser) || + id === '$service-worker' + ) { // ids with :$ don't work with reverse proxies like nginx return `\0virtual:${id.substring(1)}`; } @@ -473,28 +477,15 @@ async function kit({ svelte_config }) { : 'globalThis.__sveltekit_dev'; switch (id) { - case env_static_private: - return create_static_module('$env/static/private', env.private); - - case env_static_public: - return create_static_module('$env/static/public', env.public); - case env_dynamic_private: - return create_dynamic_module( - 'private', - vite_config_env.command === 'serve' ? env.private : undefined - ); + return create_dynamic_module('private', undefined); case env_dynamic_public: // populate `$env/dynamic/public` from `window` if (browser) { return `export const env = ${global}.env;`; } - - return create_dynamic_module( - 'public', - vite_config_env.command === 'serve' ? env.public : undefined - ); + return create_dynamic_module('public', undefined); case service_worker: return create_service_worker_module(svelte_config); @@ -590,7 +581,7 @@ async function kit({ svelte_config }) { if (is_server_only) { // in dev, this doesn't exist, so we need to create it - manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; + manifest_data ??= sync.all(svelte_config, vite_config_env.mode, env).manifest_data; /** @type {Set} */ const entrypoints = new Set(); @@ -975,7 +966,7 @@ async function kit({ svelte_config }) { * @see https://vitejs.dev/guide/api-plugin.html#configureserver */ async configureServer(vite) { - return await dev(vite, vite_config, svelte_config, () => remotes); + return await dev(vite, vite_config, svelte_config, () => remotes, env); }, /** diff --git a/packages/kit/src/exports/vite/types.d.ts b/packages/kit/src/exports/vite/types.d.ts index 900aa43541ea..d72c90ce8cbe 100644 --- a/packages/kit/src/exports/vite/types.d.ts +++ b/packages/kit/src/exports/vite/types.d.ts @@ -1,3 +1,8 @@ export interface EnforcedConfig { [key: string]: EnforcedConfig | true; } + +export interface Env { + public: Record; + private: Record; +} diff --git a/packages/kit/src/exports/vite/utils.js b/packages/kit/src/exports/vite/utils.js index 77743bda77c9..642d1c247f79 100644 --- a/packages/kit/src/exports/vite/utils.js +++ b/packages/kit/src/exports/vite/utils.js @@ -65,6 +65,7 @@ function escape_for_regexp(str) { * Load environment variables from process.env and .env files * @param {import('types').ValidatedKitConfig['env']} env_config * @param {string} mode + * @returns {import('./types.js').Env} */ export function get_env(env_config, mode) { const { publicPrefix: public_prefix, privatePrefix: private_prefix } = env_config; diff --git a/packages/kit/test/apps/basics/test/cross-platform/server.test.js b/packages/kit/test/apps/basics/test/cross-platform/server.test.js index 678a07d575eb..e96d8118927c 100644 --- a/packages/kit/test/apps/basics/test/cross-platform/server.test.js +++ b/packages/kit/test/apps/basics/test/cross-platform/server.test.js @@ -13,3 +13,25 @@ test.describe('Static files', () => { expect(response.status()).toBe(404); }); }); + +test.describe('$env access outside the Vite pipeline', () => { + test('$env/static/public', async () => { + const env = await import('$env/static/public'); + expect(env.PUBLIC_DYNAMIC).toBe('accessible anywhere/evaluated at run time'); + }); + + test('$env/static/private', async () => { + const env = await import('$env/static/private'); + expect(env.PRIVATE_STATIC).toBe('accessible to server-side code/replaced at build time'); + }); + + test('$env/dynamic/public', async () => { + const { env } = await import('$env/dynamic/public'); + expect(env.PUBLIC_DYNAMIC).toBe('accessible anywhere/evaluated at run time'); + }); + + test('$env/dynamic/private', async () => { + const { env } = await import('$env/dynamic/private'); + expect(env.PRIVATE_DYNAMIC).toBe('accessible to server-side code/evaluated at run time'); + }); +}); From aa668d09d75335eab20cc87f1bb28d5a79d1abe6 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 19:06:10 +0800 Subject: [PATCH 02/18] fix unit test --- packages/kit/src/core/sync/write_tsconfig.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index fbd780d74bdd..68c67423dd65 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -21,6 +21,7 @@ test('Creates tsconfig path aliases from kit.alias', () => { // check in the implementation expect(compilerOptions.paths).toEqual({ '$app/types': ['./types/index.d.ts'], + '$env/*': ['./env/*'], simpleKey: ['../simple/value'], 'simpleKey/*': ['../simple/value/*'], key: ['../value'], From 929dc49fbd6233f2f752ad18adb2e2552fb0e12f Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 19:09:08 +0800 Subject: [PATCH 03/18] adjust comment --- packages/kit/src/exports/vite/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index c6c80390e2b9..dd50d268184a 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -450,7 +450,7 @@ async function kit({ svelte_config }) { const browser = !options?.ssr; - // treat $env/static/[public|private] as virtual + // treat $env/dynamic/[public|private] as virtual if ( (id.startsWith('$env/dynamic') && vite_config_env.command !== 'serve') || (id === '$env/dynamic/public' && browser) || From e8e98a570c82db9db34aa48cbb32db1beea003ce Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 19:20:37 +0800 Subject: [PATCH 04/18] we still need to load them because we exclude $env during build --- packages/kit/src/core/sync/write_env.js | 20 ++++++++++++++++---- packages/kit/src/core/sync/write_tsconfig.js | 3 ++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js index a107a00d9ca4..05de9ae8fe65 100644 --- a/packages/kit/src/core/sync/write_env.js +++ b/packages/kit/src/core/sync/write_env.js @@ -9,14 +9,26 @@ import { create_dynamic_module, create_static_module } from '../env.js'; */ export function write_env(config, env) { const env_static_private = create_static_module('$env/static/private', env.private); - write_if_changed(path.join(config.outDir, 'env', 'static', 'private.js'), env_static_private); + write_if_changed( + path.join(config.outDir, 'generated', 'env', 'static', 'private.js'), + env_static_private + ); const env_static_public = create_static_module('$env/static/public', env.public); - write_if_changed(path.join(config.outDir, 'env', 'static', 'public.js'), env_static_public); + write_if_changed( + path.join(config.outDir, 'generated', 'env', 'static', 'public.js'), + env_static_public + ); const env_dynamic_private = create_dynamic_module('private', env.private); - write_if_changed(path.join(config.outDir, 'env', 'dynamic', 'private.js'), env_dynamic_private); + write_if_changed( + path.join(config.outDir, 'generated', 'env', 'dynamic', 'private.js'), + env_dynamic_private + ); const env_dynamic_public = create_dynamic_module('public', env.public); - write_if_changed(path.join(config.outDir, 'env', 'dynamic', 'public.js'), env_dynamic_public); + write_if_changed( + path.join(config.outDir, 'generated', 'env', 'dynamic', 'public.js'), + env_dynamic_public + ); } diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index fd0754aa1127..19dba18f264f 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -100,7 +100,8 @@ export function get_tsconfig(kit) { // generated options paths: { ...get_tsconfig_paths(kit), - '$env/*': ['./env/*'], + // This allows files outside the Vite pipeline to access $env + '$env/*': ['./generated/env/*'], '$app/types': ['./types/index.d.ts'] }, rootDirs: [config_relative('.'), './types'], From 71e9325f771404dfdf886878430a788483ffe958 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 19:21:25 +0800 Subject: [PATCH 05/18] forgot this --- packages/kit/src/exports/vite/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index dd50d268184a..db51871796b6 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -460,6 +460,10 @@ async function kit({ svelte_config }) { return `\0virtual:${id.substring(1)}`; } + if (id.startsWith('$env/')) { + return `${kit.outDir}/generated/${id.slice(1)}.js`; + } + if (id === '__sveltekit/remote') { return `${runtime_directory}/client/remote-functions/index.js`; } From d74b806e2266f1f3aa7ace44aeefad628d6b63de Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Wed, 4 Feb 2026 19:24:03 +0800 Subject: [PATCH 06/18] come onnnn --- packages/kit/src/core/sync/write_tsconfig.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index 68c67423dd65..768d904de28e 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -21,7 +21,7 @@ test('Creates tsconfig path aliases from kit.alias', () => { // check in the implementation expect(compilerOptions.paths).toEqual({ '$app/types': ['./types/index.d.ts'], - '$env/*': ['./env/*'], + '$env/*': ['./generated/env/*'], simpleKey: ['../simple/value'], 'simpleKey/*': ['../simple/value/*'], key: ['../value'], From 0f17dc807a4633438b7328b6068062a264296628 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 02:40:45 +0800 Subject: [PATCH 07/18] fix tsconfig test --- packages/kit/src/core/sync/write_tsconfig.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index 768d904de28e..f7c817bcdddd 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -90,6 +90,9 @@ test('Creates tsconfig include from kit.files', () => { '../src/**/*.js', '../src/**/*.ts', '../src/**/*.svelte', + '../test/**/*.js', + '../test/**/*.ts', + '../test/**/*.svelte', '../tests/**/*.js', '../tests/**/*.ts', '../tests/**/*.svelte' From fff122fe479f91d675283243ca58ff7c390c4843 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 02:40:56 +0800 Subject: [PATCH 08/18] standardise module ids --- packages/kit/src/exports/vite/index.js | 32 ++++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index db51871796b6..fe75d91ce5c4 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -32,6 +32,8 @@ import { dedent, isSvelte5Plus } from '../../core/sync/utils.js'; import { env_dynamic_private, env_dynamic_public, + env_static_private, + env_static_public, service_worker, sveltekit_environment, sveltekit_server @@ -421,7 +423,7 @@ async function kit({ svelte_config }) { const plugin_virtual_modules = { name: 'vite-plugin-sveltekit-virtual-modules', - resolveId(id, importer, options) { + resolveId(id, importer) { if (id === '__sveltekit/manifest') { return `${kit.outDir}/generated/client-optimized/app.js`; } @@ -448,22 +450,12 @@ async function kit({ svelte_config }) { } } - const browser = !options?.ssr; - - // treat $env/dynamic/[public|private] as virtual - if ( - (id.startsWith('$env/dynamic') && vite_config_env.command !== 'serve') || - (id === '$env/dynamic/public' && browser) || - id === '$service-worker' - ) { + // treat $env/static/[public|private] as virtual + if (id.startsWith('$env/') || id === '$service-worker') { // ids with :$ don't work with reverse proxies like nginx return `\0virtual:${id.substring(1)}`; } - if (id.startsWith('$env/')) { - return `${kit.outDir}/generated/${id.slice(1)}.js`; - } - if (id === '__sveltekit/remote') { return `${runtime_directory}/client/remote-functions/index.js`; } @@ -481,15 +473,25 @@ async function kit({ svelte_config }) { : 'globalThis.__sveltekit_dev'; switch (id) { + case env_static_private: + return read(`${kit.outDir}/generated/env/static/private.js`); + + case env_static_public: + return read(`${kit.outDir}/generated/env/static/public.js`); + case env_dynamic_private: - return create_dynamic_module('private', undefined); + return vite_config_env.command === 'serve' + ? read(`${kit.outDir}/generated/env/dynamic/private.js`) + : create_dynamic_module('private', undefined); case env_dynamic_public: // populate `$env/dynamic/public` from `window` if (browser) { return `export const env = ${global}.env;`; } - return create_dynamic_module('public', undefined); + return vite_config_env.command === 'serve' + ? read(`${kit.outDir}/generated/env/dynamic/public.js`) + : create_dynamic_module('public', undefined); case service_worker: return create_service_worker_module(svelte_config); From a4c855cffcfd9ed84529cb6c97b602c42e9e4b60 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 03:07:46 +0800 Subject: [PATCH 09/18] don't serialise dynamic env values --- packages/kit/src/core/env.js | 32 ++++++++++++++++++------- packages/kit/src/core/sync/sync.js | 2 +- packages/kit/src/core/sync/write_env.js | 7 +++--- packages/kit/src/exports/vite/index.js | 4 ++-- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/kit/src/core/env.js b/packages/kit/src/core/env.js index 455eb0f44b68..76c1968afb28 100644 --- a/packages/kit/src/core/env.js +++ b/packages/kit/src/core/env.js @@ -1,6 +1,7 @@ import { GENERATED_COMMENT } from '../constants.js'; +import { s } from '../utils/misc.js'; import { dedent } from './sync/utils.js'; -import { runtime_base } from './utils.js'; +import { runtime_base, runtime_directory } from './utils.js'; /** * @typedef {'public' | 'private'} EnvType @@ -30,15 +31,30 @@ export function create_static_module(id, env) { } /** + * @overload * @param {EnvType} type - * @param {Record | undefined} dev_values If in a development mode, values to pre-populate the module with. + * @returns {string} + */ +/** + * @overload + * @param {EnvType} type + * @param {string} mode + * @param {import('types').ValidatedKitConfig['env']} env_config + * @returns {string} */ -export function create_dynamic_module(type, dev_values) { - if (dev_values) { - const keys = Object.entries(dev_values).map( - ([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}` - ); - return `export const env = {\n${keys.join(',\n')}\n}`; +/** + * @param {EnvType} type + * @param {string} [mode] + * @param {import('types').ValidatedKitConfig['env']} [env_config] + * @returns {string} + */ +export function create_dynamic_module(type, mode, env_config) { + if (mode && env_config) { + return dedent` + import { get_env } from '${runtime_directory}/../exports/vite/utils.js'; + + export const env = get_env(${s(env_config)}, ${s(mode)}).${type}; + `; } return `export { ${type}_env as env } from '${runtime_base}/shared-server.js';`; } diff --git a/packages/kit/src/core/sync/sync.js b/packages/kit/src/core/sync/sync.js index 1d86642abc92..1daba664038e 100644 --- a/packages/kit/src/core/sync/sync.js +++ b/packages/kit/src/core/sync/sync.js @@ -17,7 +17,7 @@ import { get_env } from '../../exports/vite/utils.js'; * @param {import('../../exports/vite/types.js').Env} env */ export function init(config, mode, env) { - write_env(config.kit, env); + write_env(config.kit, mode, env); write_tsconfig(config.kit); write_ambient(config.kit, mode); } diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js index 05de9ae8fe65..05abb0bd25b3 100644 --- a/packages/kit/src/core/sync/write_env.js +++ b/packages/kit/src/core/sync/write_env.js @@ -5,9 +5,10 @@ import { create_dynamic_module, create_static_module } from '../env.js'; /** * Writes env variable modules to the output directory * @param {import('types').ValidatedKitConfig} config + * @param {string} mode * @param {import('../../exports/vite/types.js').Env} env */ -export function write_env(config, env) { +export function write_env(config, mode, env) { const env_static_private = create_static_module('$env/static/private', env.private); write_if_changed( path.join(config.outDir, 'generated', 'env', 'static', 'private.js'), @@ -20,13 +21,13 @@ export function write_env(config, env) { env_static_public ); - const env_dynamic_private = create_dynamic_module('private', env.private); + const env_dynamic_private = create_dynamic_module('private', mode, config.env); write_if_changed( path.join(config.outDir, 'generated', 'env', 'dynamic', 'private.js'), env_dynamic_private ); - const env_dynamic_public = create_dynamic_module('public', env.public); + const env_dynamic_public = create_dynamic_module('public', mode, config.env); write_if_changed( path.join(config.outDir, 'generated', 'env', 'dynamic', 'public.js'), env_dynamic_public diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index fe75d91ce5c4..b2fde59f9d18 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -482,7 +482,7 @@ async function kit({ svelte_config }) { case env_dynamic_private: return vite_config_env.command === 'serve' ? read(`${kit.outDir}/generated/env/dynamic/private.js`) - : create_dynamic_module('private', undefined); + : create_dynamic_module('private'); case env_dynamic_public: // populate `$env/dynamic/public` from `window` @@ -491,7 +491,7 @@ async function kit({ svelte_config }) { } return vite_config_env.command === 'serve' ? read(`${kit.outDir}/generated/env/dynamic/public.js`) - : create_dynamic_module('public', undefined); + : create_dynamic_module('public'); case service_worker: return create_service_worker_module(svelte_config); From 9273c077802a6ad080ccd63c32934d503d71cc4e Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 03:25:26 +0800 Subject: [PATCH 10/18] virtual modules still useful! --- packages/kit/src/core/env.js | 31 +++++--------------- packages/kit/src/core/sync/write_env.js | 27 +++++++++++++++-- packages/kit/src/core/sync/write_tsconfig.js | 12 ++++---- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/packages/kit/src/core/env.js b/packages/kit/src/core/env.js index 76c1968afb28..0638d25f8072 100644 --- a/packages/kit/src/core/env.js +++ b/packages/kit/src/core/env.js @@ -1,7 +1,6 @@ import { GENERATED_COMMENT } from '../constants.js'; -import { s } from '../utils/misc.js'; import { dedent } from './sync/utils.js'; -import { runtime_base, runtime_directory } from './utils.js'; +import { runtime_base } from './utils.js'; /** * @typedef {'public' | 'private'} EnvType @@ -31,30 +30,16 @@ export function create_static_module(id, env) { } /** - * @overload * @param {EnvType} type + * @param {Record | undefined} dev_values If in a development mode, values to pre-populate the module with. * @returns {string} */ -/** - * @overload - * @param {EnvType} type - * @param {string} mode - * @param {import('types').ValidatedKitConfig['env']} env_config - * @returns {string} - */ -/** - * @param {EnvType} type - * @param {string} [mode] - * @param {import('types').ValidatedKitConfig['env']} [env_config] - * @returns {string} - */ -export function create_dynamic_module(type, mode, env_config) { - if (mode && env_config) { - return dedent` - import { get_env } from '${runtime_directory}/../exports/vite/utils.js'; - - export const env = get_env(${s(env_config)}, ${s(mode)}).${type}; - `; +export function create_dynamic_module(type, dev_values) { + if (dev_values) { + const keys = Object.entries(dev_values).map( + ([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}` + ); + return `export const env = {\n${keys.join(',\n')}\n}`; } return `export { ${type}_env as env } from '${runtime_base}/shared-server.js';`; } diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js index 05abb0bd25b3..a228726c5f0b 100644 --- a/packages/kit/src/core/sync/write_env.js +++ b/packages/kit/src/core/sync/write_env.js @@ -1,6 +1,28 @@ import path from 'node:path'; -import { write_if_changed } from './utils.js'; -import { create_dynamic_module, create_static_module } from '../env.js'; +import { dedent, write_if_changed } from './utils.js'; +import { create_static_module } from '../env.js'; +import { runtime_directory } from '../utils.js'; +import { s } from '../../utils/misc.js'; + +/** + * This version deviates from the one in env.js because we don't want to + * serialise the user's dynamic environment variables. Instead, it loads the + * environment variables directly. This is okay because it will only be used by + * modules importing $env/dynamic/* from outside the Vite pipeline. Those inside + * the Vite pipeline will load the virtual module which reuses the already loaded + * environment variables. + * @param {import('../env.js').EnvType} type + * @param {string} mode + * @param {import('types').ValidatedKitConfig['env']} env_config + * @returns {string} + */ +function create_dynamic_module(type, mode, env_config) { + return dedent` + import { get_env } from '${runtime_directory}/../exports/vite/utils.js'; + + export const env = get_env(${s(env_config)}, ${s(mode)}).${type}; + `; +} /** * Writes env variable modules to the output directory @@ -22,6 +44,7 @@ export function write_env(config, mode, env) { ); const env_dynamic_private = create_dynamic_module('private', mode, config.env); + write_if_changed( path.join(config.outDir, 'generated', 'env', 'dynamic', 'private.js'), env_dynamic_private diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index 19dba18f264f..ed02cae86e6c 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -62,10 +62,8 @@ export function get_tsconfig(kit) { config_relative('vite.config.js'), config_relative('vite.config.ts') ]); - // TODO(v2): find a better way to include all src files. We can't just use routes/lib only because - // people might have other folders/files in src that they want included. - const src_includes = [kit.files.routes, kit.files.lib, path.resolve('src')].filter((dir) => { - const relative = path.relative(path.resolve('src'), dir); + const src_includes = [kit.files.routes, kit.files.lib, kit.files.src].filter((dir) => { + const relative = path.relative(kit.files.src, dir); return !relative || relative.startsWith('..'); }); for (const dir of src_includes) { @@ -76,10 +74,14 @@ export function get_tsconfig(kit) { // Test folder is a special case - we advocate putting tests in a top-level test folder // and it's not configurable (should we make it?) - const test_folder = project_relative('tests'); + const test_folder = project_relative('test'); include.add(config_relative(`${test_folder}/**/*.js`)); include.add(config_relative(`${test_folder}/**/*.ts`)); include.add(config_relative(`${test_folder}/**/*.svelte`)); + const tests_folder = project_relative('tests'); + include.add(config_relative(`${tests_folder}/**/*.js`)); + include.add(config_relative(`${tests_folder}/**/*.ts`)); + include.add(config_relative(`${tests_folder}/**/*.svelte`)); const exclude = [config_relative('node_modules/**')]; // Add service worker to exclude list so that worker types references in it don't spill over into the rest of the app From 4773cf8f2f09946122cbe2b007da549df4478a4b Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 03:30:40 +0800 Subject: [PATCH 11/18] revert --- packages/kit/src/core/sync/write_tsconfig.js | 10 ++++------ packages/kit/src/core/sync/write_tsconfig.spec.js | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index ed02cae86e6c..a62635a35b9c 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -62,8 +62,10 @@ export function get_tsconfig(kit) { config_relative('vite.config.js'), config_relative('vite.config.ts') ]); - const src_includes = [kit.files.routes, kit.files.lib, kit.files.src].filter((dir) => { - const relative = path.relative(kit.files.src, dir); + // TODO(v2): find a better way to include all src files. We can't just use routes/lib only because + // people might have other folders/files in src that they want included. + const src_includes = [kit.files.routes, kit.files.lib, path.resolve('src')].filter((dir) => { + const relative = path.relative(path.resolve('src'), dir); return !relative || relative.startsWith('..'); }); for (const dir of src_includes) { @@ -74,10 +76,6 @@ export function get_tsconfig(kit) { // Test folder is a special case - we advocate putting tests in a top-level test folder // and it's not configurable (should we make it?) - const test_folder = project_relative('test'); - include.add(config_relative(`${test_folder}/**/*.js`)); - include.add(config_relative(`${test_folder}/**/*.ts`)); - include.add(config_relative(`${test_folder}/**/*.svelte`)); const tests_folder = project_relative('tests'); include.add(config_relative(`${tests_folder}/**/*.js`)); include.add(config_relative(`${tests_folder}/**/*.ts`)); diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index f7c817bcdddd..768d904de28e 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -90,9 +90,6 @@ test('Creates tsconfig include from kit.files', () => { '../src/**/*.js', '../src/**/*.ts', '../src/**/*.svelte', - '../test/**/*.js', - '../test/**/*.ts', - '../test/**/*.svelte', '../tests/**/*.js', '../tests/**/*.ts', '../tests/**/*.svelte' From 3513d44e9fa1b7cb1ff26e44a82817df5d73af7f Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 03:34:21 +0800 Subject: [PATCH 12/18] changeset --- .changeset/proud-socks-smash.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/proud-socks-smash.md diff --git a/.changeset/proud-socks-smash.md b/.changeset/proud-socks-smash.md new file mode 100644 index 000000000000..42b301bded91 --- /dev/null +++ b/.changeset/proud-socks-smash.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: `$env/*` modules can now be imported from Playwright and other code running without Vite From 64b3cfd381151d570c8a0adcdf26e88925e9d4eb Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 03:44:10 +0800 Subject: [PATCH 13/18] forgot to save --- packages/kit/src/exports/vite/index.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index b2fde59f9d18..3a46fcca6211 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -480,18 +480,21 @@ async function kit({ svelte_config }) { return read(`${kit.outDir}/generated/env/static/public.js`); case env_dynamic_private: - return vite_config_env.command === 'serve' - ? read(`${kit.outDir}/generated/env/dynamic/private.js`) - : create_dynamic_module('private'); + return create_dynamic_module( + 'private', + vite_config_env.command === 'serve' ? env.private : undefined + ); case env_dynamic_public: // populate `$env/dynamic/public` from `window` if (browser) { return `export const env = ${global}.env;`; } - return vite_config_env.command === 'serve' - ? read(`${kit.outDir}/generated/env/dynamic/public.js`) - : create_dynamic_module('public'); + + return create_dynamic_module( + 'public', + vite_config_env.command === 'serve' ? env.public : undefined + ); case service_worker: return create_service_worker_module(svelte_config); From efa1e8cf46037f6332da5f5fc8b0926d6b5bddbe Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 04:28:47 +0800 Subject: [PATCH 14/18] separate get_env to avoid type errors --- packages/kit/src/core/adapt/builder.js | 2 +- packages/kit/src/core/sync/sync.js | 2 +- packages/kit/src/core/sync/write_ambient.js | 2 +- packages/kit/src/core/sync/write_env.js | 2 +- .../exports/vite/build/build_service_worker.js | 3 ++- packages/kit/src/exports/vite/env.js | 18 ++++++++++++++++++ packages/kit/src/exports/vite/index.js | 2 +- 7 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 packages/kit/src/exports/vite/env.js diff --git a/packages/kit/src/core/adapt/builder.js b/packages/kit/src/core/adapt/builder.js index 20124e43e334..d956c3866fc5 100644 --- a/packages/kit/src/core/adapt/builder.js +++ b/packages/kit/src/core/adapt/builder.js @@ -11,7 +11,7 @@ import zlib from 'node:zlib'; import { copy, rimraf, mkdirp, posixify } from '../../utils/filesystem.js'; import { generate_manifest } from '../generate_manifest/index.js'; import { get_route_segments } from '../../utils/routing.js'; -import { get_env } from '../../exports/vite/utils.js'; +import { get_env } from '../../exports/vite/env.js'; import generate_fallback from '../postbuild/fallback.js'; import { write } from '../sync/utils.js'; import { list_files } from '../utils.js'; diff --git a/packages/kit/src/core/sync/sync.js b/packages/kit/src/core/sync/sync.js index 1daba664038e..b6cffdc63dc2 100644 --- a/packages/kit/src/core/sync/sync.js +++ b/packages/kit/src/core/sync/sync.js @@ -8,7 +8,7 @@ import { write_ambient } from './write_ambient.js'; import { write_non_ambient } from './write_non_ambient.js'; import { write_server } from './write_server.js'; import { write_env } from './write_env.js'; -import { get_env } from '../../exports/vite/utils.js'; +import { get_env } from '../../exports/vite/env.js'; /** * Initialize SvelteKit's generated files that only depend on the config and mode. diff --git a/packages/kit/src/core/sync/write_ambient.js b/packages/kit/src/core/sync/write_ambient.js index 1f2188097ade..e02d3c21db6d 100644 --- a/packages/kit/src/core/sync/write_ambient.js +++ b/packages/kit/src/core/sync/write_ambient.js @@ -1,7 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; -import { get_env } from '../../exports/vite/utils.js'; +import { get_env } from '../../exports/vite/env.js'; import { GENERATED_COMMENT } from '../../constants.js'; import { create_dynamic_types, create_static_types } from '../env.js'; import { write_if_changed } from './utils.js'; diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js index a228726c5f0b..efff88f4bf6f 100644 --- a/packages/kit/src/core/sync/write_env.js +++ b/packages/kit/src/core/sync/write_env.js @@ -18,7 +18,7 @@ import { s } from '../../utils/misc.js'; */ function create_dynamic_module(type, mode, env_config) { return dedent` - import { get_env } from '${runtime_directory}/../exports/vite/utils.js'; + import { get_env } from '${runtime_directory}/../exports/vite/env.js'; export const env = get_env(${s(env_config)}, ${s(mode)}).${type}; `; diff --git a/packages/kit/src/exports/vite/build/build_service_worker.js b/packages/kit/src/exports/vite/build/build_service_worker.js index a90c62dd1a4a..6f5a5fa84f18 100644 --- a/packages/kit/src/exports/vite/build/build_service_worker.js +++ b/packages/kit/src/exports/vite/build/build_service_worker.js @@ -2,7 +2,8 @@ import fs from 'node:fs'; import * as vite from 'vite'; import { dedent } from '../../../core/sync/utils.js'; import { s } from '../../../utils/misc.js'; -import { get_config_aliases, strip_virtual_prefix, get_env, normalize_id } from '../utils.js'; +import { get_config_aliases, strip_virtual_prefix, normalize_id } from '../utils.js'; +import { get_env } from '../env.js'; import { create_static_module } from '../../../core/env.js'; import { env_static_public, service_worker } from '../module_ids.js'; diff --git a/packages/kit/src/exports/vite/env.js b/packages/kit/src/exports/vite/env.js new file mode 100644 index 000000000000..7f80fa30f96a --- /dev/null +++ b/packages/kit/src/exports/vite/env.js @@ -0,0 +1,18 @@ +import { loadEnv } from 'vite'; +import { filter_env } from '../../utils/env.js'; + +/** + * Load environment variables from process.env and .env files + * @param {import('types').ValidatedKitConfig['env']} env_config + * @param {string} mode + * @returns {import('./types.js').Env} + */ +export function get_env(env_config, mode) { + const { publicPrefix: public_prefix, privatePrefix: private_prefix } = env_config; + const env = loadEnv(mode, env_config.dir, ''); + + return { + public: filter_env(env, public_prefix, private_prefix), + private: filter_env(env, private_prefix, public_prefix) + }; +} diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 3a46fcca6211..5baa0ee568c6 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -19,7 +19,6 @@ import { preview } from './preview/index.js'; import { error_for_missing_config, get_config_aliases, - get_env, normalize_id, stackless } from './utils.js'; @@ -41,6 +40,7 @@ import { import { import_peer } from '../../utils/import.js'; import { compact } from '../../utils/array.js'; import { should_ignore } from './static_analysis/utils.js'; +import { get_env } from './env.js'; const cwd = posixify(process.cwd()); From be7912820f4b131d88b39ac48225dea6640c0af3 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 04:30:14 +0800 Subject: [PATCH 15/18] oops --- packages/kit/src/exports/vite/utils.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/kit/src/exports/vite/utils.js b/packages/kit/src/exports/vite/utils.js index 642d1c247f79..0b4ec5249e93 100644 --- a/packages/kit/src/exports/vite/utils.js +++ b/packages/kit/src/exports/vite/utils.js @@ -1,8 +1,6 @@ import path from 'node:path'; -import { loadEnv } from 'vite'; import { posixify } from '../../utils/filesystem.js'; import { negotiate } from '../../utils/http.js'; -import { filter_env } from '../../utils/env.js'; import { escape_html } from '../../utils/escape.js'; import { dedent } from '../../core/sync/utils.js'; import { @@ -61,22 +59,6 @@ function escape_for_regexp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, (match) => '\\' + match); } -/** - * Load environment variables from process.env and .env files - * @param {import('types').ValidatedKitConfig['env']} env_config - * @param {string} mode - * @returns {import('./types.js').Env} - */ -export function get_env(env_config, mode) { - const { publicPrefix: public_prefix, privatePrefix: private_prefix } = env_config; - const env = loadEnv(mode, env_config.dir, ''); - - return { - public: filter_env(env, public_prefix, private_prefix), - private: filter_env(env, private_prefix, public_prefix) - }; -} - /** * @param {import('http').IncomingMessage} req * @param {import('http').ServerResponse} res From 25a3b37d4e39f0d83ab08a549c6b1487d4c7b966 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 04:46:43 +0800 Subject: [PATCH 16/18] format --- packages/kit/src/exports/vite/index.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 5baa0ee568c6..7f3145897a80 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -16,12 +16,7 @@ import { build_service_worker } from './build/build_service_worker.js'; import { assets_base, find_deps, resolve_symlinks } from './build/utils.js'; import { dev } from './dev/index.js'; import { preview } from './preview/index.js'; -import { - error_for_missing_config, - get_config_aliases, - normalize_id, - stackless -} from './utils.js'; +import { error_for_missing_config, get_config_aliases, normalize_id, stackless } from './utils.js'; import { write_client_manifest } from '../../core/sync/write_client_manifest.js'; import prerender from '../../core/postbuild/prerender.js'; import analyse from '../../core/postbuild/analyse.js'; From e217ad47bb4ffc72896e9030c98363157df4d57f Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 05:18:12 +0800 Subject: [PATCH 17/18] avoid internal types --- packages/kit/src/exports/vite/env.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/env.js b/packages/kit/src/exports/vite/env.js index 7f80fa30f96a..6c359d06e478 100644 --- a/packages/kit/src/exports/vite/env.js +++ b/packages/kit/src/exports/vite/env.js @@ -3,7 +3,7 @@ import { filter_env } from '../../utils/env.js'; /** * Load environment variables from process.env and .env files - * @param {import('types').ValidatedKitConfig['env']} env_config + * @param {{ dir: string; publicPrefix: string; privatePrefix: string }} env_config * @param {string} mode * @returns {import('./types.js').Env} */ From 9cc1ebeef2238eb748d1aa2057856786ab2a4345 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 5 Feb 2026 18:07:22 +0800 Subject: [PATCH 18/18] load dynamic env once --- packages/kit/src/core/sync/write_env.js | 21 ++++++++++++------- packages/kit/src/core/sync/write_tsconfig.js | 5 ++++- .../kit/src/core/sync/write_tsconfig.spec.js | 5 ++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/kit/src/core/sync/write_env.js b/packages/kit/src/core/sync/write_env.js index efff88f4bf6f..3cebbd354786 100644 --- a/packages/kit/src/core/sync/write_env.js +++ b/packages/kit/src/core/sync/write_env.js @@ -12,15 +12,13 @@ import { s } from '../../utils/misc.js'; * the Vite pipeline will load the virtual module which reuses the already loaded * environment variables. * @param {import('../env.js').EnvType} type - * @param {string} mode - * @param {import('types').ValidatedKitConfig['env']} env_config * @returns {string} */ -function create_dynamic_module(type, mode, env_config) { +function create_dynamic_module(type) { return dedent` - import { get_env } from '${runtime_directory}/../exports/vite/env.js'; + import { env as full_env } from './internal.js'; - export const env = get_env(${s(env_config)}, ${s(mode)}).${type}; + export const env = full_env.${type}; `; } @@ -43,14 +41,23 @@ export function write_env(config, mode, env) { env_static_public ); - const env_dynamic_private = create_dynamic_module('private', mode, config.env); + const env_dynamic = dedent` + import { get_env } from '${runtime_directory}/../exports/vite/env.js'; + + export const env = get_env(${s(config.env)}, ${s(mode)}); + `; + write_if_changed( + path.join(config.outDir, 'generated', 'env', 'dynamic', 'internal.js'), + env_dynamic + ); + const env_dynamic_private = create_dynamic_module('private'); write_if_changed( path.join(config.outDir, 'generated', 'env', 'dynamic', 'private.js'), env_dynamic_private ); - const env_dynamic_public = create_dynamic_module('public', mode, config.env); + const env_dynamic_public = create_dynamic_module('public'); write_if_changed( path.join(config.outDir, 'generated', 'env', 'dynamic', 'public.js'), env_dynamic_public diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index a62635a35b9c..e5727257acbb 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -101,7 +101,10 @@ export function get_tsconfig(kit) { paths: { ...get_tsconfig_paths(kit), // This allows files outside the Vite pipeline to access $env - '$env/*': ['./generated/env/*'], + '$env/static/private': ['./generated/env/static/private.js'], + '$env/static/public': ['./generated/env/static/public.js'], + '$env/dynamic/private': ['./generated/env/dynamic/private.js'], + '$env/dynamic/public': ['./generated/env/dynamic/public.js'], '$app/types': ['./types/index.d.ts'] }, rootDirs: [config_relative('.'), './types'], diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index 768d904de28e..22d700615306 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -21,7 +21,10 @@ test('Creates tsconfig path aliases from kit.alias', () => { // check in the implementation expect(compilerOptions.paths).toEqual({ '$app/types': ['./types/index.d.ts'], - '$env/*': ['./generated/env/*'], + '$env/static/private': ['./generated/env/static/private.js'], + '$env/static/public': ['./generated/env/static/public.js'], + '$env/dynamic/private': ['./generated/env/dynamic/private.js'], + '$env/dynamic/public': ['./generated/env/dynamic/public.js'], simpleKey: ['../simple/value'], 'simpleKey/*': ['../simple/value/*'], key: ['../value'],