@sveltejs/kit 3.0.0-next.6 → 3.0.0-next.7

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 (64) hide show
  1. package/package.json +7 -2
  2. package/src/core/adapt/builder.js +11 -39
  3. package/src/core/config/index.js +76 -71
  4. package/src/core/config/options.js +280 -285
  5. package/src/core/config/types.d.ts +1 -1
  6. package/src/core/env.js +85 -1
  7. package/src/core/generate_manifest/index.js +12 -15
  8. package/src/core/sync/create_manifest_data/index.js +6 -44
  9. package/src/core/sync/write_client_manifest.js +7 -14
  10. package/src/core/sync/write_non_ambient.js +10 -7
  11. package/src/core/sync/write_root.js +9 -30
  12. package/src/core/sync/write_server.js +0 -1
  13. package/src/core/sync/write_types/index.js +11 -10
  14. package/src/exports/index.js +3 -3
  15. package/src/exports/internal/client.js +5 -0
  16. package/src/exports/internal/index.js +1 -91
  17. package/src/exports/internal/{event.js → server/event.js} +1 -2
  18. package/src/exports/internal/server/index.js +33 -0
  19. package/src/exports/internal/shared.js +89 -0
  20. package/src/exports/node/index.js +1 -1
  21. package/src/exports/params.js +63 -0
  22. package/src/exports/public.d.ts +82 -32
  23. package/src/exports/url.js +84 -0
  24. package/src/exports/vite/dev/index.js +28 -17
  25. package/src/exports/vite/index.js +217 -156
  26. package/src/exports/vite/preview/index.js +1 -1
  27. package/src/exports/vite/utils.js +3 -5
  28. package/src/runtime/app/paths/client.js +3 -7
  29. package/src/runtime/app/paths/server.js +1 -1
  30. package/src/runtime/app/server/remote/query.js +6 -12
  31. package/src/runtime/app/state/client.js +1 -2
  32. package/src/runtime/app/stores.js +13 -76
  33. package/src/runtime/client/client.js +26 -79
  34. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  35. package/src/runtime/client/remote-functions/form.svelte.js +5 -24
  36. package/src/runtime/client/remote-functions/prerender.svelte.js +10 -3
  37. package/src/runtime/client/remote-functions/query/instance.svelte.js +18 -9
  38. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +16 -6
  39. package/src/runtime/client/remote-functions/shared.svelte.js +1 -2
  40. package/src/runtime/client/state.svelte.js +66 -49
  41. package/src/runtime/client/types.d.ts +1 -1
  42. package/src/runtime/client/utils.js +0 -96
  43. package/src/runtime/form-utils.js +15 -2
  44. package/src/runtime/server/index.js +1 -1
  45. package/src/runtime/server/page/load_data.js +1 -1
  46. package/src/runtime/server/page/render.js +15 -24
  47. package/src/runtime/server/page/server_routing.js +13 -9
  48. package/src/runtime/server/remote.js +21 -12
  49. package/src/runtime/server/respond.js +11 -8
  50. package/src/runtime/telemetry/otel.js +1 -1
  51. package/src/types/ambient.d.ts +5 -1
  52. package/src/types/global-private.d.ts +1 -1
  53. package/src/types/internal.d.ts +9 -10
  54. package/src/utils/error.js +1 -1
  55. package/src/utils/mime.js +9 -0
  56. package/src/utils/params.js +66 -0
  57. package/src/utils/routing.js +84 -38
  58. package/src/utils/streaming.js +14 -4
  59. package/src/utils/url.js +0 -79
  60. package/src/version.js +1 -1
  61. package/types/index.d.ts +98 -87
  62. package/types/index.d.ts.map +10 -7
  63. package/src/exports/internal/server.js +0 -22
  64. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
@@ -17,10 +17,12 @@ import {
17
17
  resolve_explicit_env_entry,
18
18
  create_sveltekit_env_service_worker,
19
19
  create_sveltekit_env_service_worker_dev,
20
- create_sveltekit_env_private
20
+ create_sveltekit_env_private,
21
+ create_exported_declarations
21
22
  } from '../../core/env.js';
22
23
  import * as sync from '../../core/sync/sync.js';
23
24
  import { create_assets } from '../../core/sync/create_manifest_data/index.js';
25
+ import { load_and_validate_params } from '../../utils/params.js';
24
26
  import { runtime_directory, logger } from '../../core/utils.js';
25
27
  import { generate_manifest } from '../../core/generate_manifest/index.js';
26
28
  import { build_server_nodes } from './build/build_server.js';
@@ -54,10 +56,13 @@ import {
54
56
  import { import_peer } from '../../utils/import.js';
55
57
  import { compact } from '../../utils/array.js';
56
58
  import { should_ignore, has_children } from './static_analysis/utils.js';
57
- import { process_config, split_config } from '../../core/config/index.js';
59
+ import { process_config, split_config, validate_config } from '../../core/config/index.js';
58
60
  import { treeshake_prerendered_remotes } from './build/remote.js';
59
61
 
60
- /** @type {string} */
62
+ /**
63
+ * Populated after Vite plugins' `config` hooks run
64
+ * @type {string}
65
+ */
61
66
  let root;
62
67
 
63
68
  /** @type {import('./types.js').EnforcedConfig} */
@@ -162,7 +167,7 @@ export async function sveltekit(config) {
162
167
  // any options passed to the plugin that SvelteKit doesn't use itself are
163
168
  // forwarded to vite-plugin-svelte, which does its own validation
164
169
  const split = split_config(config ?? {});
165
- const svelte_config = process_config(split.svelte_config, { cwd });
170
+ const svelte_config = validate_config(split.svelte_config);
166
171
 
167
172
  if (Array.isArray(svelte_config.preprocess)) {
168
173
  svelte_config.preprocess.push(warning_preprocessor);
@@ -197,7 +202,7 @@ export async function sveltekit(config) {
197
202
  }
198
203
 
199
204
  return [
200
- plugin_svelte_config(),
205
+ plugin_root(),
201
206
  ...vite_plugin_svelte.svelte(inline_vps_config),
202
207
  ...kit({
203
208
  svelte_config
@@ -213,7 +218,7 @@ function resolve_root(vite_config) {
213
218
  /**
214
219
  * @return {Plugin}
215
220
  */
216
- function plugin_svelte_config() {
221
+ function plugin_root() {
217
222
  return {
218
223
  name: 'vite-plugin-sveltekit-resolve-svelte-config',
219
224
  // make sure it runs first
@@ -223,9 +228,8 @@ function plugin_svelte_config() {
223
228
  handler(config) {
224
229
  root = resolve_root(config);
225
230
 
226
- // TODO: mjs mts?
227
231
  const config_file = ['svelte.config.js', 'svelte.config.ts'].find((file) =>
228
- fs.existsSync(`${root}/${file}`)
232
+ fs.existsSync(path.join(root, file))
229
233
  );
230
234
  if (config_file) {
231
235
  throw new Error(
@@ -255,7 +259,7 @@ function plugin_svelte_config() {
255
259
  * - https://rolldown.rs/apis/plugin-api#output-generation-hooks
256
260
  *
257
261
  * @param {object} opts
258
- * @param {import('types').ValidatedConfig} opts.svelte_config options are only resolved after the Vite `config` hook runs
262
+ * @param {import('types').ValidatedConfig} opts.svelte_config
259
263
  * @return {Plugin[]}
260
264
  */
261
265
  function kit({ svelte_config }) {
@@ -291,7 +295,7 @@ function kit({ svelte_config }) {
291
295
  let initial_config;
292
296
 
293
297
  /** @type {string | null} */
294
- let service_worker_entry_file = resolve_entry(svelte_config.kit.files.serviceWorker);
298
+ let service_worker_entry_file;
295
299
  /** @type {import('node:path').ParsedPath} */
296
300
  let parsed_service_worker;
297
301
 
@@ -321,10 +325,6 @@ function kit({ svelte_config }) {
321
325
  options: svelte_config
322
326
  },
323
327
 
324
- applyToEnvironment(environment) {
325
- return environment.name !== 'serviceWorker';
326
- },
327
-
328
328
  /**
329
329
  * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
330
330
  * @see https://vitejs.dev/guide/api-plugin.html#config
@@ -335,7 +335,7 @@ function kit({ svelte_config }) {
335
335
  initial_config = config;
336
336
  is_build = config_env.command === 'build';
337
337
 
338
- ({ kit } = svelte_config);
338
+ ({ kit } = process_config(svelte_config, root));
339
339
  out_dir = posixify(kit.outDir);
340
340
  out = `${out_dir}/output`;
341
341
 
@@ -466,7 +466,7 @@ function kit({ svelte_config }) {
466
466
  __SVELTEKIT_PATHS_RELATIVE__: s(kit.paths.relative),
467
467
  __SVELTEKIT_CLIENT_ROUTING__: s(kit.router.resolution === 'client'),
468
468
  __SVELTEKIT_HASH_ROUTING__: s(kit.router.type === 'hash'),
469
- __SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.experimental.tracing.server),
469
+ __SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.tracing.server),
470
470
  __SVELTEKIT_EXPERIMENTAL_USE_TRANSFORM_ERROR__: s(kit.experimental.handleRenderingErrors),
471
471
  __SVELTEKIT_ROOT__: s(root),
472
472
  __SVELTEKIT_DEV__: s(!is_build)
@@ -495,6 +495,23 @@ function kit({ svelte_config }) {
495
495
  /** @type {NonNullable<UserConfig['ssr']>} */ (new_config.ssr).external = ['cookie'];
496
496
  }
497
497
 
498
+ // Vite's `define` is a compile-time text replacement, but Vitest strips
499
+ // user `define` from the server config and reinstalls the values only as
500
+ // `globalThis` properties inside test workers, so anything
501
+ // that runs outside of a test will freak out over
502
+ // them not being defined
503
+ if (process.env.VITEST === 'true') {
504
+ for (const key in new_config.define) {
505
+ const value = new_config.define[key];
506
+ try {
507
+ /** @type {Record<string, any>} */ (globalThis)[key] = JSON.parse(value);
508
+ } catch {
509
+ // `kit_global` isn't JSON, so don't try to parse it. We may one day
510
+ // need to define it in Vitest somehow but for now, ignore it
511
+ }
512
+ }
513
+ }
514
+
498
515
  warn_overridden_config(config, new_config);
499
516
 
500
517
  return new_config;
@@ -519,10 +536,6 @@ function kit({ svelte_config }) {
519
536
  const plugin_virtual_modules = {
520
537
  name: 'vite-plugin-sveltekit-virtual-modules',
521
538
 
522
- applyToEnvironment(environment) {
523
- return environment.name !== 'serviceWorker';
524
- },
525
-
526
539
  async configResolved(config) {
527
540
  explicit_env_entry = resolve_explicit_env_entry(kit);
528
541
  explicit_env_config = await sync.env(kit, explicit_env_entry, config.root, config.mode);
@@ -558,6 +571,10 @@ function kit({ svelte_config }) {
558
571
  });
559
572
  },
560
573
 
574
+ applyToEnvironment(environment) {
575
+ return environment.name !== 'serviceWorker';
576
+ },
577
+
561
578
  resolveId: {
562
579
  filter: {
563
580
  id: [exactRegex('$service-worker'), prefixRegex('__sveltekit/')]
@@ -598,7 +615,7 @@ function kit({ svelte_config }) {
598
615
  return create_service_worker_module(svelte_config);
599
616
 
600
617
  case sveltekit_env:
601
- return create_sveltekit_env(explicit_env_config, env, explicit_env_entry);
618
+ return create_sveltekit_env(explicit_env_config, env, explicit_env_entry, !is_build);
602
619
 
603
620
  case sveltekit_env_public_client:
604
621
  return create_sveltekit_env_public(
@@ -741,49 +758,56 @@ function kit({ svelte_config }) {
741
758
  if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client);
742
759
  if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal);
743
760
 
744
- const chain = [normalized];
745
-
746
- let current = normalized;
747
- let includes_remote_file = false;
761
+ // Walk up the import graph from the server-only module, looking for a chain
762
+ // that leads back to a client entrypoint. We search all candidates (not just
763
+ // the first) because a module can be imported by both server and client code,
764
+ // and a greedy first-match could follow a server-only branch that never
765
+ // reaches an entrypoint — see https://github.com/sveltejs/kit/issues/16232
766
+ /** @type {Set<string>} */
767
+ const visited = new Set([normalized]);
748
768
 
749
- while (true) {
769
+ /**
770
+ * @param {string} current
771
+ * @param {string[]} chain
772
+ * @returns {string[] | null}
773
+ */
774
+ function find_chain(current, chain) {
750
775
  const importers = import_map.get(current);
751
- if (!importers) break;
776
+ if (!importers) return null;
752
777
 
753
- const candidates = Array.from(importers).filter((importer) => !chain.includes(importer));
754
- if (candidates.length === 0) break;
778
+ for (const importer of importers) {
779
+ if (visited.has(importer)) continue;
780
+ visited.add(importer);
755
781
 
756
- chain.push((current = candidates[0]));
782
+ const next_chain = [...chain, importer];
783
+ if (entrypoints.has(importer)) {
784
+ return next_chain;
785
+ }
786
+ const result = find_chain(importer, next_chain);
787
+ if (result) return result;
788
+ }
789
+ return null;
790
+ }
757
791
 
758
- includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => {
759
- return current.endsWith(`.remote${ext}`);
760
- });
792
+ const chain = find_chain(normalized, [normalized]);
761
793
 
762
- if (entrypoints.has(current)) {
763
- const pyramid = chain
764
- .reverse()
765
- .map((id, i) => {
766
- return `${' '.repeat(i + 1)}${id}`;
767
- })
768
- .join(' imports\n');
769
-
770
- if (includes_remote_file) {
771
- error_for_missing_config(
772
- 'remote functions',
773
- 'kit.experimental.remoteFunctions',
774
- 'true'
775
- );
776
- }
794
+ if (chain) {
795
+ const pyramid = chain
796
+ .reverse()
797
+ .map((id, i) => {
798
+ return `${' '.repeat(i + 1)}${id}`;
799
+ })
800
+ .join(' imports\n');
777
801
 
778
- let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`;
779
- message += `\n\n${pyramid}`;
780
- message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`;
802
+ let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`;
803
+ message += `\n\n${pyramid}`;
804
+ message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`;
781
805
 
782
- throw stackless(message);
783
- }
806
+ throw stackless(message);
784
807
  }
785
808
 
786
- throw new Error('An impossible situation occurred');
809
+ // No chain from this server-only module to a client entrypoint was found —
810
+ // the module is only imported from server code, which is valid.
787
811
  }
788
812
  }
789
813
  };
@@ -805,7 +829,7 @@ function kit({ svelte_config }) {
805
829
  name: 'vite-plugin-sveltekit-remote',
806
830
 
807
831
  applyToEnvironment(environment) {
808
- return environment.name !== 'serviceWorker';
832
+ return svelte_config.kit.experimental.remoteFunctions && environment.name !== 'serviceWorker';
809
833
  },
810
834
 
811
835
  // prevent other plugins from resolving our remote virtual module
@@ -823,10 +847,6 @@ function kit({ svelte_config }) {
823
847
  id: prefixRegex('\0sveltekit-remote:')
824
848
  },
825
849
  handler(id) {
826
- if (!kit.experimental.remoteFunctions) {
827
- return null;
828
- }
829
-
830
850
  // On-the-fly generated entry point for remote file just forwards the original module
831
851
  // We're not using manualChunks because it can cause problems with circular dependencies
832
852
  // (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general
@@ -839,18 +859,10 @@ function kit({ svelte_config }) {
839
859
  },
840
860
 
841
861
  configureServer(_dev_server) {
842
- if (!kit.experimental.remoteFunctions) {
843
- return;
844
- }
845
-
846
862
  dev_server = _dev_server;
847
863
  },
848
864
 
849
865
  async transform(code, id) {
850
- if (!kit.experimental.remoteFunctions) {
851
- return;
852
- }
853
-
854
866
  const normalized = normalize_id(id, normalized_lib, normalized_cwd);
855
867
  if (!svelte_config.kit.moduleExtensions.some((ext) => normalized.endsWith(`.remote${ext}`))) {
856
868
  return;
@@ -876,7 +888,7 @@ function kit({ svelte_config }) {
876
888
  '\n\n' +
877
889
  dedent`
878
890
  import * as $$_self_$$ from './${path.basename(id)}';
879
- import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal';
891
+ import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal/server';
880
892
 
881
893
  ${dev_server ? 'await Promise.resolve()' : ''}
882
894
 
@@ -934,15 +946,17 @@ function kit({ svelte_config }) {
934
946
  }
935
947
  }
936
948
 
937
- let namespace = '__remote';
938
- let uid = 1;
939
- while (map.has(namespace)) namespace = `__remote${uid++}`;
940
-
941
- const exports = Array.from(map).map(([name, type]) => {
942
- return `export const ${name} = ${namespace}.${type}('${remote.hash}/${name}');`;
943
- });
949
+ const { namespace, declarations, reexports } = create_exported_declarations(
950
+ map.keys(),
951
+ (name, ns) => `${ns}.${map.get(name)}('${remote.hash}/${name}')`,
952
+ '__remote'
953
+ );
944
954
 
945
- let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${exports.join('\n')}\n`;
955
+ let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${declarations.join('\n')}`;
956
+ if (reexports.length > 0) {
957
+ result += `\nexport { ${reexports.join(', ')} };`;
958
+ }
959
+ result += '\n';
946
960
 
947
961
  if (dev_server) {
948
962
  result += `\nimport.meta.hot?.accept();\n`;
@@ -954,6 +968,26 @@ function kit({ svelte_config }) {
954
968
  }
955
969
  };
956
970
 
971
+ /** @type {Plugin} */
972
+ const plugin_remote_guard = {
973
+ name: 'vite-plugin-sveltekit-remote-guard',
974
+
975
+ applyToEnvironment() {
976
+ return !svelte_config.kit.experimental.remoteFunctions;
977
+ },
978
+
979
+ transform: {
980
+ filter: {
981
+ id: new RegExp(
982
+ `.remote(${svelte_config.kit.moduleExtensions.join('|')})$`.replaceAll('.', '\\.')
983
+ )
984
+ },
985
+ handler() {
986
+ error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true');
987
+ }
988
+ }
989
+ };
990
+
957
991
  /** @type {Manifest} */
958
992
  let vite_server_manifest;
959
993
  /** @type {Manifest | null} */
@@ -979,6 +1013,8 @@ function kit({ svelte_config }) {
979
1013
 
980
1014
  if (!service_worker_entry_file) return;
981
1015
 
1016
+ service_worker_entry_file = posixify(service_worker_entry_file);
1017
+
982
1018
  if (kit.paths.assets) {
983
1019
  throw new Error('Cannot use service worker alongside config.paths.assets');
984
1020
  }
@@ -1022,8 +1058,8 @@ function kit({ svelte_config }) {
1022
1058
  return new_config;
1023
1059
  },
1024
1060
 
1025
- // the serviceWorker environment only applies during build because Vite currently
1026
- // only supports the default client environment during development
1061
+ // our serviceWorker environment only exists when building because Vite only
1062
+ // supports the default client environment during development (for now)
1027
1063
  applyToEnvironment(environment) {
1028
1064
  return environment.name === 'serviceWorker';
1029
1065
  },
@@ -1156,32 +1192,30 @@ function kit({ svelte_config }) {
1156
1192
  /** @type {Plugin} */
1157
1193
  const plugin_service_worker_env = {
1158
1194
  name: 'vite-plugin-sveltekit-service-worker-env',
1159
-
1160
- transform: {
1161
- filter: {
1162
- id: service_worker_entry_file || '<skip>'
1163
- },
1164
- handler(code) {
1165
- // prepend the service worker with an import that configures
1166
- // `env`, in case `$app/env/public` is imported. In production
1167
- // this is required: dynamic public env vars aren't known at
1168
- // build time, so `env.js` is loaded at runtime. In dev, the
1169
- // imported module just inlines the current values instead.
1170
- return {
1171
- code: `import '__sveltekit/env/service-worker';\n${code}`
1172
- };
1173
- }
1195
+ applyToEnvironment(environment) {
1196
+ return !!service_worker_entry_file && environment.config.consumer === 'client';
1197
+ },
1198
+ transform(code, id) {
1199
+ if (id !== service_worker_entry_file) return;
1200
+
1201
+ // prepend the service worker with an import that configures
1202
+ // `env`, in case `$app/env/public` is imported. In production
1203
+ // this is required: dynamic public env vars aren't known at
1204
+ // build time, so `env.js` is loaded at runtime. In dev, the
1205
+ // imported module just inlines the current values instead.
1206
+ return {
1207
+ code: `import '__sveltekit/env/service-worker';\n${code}`
1208
+ };
1174
1209
  }
1175
1210
  };
1176
1211
 
1212
+ /** @type {() => Promise<void> | undefined} */
1213
+ let finalise;
1214
+
1177
1215
  /** @type {Plugin} */
1178
1216
  const plugin_compile = {
1179
1217
  name: 'vite-plugin-sveltekit-compile',
1180
1218
 
1181
- applyToEnvironment(environment) {
1182
- return environment.name !== 'serviceWorker';
1183
- },
1184
-
1185
1219
  /**
1186
1220
  * Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
1187
1221
  * @see https://vitejs.dev/guide/api-plugin.html#config
@@ -1229,11 +1263,10 @@ function kit({ svelte_config }) {
1229
1263
  }
1230
1264
  });
1231
1265
 
1232
- // ...and every matcher
1233
- Object.entries(manifest_data.matchers).forEach(([key, file]) => {
1234
- const name = posixify(path.join('entries/matchers', key));
1235
- server_input[name] = path.resolve(root, file);
1236
- });
1266
+ // ...and the params file
1267
+ if (manifest_data.params) {
1268
+ server_input['entries/params'] = path.resolve(root, manifest_data.params);
1269
+ }
1237
1270
 
1238
1271
  // ...and the hooks files
1239
1272
  if (manifest_data.hooks.server) {
@@ -1254,13 +1287,6 @@ function kit({ svelte_config }) {
1254
1287
  if (kit.adapter && !kit.adapter.supports?.instrumentation?.()) {
1255
1288
  throw new Error(`${server_instrumentation} is unsupported in ${kit.adapter.name}.`);
1256
1289
  }
1257
- if (!kit.experimental.instrumentation.server) {
1258
- error_for_missing_config(
1259
- '`instrumentation.server.js`',
1260
- 'kit.experimental.instrumentation.server',
1261
- 'true'
1262
- );
1263
- }
1264
1290
  server_input['instrumentation.server'] = server_instrumentation;
1265
1291
  }
1266
1292
 
@@ -1448,6 +1474,10 @@ function kit({ svelte_config }) {
1448
1474
  return preview(vite, vite_config, svelte_config);
1449
1475
  },
1450
1476
 
1477
+ applyToEnvironment(environment) {
1478
+ return environment.name !== 'serviceWorker';
1479
+ },
1480
+
1451
1481
  renderChunk(code, chunk) {
1452
1482
  if (code.includes('__SVELTEKIT_TRACK__')) {
1453
1483
  return {
@@ -1479,6 +1509,12 @@ function kit({ svelte_config }) {
1479
1509
  }
1480
1510
  mkdirp(out);
1481
1511
 
1512
+ await load_and_validate_params({
1513
+ routes: manifest_data.routes,
1514
+ params_path: manifest_data.params,
1515
+ root
1516
+ });
1517
+
1482
1518
  const { output: server_chunks } = /** @type {Rolldown.RolldownOutput} */ (
1483
1519
  await builder.build(builder.environments.ssr)
1484
1520
  );
@@ -1776,63 +1812,88 @@ function kit({ svelte_config }) {
1776
1812
  })};\n`
1777
1813
  );
1778
1814
 
1779
- if (service_worker_entry_file) {
1780
- log.info('Building service worker');
1781
-
1782
- // mirror client settings that we couldn't set per environment in the config hook
1783
- builder.environments.serviceWorker.config.define =
1784
- builder.environments.client.config.define;
1785
- builder.environments.serviceWorker.config.resolve.alias = [
1786
- ...get_config_aliases(kit, vite_config.root)
1787
- ];
1815
+ // defer the adapt step to run after any buildApp hooks the adapter might have
1816
+ finalise = async () => {
1817
+ // defer creating the service worker too because other plugins might build
1818
+ // the client environment again and overwrite our service worker which
1819
+ // outputs to the same directory
1820
+ if (service_worker_entry_file) {
1821
+ log.info('Building service worker');
1822
+
1823
+ // mirror client settings that we couldn't set per environment in the config hook
1824
+ builder.environments.serviceWorker.config.define =
1825
+ builder.environments.client.config.define;
1826
+ builder.environments.serviceWorker.config.resolve.alias = [
1827
+ ...get_config_aliases(kit, vite_config.root)
1828
+ ];
1788
1829
 
1789
- // we have to overwrite this because it can't be configured per environment in the config hook
1790
- builder.environments.serviceWorker.config.experimental.renderBuiltUrl = (filename) => {
1791
- return {
1792
- runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname`
1830
+ // we have to overwrite this because it can't be configured per environment in the config hook
1831
+ builder.environments.serviceWorker.config.experimental.renderBuiltUrl = (filename) => {
1832
+ return {
1833
+ runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname`
1834
+ };
1793
1835
  };
1794
- };
1795
-
1796
- await builder.build(builder.environments.serviceWorker);
1797
- }
1798
-
1799
- console.log(
1800
- `\nRun ${styleText(['bold', 'cyan'], 'npm run preview')} to preview your production build locally.`
1801
- );
1802
1836
 
1803
- if (kit.adapter) {
1804
- const { adapt } = await import('../../core/adapt/index.js');
1805
- await adapt(
1806
- svelte_config,
1807
- build_data,
1808
- metadata,
1809
- prerendered,
1810
- prerender_results.prerender_map,
1811
- log,
1812
- remotes,
1813
- vite_config,
1814
- explicit_env_config
1815
- );
1816
- } else {
1817
- console.log(styleText(['bold', 'yellow'], '\nNo adapter specified'));
1837
+ await builder.build(builder.environments.serviceWorker);
1838
+ }
1818
1839
 
1819
- const link = styleText(['bold', 'cyan'], 'https://svelte.dev/docs/kit/adapters');
1820
1840
  console.log(
1821
- `See ${link} to learn how to configure your app to run on the platform of your choosing`
1841
+ `\nRun ${styleText(['bold', 'cyan'], 'npm run preview')} to preview your production build locally.`
1822
1842
  );
1843
+
1844
+ if (kit.adapter) {
1845
+ const { adapt } = await import('../../core/adapt/index.js');
1846
+ await adapt(
1847
+ svelte_config,
1848
+ build_data,
1849
+ metadata,
1850
+ prerendered,
1851
+ prerender_results.prerender_map,
1852
+ log,
1853
+ remotes,
1854
+ vite_config,
1855
+ explicit_env_config
1856
+ );
1857
+ } else {
1858
+ console.log(styleText(['bold', 'yellow'], '\nNo adapter specified'));
1859
+
1860
+ const link = styleText(['bold', 'cyan'], 'https://svelte.dev/docs/kit/adapters');
1861
+ console.log(
1862
+ `See ${link} to learn how to configure your app to run on the platform of your choosing`
1863
+ );
1864
+ }
1865
+ };
1866
+ }
1867
+ };
1868
+
1869
+ /** @type {Plugin} */
1870
+ const plugin_adapter = {
1871
+ name: 'vite-plugin-sveltekit-adapter',
1872
+ apply: 'build',
1873
+ buildApp: {
1874
+ // this will run after any buildApp hooks provided by other Vite plugins
1875
+ // see https://vite.dev/guide/api-environment-frameworks#environments-during-build
1876
+ order: 'post',
1877
+ async handler() {
1878
+ await finalise?.();
1823
1879
  }
1824
1880
  }
1825
1881
  };
1826
1882
 
1827
- return [
1828
- plugin_setup,
1829
- plugin_remote,
1830
- plugin_virtual_modules,
1831
- process.env.TEST !== 'true' ? plugin_guard : undefined,
1832
- service_worker_entry_file && plugin_service_worker_env,
1833
- plugin_service_worker,
1834
- plugin_compile
1835
- ].filter((p) => !!p);
1883
+ return /** @type {Plugin[]} */ (
1884
+ [
1885
+ svelte_config.kit.adapter?.vite?.plugins,
1886
+ plugin_setup,
1887
+ plugin_remote_guard,
1888
+ plugin_remote,
1889
+ plugin_virtual_modules,
1890
+ process.env.TEST !== 'true' ? plugin_guard : undefined,
1891
+ plugin_service_worker,
1892
+ plugin_service_worker_env,
1893
+ plugin_compile,
1894
+ plugin_adapter
1895
+ ].filter(Boolean)
1896
+ );
1836
1897
  }
1837
1898
 
1838
1899
  /**
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
- import { lookup } from 'mrmime';
4
+ import { lookup } from '../../../utils/mime.js';
5
5
  import sirv from 'sirv';
6
6
  import { loadEnv, normalizePath } from 'vite';
7
7
  import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
@@ -152,17 +152,15 @@ export function normalize_id(id, lib, cwd) {
152
152
  export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');
153
153
 
154
154
  /**
155
- * For `error_for_missing_config('instrumentation.server.js', 'experimental.instrumentation.server', true)`,
155
+ * For `error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true')`,
156
156
  * returns:
157
157
  *
158
158
  * ```
159
- * To enable `instrumentation.server.js`, add the following to the SvelteKit plugin in your `vite.config.js`:
159
+ * To enable remote functions, add the following to the SvelteKit plugin in your `vite.config.js`:
160
160
  *
161
161
  *\`\`\`js
162
162
  * experimental: {
163
- * instrumentation: {
164
- * server: true
165
- * }
163
+ * remoteFunctions: true
166
164
  * }
167
165
  *\`\`\`
168
166
  *```
@@ -1,4 +1,4 @@
1
- /** @import { Asset, RouteId, RouteIdWithSearchOrHash, Pathname, PathnameWithSearchOrHash, ResolvedPathname } from '$app/types' */
1
+ /** @import { Asset, RouteId, RouteIdWithSearchOrHash, Pathname, PathnameWithSearchOrHash, ResolvedPathname, RouteParams } from '$app/types' */
2
2
  /** @import { ResolveArgs } from './types.js' */
3
3
  import { base, assets, hash_routing } from './internal/client.js';
4
4
  import { resolve_route } from '../../../utils/routing.js';
@@ -59,11 +59,7 @@ export function resolve(...args) {
59
59
  );
60
60
  }
61
61
 
62
- // The type error is correct here, and if someone doesn't pass params when they should there's a runtime error,
63
- // but we don't want to adjust the internal resolve_route function to accept `undefined`, hence the type cast.
64
- return (
65
- base + pathname_prefix + resolve_route(args[0], /** @type {Record<string, string>} */ (args[1]))
66
- );
62
+ return base + pathname_prefix + resolve_route(args[0], args[1] ?? {});
67
63
  }
68
64
 
69
65
  /**
@@ -84,7 +80,7 @@ export function resolve(...args) {
84
80
  * @since 2.52.0
85
81
  *
86
82
  * @param {Pathname | URL | (string & {})} url
87
- * @returns {Promise<{ id: RouteId, params: Record<string, string> } | null>}
83
+ * @returns {Promise<{ [K in RouteId]: { id: K; params: RouteParams<K>; } }[RouteId] | null>}
88
84
  */
89
85
  export async function match(url) {
90
86
  if (typeof url === 'string') {
@@ -21,7 +21,7 @@ export function resolve(id, params) {
21
21
  );
22
22
  }
23
23
 
24
- const resolved = resolve_route(id, /** @type {Record<string, string>} */ (params));
24
+ const resolved = resolve_route(id, params ?? {});
25
25
 
26
26
  if (relative) {
27
27
  const store = try_get_request_store();