@sveltejs/kit 2.61.1 → 2.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/package.json +14 -3
  2. package/src/cli.js +32 -6
  3. package/src/core/adapt/builder.js +31 -5
  4. package/src/core/adapt/index.js +5 -2
  5. package/src/core/config/index.js +100 -36
  6. package/src/core/config/options.js +1 -0
  7. package/src/core/env.js +313 -8
  8. package/src/core/postbuild/analyse.js +2 -1
  9. package/src/core/postbuild/fallback.js +7 -8
  10. package/src/core/postbuild/prerender.js +6 -2
  11. package/src/core/sync/sync.js +16 -0
  12. package/src/core/sync/write_ambient.js +12 -6
  13. package/src/core/sync/write_env.js +32 -0
  14. package/src/core/sync/write_root.js +1 -1
  15. package/src/core/sync/write_server.js +3 -2
  16. package/src/core/sync/write_tsconfig.js +1 -0
  17. package/src/exports/hooks/index.js +13 -0
  18. package/src/exports/internal/env.js +71 -0
  19. package/src/exports/internal/types.d.ts +3 -0
  20. package/src/exports/node/index.js +2 -10
  21. package/src/exports/public.d.ts +41 -1
  22. package/src/exports/vite/build/build_service_worker.js +20 -4
  23. package/src/exports/vite/dev/index.js +2 -2
  24. package/src/exports/vite/index.js +157 -33
  25. package/src/exports/vite/module_ids.js +10 -1
  26. package/src/exports/vite/utils.js +6 -0
  27. package/src/runtime/app/env/index.js +2 -0
  28. package/src/runtime/app/env/internal.js +11 -0
  29. package/src/runtime/app/env/private.js +1 -0
  30. package/src/runtime/app/env/public/client.js +7 -0
  31. package/src/runtime/app/env/public/index.js +1 -0
  32. package/src/runtime/app/env/public/server.js +7 -0
  33. package/src/runtime/app/env/standard-schema.d.ts +0 -0
  34. package/src/runtime/app/env/types.d.ts +19 -0
  35. package/src/runtime/app/environment/index.js +10 -2
  36. package/src/runtime/app/server/remote/query.js +1 -1
  37. package/src/runtime/app/state/client.js +10 -6
  38. package/src/runtime/client/client.js +68 -51
  39. package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
  40. package/src/runtime/client/utils.js +1 -1
  41. package/src/runtime/server/env_module.js +13 -3
  42. package/src/runtime/server/fetch.js +12 -14
  43. package/src/runtime/server/index.js +2 -0
  44. package/src/runtime/server/page/render.js +11 -3
  45. package/src/runtime/server/respond.js +8 -11
  46. package/src/types/ambient-private.d.ts +25 -9
  47. package/src/types/global-private.d.ts +2 -0
  48. package/src/types/internal.d.ts +1 -0
  49. package/src/utils/http.js +21 -0
  50. package/src/utils/import.js +2 -2
  51. package/src/version.js +1 -1
  52. package/types/index.d.ts +76 -4
  53. package/types/index.d.ts.map +7 -1
@@ -1,8 +1,8 @@
1
1
  import { createReadStream } from 'node:fs';
2
2
  import { Readable } from 'node:stream';
3
- import * as set_cookie_parser from 'set-cookie-parser';
4
3
  import { SvelteKitError } from '../internal/index.js';
5
4
  import { noop } from '../../utils/functions.js';
5
+ import { get_set_cookies } from '../../utils/http.js';
6
6
 
7
7
  /**
8
8
  * @param {import('http').IncomingMessage} req
@@ -169,15 +169,7 @@ export async function getRequest({ request, base, bodySizeLimit }) {
169
169
  export async function setResponse(res, response) {
170
170
  for (const [key, value] of response.headers) {
171
171
  try {
172
- res.setHeader(
173
- key,
174
- key === 'set-cookie'
175
- ? set_cookie_parser.splitCookiesString(
176
- // This is absurd but necessary, TODO: investigate why
177
- /** @type {string}*/ (response.headers.get(key))
178
- )
179
- : value
180
- );
172
+ res.setHeader(key, key === 'set-cookie' ? get_set_cookies(response.headers) : value);
181
173
  } catch (error) {
182
174
  res.getHeaderNames().forEach((name) => res.removeHeader(name));
183
175
  res.writeHead(500).end(String(error));
@@ -141,7 +141,7 @@ export interface Builder {
141
141
  generateFallback: (dest: string) => Promise<void>;
142
142
 
143
143
  /**
144
- * Generate a module exposing build-time environment variables as `$env/dynamic/public`.
144
+ * Generate a module exposing build-time environment variables as `$env/dynamic/public` if the app uses it.
145
145
  */
146
146
  generateEnvModule: () => void;
147
147
 
@@ -476,6 +476,13 @@ export interface KitConfig {
476
476
  };
477
477
  /** Experimental features. Here be dragons. These are not subject to semantic versioning, so breaking changes or removal can happen in any release. */
478
478
  experimental?: {
479
+ /**
480
+ * Whether to enable explicit environment variables using `src/env.js` or `src/env.ts`.
481
+ * @since 2.62.0
482
+ * @default false
483
+ */
484
+ explicitEnvironmentVariables?: boolean;
485
+
479
486
  /**
480
487
  * Options for enabling server-side [OpenTelemetry](https://opentelemetry.io/) tracing for SvelteKit operations including the [`handle` hook](https://svelte.dev/docs/kit/hooks#Server-hooks-handle), [`load` functions](https://svelte.dev/docs/kit/load), [form actions](https://svelte.dev/docs/kit/form-actions), and [remote functions](https://svelte.dev/docs/kit/remote-functions).
481
488
  * @default { server: false, serverFile: false }
@@ -2314,4 +2321,37 @@ export type RemoteLiveQueryFunction<Input, Output, _Validated = Input> = (
2314
2321
  arg: undefined extends Input ? Input | void : Input
2315
2322
  ) => RemoteLiveQuery<Output>;
2316
2323
 
2324
+ /**
2325
+ * [Environment variables](https://svelte.dev/docs/kit/environment-variables) can be configured by exporting
2326
+ * a `variables` object from `src/env.ts`, using [`defineEnvVars`](https://svelte.dev/docs/kit/@sveltejs-kit-hooks#defineEnvVars).
2327
+ */
2328
+ export interface EnvVarConfig<T> {
2329
+ /**
2330
+ * Whether the environment variable can be accessed by client-side code.
2331
+ * - if `true`, it can be imported from `$app/env/public`
2332
+ * - if `false`, it can be imported from `$app/env/private`, which is a [server-only module](https://svelte.dev/docs/kit/server-only-modules)
2333
+ * @default false
2334
+ */
2335
+ public?: boolean;
2336
+ /**
2337
+ * Whether the value is determined at build time or when the app runs.
2338
+ * - if `true`, the build time value is inlined into the bundle. This enables optimisations like dead-code elimination
2339
+ * - if `false`, the value is read from the environment when the app starts
2340
+ * @default false
2341
+ */
2342
+ static?: boolean;
2343
+ /**
2344
+ * A [Standard Schema](https://standardschema.dev/) validator that is applied to the value when the app starts.
2345
+ * The validator can output any value — not necessarily a string — but public, non-static values must be
2346
+ * serializable by [devalue](https://github.com/sveltejs/devalue) so that they can be sent to the browser.
2347
+ *
2348
+ * If omitted, the value must be a non-empty string.
2349
+ */
2350
+ schema?: StandardSchemaV1<string | undefined, T>;
2351
+ /**
2352
+ * A description of the variable that will be used for inline documentation on hover.
2353
+ */
2354
+ description?: string;
2355
+ }
2356
+
2317
2357
  export * from './index.js';
@@ -1,10 +1,11 @@
1
+ /** @import { EnvVarConfig } from '@sveltejs/kit' */
1
2
  import fs from 'node:fs';
2
3
  import process from 'node:process';
3
4
  import * as vite from 'vite';
4
5
  import { dedent } from '../../../core/sync/utils.js';
5
6
  import { s } from '../../../utils/misc.js';
6
7
  import { get_config_aliases, strip_virtual_prefix, get_env, normalize_id } from '../utils.js';
7
- import { create_static_module } from '../../../core/env.js';
8
+ import { create_static_module, create_sveltekit_env_public } from '../../../core/env.js';
8
9
  import { env_static_public, service_worker } from '../module_ids.js';
9
10
 
10
11
  // @ts-ignore `vite.rolldownVersion` only exists in `rolldown-vite`
@@ -18,6 +19,7 @@ const is_rolldown = !!vite.rolldownVersion;
18
19
  * @param {string} service_worker_entry_file
19
20
  * @param {import('types').Prerendered} prerendered
20
21
  * @param {import('vite').Manifest} client_manifest
22
+ * @param {Record<string, EnvVarConfig<any>> | null} env_config
21
23
  */
22
24
  export async function build_service_worker(
23
25
  out,
@@ -26,7 +28,8 @@ export async function build_service_worker(
26
28
  manifest_data,
27
29
  service_worker_entry_file,
28
30
  prerendered,
29
- client_manifest
31
+ client_manifest,
32
+ env_config
30
33
  ) {
31
34
  const build = new Set();
32
35
  for (const key in client_manifest) {
@@ -85,7 +88,20 @@ export async function build_service_worker(
85
88
  }
86
89
 
87
90
  if (id === env_static_public) {
88
- return create_static_module('$env/static/public', env.public);
91
+ return create_static_module(
92
+ '$env/static/public',
93
+ env.public,
94
+ kit.experimental.explicitEnvironmentVariables
95
+ );
96
+ }
97
+
98
+ if (id === '\0virtual:app/env/public') {
99
+ // TODO ideally we would only add the `importScripts` if there are dynamic vars that are known to be used
100
+ return create_sveltekit_env_public(
101
+ env_config,
102
+ env.all,
103
+ `importScripts('${kit.paths.base}/${kit.appDir}/env.script.js'); const env = globalThis.__sveltekit_sw.env;`
104
+ );
89
105
  }
90
106
 
91
107
  const normalized_cwd = vite.normalizePath(process.cwd());
@@ -93,7 +109,7 @@ export async function build_service_worker(
93
109
  const relative = normalize_id(id, normalized_lib, normalized_cwd);
94
110
  const stripped = strip_virtual_prefix(relative);
95
111
  throw new Error(
96
- `Cannot import ${stripped} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
112
+ `Cannot import ${stripped} into service-worker code. Only the modules $service-worker, $env/static/public and $app/env/public are available in service workers.`
97
113
  );
98
114
  }
99
115
  };
@@ -322,7 +322,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
322
322
  // ssrFixStacktrace can fail on StackBlitz web containers and we don't know why
323
323
  // by ignoring it the line numbers are wrong, but at least we can show the error
324
324
  }
325
- return error.stack;
325
+ return error.stack?.replaceAll('\0', ''); // remove null bytes from e.g. virtual module IDs, or the response will fail
326
326
  }
327
327
 
328
328
  update_manifest();
@@ -587,7 +587,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
587
587
  } catch (e) {
588
588
  const error = coalesce_to_error(e);
589
589
  res.statusCode = 500;
590
- res.end(fix_stack_trace(error));
590
+ res.end(fix_stack_trace(error) || error.message); // handle `stackless` errors
591
591
  }
592
592
  });
593
593
  };
@@ -1,18 +1,28 @@
1
- /** @import { Options } from '@sveltejs/vite-plugin-svelte' */
1
+ /** @import { EnvVarConfig } from '@sveltejs/kit' */
2
+ /** @import { Options, SvelteConfig } from '@sveltejs/vite-plugin-svelte' */
2
3
  /** @import { PreprocessorGroup } from 'svelte/compiler' */
4
+ /** @import { KitConfig } from '@sveltejs/kit' */
3
5
  /** @import { ConfigEnv, Manifest, Plugin, ResolvedConfig, UserConfig, ViteDevServer } from 'vite' */
6
+ /** @import { ValidatedConfig } from 'types' */
4
7
  import fs from 'node:fs';
5
8
  import path from 'node:path';
6
9
  import process from 'node:process';
7
-
8
10
  import colors from 'kleur';
9
11
 
10
12
  import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js';
11
- import { create_static_module, create_dynamic_module } from '../../core/env.js';
13
+ import {
14
+ create_dynamic_module,
15
+ create_sveltekit_env,
16
+ create_sveltekit_env_public,
17
+ create_static_module,
18
+ resolve_explicit_env_entry,
19
+ create_sveltekit_env_service_worker_dev,
20
+ create_sveltekit_env_private
21
+ } from '../../core/env.js';
12
22
  import * as sync from '../../core/sync/sync.js';
13
23
  import { create_assets } from '../../core/sync/create_manifest_data/index.js';
14
24
  import { runtime_directory, logger } from '../../core/utils.js';
15
- import { load_config } from '../../core/config/index.js';
25
+ import { load_svelte_config, process_config } from '../../core/config/index.js';
16
26
  import { generate_manifest } from '../../core/generate_manifest/index.js';
17
27
  import { build_server_nodes } from './build/build_server.js';
18
28
  import { build_service_worker } from './build/build_service_worker.js';
@@ -38,8 +48,12 @@ import {
38
48
  env_static_private,
39
49
  env_static_public,
40
50
  service_worker,
41
- sveltekit_environment,
42
- sveltekit_server
51
+ sveltekit_env,
52
+ sveltekit_env_private,
53
+ sveltekit_env_service_worker,
54
+ sveltekit_server,
55
+ sveltekit_env_public_client,
56
+ sveltekit_env_public_server
43
57
  } from './module_ids.js';
44
58
  import { import_peer } from '../../utils/import.js';
45
59
  import { compact } from '../../utils/array.js';
@@ -133,10 +147,31 @@ const warning_preprocessor = {
133
147
 
134
148
  /**
135
149
  * Returns the SvelteKit Vite plugins.
150
+ * Since version 2.62.0 you can pass [configuration](configuration) directly, in which case `svelte.config.js` is ignored.
151
+ * @param {KitConfig & Omit<SvelteConfig, 'onwarn'>} [config]
136
152
  * @returns {Promise<Plugin[]>}
137
153
  */
138
- export async function sveltekit() {
139
- const svelte_config = await load_config();
154
+ export async function sveltekit(config) {
155
+ /** @type {ValidatedConfig} */
156
+ let svelte_config;
157
+
158
+ if (config !== undefined) {
159
+ const { extensions, compilerOptions, vitePlugin, preprocess, ...kit } = config;
160
+ svelte_config = process_config(
161
+ { extensions, compilerOptions, vitePlugin, preprocess, kit },
162
+ { cwd, source: 'SvelteKit options from Vite config' }
163
+ );
164
+
165
+ const config_file = ['svelte.config.js', 'svelte.config.ts'].find((file) =>
166
+ fs.existsSync(file)
167
+ );
168
+
169
+ if (config_file) {
170
+ console.warn(`${config_file} is ignored when options are passed via your Vite config`);
171
+ }
172
+ } else {
173
+ svelte_config = await load_svelte_config();
174
+ }
140
175
 
141
176
  /** @type {Options['preprocess']} */
142
177
  let preprocess = svelte_config.preprocess;
@@ -214,7 +249,7 @@ async function kit({ svelte_config }) {
214
249
  /** @type {boolean} */
215
250
  let is_build;
216
251
 
217
- /** @type {{ public: Record<string, string>; private: Record<string, string> }} */
252
+ /** @type {{ all: Record<string, string>; public: Record<string, string>; private: Record<string, string> }} */
218
253
  let env;
219
254
 
220
255
  /** @type {() => Promise<void>} */
@@ -243,6 +278,9 @@ async function kit({ svelte_config }) {
243
278
  /** @type {Plugin} */
244
279
  const plugin_setup = {
245
280
  name: 'vite-plugin-sveltekit-setup',
281
+ api: {
282
+ options: svelte_config
283
+ },
246
284
 
247
285
  /**
248
286
  * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
@@ -324,7 +362,7 @@ async function kit({ svelte_config }) {
324
362
  // because they for example use esbuild.build with `platform: 'browser'`
325
363
  'esm-env',
326
364
  // This forces `$app/*` modules to be bundled, since they depend on
327
- // virtual modules like `__sveltekit/environment` (this isn't a valid bare
365
+ // virtual modules like `__sveltekit/env` (this isn't a valid bare
328
366
  // import, but it works with vite-node's externalization logic, which
329
367
  // uses basic concatenation)
330
368
  '@sveltejs/kit/src/runtime'
@@ -368,6 +406,7 @@ async function kit({ svelte_config }) {
368
406
 
369
407
  const define = {
370
408
  __SVELTEKIT_APP_DIR__: s(kit.appDir),
409
+ __SVELTEKIT_APP_VERSION__: s(kit.version.name),
371
410
  __SVELTEKIT_EMBEDDED__: s(kit.embedded),
372
411
  __SVELTEKIT_FORK_PRELOADS__: s(kit.experimental.forkPreloads),
373
412
  __SVELTEKIT_PATHS_ASSETS__: s(kit.paths.assets),
@@ -377,6 +416,9 @@ async function kit({ svelte_config }) {
377
416
  __SVELTEKIT_HASH_ROUTING__: s(kit.router.type === 'hash'),
378
417
  __SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.experimental.tracing.server),
379
418
  __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__: s(kit.experimental.handleRenderingErrors),
419
+ __SVELTEKIT_EXPERIMENTAL_EXPLICIT_ENVIRONMENT_VARIABLES__: s(
420
+ kit.experimental.explicitEnvironmentVariables
421
+ ),
380
422
  __SVELTEKIT_DEV__: s(!is_build)
381
423
  };
382
424
 
@@ -445,10 +487,50 @@ async function kit({ svelte_config }) {
445
487
  }
446
488
  };
447
489
 
490
+ /** @type {string | null} */
491
+ let explicit_env_entry = null;
492
+
493
+ /** @type {Record<string, EnvVarConfig<any>> | null} */
494
+ let explicit_env_config = null;
495
+
448
496
  /** @type {Plugin} */
449
497
  const plugin_virtual_modules = {
450
498
  name: 'vite-plugin-sveltekit-virtual-modules',
451
499
 
500
+ async configResolved(config) {
501
+ explicit_env_entry = resolve_explicit_env_entry(kit);
502
+ explicit_env_config = await sync.env(kit, explicit_env_entry, config.mode);
503
+ },
504
+
505
+ configureServer(server) {
506
+ if (!kit.experimental.explicitEnvironmentVariables) {
507
+ return;
508
+ }
509
+
510
+ server.watcher.on('all', async (_, file) => {
511
+ if (!file.includes('env')) {
512
+ return;
513
+ }
514
+
515
+ const resolved = resolve_explicit_env_entry(kit);
516
+
517
+ if (file === explicit_env_entry || file === resolved) {
518
+ explicit_env_entry = resolved;
519
+ explicit_env_config = await sync.env(kit, explicit_env_entry, vite_config_env.mode);
520
+
521
+ for (const id of [sveltekit_env, sveltekit_env_public_client]) {
522
+ const module = server.moduleGraph.getModuleById(id);
523
+
524
+ if (module) {
525
+ server.moduleGraph.invalidateModule(module);
526
+ }
527
+ }
528
+
529
+ server.ws.send({ type: 'full-reload' });
530
+ }
531
+ });
532
+ },
533
+
452
534
  resolveId(id, importer) {
453
535
  if (id === '__sveltekit/manifest') {
454
536
  return `${out_dir}/generated/client-optimized/app.js`;
@@ -458,6 +540,7 @@ async function kit({ svelte_config }) {
458
540
  // This check won't catch transitive imports, but it will warn when the import comes from a service-worker directly.
459
541
  // Transitive imports will be caught during the build.
460
542
  // TODO move this logic to plugin_guard
543
+ // TODO allow $app/env/public
461
544
  if (importer) {
462
545
  const parsed_importer = path.parse(importer);
463
546
 
@@ -465,13 +548,19 @@ async function kit({ svelte_config }) {
465
548
  parsed_importer.dir === parsed_service_worker.dir &&
466
549
  parsed_importer.name === parsed_service_worker.name;
467
550
 
468
- if (importer_is_service_worker && id !== '$service-worker' && id !== '$env/static/public') {
551
+ if (
552
+ importer_is_service_worker &&
553
+ id !== '$service-worker' &&
554
+ id !== '$env/static/public' &&
555
+ id !== 'virtual:$app/env/public' &&
556
+ id !== '__sveltekit/env/service-worker'
557
+ ) {
469
558
  throw new Error(
470
559
  `Cannot import ${normalize_id(
471
560
  id,
472
561
  normalized_lib,
473
562
  normalized_cwd
474
- )} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
563
+ )} into service-worker code. Only the modules $service-worker, $env/static/public and $app/env/public are available in service workers.`
475
564
  );
476
565
  }
477
566
  }
@@ -498,17 +587,20 @@ async function kit({ svelte_config }) {
498
587
  ? `globalThis.__sveltekit_${version_hash}`
499
588
  : 'globalThis.__sveltekit_dev';
500
589
 
590
+ const explicit_env_flag = kit.experimental.explicitEnvironmentVariables;
591
+
501
592
  switch (id) {
502
593
  case env_static_private:
503
- return create_static_module('$env/static/private', env.private);
594
+ return create_static_module('$env/static/private', env.private, explicit_env_flag);
504
595
 
505
596
  case env_static_public:
506
- return create_static_module('$env/static/public', env.public);
597
+ return create_static_module('$env/static/public', env.public, explicit_env_flag);
507
598
 
508
599
  case env_dynamic_private:
509
600
  return create_dynamic_module(
510
601
  'private',
511
- vite_config_env.command === 'serve' ? env.private : undefined
602
+ vite_config_env.command === 'serve' ? env.private : undefined,
603
+ explicit_env_flag
512
604
  );
513
605
 
514
606
  case env_dynamic_public:
@@ -519,29 +611,35 @@ async function kit({ svelte_config }) {
519
611
 
520
612
  return create_dynamic_module(
521
613
  'public',
522
- vite_config_env.command === 'serve' ? env.public : undefined
614
+ vite_config_env.command === 'serve' ? env.public : undefined,
615
+ explicit_env_flag
523
616
  );
524
617
 
525
618
  case service_worker:
526
619
  return create_service_worker_module(svelte_config);
527
620
 
528
- case sveltekit_environment: {
529
- const { version } = svelte_config.kit;
621
+ case sveltekit_env:
622
+ return create_sveltekit_env(explicit_env_config, env.all, explicit_env_entry);
530
623
 
531
- return dedent`
532
- export const version = ${s(version.name)};
533
- export let building = false;
534
- export let prerendering = false;
624
+ case sveltekit_env_public_client:
625
+ return create_sveltekit_env_public(
626
+ explicit_env_config,
627
+ env.all,
628
+ `const env = ${global}.env;`
629
+ );
535
630
 
536
- export function set_building() {
537
- building = true;
538
- }
631
+ case sveltekit_env_public_server:
632
+ return create_sveltekit_env_public(
633
+ explicit_env_config,
634
+ env.all,
635
+ `import { rendered_env as env } from '__sveltekit/env';`
636
+ );
539
637
 
540
- export function set_prerendering() {
541
- prerendering = true;
542
- }
543
- `;
544
- }
638
+ case sveltekit_env_private:
639
+ return create_sveltekit_env_private(explicit_env_config, env.all);
640
+
641
+ case sveltekit_env_service_worker:
642
+ return create_sveltekit_env_service_worker_dev(explicit_env_config, env.all, global);
545
643
 
546
644
  case sveltekit_server: {
547
645
  return dedent`
@@ -568,7 +666,7 @@ async function kit({ svelte_config }) {
568
666
 
569
667
  /**
570
668
  * Ensures that client-side code can't accidentally import server-side code,
571
- * whether in `*.server.js` files, `$app/server`, `$lib/server`, or `$env/[static|dynamic]/private`
669
+ * whether in `*.server.js` files, `$app/server`, `$lib/server`, `$app/env/private`, or `$env/[static|dynamic]/private`
572
670
  * @type {Plugin}
573
671
  */
574
672
  const plugin_guard = {
@@ -610,6 +708,7 @@ async function kit({ svelte_config }) {
610
708
  const is_server_only =
611
709
  normalized === '$env/static/private' ||
612
710
  normalized === '$env/dynamic/private' ||
711
+ normalized === '$app/env/private' ||
613
712
  normalized === '$app/server' ||
614
713
  normalized.startsWith('$lib/server/') ||
615
714
  (is_internal && server_only_pattern.test(path.basename(id)));
@@ -817,6 +916,26 @@ async function kit({ svelte_config }) {
817
916
  }
818
917
  };
819
918
 
919
+ /** @type {Plugin} */
920
+ const plugin_service_worker_env = {
921
+ name: 'vite-plugin-sveltekit-service-worker-env',
922
+
923
+ transform: {
924
+ filter: {
925
+ id: service_worker_entry_file || '<skip>'
926
+ },
927
+ handler(code) {
928
+ // in dev, we prepend the service worker with an import that
929
+ // configures `env`, in case `$app/env/public` is imported,
930
+ // in prod, where we currently use non-module service
931
+ // workers, we have to use `importScripts` instead
932
+ return {
933
+ code: `import '__sveltekit/env/service-worker';\n${code}`
934
+ };
935
+ }
936
+ }
937
+ };
938
+
820
939
  /** @type {Plugin} */
821
940
  const plugin_compile = {
822
941
  name: 'vite-plugin-sveltekit-compile',
@@ -1365,7 +1484,8 @@ async function kit({ svelte_config }) {
1365
1484
  manifest_data,
1366
1485
  service_worker_entry_file,
1367
1486
  prerendered,
1368
- client_manifest
1487
+ client_manifest,
1488
+ explicit_env_config
1369
1489
  );
1370
1490
  }
1371
1491
 
@@ -1388,7 +1508,8 @@ async function kit({ svelte_config }) {
1388
1508
  prerender_map,
1389
1509
  log,
1390
1510
  remotes,
1391
- vite_config
1511
+ vite_config,
1512
+ explicit_env_config
1392
1513
  );
1393
1514
  } else {
1394
1515
  console.log(colors.bold().yellow('\nNo adapter specified'));
@@ -1421,6 +1542,9 @@ async function kit({ svelte_config }) {
1421
1542
  kit.experimental.remoteFunctions && plugin_remote,
1422
1543
  plugin_virtual_modules,
1423
1544
  plugin_guard,
1545
+ kit.experimental.explicitEnvironmentVariables &&
1546
+ service_worker_entry_file &&
1547
+ plugin_service_worker_env,
1424
1548
  plugin_compile
1425
1549
  ].filter((p) => !!p);
1426
1550
  }
@@ -6,11 +6,20 @@ export const env_static_public = '\0virtual:env/static/public';
6
6
  export const env_dynamic_private = '\0virtual:env/dynamic/private';
7
7
  export const env_dynamic_public = '\0virtual:env/dynamic/public';
8
8
 
9
+ export const sveltekit_env = '\0virtual:__sveltekit/env';
10
+ export const sveltekit_env_public_client = '\0virtual:__sveltekit/env/public/client';
11
+ export const sveltekit_env_public_server = '\0virtual:__sveltekit/env/public/server';
12
+ export const sveltekit_env_private = '\0virtual:__sveltekit/env/private';
13
+ export const sveltekit_env_service_worker = '\0virtual:__sveltekit/env/service-worker';
14
+
9
15
  export const service_worker = '\0virtual:service-worker';
10
16
 
11
- export const sveltekit_environment = '\0virtual:__sveltekit/environment';
12
17
  export const sveltekit_server = '\0virtual:__sveltekit/server';
13
18
 
14
19
  export const app_server = posixify(
15
20
  fileURLToPath(new URL('../../runtime/app/server/index.js', import.meta.url))
16
21
  );
22
+
23
+ export const app_env_private = posixify(
24
+ fileURLToPath(new URL('../../runtime/app/env/private.js', import.meta.url))
25
+ );
@@ -7,6 +7,7 @@ import { escape_html } from '../../utils/escape.js';
7
7
  import { dedent } from '../../core/sync/utils.js';
8
8
  import {
9
9
  app_server,
10
+ app_env_private,
10
11
  env_dynamic_private,
11
12
  env_dynamic_public,
12
13
  env_static_private,
@@ -71,6 +72,7 @@ export function get_env(env_config, mode) {
71
72
  const env = loadEnv(mode, env_config.dir, '');
72
73
 
73
74
  return {
75
+ all: env,
74
76
  public: filter_env(env, public_prefix, private_prefix),
75
77
  private: filter_env(env, private_prefix, public_prefix)
76
78
  };
@@ -155,6 +157,10 @@ export function normalize_id(id, lib, cwd) {
155
157
  return '$app/server';
156
158
  }
157
159
 
160
+ if (id === app_env_private) {
161
+ return '$app/env/private';
162
+ }
163
+
158
164
  if (id === env_static_private) {
159
165
  return '$env/static/private';
160
166
  }
@@ -0,0 +1,2 @@
1
+ export { BROWSER as browser, DEV as dev } from 'esm-env';
2
+ export { building, version } from './internal.js';
@@ -0,0 +1,11 @@
1
+ export const version = __SVELTEKIT_APP_VERSION__;
2
+ export let building = false;
3
+ export let prerendering = false;
4
+
5
+ export function set_building() {
6
+ building = true;
7
+ }
8
+
9
+ export function set_prerendering() {
10
+ prerendering = true;
11
+ }
@@ -0,0 +1 @@
1
+ export * from '__sveltekit/env/private';
@@ -0,0 +1,7 @@
1
+ export * from '__sveltekit/env/public/client';
2
+
3
+ if (!__SVELTEKIT_EXPERIMENTAL_EXPLICIT_ENVIRONMENT_VARIABLES__) {
4
+ throw new Error(
5
+ 'Cannot import `$app/env/public` unless `experimental.explicitEnvironmentVariables` is enabled'
6
+ );
7
+ }
@@ -0,0 +1 @@
1
+ export * from '#app/env/public';
@@ -0,0 +1,7 @@
1
+ export * from '__sveltekit/env/public/server';
2
+
3
+ if (!__SVELTEKIT_EXPERIMENTAL_EXPLICIT_ENVIRONMENT_VARIABLES__) {
4
+ throw new Error(
5
+ 'Cannot import `$app/env/public` unless `experimental.explicitEnvironmentVariables` is enabled'
6
+ );
7
+ }
File without changes
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `true` if the app is running in the browser.
3
+ */
4
+ export const browser: boolean;
5
+
6
+ /**
7
+ * Whether the dev server is running. This is not guaranteed to correspond to `NODE_ENV` or `MODE`.
8
+ */
9
+ export const dev: boolean;
10
+
11
+ /**
12
+ * SvelteKit analyses your app during the `build` step by running it. During this process, `building` is `true`. This also applies during prerendering.
13
+ */
14
+ export const building: boolean;
15
+
16
+ /**
17
+ * The value of `config.kit.version.name`.
18
+ */
19
+ export const version: string;
@@ -1,2 +1,10 @@
1
- export { BROWSER as browser, DEV as dev } from 'esm-env';
2
- export { building, version } from '__sveltekit/environment';
1
+ export * from '../env/index.js';
2
+
3
+ if (__SVELTEKIT_EXPERIMENTAL_EXPLICIT_ENVIRONMENT_VARIABLES__) {
4
+ throw new Error(
5
+ 'Cannot import `$app/environment` when `experimental.explicitEnvironmentVariables` is enabled. Use `$app/env` instead.'
6
+ );
7
+ }
8
+
9
+ // force the Vite client to load, so that defines are definitely defined
10
+ import.meta.hot;
@@ -3,7 +3,7 @@
3
3
  /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
4
4
  import { get_request_store } from '@sveltejs/kit/internal/server';
5
5
  import { create_remote_key, stringify, stringify_remote_arg } from '../../../shared.js';
6
- import { prerendering } from '__sveltekit/environment';
6
+ import { prerendering } from '$app/env/internal';
7
7
  import {
8
8
  create_validator,
9
9
  get_cache,