diff --git a/.changeset/quick-badgers-notice.md b/.changeset/quick-badgers-notice.md
new file mode 100644
index 000000000000..eac206f9e905
--- /dev/null
+++ b/.changeset/quick-badgers-notice.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': major
+---
+
+breaking: remove `$app/stores`
diff --git a/documentation/docs/20-core-concepts/10-routing.md b/documentation/docs/20-core-concepts/10-routing.md
index ee8629ebc45e..af646d056ce8 100644
--- a/documentation/docs/20-core-concepts/10-routing.md
+++ b/documentation/docs/20-core-concepts/10-routing.md
@@ -157,9 +157,6 @@ If an error occurs during `load`, SvelteKit will render a default error page. Yo
{page.status}: {page.error.message}
```
-> [!LEGACY]
-> `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead.
-
SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and then `src/routes/+error.svelte` before rendering the default error page. If _that_ fails (or if the error was thrown from the `load` function of the root `+layout`, which sits 'above' the root `+error`), SvelteKit will bail out and render a static fallback error page, which you can customise by creating a `src/error.html` file.
If the error occurs inside a `load` function in `+layout(.server).js`, the closest error boundary in the tree is an `+error.svelte` file _above_ that layout (not next to it).
diff --git a/documentation/docs/20-core-concepts/20-load.md b/documentation/docs/20-core-concepts/20-load.md
index 3956f47aedf6..2c895dc6af72 100644
--- a/documentation/docs/20-core-concepts/20-load.md
+++ b/documentation/docs/20-core-concepts/20-load.md
@@ -171,10 +171,6 @@ In some cases, we might need the opposite — a parent layout might need to acce
Type information for `page.data` is provided by `App.PageData`.
-> [!LEGACY]
-> `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead.
-> It provides a `page` store with the same interface that you can subscribe to, e.g. `$page.data.title`.
-
## Universal vs server
As we've seen, there are two types of `load` function:
diff --git a/documentation/docs/20-core-concepts/50-state-management.md b/documentation/docs/20-core-concepts/50-state-management.md
index 874bc6968e1b..5adcb4fce08a 100644
--- a/documentation/docs/20-core-concepts/50-state-management.md
+++ b/documentation/docs/20-core-concepts/50-state-management.md
@@ -82,7 +82,7 @@ If you're not using SSR, then there's no risk of accidentally exposing one user'
## Using state and stores with context
-You might wonder how we're able to use `page.data` and other [app state]($app-state) (or [app stores]($app-stores)) if we can't use global state. The answer is that app state and app stores on the server use Svelte's [context API](/tutorial/svelte/context-api) — the state (or store) is attached to the component tree with `setContext`, and when you subscribe you retrieve it with `getContext`. We can do the same thing with our own state:
+You might wonder how we're able to use `page.data` and other [app state]($app-state) if we can't use global state. The answer is that app state and app stores on the server use Svelte's [context API](/tutorial/svelte/context-api) — the state (or store) is attached to the component tree with `setContext`, and when you subscribe you retrieve it with `getContext`. We can do the same thing with our own state:
```svelte
diff --git a/documentation/docs/30-advanced/25-errors.md b/documentation/docs/30-advanced/25-errors.md
index 95538d279afe..bcaafae28cb7 100644
--- a/documentation/docs/30-advanced/25-errors.md
+++ b/documentation/docs/30-advanced/25-errors.md
@@ -51,9 +51,6 @@ This throws an exception that SvelteKit catches, causing it to set the response
{page.error.message}
```
-> [!LEGACY]
-> `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead.
-
You can add extra properties to the error object if needed...
```js
diff --git a/documentation/docs/30-advanced/67-shallow-routing.md b/documentation/docs/30-advanced/67-shallow-routing.md
index b69cee744fb1..09dbd8e4f178 100644
--- a/documentation/docs/30-advanced/67-shallow-routing.md
+++ b/documentation/docs/30-advanced/67-shallow-routing.md
@@ -37,9 +37,6 @@ The second argument is the new page state, which can be accessed via the [page o
To set page state without creating a new history entry, use `replaceState` instead of `pushState`.
-> [!LEGACY]
-> `page.state` from `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$page.state` from `$app/stores` instead.
-
## Loading data for a route
When shallow routing, you may want to render another `+page.svelte` inside the current page. For example, clicking on a photo thumbnail could pop up the detail view without navigating to the photo page.
diff --git a/documentation/docs/98-reference/20-$app-state.md b/documentation/docs/98-reference/20-$app-state.md
index 9362eacad82f..cbb39bc4b609 100644
--- a/documentation/docs/98-reference/20-$app-state.md
+++ b/documentation/docs/98-reference/20-$app-state.md
@@ -4,7 +4,4 @@ title: $app/state
SvelteKit makes three read-only state objects available via the `$app/state` module — `page`, `navigating` and `updated`.
-> [!NOTE]
-> This module was added in 2.12. If you're using an earlier version of SvelteKit, use [`$app/stores`]($app-stores) instead.
-
> MODULE: $app/state
diff --git a/documentation/docs/98-reference/20-$app-stores.md b/documentation/docs/98-reference/20-$app-stores.md
index ff7cf8999e82..e33c307095d2 100644
--- a/documentation/docs/98-reference/20-$app-stores.md
+++ b/documentation/docs/98-reference/20-$app-stores.md
@@ -2,6 +2,4 @@
title: $app/stores
---
-This module contains store-based equivalents of the exports from [`$app/state`]($app-state). If you're using SvelteKit 2.12 or later, use that module instead.
-
-> MODULE: $app/stores
+This module contained store-based equivalents of the exports from [`$app/state`]($app-state) but was removed in 3.0.
diff --git a/packages/kit/scripts/generate-dts.js b/packages/kit/scripts/generate-dts.js
index 60c7fe7d103f..8637db80dbf8 100644
--- a/packages/kit/scripts/generate-dts.js
+++ b/packages/kit/scripts/generate-dts.js
@@ -13,8 +13,7 @@ await createBundle({
'$app/navigation': 'src/runtime/app/navigation.js',
'$app/paths': 'src/runtime/app/paths/public.d.ts',
'$app/server': 'src/runtime/app/server/index.js',
- '$app/state': 'src/runtime/app/state/index.js',
- '$app/stores': 'src/runtime/app/stores.js'
+ '$app/state': 'src/runtime/app/state/index.js'
},
include: ['src']
});
diff --git a/packages/kit/src/core/sync/write_root.js b/packages/kit/src/core/sync/write_root.js
index 839cba4b4c00..429830542a19 100644
--- a/packages/kit/src/core/sync/write_root.js
+++ b/packages/kit/src/core/sync/write_root.js
@@ -81,45 +81,29 @@ export function write_root(manifest_data, config, output) {
-{$page.error.message}
+{page.error.message}
diff --git a/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte
deleted file mode 100644
index 96eaa6f14a32..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/client-access/+page.svelte
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-{`${pathname}`}
-
- {
- getStores().page.subscribe(($page) => (pathname = $page.url.pathname))();
- }}>click
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/+error.svelte b/packages/kit/test/apps/basics/src/routes/store/data/+error.svelte
deleted file mode 100644
index 9f5c4cf0a40d..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/+error.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- goto($page.url.toString())}>Reload
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/+layout.js b/packages/kit/test/apps/basics/src/routes/store/data/+layout.js
deleted file mode 100644
index 5d007f4b6557..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/+layout.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export function load() {
- return {
- name: 'SvelteKit',
- value: 123
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/+layout.svelte b/packages/kit/test/apps/basics/src/routes/store/data/+layout.svelte
deleted file mode 100644
index ee85d2efaf6c..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/+layout.svelte
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-{JSON.stringify($page.data)}
-{$page.error?.message}
-{$page.url.hash}
-
-
- xxx yyy
- zzz foo
-
-
-
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/[item]/+page.js b/packages/kit/test/apps/basics/src/routes/store/data/[item]/+page.js
deleted file mode 100644
index 492e40233922..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/[item]/+page.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { error } from '@sveltejs/kit';
-
-/** @type {import('./$types').PageLoad} */
-export function load({ params }) {
- if (params.item === 'xxx') {
- error(500, 'Params = xxx');
- }
-
- if (params.item === 'yyy') {
- error(500, 'Params = yyy');
- }
-
- return {
- page: params.item,
- value: 456
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/[item]/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/[item]/+page.svelte
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.js b/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.js
deleted file mode 100644
index 9a1976ddf63d..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.js
+++ /dev/null
@@ -1,18 +0,0 @@
-let is_first = true;
-
-export function load({ url }) {
- if (url.searchParams.get('reset')) {
- is_first = true;
- return {};
- }
-
- if (is_first) {
- is_first = false;
- throw new Error('uh oh');
- }
-
- return {
- foo: true,
- number: 2
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.svelte
deleted file mode 100644
index a1ecfd93e2bf..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/foo/+page.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-data - foo
-Number prop: {data.number}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/+layout.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/+layout.svelte
deleted file mode 100644
index c64728ad22d0..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/+layout.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-$page.data was updated {count} time(s)
-a
-b
-
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/a/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/a/+page.svelte
deleted file mode 100644
index 2f9719636a99..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/a/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-Page A
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/b/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/b/+page.svelte
deleted file mode 100644
index b70c2293cbaa..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/b/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-Page B
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/+layout.js b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/+layout.js
deleted file mode 100644
index 0e41121ddc5a..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/+layout.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export function load() {
- return {
- value: 'layout'
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/+page.svelte
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same-deep/nested/+page.js b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same-deep/nested/+page.js
deleted file mode 100644
index e7d4ff24d74c..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same-deep/nested/+page.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export function load() {
- return {
- value: 'page'
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same-deep/nested/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same-deep/nested/+page.svelte
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same/+page.js b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same/+page.js
deleted file mode 100644
index e7d4ff24d74c..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same/+page.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export function load() {
- return {
- value: 'page'
- };
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/data/store-update/same-keys/same/+page.svelte
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/+layout.svelte b/packages/kit/test/apps/basics/src/routes/store/navigating/+layout.svelte
deleted file mode 100644
index c15660dbf490..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/+layout.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- a
- b
- c
-
-
-
- {#if $navigating}
-
- navigating from {$navigating.from.url.pathname} to {$navigating.to.url.pathname} ({$navigating.type})
-
- {:else}
-
not currently navigating
- {/if}
-
-
-
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.js b/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.js
deleted file mode 100644
index 8c061074d89b..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/** @type {import('./$types').PageLoad} */
-export async function load() {
- await new Promise((f) => setTimeout(f, 250));
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.svelte
deleted file mode 100644
index 3a8b953071ad..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/a/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-a
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.js b/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.js
deleted file mode 100644
index 8c061074d89b..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/** @type {import('./$types').PageLoad} */
-export async function load() {
- await new Promise((f) => setTimeout(f, 250));
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.svelte
deleted file mode 100644
index db2e4f2757c0..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/b/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-b
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.js b/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.js
deleted file mode 100644
index 3b4c7fb0d06c..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @type {import('./$types').PageLoad} */
-export async function load() {
- await new Promise((f) => setTimeout(f, 1000));
- return {};
-}
diff --git a/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.svelte
deleted file mode 100644
index 2b98ed2e7228..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/navigating/c/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-c
diff --git a/packages/kit/test/apps/basics/src/routes/store/subscribe/+layout.svelte b/packages/kit/test/apps/basics/src/routes/store/subscribe/+layout.svelte
deleted file mode 100644
index 4712a7b94581..000000000000
--- a/packages/kit/test/apps/basics/src/routes/store/subscribe/+layout.svelte
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-{count}
-
- {
- invalidate('/state/subscribe');
- }}>invalidate
-
- {
- replaceState(`/store/subscribe`, { active: true });
- }}>replaceState
-
- {
- pushState(`/store/subscribe`, { active: false });
- }}>pushState
-
- {
- goto(`/store/subscribe`);
- }}>goto
-
- {
- applyAction({ type: 'success', status: 200 });
- }}>applyAction
-
-{@render children()}
diff --git a/packages/kit/test/apps/basics/src/routes/store/subscribe/+page.svelte b/packages/kit/test/apps/basics/src/routes/store/subscribe/+page.svelte
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index 61607bd6d726..a499e1fea5fa 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -400,88 +400,6 @@ test.describe('SPA mode / no SSR', () => {
});
});
-// TODO SvelteKit 3: remove these tests
-test.describe('$app/stores', () => {
- test('can use $app/stores from anywhere on client', async ({ page }) => {
- await page.goto('/store/client-access');
- await expect(page.locator('h1')).toHaveText('undefined');
- await page.locator('button').click();
- await expect(page.locator('h1')).toHaveText('/store/client-access');
- });
-
- test('$page.data does not update if data is unchanged', async ({ page, app }) => {
- await page.goto('/store/data/store-update/a');
- await app.goto('/store/data/store-update/b');
- await expect(page.locator('p')).toHaveText('$page.data was updated 0 time(s)');
- });
-
- test('$page.data does update if keys did not change but data did', async ({ page, app }) => {
- await page.goto('/store/data/store-update/same-keys/same');
- await app.goto('/store/data/store-update/same-keys');
- await expect(page.locator('p')).toHaveText('$page.data was updated 1 time(s)');
- });
-
- test('$page.data does update if keys did not change but data did (2)', async ({ page, app }) => {
- await page.goto('/store/data/store-update/same-keys/same-deep/nested');
- await app.goto('/store/data/store-update/same-keys');
- await expect(page.locator('p')).toHaveText('$page.data was updated 1 time(s)');
- });
-
- test('page subscribers are notified when invalidate is called', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'invalidate' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.locator('button', { hasText: 'invalidate' }).click();
- await expect(page.locator('p')).toHaveText('3');
- });
-
- test('page subscribers are notified when replaceState is called', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'replaceState' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.locator('button', { hasText: 'replaceState' }).click();
- await expect(page.locator('p')).toHaveText('3');
- });
-
- test('page subscribers are notified when pushState is called', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'pushState' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.locator('button', { hasText: 'pushState' }).click();
- await expect(page.locator('p')).toHaveText('3');
- });
-
- test('page subscribers are notified when goto is called', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'goto' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.locator('button', { hasText: 'goto' }).click();
- await expect(page.locator('p')).toHaveText('3');
- });
-
- test('page subscribers are notified when applyAction is called', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'applyAction' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.locator('button', { hasText: 'applyAction' }).click();
- await expect(page.locator('p')).toHaveText('3');
- });
-
- test('page subscribers are notified only once after popstate', async ({ page }) => {
- await page.goto('/store/subscribe');
- await expect(page.locator('p')).toHaveText('1');
- await page.locator('button', { hasText: 'pushState' }).click();
- await expect(page.locator('p')).toHaveText('2');
- await page.goBack();
- await expect(page.locator('p')).toHaveText('3');
- });
-});
-
test.describe('$app/state', () => {
test('can use $app/state from anywhere on client', async ({ page }) => {
await page.goto('/state/client-access');
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index 768a69f8039d..0e3ecd2071c3 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -757,6 +757,7 @@ test.describe('$app/paths', () => {
process.env.SVELTE_ASYNC === 'true',
'does not work with async, should use new functions instead'
);
+
const absolute = `${baseURL}/favicon.png`;
await page.goto('/');
@@ -804,131 +805,6 @@ test.describe('$app/paths', () => {
});
});
-// TODO SvelteKit 3: remove these tests
-test.describe('$app/stores', () => {
- test('can access page.url', async ({ baseURL, page }) => {
- await page.goto('/origin');
- expect(await page.textContent('h1')).toBe(baseURL);
- });
-
- test('page store contains data', async ({ page, clicknav }) => {
- await page.goto('/store/data/www');
-
- const foo = { bar: 'Custom layout' };
-
- expect(await page.textContent('#store-data')).toBe(
- JSON.stringify({ foo, name: 'SvelteKit', value: 456, page: 'www' })
- );
-
- await clicknav('a[href="/store/data/zzz"]');
- expect(await page.textContent('#store-data')).toBe(
- JSON.stringify({ foo, name: 'SvelteKit', value: 456, page: 'zzz' })
- );
-
- await clicknav('a[href="/store/data/xxx"]');
- expect(await page.textContent('#store-data')).toBe(
- JSON.stringify({ foo, name: 'SvelteKit', value: 123 })
- );
- expect(await page.textContent('#store-error')).toBe('Params = xxx');
-
- await clicknav('a[href="/store/data/yyy"]');
- expect(await page.textContent('#store-data')).toBe(
- JSON.stringify({ foo, name: 'SvelteKit', value: 123 })
- );
- expect(await page.textContent('#store-error')).toBe('Params = yyy');
- });
-
- test('should load data after reloading by goto', async ({
- page,
- clicknav,
- javaScriptEnabled
- }) => {
- await page.goto('/store/data/foo?reset=true');
- const stuff1 = { foo: { bar: 'Custom layout' }, name: 'SvelteKit', value: 123 };
- const stuff2 = { ...stuff1, foo: true, number: 2 };
- const stuff3 = { ...stuff2 };
- await page.goto('/store/data/www');
-
- await clicknav('a[href="/store/data/foo"]');
- expect(JSON.parse((await page.textContent('#store-data')) ?? '')).toEqual(stuff1);
-
- await clicknav('#reload-button');
- expect(JSON.parse((await page.textContent('#store-data')) ?? '')).toEqual(
- javaScriptEnabled ? stuff2 : stuff1
- );
-
- await clicknav('a[href="/store/data/zzz"]');
- await clicknav('a[href="/store/data/foo"]');
- expect(JSON.parse((await page.textContent('#store-data')) ?? '')).toEqual(stuff3);
- });
-
- test('navigating store contains from, to and type', async ({ app, page, javaScriptEnabled }) => {
- await page.goto('/store/navigating/a');
-
- expect(await page.textContent('#nav-status')).toBe('not currently navigating');
-
- if (javaScriptEnabled) {
- await app.preloadCode('/store/navigating/b');
-
- const res = await Promise.all([
- page.click('a[href="/store/navigating/b"]'),
- page.textContent('#navigating')
- ]);
-
- expect(res[1]).toBe('navigating from /store/navigating/a to /store/navigating/b (link)');
-
- await page.waitForSelector('#not-navigating');
- expect(await page.textContent('#nav-status')).toBe('not currently navigating');
-
- await Promise.all([
- expect(page.locator('#navigating')).toHaveText(
- 'navigating from /store/navigating/b to /store/navigating/a (popstate)'
- ),
- page.goBack()
- ]);
- }
- });
-
- test('navigating store clears after aborted navigation', async ({ page, javaScriptEnabled }) => {
- await page.goto('/store/navigating/a');
-
- expect(await page.textContent('#nav-status')).toBe('not currently navigating');
-
- if (javaScriptEnabled) {
- await page.click('a[href="/store/navigating/c"]');
- await page.waitForTimeout(100); // gross, but necessary since no navigation occurs
- await page.click('a[href="/store/navigating/a"]');
-
- await page.waitForSelector('#not-navigating', { timeout: 5000 });
- expect(await page.textContent('#nav-status')).toBe('not currently navigating');
- }
- });
-
- test('should update page store when URL hash is changed through the address bar', async ({
- baseURL,
- page,
- javaScriptEnabled
- }) => {
- const href = `${baseURL}/store/data/zzz`;
- await page.goto(href);
-
- expect(await page.textContent('#url-hash')).toBe('');
-
- if (javaScriptEnabled) {
- for (const urlHash of ['#1', '#2', '#5', '#8']) {
- await page.evaluate(
- ({ href, urlHash }) => {
- location.href = `${href}${urlHash}`;
- },
- { href, urlHash }
- );
-
- expect(await page.textContent('#url-hash')).toBe(urlHash);
- }
- }
- });
-});
-
test.describe('$app/state', () => {
test('can access page.url', async ({ baseURL, page }) => {
await page.goto('/origin');
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index 0a7d572f0820..015be315ad7c 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -1341,7 +1341,7 @@ declare module '@sveltejs/kit' {
};
/**
- * The shape of the [`page`](https://svelte.dev/docs/kit/$app-state#page) reactive object and the [`$page`](https://svelte.dev/docs/kit/$app-stores) store.
+ * The shape of the [`page`](https://svelte.dev/docs/kit/$app-state#page) reactive object.
*/
export interface Page<
Params extends AppLayoutParams<'/'> = AppLayoutParams<'/'>,
@@ -2738,8 +2738,6 @@ declare module '@sveltejs/kit' {
wasNormalized: boolean;
denormalize: (url?: string | URL) => URL;
};
- export type LessThan = TNumber extends TArray["length"] ? TArray[number] : LessThan;
- export type NumericRange = Exclude, LessThan>;
type ValidPageOption = (typeof valid_page_options_array)[number];
type PageOptions = Partial>;
const valid_page_options_array: readonly ["ssr", "prerender", "csr", "trailingSlash", "config", "entries", "load"];
@@ -3372,47 +3370,6 @@ declare module '$app/state' {
check(): Promise;
};
- export {};
-}
-
-declare module '$app/stores' {
- export function getStores(): {
-
- page: typeof page;
-
- navigating: typeof navigating;
-
- updated: typeof updated;
- };
- /**
- * A readable store whose value contains page data.
- *
- * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
- *
- * @deprecated Use `page` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
- * */
- export const page: import("svelte/store").Readable;
- /**
- * A readable store.
- * When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties.
- * When navigating finishes, its value reverts to `null`.
- *
- * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
- *
- * @deprecated Use `navigating` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
- * */
- export const navigating: import("svelte/store").Readable;
- /**
- * A readable store whose initial value is `false`. If [`version.pollInterval`](https://svelte.dev/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
- *
- * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
- *
- * @deprecated Use `updated` from `$app/state` instead (requires Svelte 5, [see docs for more info](https://svelte.dev/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated))
- * */
- export const updated: import("svelte/store").Readable & {
- check(): Promise;
- };
-
export {};
}/**
* It's possible to tell SvelteKit how to type objects inside your app by declaring the `App` namespace. By default, a new project will have a file called `src/app.d.ts` containing the following:
@@ -3447,23 +3404,27 @@ declare namespace App {
/**
* The interface that defines `event.locals`, which can be accessed in server [hooks](https://svelte.dev/docs/kit/hooks) (`handle`, and `handleError`), server-only `load` functions, and `+server.js` files.
*/
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface Locals {}
/**
- * Defines the common shape of the [page.data state](https://svelte.dev/docs/kit/$app-state#page) and [$page.data store](https://svelte.dev/docs/kit/$app-stores#page) - that is, the data that is shared between all pages.
+ * Defines the common shape of the [page.data state](https://svelte.dev/docs/kit/$app-state#page) - that is, the data that is shared between all pages.
* The `Load` and `ServerLoad` functions in `./$types` will be narrowed accordingly.
* Use optional properties for data that is only present on specific pages. Do not add an index signature (`[key: string]: any`).
*/
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface PageData {}
/**
* The shape of the `page.state` object, which can be manipulated using the [`pushState`](https://svelte.dev/docs/kit/$app-navigation#pushState) and [`replaceState`](https://svelte.dev/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`.
*/
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface PageState {}
/**
* If your adapter provides [platform-specific context](https://svelte.dev/docs/kit/adapters#Platform-specific-context) via `event.platform`, you can specify it here.
*/
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface Platform {}
}