@sveltejs/kit 3.0.0-next.12 → 3.0.0-next.14

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 (77) hide show
  1. package/package.json +11 -11
  2. package/src/cli.js +2 -2
  3. package/src/core/adapt/builder.js +8 -5
  4. package/src/core/generate_manifest/index.js +6 -0
  5. package/src/core/postbuild/entities.js +8 -2
  6. package/src/core/postbuild/fallback.js +2 -1
  7. package/src/core/postbuild/prerender.js +15 -6
  8. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  9. package/src/core/sync/create_manifest_data/index.js +33 -2
  10. package/src/core/sync/write_app_types.js +73 -29
  11. package/src/core/sync/write_tsconfig/index.js +15 -2
  12. package/src/core/sync/write_types/index.js +5 -2
  13. package/src/exports/index.js +23 -12
  14. package/src/exports/internal/shared.js +4 -12
  15. package/src/exports/node/index.js +2 -7
  16. package/src/exports/public.d.ts +61 -12
  17. package/src/exports/vite/build/remote.js +10 -12
  18. package/src/exports/vite/dev/index.js +32 -19
  19. package/src/exports/vite/index.js +162 -133
  20. package/src/exports/vite/utils.js +1 -7
  21. package/src/runtime/app/server/remote/form.js +9 -1
  22. package/src/runtime/app/server/remote/prerender.js +13 -9
  23. package/src/runtime/app/server/remote/query.js +0 -6
  24. package/src/runtime/app/server/remote/requested.js +4 -4
  25. package/src/runtime/app/state/client.js +3 -0
  26. package/src/runtime/app/state/index.js +2 -2
  27. package/src/runtime/app/state/server.js +3 -0
  28. package/src/runtime/client/client.js +731 -342
  29. package/src/runtime/client/constants.js +2 -6
  30. package/src/runtime/client/fetcher.js +24 -25
  31. package/src/runtime/client/remote-functions/form.svelte.js +42 -14
  32. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  33. package/src/runtime/client/remote-functions/query/index.js +1 -1
  34. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -2
  35. package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -2
  36. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +2 -2
  37. package/src/runtime/client/remote-functions/query-live/iterator.js +10 -8
  38. package/src/runtime/client/remote-functions/query-live/proxy.js +0 -10
  39. package/src/runtime/client/remote-functions/shared.svelte.js +12 -11
  40. package/src/runtime/client/state.svelte.js +10 -22
  41. package/src/runtime/client/types.d.ts +1 -2
  42. package/src/runtime/client/utils.js +22 -14
  43. package/src/runtime/components/root.svelte +4 -14
  44. package/src/runtime/form-utils.js +4 -6
  45. package/src/runtime/pathname.js +37 -0
  46. package/src/runtime/props.svelte.js +71 -0
  47. package/src/runtime/server/fetch.js +9 -14
  48. package/src/runtime/server/index.js +10 -24
  49. package/src/runtime/server/page/crypto.js +2 -2
  50. package/src/runtime/server/page/csp.js +88 -104
  51. package/src/runtime/server/page/index.js +1 -2
  52. package/src/runtime/server/page/load_data.js +16 -33
  53. package/src/runtime/server/page/render.js +46 -25
  54. package/src/runtime/server/page/respond_with_error.js +1 -3
  55. package/src/runtime/server/page/serialize_data.js +2 -13
  56. package/src/runtime/server/page/server_routing.js +58 -9
  57. package/src/runtime/server/respond.js +20 -29
  58. package/src/runtime/server/state.js +43 -0
  59. package/src/runtime/shared.js +4 -2
  60. package/src/runtime/utils.js +3 -0
  61. package/src/types/ambient-private.d.ts +2 -2
  62. package/src/types/ambient.d.ts +59 -8
  63. package/src/types/global-private.d.ts +1 -1
  64. package/src/types/internal.d.ts +4 -8
  65. package/src/types/private.d.ts +3 -12
  66. package/src/utils/hash.js +21 -0
  67. package/src/utils/http.js +8 -7
  68. package/src/utils/import.js +2 -1
  69. package/src/utils/params.js +1 -1
  70. package/src/utils/regex.js +9 -0
  71. package/src/utils/routing.js +52 -27
  72. package/src/utils/url.js +1 -0
  73. package/src/version.js +1 -1
  74. package/types/index.d.ts +165 -66
  75. package/types/index.d.ts.map +2 -1
  76. package/src/exports/node/polyfills.js +0 -30
  77. package/src/runtime/types.d.ts +0 -8
@@ -1,7 +1,7 @@
1
1
  /** @import { EnvVarConfig, KitConfig } from '@sveltejs/kit' */
2
2
  /** @import { Options, SvelteConfig } from '@sveltejs/vite-plugin-svelte' */
3
3
  /** @import { PreprocessorGroup } from 'svelte/compiler' */
4
- /** @import { BuildData, ManifestData, Prerendered, ServerMetadata, RemoteInternals, ValidatedConfig, ValidatedKitConfig } from 'types' */
4
+ /** @import { Asset, BuildData, ManifestData, Prerendered, RemoteChunk, RemoteInternals, RouteData, ServerMetadata, ValidatedConfig, ValidatedKitConfig } from 'types' */
5
5
  /** @import { Manifest, Plugin, ResolvedConfig, Rolldown, UserConfig, ViteDevServer } from 'vite' */
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
@@ -46,6 +46,11 @@ import analyse from '../../core/postbuild/analyse.js';
46
46
  import { s } from '../../utils/misc.js';
47
47
  import { hash } from '../../utils/hash.js';
48
48
  import { dedent } from '../../core/sync/utils.js';
49
+ import {
50
+ is_app_route,
51
+ is_endpoint_route,
52
+ is_page_route
53
+ } from '../../core/sync/create_manifest_data/index.js';
49
54
  import { get_import_aliases, get_hash_import_keys } from '../../utils/imports.js';
50
55
  import {
51
56
  app_env_private,
@@ -64,13 +69,6 @@ import { process_config, split_config, validate_config } from '../../core/config
64
69
  import { treeshake_prerendered_remotes } from './build/remote.js';
65
70
  import { get_runner } from '../../runner.js';
66
71
 
67
- /**
68
- * The posix-ified root of the project based on the Vite configuration.
69
- * Populated after Vite plugins' `config` hooks run
70
- * @type {string}
71
- */
72
- let root;
73
-
74
72
  /** @type {import('./types.js').EnforcedConfig} */
75
73
  const enforced_config = {
76
74
  appType: true,
@@ -123,7 +121,7 @@ const warning_preprocessor = {
123
121
  const fixed = basename.replace('.svelte', '(.server).js/ts');
124
122
 
125
123
  const message =
126
- `\n${styleText(['bold', 'red'], path.relative(root, filename))}\n` +
124
+ `\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
127
125
  `\`${match[1]}\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`;
128
126
 
129
127
  if (!warned.has(message)) {
@@ -140,7 +138,7 @@ const warning_preprocessor = {
140
138
 
141
139
  if (basename.startsWith('+layout.') && !has_children(content, true)) {
142
140
  const message =
143
- `\n${styleText(['bold', 'red'], path.relative(root, filename))}\n` +
141
+ `\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
144
142
  '`<slot />` or `{@render ...}` tag' +
145
143
  ' missing — inner content will not be rendered';
146
144
 
@@ -206,13 +204,7 @@ export async function sveltekit(config) {
206
204
  inline_vps_config.compilerOptions = svelte_config.compilerOptions;
207
205
  }
208
206
 
209
- return [
210
- plugin_root(),
211
- ...vite_plugin_svelte.svelte(inline_vps_config),
212
- ...kit({
213
- svelte_config
214
- })
215
- ];
207
+ return [...vite_plugin_svelte.svelte(inline_vps_config), ...kit({ svelte_config })];
216
208
  }
217
209
 
218
210
  /** @param {UserConfig | ResolvedConfig} vite_config */
@@ -220,39 +212,6 @@ function resolve_root(vite_config) {
220
212
  return posixify(vite_config.root ? path.resolve(vite_config.root) : process.cwd());
221
213
  }
222
214
 
223
- /**
224
- * @return {Plugin}
225
- */
226
- function plugin_root() {
227
- return {
228
- name: 'vite-plugin-sveltekit-resolve-svelte-config',
229
- // make sure it runs first
230
- enforce: 'pre',
231
- config: {
232
- order: 'pre',
233
- handler(config) {
234
- root = resolve_root(config);
235
-
236
- const config_file = ['svelte.config.js', 'svelte.config.ts'].find((file) =>
237
- fs.existsSync(path.join(root, file))
238
- );
239
- if (config_file) {
240
- throw new Error(
241
- `${config_file} is no longer used. Please pass configuration via the \`sveltekit(...)\` plugin in your Vite config.`
242
- );
243
- }
244
- }
245
- },
246
- // TODO: do we even need to set `root` based on the final Vite config?
247
- configResolved: {
248
- order: 'pre',
249
- handler(config) {
250
- root = resolve_root(config);
251
- }
252
- }
253
- };
254
- }
255
-
256
215
  /**
257
216
  * Returns the SvelteKit Vite plugin. Vite executes Rolldown hooks as well as some of its own.
258
217
  * Background reading is available at:
@@ -271,6 +230,12 @@ function kit({ svelte_config }) {
271
230
  /** @type {typeof import('vite')} */
272
231
  let vite;
273
232
 
233
+ /**
234
+ * The posix-ified root of the project based on the Vite configuration.
235
+ * @type {string}
236
+ */
237
+ let root;
238
+
274
239
  /** @type {ValidatedKitConfig} */
275
240
  let kit;
276
241
  /** @type {string} `kit.outDir` but posix-ified */
@@ -324,6 +289,27 @@ function kit({ svelte_config }) {
324
289
  /** @type {string} name for `globalThis.__sveltekit_xxx` */
325
290
  let kit_global;
326
291
 
292
+ /** @type {Plugin} */
293
+ const plugin_resolve_root = {
294
+ name: 'vite-plugin-sveltekit-resolve-root',
295
+ // make sure it runs first
296
+ enforce: 'pre',
297
+ config: {
298
+ order: 'pre',
299
+ handler(config) {
300
+ root = resolve_root(config);
301
+
302
+ for (const file of ['svelte.config.js', 'svelte.config.ts']) {
303
+ if (fs.existsSync(path.join(root, file))) {
304
+ throw new Error(
305
+ `${file} is no longer used. Please pass configuration via the \`sveltekit(...)\` plugin in your Vite config.`
306
+ );
307
+ }
308
+ }
309
+ }
310
+ }
311
+ };
312
+
327
313
  /** @type {Plugin} */
328
314
  const plugin_setup = {
329
315
  name: 'vite-plugin-sveltekit-setup',
@@ -450,7 +436,9 @@ function kit({ svelte_config }) {
450
436
  // this does not affect app code, just handling of imported libraries that use $app or $env
451
437
  '$app',
452
438
  '$env'
453
- ]
439
+ ],
440
+ // avoid Vite dev server reloading the first time a page is requested
441
+ include: ['@sveltejs/kit > devalue', '@sveltejs/kit > esm-env']
454
442
  },
455
443
  ssr: {
456
444
  noExternal: [
@@ -854,7 +842,7 @@ function kit({ svelte_config }) {
854
842
  /** @type {ViteDevServer} */
855
843
  let dev_server;
856
844
 
857
- /** @type {Array<{ hash: string, file: string }>} */
845
+ /** @type {RemoteChunk[]} */
858
846
  const remotes = [];
859
847
 
860
848
  /** @type {Map<string, string>} Maps remote hash -> original module id */
@@ -912,7 +900,7 @@ function kit({ svelte_config }) {
912
900
  file
913
901
  };
914
902
 
915
- remotes.push(remote);
903
+ if (this.environment.name === 'ssr') remotes.push(remote);
916
904
 
917
905
  if (this.environment.config.consumer !== 'client') {
918
906
  // we need to add an `await Promise.resolve()` because if the user imports this function
@@ -1040,8 +1028,8 @@ function kit({ svelte_config }) {
1040
1028
  /** @type {Prerendered} */
1041
1029
  let prerendered;
1042
1030
 
1043
- /** @type {Set<string>} */
1044
- let build_files;
1031
+ /** @type {Array<{ path: string }>} */
1032
+ let immutable;
1045
1033
  /** @type {string} */
1046
1034
  let manifest_data_code;
1047
1035
 
@@ -1127,35 +1115,18 @@ function kit({ svelte_config }) {
1127
1115
  ]
1128
1116
  },
1129
1117
  handler(id) {
1130
- if (!build_files) {
1131
- build_files = new Set();
1132
- const manifest = vite_client_manifest ?? vite_server_manifest;
1133
- for (const key in manifest) {
1134
- const { file, css = [], assets = [] } = manifest[key];
1135
- build_files.add(file);
1136
- css.forEach((file) => build_files.add(file));
1137
- assets.forEach((file) => build_files.add(file));
1138
- }
1139
-
1140
- if (kit.output.bundleStrategy === 'inline') {
1141
- // the bundle and stylesheet are inlined into the page and their files
1142
- // deleted, so they must not appear in the list of cacheable assets
1143
- for (const file of build_files) {
1144
- if (!fs.existsSync(`${out}/client/${file}`)) {
1145
- build_files.delete(file);
1146
- }
1147
- }
1148
- }
1118
+ if (!manifest_data_code) {
1119
+ // the client build computes `immutable`, unless it was skipped
1120
+ // because every route has `csr: false`
1121
+ immutable ??= collect_immutable(vite_server_manifest, kit.appDir, new Set());
1149
1122
 
1150
1123
  manifest_data_code = dedent`
1151
1124
  export const immutable = [
1152
- ${Array.from(build_files)
1153
- .map((file) => s({ path: file }))
1154
- .join(',\n')}
1125
+ ${immutable.map((entry) => s(entry)).join(',\n')}
1155
1126
  ];
1156
1127
 
1157
1128
  export const assets = [
1158
- ${manifest_data.assets.map((asset) => s({ path: asset.file })).join(',\n')}
1129
+ ${stringify_assets(manifest_data.assets)}
1159
1130
  ];
1160
1131
 
1161
1132
  export const prerendered = [
@@ -1163,7 +1134,7 @@ function kit({ svelte_config }) {
1163
1134
  ];
1164
1135
 
1165
1136
  export const routes = [
1166
- ${manifest_data.routes.map((route) => s({ id: route.id })).join(',\n')}
1137
+ ${stringify_routes(manifest_data.routes)}
1167
1138
  ];
1168
1139
  `;
1169
1140
  }
@@ -1604,7 +1575,7 @@ function kit({ svelte_config }) {
1604
1575
  // the client build and after prerendering respectively.
1605
1576
  replace_manifest_placeholder_variables(server_chunks, `${out}/server`, {
1606
1577
  assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
1607
- routes: manifest_data.routes.map((route) => ({ id: route.id }))
1578
+ routes: get_manifest_routes(manifest_data.routes)
1608
1579
  });
1609
1580
 
1610
1581
  const verbose = builder.config.logLevel === 'info';
@@ -1731,48 +1702,47 @@ function kit({ svelte_config }) {
1731
1702
  read(`${out}/client/.vite/manifest.json`)
1732
1703
  ));
1733
1704
 
1705
+ /**
1706
+ * @param {string} entry
1707
+ * @param {boolean} [add_dynamic_css]
1708
+ */
1709
+ const deps_of = (entry, add_dynamic_css = false) =>
1710
+ find_deps(vite_manifest, posixify(path.relative(root, entry)), add_dynamic_css, root);
1711
+
1712
+ // the inline bundle and stylesheet are deleted further down, after
1713
+ // being inlined into the page, so they must not appear in `immutable`
1714
+ /** @type {Set<string>} */
1715
+ const inlined = new Set();
1716
+ /** @type {Rolldown.OutputAsset | undefined} */
1717
+ let inline_style;
1718
+
1719
+ if (kit.output.bundleStrategy === 'inline') {
1720
+ inline_style = /** @type {Rolldown.OutputAsset | undefined} */ (
1721
+ client_chunks.find(
1722
+ (chunk) =>
1723
+ chunk.type === 'asset' && chunk.names.length === 1 && chunk.names[0] === 'style.css'
1724
+ )
1725
+ );
1726
+
1727
+ inlined.add(deps_of(`${runtime_directory}/client/bundle.js`).file);
1728
+ if (inline_style) inlined.add(inline_style.fileName);
1729
+ }
1730
+
1734
1731
  // Replace manifest placeholders in client output. `immutable` is
1735
1732
  // computed from the Vite client manifest, `assets` and `routes`
1736
1733
  // from `manifest_data`. `prerendered` is left as a placeholder
1737
1734
  // for now — it's replaced after prerendering completes.
1738
- /** @type {Set<string>} */
1739
- const immutable = new Set();
1740
-
1741
- /** @param {string} file */
1742
- const add_immutable = (file) => {
1743
- if (
1744
- file.startsWith(`${kit.appDir}/immutable`) &&
1745
- fs.existsSync(`${out}/client/${file}`)
1746
- ) {
1747
- immutable.add(file);
1748
- }
1749
- };
1750
-
1751
- for (const key in vite_manifest) {
1752
- const { file, css = [], assets = [] } = vite_manifest[key];
1753
- add_immutable(file);
1754
- css.forEach(add_immutable);
1755
- assets.forEach(add_immutable);
1756
- }
1735
+ immutable = collect_immutable(vite_manifest, kit.appDir, inlined);
1757
1736
 
1758
1737
  replace_manifest_placeholder_variables(client_chunks, `${out}/client`, {
1759
- immutable: Array.from(immutable).map((file) => ({ path: file })),
1738
+ immutable,
1760
1739
  assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
1761
- routes: manifest_data.routes.map((route) => ({ id: route.id }))
1740
+ routes: get_manifest_routes(manifest_data.routes)
1762
1741
  });
1763
1742
 
1764
1743
  // Now that the client build is done, replace the `build` sentinel
1765
1744
  // in the SSR output with the real build files
1766
- replace_manifest_placeholder_strings(`${out}/server`, {
1767
- immutable: Array.from(immutable).map((file) => ({ path: file }))
1768
- });
1769
-
1770
- /**
1771
- * @param {string} entry
1772
- * @param {boolean} [add_dynamic_css]
1773
- */
1774
- const deps_of = (entry, add_dynamic_css = false) =>
1775
- find_deps(vite_manifest, posixify(path.relative(root, entry)), add_dynamic_css, root);
1745
+ replace_manifest_placeholder_strings(`${out}/server`, { immutable });
1776
1746
 
1777
1747
  const has_explicit_dynamic_public_env = Object.values(explicit_env_config ?? {}).some(
1778
1748
  (variable) => variable.public && !variable.static
@@ -1861,25 +1831,16 @@ function kit({ svelte_config }) {
1861
1831
  };
1862
1832
 
1863
1833
  if (svelte_config.kit.output.bundleStrategy === 'inline') {
1864
- const style = /** @type {Rolldown.OutputAsset} */ (
1865
- client_chunks.find(
1866
- (chunk) =>
1867
- chunk.type === 'asset' &&
1868
- chunk.names.length === 1 &&
1869
- chunk.names[0] === 'style.css'
1870
- )
1871
- );
1872
-
1873
1834
  build_data.client.inline = {
1874
1835
  script: read(`${out}/client/${start.file}`),
1875
- style: /** @type {string | undefined} */ (style?.source)
1836
+ style: /** @type {string | undefined} */ (inline_style?.source)
1876
1837
  };
1877
1838
 
1878
1839
  // the bundle and stylesheet are inlined into the page, so the
1879
1840
  // emitted files are never loaded
1880
1841
  fs.unlinkSync(`${out}/client/${start.file}`);
1881
1842
  fs.rmSync(`${out}/client/${start.file}.map`, { force: true });
1882
- if (style) fs.unlinkSync(`${out}/client/${style.fileName}`);
1843
+ if (inline_style) fs.unlinkSync(`${out}/client/${inline_style.fileName}`);
1883
1844
  }
1884
1845
  }
1885
1846
 
@@ -1962,6 +1923,7 @@ function kit({ svelte_config }) {
1962
1923
  vite,
1963
1924
  out,
1964
1925
  remotes,
1926
+ remote_original_by_hash,
1965
1927
  metadata,
1966
1928
  process.cwd(),
1967
1929
  server_chunks,
@@ -2054,6 +2016,7 @@ function kit({ svelte_config }) {
2054
2016
  return /** @type {Plugin[]} */ (
2055
2017
  [
2056
2018
  svelte_config.kit.adapter?.vite?.plugins,
2019
+ plugin_resolve_root,
2057
2020
  plugin_setup,
2058
2021
  plugin_remote_guard,
2059
2022
  plugin_remote,
@@ -2102,11 +2065,7 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
2102
2065
  const resolved = resolved_config[key];
2103
2066
 
2104
2067
  if (enforced === true) {
2105
- // Normalize path separators before comparing to avoid false positives on Windows,
2106
- // where config values like `root` may use backslashes while SvelteKit uses forward slashes.
2107
- const a = typeof config[key] === 'string' ? posixify(config[key]) : config[key];
2108
- const b = typeof resolved === 'string' ? posixify(resolved) : resolved;
2109
- if (a !== b) {
2068
+ if (comparable(config[key]) !== comparable(resolved)) {
2110
2069
  out.push(path + key);
2111
2070
  }
2112
2071
  } else {
@@ -2117,6 +2076,79 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
2117
2076
  return out;
2118
2077
  }
2119
2078
 
2079
+ /**
2080
+ * Collects the content-hashed files of a Vite manifest, in the shape of
2081
+ * `$app/manifest`'s `immutable` export.
2082
+ *
2083
+ * @param {Manifest} manifest
2084
+ * @param {string} app_dir
2085
+ * @param {Set<string>} inlined files deleted from the output after being inlined into the page
2086
+ * @returns {Array<{ path: string }>}
2087
+ */
2088
+ const collect_immutable = (manifest, app_dir, inlined) => {
2089
+ const prefix = `${app_dir}/immutable`;
2090
+
2091
+ /** @type {Set<string>} */
2092
+ const files = new Set();
2093
+
2094
+ /** @param {string} file */
2095
+ const add = (file) => {
2096
+ if (file.startsWith(prefix) && !inlined.has(file)) files.add(file);
2097
+ };
2098
+
2099
+ for (const key in manifest) {
2100
+ const { file, css, assets } = manifest[key];
2101
+ add(file);
2102
+ if (css) for (let i = 0; i < css.length; i++) add(css[i]);
2103
+ if (assets) for (let i = 0; i < assets.length; i++) add(assets[i]);
2104
+ }
2105
+
2106
+ return Array.from(files, (path) => ({ path }));
2107
+ };
2108
+
2109
+ /**
2110
+ * Normalizes a config value for comparison, since Windows paths may use backslashes
2111
+ * and differ in casing (e.g. the drive letter) depending on where they came from.
2112
+ * @param {any} value
2113
+ */
2114
+ function comparable(value) {
2115
+ if (typeof value !== 'string') return value;
2116
+ const normalized = posixify(value);
2117
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
2118
+ }
2119
+
2120
+ /**
2121
+ * @param {Asset[] | undefined} assets
2122
+ * @returns {string}
2123
+ */
2124
+ function stringify_assets(assets) {
2125
+ return assets?.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
2126
+ }
2127
+
2128
+ /**
2129
+ * @param {RouteData[] | undefined} routes
2130
+ * @returns {Array<{ id: string; page: boolean; endpoint: boolean }>}
2131
+ */
2132
+ function get_manifest_routes(routes) {
2133
+ return (
2134
+ routes?.filter(is_app_route).map((route) => ({
2135
+ id: route.id,
2136
+ page: is_page_route(route),
2137
+ endpoint: is_endpoint_route(route)
2138
+ })) ?? []
2139
+ );
2140
+ }
2141
+
2142
+ /**
2143
+ * @param {RouteData[] | undefined} routes
2144
+ * @returns {string}
2145
+ */
2146
+ function stringify_routes(routes) {
2147
+ return get_manifest_routes(routes)
2148
+ .map((route) => s(route))
2149
+ .join(',\n');
2150
+ }
2151
+
2120
2152
  /**
2121
2153
  * Creates the `$app/manifest` data module. During development, real values
2122
2154
  * are emitted for `assets` and `routes` (the only data known at that point).
@@ -2149,20 +2181,17 @@ const create_manifest_data_module = (is_build, manifest_data) => {
2149
2181
  // In dev, `manifest_data` may not be set yet on the very first load,
2150
2182
  // but `configureServer` (which calls `sync.create`) runs before any
2151
2183
  // module is served, so it will be set by the time this is called.
2152
- const routes = manifest_data?.routes.map((route) => s({ id: route.id })).join(',\n') ?? '';
2153
- const assets = manifest_data?.assets.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
2154
-
2155
2184
  return dedent`
2156
2185
  // empty during dev
2157
2186
  export const immutable = [];
2158
2187
  export const prerendered = [];
2159
2188
 
2160
2189
  export const assets = [
2161
- ${assets}
2190
+ ${stringify_assets(manifest_data?.assets)}
2162
2191
  ];
2163
2192
 
2164
2193
  export const routes = [
2165
- ${routes}
2194
+ ${stringify_routes(manifest_data?.routes)}
2166
2195
  ];
2167
2196
  `;
2168
2197
  };
@@ -2178,7 +2207,7 @@ const create_manifest_data_module = (is_build, manifest_data) => {
2178
2207
  * immutable?: Array<{ path: string }>;
2179
2208
  * assets?: Array<{ path: string }>;
2180
2209
  * prerendered?: Array<{ path: string }>;
2181
- * routes?: Array<{ id: string }>;
2210
+ * routes?: Array<{ id: string; page: boolean; endpoint: boolean }>;
2182
2211
  * }} values
2183
2212
  */
2184
2213
  const replace_manifest_placeholder_variables = (chunks, output_dir, values) => {
@@ -2,6 +2,7 @@ import path from 'node:path';
2
2
  import { posixify } from '../../utils/os.js';
3
3
  import { negotiate } from '../../utils/http.js';
4
4
  import { escape_html } from '../../utils/escape.js';
5
+ import { escape_for_regexp } from '../../utils/regex.js';
5
6
  import { stackless } from '../../utils/error.js';
6
7
  import { dedent } from '../../core/sync/utils.js';
7
8
  import { app_server, app_env_private, sveltekit_env_private } from './module_ids.js';
@@ -44,13 +45,6 @@ export function get_config_aliases(config, root) {
44
45
  return alias;
45
46
  }
46
47
 
47
- /**
48
- * @param {string} str
49
- */
50
- function escape_for_regexp(str) {
51
- return str.replace(/[.*+?^${}()|[\]\\]/g, (match) => '\\' + match);
52
- }
53
-
54
48
  /**
55
49
  * Silently respond with 404 for Chrome DevTools workspaces request.
56
50
  * Chrome always requests this at the root, regardless of base path.
@@ -146,7 +146,15 @@ export function form(validate_or_fn, maybe_fn) {
146
146
  Object.defineProperty(instance, '__', { value: __ });
147
147
 
148
148
  Object.defineProperty(instance, 'action', {
149
- get: () => `?/remote=${__.key ? `${__.id}/${encodeURIComponent(__.key)}` : __.id}`,
149
+ get: () => {
150
+ const search = new URLSearchParams(get_request_store().event.url.search);
151
+ search.delete('/remote');
152
+
153
+ const query = search.toString();
154
+ const action_id = __.key ? `${__.id}/${encodeURIComponent(__.key)}` : __.id;
155
+
156
+ return `?${query ? `${query}&` : ''}/remote=${action_id}`;
157
+ },
150
158
  enumerable: true
151
159
  });
152
160
 
@@ -1,7 +1,8 @@
1
1
  /** @import { RemoteResource, RemotePrerenderFunction } from '@sveltejs/kit' */
2
- /** @import { RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
2
+ /** @import { RemoteFunctionResponse, RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
3
3
  /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
4
- import { json, error } from '@sveltejs/kit';
4
+ import { json } from '@sveltejs/kit';
5
+ import { HttpError } from '@sveltejs/kit/internal';
5
6
  import { get_request_store } from '@sveltejs/kit/internal/server';
6
7
  import { stringify, stringify_remote_arg } from '../../../shared.js';
7
8
  import { noop } from '../../../../utils/functions.js';
@@ -99,25 +100,28 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
99
100
  const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`;
100
101
 
101
102
  if (!state.prerendering && !__SVELTEKIT_DEV__ && !event.isRemoteRequest) {
103
+ /** @type {RemoteFunctionResponse | undefined} */
104
+ let prerendered;
105
+
102
106
  try {
103
107
  // TODO adapters can provide prerendered data more efficiently than
104
108
  // fetching from the public internet
105
109
  // `request.url` rather than `event.url`, which throws inside queries
106
110
  const response = await fetch(new URL(url, event.request.url).href);
107
111
 
108
- if (!response.ok) {
109
- throw new Error('Prerendered response not found');
112
+ if (response.ok) {
113
+ prerendered = /** @type {RemoteFunctionResponse} */ (await response.json());
110
114
  }
115
+ } catch {
116
+ // not available prerendered, fallback to normal function
117
+ }
111
118
 
112
- const prerendered = /** @type {RemoteFunctionResponse} */ await response.json();
113
-
119
+ if (prerendered) {
114
120
  if (prerendered.type === 'error') {
115
- error(prerendered.status, prerendered.error);
121
+ throw new HttpError(prerendered.error);
116
122
  }
117
123
 
118
124
  return parse_remote_response(prerendered.data, state.transport)._;
119
- } catch {
120
- // not available prerendered, fallback to normal function
121
125
  }
122
126
  }
123
127
 
@@ -575,12 +575,6 @@ function create_live_query_resource(__, payload, event, state, get_generator) {
575
575
 
576
576
  return Promise.resolve();
577
577
  },
578
- /** @ts-expect-error This method no longer exists */
579
- run() {
580
- throw new Error(
581
- '`.run()` has been removed from live queries. Use `for await (const value of liveQuery())` instead.'
582
- );
583
- },
584
578
  /** @type {Promise<any>['then']} */
585
579
  then(onfulfilled, onrejected) {
586
580
  return get_promise().then(onfulfilled, onrejected);
@@ -152,10 +152,10 @@ export function requested(query, limit) {
152
152
  for (const payload of skipped) {
153
153
  record_failure(
154
154
  payload,
155
- new HttpError(
156
- 400,
157
- `Requested refresh was rejected because it exceeded requested(${__.name}, ${limit}) limit`
158
- )
155
+ new HttpError({
156
+ status: 400,
157
+ message: `Requested refresh was rejected because it exceeded requested(${__.name}, ${limit}) limit`
158
+ })
159
159
  );
160
160
  }
161
161
 
@@ -20,6 +20,9 @@ export const page = {
20
20
  get route() {
21
21
  return _page.route;
22
22
  },
23
+ get shallow() {
24
+ return _page.shallow;
25
+ },
23
26
  get state() {
24
27
  return _page.state;
25
28
  },
@@ -14,8 +14,8 @@ import { BROWSER } from 'esm-env';
14
14
  * A read-only reactive object with information about the current page, serving several use cases:
15
15
  * - retrieving the combined `data` of all pages/layouts anywhere in your component tree (also see [loading data](https://svelte.dev/docs/kit/load))
16
16
  * - retrieving the current value of the `form` prop anywhere in your component tree (also see [form actions](https://svelte.dev/docs/kit/form-actions))
17
- * - retrieving the page state that was set through `goto`, `pushState` or `replaceState` (also see [goto](https://svelte.dev/docs/kit/$app-navigation#goto) and [shallow routing](https://svelte.dev/docs/kit/shallow-routing))
18
- * - retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error
17
+ * - retrieving the page state that was set through `goto` (also see [goto](https://svelte.dev/docs/kit/$app-navigation#goto) and [shallow routing](https://svelte.dev/docs/kit/shallow-routing))
18
+ * - retrieving metadata such as the URL you're on, the current route and its parameters, the target of a shallow navigation, and whether or not there was an error
19
19
  *
20
20
  * ```svelte
21
21
  * <!--- file: +layout.svelte --->
@@ -33,6 +33,9 @@ export const page = {
33
33
  get route() {
34
34
  return (DEV ? context_dev('page.route') : context()).page.route;
35
35
  },
36
+ get shallow() {
37
+ return (DEV ? context_dev('page.shallow') : context()).page.shallow;
38
+ },
36
39
  get state() {
37
40
  return (DEV ? context_dev('page.state') : context()).page.state;
38
41
  },