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

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 (46) hide show
  1. package/package.json +10 -10
  2. package/src/core/postbuild/prerender.js +3 -3
  3. package/src/core/sync/write_app_types.js +1 -2
  4. package/src/core/sync/write_tsconfig/index.js +13 -1
  5. package/src/exports/index.js +23 -12
  6. package/src/exports/internal/shared.js +4 -12
  7. package/src/exports/public.d.ts +59 -11
  8. package/src/exports/vite/build/remote.js +10 -12
  9. package/src/exports/vite/dev/index.js +32 -19
  10. package/src/exports/vite/index.js +118 -123
  11. package/src/runtime/app/server/remote/form.js +9 -1
  12. package/src/runtime/app/server/remote/prerender.js +13 -9
  13. package/src/runtime/app/server/remote/requested.js +4 -4
  14. package/src/runtime/app/state/client.js +3 -0
  15. package/src/runtime/app/state/index.js +2 -2
  16. package/src/runtime/app/state/server.js +3 -0
  17. package/src/runtime/client/client.js +584 -305
  18. package/src/runtime/client/constants.js +2 -6
  19. package/src/runtime/client/fetcher.js +27 -17
  20. package/src/runtime/client/remote-functions/form.svelte.js +39 -7
  21. package/src/runtime/client/remote-functions/prerender.svelte.js +1 -1
  22. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -2
  23. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  24. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +2 -2
  25. package/src/runtime/client/remote-functions/query-live/iterator.js +10 -8
  26. package/src/runtime/client/remote-functions/shared.svelte.js +11 -10
  27. package/src/runtime/client/state.svelte.js +10 -22
  28. package/src/runtime/client/types.d.ts +1 -2
  29. package/src/runtime/client/utils.js +21 -14
  30. package/src/runtime/components/root.svelte +4 -14
  31. package/src/runtime/props.svelte.js +71 -0
  32. package/src/runtime/server/fetch.js +4 -6
  33. package/src/runtime/server/page/csp.js +86 -103
  34. package/src/runtime/server/page/index.js +1 -2
  35. package/src/runtime/server/page/load_data.js +15 -5
  36. package/src/runtime/server/page/render.js +27 -24
  37. package/src/runtime/server/page/respond_with_error.js +1 -3
  38. package/src/runtime/server/respond.js +0 -2
  39. package/src/types/ambient-private.d.ts +1 -1
  40. package/src/types/ambient.d.ts +1 -1
  41. package/src/types/internal.d.ts +2 -7
  42. package/src/types/private.d.ts +3 -12
  43. package/src/version.js +1 -1
  44. package/types/index.d.ts +92 -57
  45. package/types/index.d.ts.map +2 -1
  46. 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 { BuildData, ManifestData, Prerendered, RemoteChunk, RemoteInternals, 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';
@@ -64,13 +64,6 @@ import { process_config, split_config, validate_config } from '../../core/config
64
64
  import { treeshake_prerendered_remotes } from './build/remote.js';
65
65
  import { get_runner } from '../../runner.js';
66
66
 
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
67
  /** @type {import('./types.js').EnforcedConfig} */
75
68
  const enforced_config = {
76
69
  appType: true,
@@ -123,7 +116,7 @@ const warning_preprocessor = {
123
116
  const fixed = basename.replace('.svelte', '(.server).js/ts');
124
117
 
125
118
  const message =
126
- `\n${styleText(['bold', 'red'], path.relative(root, filename))}\n` +
119
+ `\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
127
120
  `\`${match[1]}\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`;
128
121
 
129
122
  if (!warned.has(message)) {
@@ -140,7 +133,7 @@ const warning_preprocessor = {
140
133
 
141
134
  if (basename.startsWith('+layout.') && !has_children(content, true)) {
142
135
  const message =
143
- `\n${styleText(['bold', 'red'], path.relative(root, filename))}\n` +
136
+ `\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
144
137
  '`<slot />` or `{@render ...}` tag' +
145
138
  ' missing — inner content will not be rendered';
146
139
 
@@ -206,13 +199,7 @@ export async function sveltekit(config) {
206
199
  inline_vps_config.compilerOptions = svelte_config.compilerOptions;
207
200
  }
208
201
 
209
- return [
210
- plugin_root(),
211
- ...vite_plugin_svelte.svelte(inline_vps_config),
212
- ...kit({
213
- svelte_config
214
- })
215
- ];
202
+ return [...vite_plugin_svelte.svelte(inline_vps_config), ...kit({ svelte_config })];
216
203
  }
217
204
 
218
205
  /** @param {UserConfig | ResolvedConfig} vite_config */
@@ -220,39 +207,6 @@ function resolve_root(vite_config) {
220
207
  return posixify(vite_config.root ? path.resolve(vite_config.root) : process.cwd());
221
208
  }
222
209
 
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
210
  /**
257
211
  * Returns the SvelteKit Vite plugin. Vite executes Rolldown hooks as well as some of its own.
258
212
  * Background reading is available at:
@@ -271,6 +225,12 @@ function kit({ svelte_config }) {
271
225
  /** @type {typeof import('vite')} */
272
226
  let vite;
273
227
 
228
+ /**
229
+ * The posix-ified root of the project based on the Vite configuration.
230
+ * @type {string}
231
+ */
232
+ let root;
233
+
274
234
  /** @type {ValidatedKitConfig} */
275
235
  let kit;
276
236
  /** @type {string} `kit.outDir` but posix-ified */
@@ -324,6 +284,27 @@ function kit({ svelte_config }) {
324
284
  /** @type {string} name for `globalThis.__sveltekit_xxx` */
325
285
  let kit_global;
326
286
 
287
+ /** @type {Plugin} */
288
+ const plugin_resolve_root = {
289
+ name: 'vite-plugin-sveltekit-resolve-root',
290
+ // make sure it runs first
291
+ enforce: 'pre',
292
+ config: {
293
+ order: 'pre',
294
+ handler(config) {
295
+ root = resolve_root(config);
296
+
297
+ for (const file of ['svelte.config.js', 'svelte.config.ts']) {
298
+ if (fs.existsSync(path.join(root, file))) {
299
+ throw new Error(
300
+ `${file} is no longer used. Please pass configuration via the \`sveltekit(...)\` plugin in your Vite config.`
301
+ );
302
+ }
303
+ }
304
+ }
305
+ }
306
+ };
307
+
327
308
  /** @type {Plugin} */
328
309
  const plugin_setup = {
329
310
  name: 'vite-plugin-sveltekit-setup',
@@ -450,7 +431,9 @@ function kit({ svelte_config }) {
450
431
  // this does not affect app code, just handling of imported libraries that use $app or $env
451
432
  '$app',
452
433
  '$env'
453
- ]
434
+ ],
435
+ // avoid Vite dev server reloading the first time a page is requested
436
+ include: ['@sveltejs/kit > devalue', '@sveltejs/kit > esm-env']
454
437
  },
455
438
  ssr: {
456
439
  noExternal: [
@@ -854,7 +837,7 @@ function kit({ svelte_config }) {
854
837
  /** @type {ViteDevServer} */
855
838
  let dev_server;
856
839
 
857
- /** @type {Array<{ hash: string, file: string }>} */
840
+ /** @type {RemoteChunk[]} */
858
841
  const remotes = [];
859
842
 
860
843
  /** @type {Map<string, string>} Maps remote hash -> original module id */
@@ -912,7 +895,7 @@ function kit({ svelte_config }) {
912
895
  file
913
896
  };
914
897
 
915
- remotes.push(remote);
898
+ if (this.environment.name === 'ssr') remotes.push(remote);
916
899
 
917
900
  if (this.environment.config.consumer !== 'client') {
918
901
  // we need to add an `await Promise.resolve()` because if the user imports this function
@@ -1040,8 +1023,8 @@ function kit({ svelte_config }) {
1040
1023
  /** @type {Prerendered} */
1041
1024
  let prerendered;
1042
1025
 
1043
- /** @type {Set<string>} */
1044
- let build_files;
1026
+ /** @type {Array<{ path: string }>} */
1027
+ let immutable;
1045
1028
  /** @type {string} */
1046
1029
  let manifest_data_code;
1047
1030
 
@@ -1127,31 +1110,14 @@ function kit({ svelte_config }) {
1127
1110
  ]
1128
1111
  },
1129
1112
  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
- }
1113
+ if (!manifest_data_code) {
1114
+ // the client build computes `immutable`, unless it was skipped
1115
+ // because every route has `csr: false`
1116
+ immutable ??= collect_immutable(vite_server_manifest, kit.appDir, new Set());
1149
1117
 
1150
1118
  manifest_data_code = dedent`
1151
1119
  export const immutable = [
1152
- ${Array.from(build_files)
1153
- .map((file) => s({ path: file }))
1154
- .join(',\n')}
1120
+ ${immutable.map((entry) => s(entry)).join(',\n')}
1155
1121
  ];
1156
1122
 
1157
1123
  export const assets = [
@@ -1731,48 +1697,47 @@ function kit({ svelte_config }) {
1731
1697
  read(`${out}/client/.vite/manifest.json`)
1732
1698
  ));
1733
1699
 
1700
+ /**
1701
+ * @param {string} entry
1702
+ * @param {boolean} [add_dynamic_css]
1703
+ */
1704
+ const deps_of = (entry, add_dynamic_css = false) =>
1705
+ find_deps(vite_manifest, posixify(path.relative(root, entry)), add_dynamic_css, root);
1706
+
1707
+ // the inline bundle and stylesheet are deleted further down, after
1708
+ // being inlined into the page, so they must not appear in `immutable`
1709
+ /** @type {Set<string>} */
1710
+ const inlined = new Set();
1711
+ /** @type {Rolldown.OutputAsset | undefined} */
1712
+ let inline_style;
1713
+
1714
+ if (kit.output.bundleStrategy === 'inline') {
1715
+ inline_style = /** @type {Rolldown.OutputAsset | undefined} */ (
1716
+ client_chunks.find(
1717
+ (chunk) =>
1718
+ chunk.type === 'asset' && chunk.names.length === 1 && chunk.names[0] === 'style.css'
1719
+ )
1720
+ );
1721
+
1722
+ inlined.add(deps_of(`${runtime_directory}/client/bundle.js`).file);
1723
+ if (inline_style) inlined.add(inline_style.fileName);
1724
+ }
1725
+
1734
1726
  // Replace manifest placeholders in client output. `immutable` is
1735
1727
  // computed from the Vite client manifest, `assets` and `routes`
1736
1728
  // from `manifest_data`. `prerendered` is left as a placeholder
1737
1729
  // 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
- }
1730
+ immutable = collect_immutable(vite_manifest, kit.appDir, inlined);
1757
1731
 
1758
1732
  replace_manifest_placeholder_variables(client_chunks, `${out}/client`, {
1759
- immutable: Array.from(immutable).map((file) => ({ path: file })),
1733
+ immutable,
1760
1734
  assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
1761
1735
  routes: manifest_data.routes.map((route) => ({ id: route.id }))
1762
1736
  });
1763
1737
 
1764
1738
  // Now that the client build is done, replace the `build` sentinel
1765
1739
  // 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);
1740
+ replace_manifest_placeholder_strings(`${out}/server`, { immutable });
1776
1741
 
1777
1742
  const has_explicit_dynamic_public_env = Object.values(explicit_env_config ?? {}).some(
1778
1743
  (variable) => variable.public && !variable.static
@@ -1861,25 +1826,16 @@ function kit({ svelte_config }) {
1861
1826
  };
1862
1827
 
1863
1828
  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
1829
  build_data.client.inline = {
1874
1830
  script: read(`${out}/client/${start.file}`),
1875
- style: /** @type {string | undefined} */ (style?.source)
1831
+ style: /** @type {string | undefined} */ (inline_style?.source)
1876
1832
  };
1877
1833
 
1878
1834
  // the bundle and stylesheet are inlined into the page, so the
1879
1835
  // emitted files are never loaded
1880
1836
  fs.unlinkSync(`${out}/client/${start.file}`);
1881
1837
  fs.rmSync(`${out}/client/${start.file}.map`, { force: true });
1882
- if (style) fs.unlinkSync(`${out}/client/${style.fileName}`);
1838
+ if (inline_style) fs.unlinkSync(`${out}/client/${inline_style.fileName}`);
1883
1839
  }
1884
1840
  }
1885
1841
 
@@ -1962,6 +1918,7 @@ function kit({ svelte_config }) {
1962
1918
  vite,
1963
1919
  out,
1964
1920
  remotes,
1921
+ remote_original_by_hash,
1965
1922
  metadata,
1966
1923
  process.cwd(),
1967
1924
  server_chunks,
@@ -2054,6 +2011,7 @@ function kit({ svelte_config }) {
2054
2011
  return /** @type {Plugin[]} */ (
2055
2012
  [
2056
2013
  svelte_config.kit.adapter?.vite?.plugins,
2014
+ plugin_resolve_root,
2057
2015
  plugin_setup,
2058
2016
  plugin_remote_guard,
2059
2017
  plugin_remote,
@@ -2102,11 +2060,7 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
2102
2060
  const resolved = resolved_config[key];
2103
2061
 
2104
2062
  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) {
2063
+ if (comparable(config[key]) !== comparable(resolved)) {
2110
2064
  out.push(path + key);
2111
2065
  }
2112
2066
  } else {
@@ -2117,6 +2071,47 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
2117
2071
  return out;
2118
2072
  }
2119
2073
 
2074
+ /**
2075
+ * Collects the content-hashed files of a Vite manifest, in the shape of
2076
+ * `$app/manifest`'s `immutable` export.
2077
+ *
2078
+ * @param {Manifest} manifest
2079
+ * @param {string} app_dir
2080
+ * @param {Set<string>} inlined files deleted from the output after being inlined into the page
2081
+ * @returns {Array<{ path: string }>}
2082
+ */
2083
+ const collect_immutable = (manifest, app_dir, inlined) => {
2084
+ const prefix = `${app_dir}/immutable`;
2085
+
2086
+ /** @type {Set<string>} */
2087
+ const files = new Set();
2088
+
2089
+ /** @param {string} file */
2090
+ const add = (file) => {
2091
+ if (file.startsWith(prefix) && !inlined.has(file)) files.add(file);
2092
+ };
2093
+
2094
+ for (const key in manifest) {
2095
+ const { file, css, assets } = manifest[key];
2096
+ add(file);
2097
+ if (css) for (let i = 0; i < css.length; i++) add(css[i]);
2098
+ if (assets) for (let i = 0; i < assets.length; i++) add(assets[i]);
2099
+ }
2100
+
2101
+ return Array.from(files, (path) => ({ path }));
2102
+ };
2103
+
2104
+ /**
2105
+ * Normalizes a config value for comparison, since Windows paths may use backslashes
2106
+ * and differ in casing (e.g. the drive letter) depending on where they came from.
2107
+ * @param {any} value
2108
+ */
2109
+ function comparable(value) {
2110
+ if (typeof value !== 'string') return value;
2111
+ const normalized = posixify(value);
2112
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
2113
+ }
2114
+
2120
2115
  /**
2121
2116
  * Creates the `$app/manifest` data module. During development, real values
2122
2117
  * are emitted for `assets` and `routes` (the only data known at that point).
@@ -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
 
@@ -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
  },