Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/forty-dots-punch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: enable redirects from queries
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ export function query_batch(id) {
}

if (result.type === 'redirect') {
// TODO double-check this
await goto(result.location);
await new Promise((r) => setTimeout(r, 100));
throw new Redirect(307, result.location);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,7 @@ export async function remote_request(url) {
const result = /** @type {RemoteFunctionResponse} */ (await response.json());

if (result.type === 'redirect') {
// resource_cache.delete(cache_key);
// version++;
// await goto(result.location);
// /** @type {Query<any>} */ (resource).refresh();
// TODO double-check this
await goto(result.location);
await new Promise((r) => setTimeout(r, 100));
throw new Redirect(307, result.location);
}

Expand Down
8 changes: 4 additions & 4 deletions packages/kit/src/runtime/server/remote.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
}

const form_data = await event.request.formData();
form_client_refreshes = JSON.parse(
/** @type {string} */ (form_data.get('sveltekit:remote_refreshes')) ?? '[]'
form_client_refreshes = /** @type {string[]} */ (
JSON.parse(/** @type {string} */ (form_data.get('sveltekit:remote_refreshes')) ?? '[]')
);
form_data.delete('sveltekit:remote_refreshes');

Expand All @@ -129,7 +129,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
/** @type {RemoteFunctionResponse} */ ({
type: 'result',
result: stringify(data, transport),
refreshes: await serialize_refreshes(/** @type {string[]} */ (form_client_refreshes))
refreshes: await serialize_refreshes(form_client_refreshes)
})
);
}
Expand Down Expand Up @@ -194,7 +194,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
* @param {string[]} client_refreshes
*/
async function serialize_refreshes(client_refreshes) {
const refreshes = /** @type {Record<string, Promise<any>>} */ (state.refreshes);
const refreshes = state.refreshes ?? {};

for (const key of client_refreshes) {
if (refreshes[key] !== undefined) continue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<a href="/remote/query-redirect/from-page">from page</a>
<a href="/remote/query-redirect/from-common-layout">from layout</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script>
import { page } from '$app/state';
import { layoutRedirect } from '../redirect.remote';

let { children } = $props();
</script>

<!-- TODO convert to await expression once experimental async turned on -->
{#await layoutRedirect(page.url.pathname) then path}
<p id="layout-query">on page {path} (== {page.url.pathname})</p>
{/await}

{@render children()}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>should never see this</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p id="redirected">redirected</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
import { pageRedirect } from '../redirect.remote';
</script>

<!-- TODO convert to await expression once experimental async turned on -->
{#await pageRedirect() then _}
<p>should never see this</p>
{/await}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { query } from '$app/server';
import { redirect } from '@sveltejs/kit';

export const layoutRedirect = query('unchecked', (path) => {
if (path !== '/remote/query-redirect/from-common-layout/redirected') {
redirect(307, '/remote/query-redirect/from-common-layout/redirected');
}

return path;
});

export const pageRedirect = query(() => {
redirect(307, '/remote/query-redirect/redirected');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p id="redirected">redirected</p>
24 changes: 24 additions & 0 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,30 @@ test.describe('remote functions', () => {
}
});

test('query redirects on page load (query in common layout)', async ({
page,
javaScriptEnabled
}) => {
// TODO remove once async SSR exists
if (!javaScriptEnabled) return;

await page.goto('/remote/query-redirect');
await page.click('a[href="/remote/query-redirect/from-common-layout"]');
await expect(page.locator('#redirected')).toHaveText('redirected');
await expect(page.locator('#layout-query')).toHaveText(
'on page /remote/query-redirect/from-common-layout/redirected (== /remote/query-redirect/from-common-layout/redirected)'
);
});

test('query redirects on page load (query on page)', async ({ page, javaScriptEnabled }) => {
// TODO remove once async SSR exists
if (!javaScriptEnabled) return;

await page.goto('/remote/query-redirect');
await page.click('a[href="/remote/query-redirect/from-page"]');
await expect(page.locator('#redirected')).toHaveText('redirected');
});

test('form works', async ({ page }) => {
await page.goto('/remote/form');
await page.fill('#input-task', 'hi');
Expand Down
Loading