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}`}

- - 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 @@ - - - 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}
- - - - 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 @@ - - - - - - - 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}

- - - - - - - - - - - -{@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 {} }