diff --git a/.changeset/dry-owls-open.md b/.changeset/dry-owls-open.md new file mode 100644 index 000000000000..cd4d1e106be7 --- /dev/null +++ b/.changeset/dry-owls-open.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: use the configured base path when calling remote functions from the client diff --git a/packages/kit/src/runtime/client/remote-functions/command.js b/packages/kit/src/runtime/client/remote-functions/command.js index d9351a289f72..4218228f3051 100644 --- a/packages/kit/src/runtime/client/remote-functions/command.js +++ b/packages/kit/src/runtime/client/remote-functions/command.js @@ -1,7 +1,7 @@ /** @import { RemoteCommand, RemoteQueryOverride } from '@sveltejs/kit' */ /** @import { RemoteFunctionResponse } from 'types' */ /** @import { Query } from './query.svelte.js' */ -import { app_dir } from '__sveltekit/paths'; +import { app_dir, base } from '__sveltekit/paths'; import * as devalue from 'devalue'; import { HttpError } from '@sveltejs/kit/internal'; import { app } from '../client.js'; @@ -25,7 +25,7 @@ export function command(id) { // Wait a tick to give room for the `updates` method to be called await Promise.resolve(); - const response = await fetch(`/${app_dir}/remote/${id}`, { + const response = await fetch(`${base}/${app_dir}/remote/${id}`, { method: 'POST', body: JSON.stringify({ payload: stringify_remote_arg(arg, app.hooks.transport), diff --git a/packages/kit/src/runtime/client/remote-functions/form.svelte.js b/packages/kit/src/runtime/client/remote-functions/form.svelte.js index cef4cabcf73f..06b846d850c5 100644 --- a/packages/kit/src/runtime/client/remote-functions/form.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/form.svelte.js @@ -1,7 +1,7 @@ /** @import { RemoteForm, RemoteQueryOverride } from '@sveltejs/kit' */ /** @import { RemoteFunctionResponse } from 'types' */ /** @import { Query } from './query.svelte.js' */ -import { app_dir } from '__sveltekit/paths'; +import { app_dir, base } from '__sveltekit/paths'; import * as devalue from 'devalue'; import { DEV } from 'esm-env'; import { HttpError } from '@sveltejs/kit/internal'; @@ -61,7 +61,7 @@ export function form(id) { data.set('sveltekit:remote_refreshes', JSON.stringify(updates.map((u) => u._key))); } - const response = await fetch(`/${app_dir}/remote/${action_id}`, { + const response = await fetch(`${base}/${app_dir}/remote/${action_id}`, { method: 'POST', body: data }); diff --git a/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js b/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js index 2158d29afec4..7a919f899da3 100644 --- a/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js @@ -1,5 +1,5 @@ /** @import { RemoteFunctionResponse } from 'types' */ -import { app_dir } from '__sveltekit/paths'; +import { app_dir, base } from '__sveltekit/paths'; import { version } from '__sveltekit/environment'; import * as devalue from 'devalue'; import { DEV } from 'esm-env'; @@ -124,7 +124,7 @@ export function prerender(id) { } } - const url = `/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`; + const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`; // Check the Cache API first if (prerender_cache) { diff --git a/packages/kit/src/runtime/client/remote-functions/query.svelte.js b/packages/kit/src/runtime/client/remote-functions/query.svelte.js index edab579bb407..a6243bc85a1b 100644 --- a/packages/kit/src/runtime/client/remote-functions/query.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/query.svelte.js @@ -1,5 +1,5 @@ /** @import { RemoteQueryFunction } from '@sveltejs/kit' */ -import { app_dir } from '__sveltekit/paths'; +import { app_dir, base } from '__sveltekit/paths'; import { remote_responses, started } from '../client.js'; import { tick } from 'svelte'; import { create_remote_function, remote_request } from './shared.svelte.js'; @@ -18,7 +18,7 @@ export function query(id) { } } - const url = `/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`; + const url = `${base}/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`; return await remote_request(url); }); diff --git a/packages/kit/test/apps/options-2/src/routes/remote/+page.svelte b/packages/kit/test/apps/options-2/src/routes/remote/+page.svelte new file mode 100644 index 000000000000..a7d595d09cde --- /dev/null +++ b/packages/kit/test/apps/options-2/src/routes/remote/+page.svelte @@ -0,0 +1,28 @@ + + +

{count}

+ + + + + +
{ + await submit().updates(get_count()); + count = await get_count(); + })} +> + + +
+ + + +

{prerendered_result}

diff --git a/packages/kit/test/apps/options-2/src/routes/remote/count.remote.js b/packages/kit/test/apps/options-2/src/routes/remote/count.remote.js new file mode 100644 index 000000000000..fc93f18dd9c2 --- /dev/null +++ b/packages/kit/test/apps/options-2/src/routes/remote/count.remote.js @@ -0,0 +1,27 @@ +import { building, dev } from '$app/environment'; +import { command, form, prerender, query } from '$app/server'; + +let count = 0; + +export const get_count = query(() => count); + +export const set_count = command( + 'unchecked', + /** @param {number} c */ + async (c) => { + return (count = c); + } +); + +export const prerendered = prerender(() => { + if (!building && !dev) { + throw new Error('this prerender should not be called at runtime in production'); + } + + return 'yes'; +}); + +export const set_count_form = form(async (form_data) => { + const c = /** @type {string} */ (form_data.get('count')); + return (count = parseInt(c)); +}); diff --git a/packages/kit/test/apps/options-2/svelte.config.js b/packages/kit/test/apps/options-2/svelte.config.js index dd4414575a39..1fee777858a0 100644 --- a/packages/kit/test/apps/options-2/svelte.config.js +++ b/packages/kit/test/apps/options-2/svelte.config.js @@ -13,6 +13,9 @@ const config = { }, output: { bundleStrategy: 'single' + }, + experimental: { + remoteFunctions: true } } }; diff --git a/packages/kit/test/apps/options-2/test/test.js b/packages/kit/test/apps/options-2/test/test.js index b7fb132aa510..4af842e6f7ee 100644 --- a/packages/kit/test/apps/options-2/test/test.js +++ b/packages/kit/test/apps/options-2/test/test.js @@ -55,6 +55,55 @@ test.describe('paths', () => { await clicknav('[data-testid="link"]'); expect(new URL(page.url()).pathname).toBe('/basepath/hello'); }); + + test('query remote function from client accounts for base path', async ({ + page, + javaScriptEnabled + }) => { + test.skip(!javaScriptEnabled); + + await page.goto('/basepath/remote'); + await expect(page.locator('#count')).toHaveText(''); + await page.locator('button', { hasText: 'get count' }).click(); + await expect(page.locator('#count')).toHaveText('0'); + }); + + test('prerender remote function from client accounts for base path', async ({ + page, + javaScriptEnabled + }) => { + test.skip(!javaScriptEnabled); + + await page.goto('/basepath/remote'); + await expect(page.locator('#prerendered')).toHaveText(''); + await page.locator('button', { hasText: 'get prerendered' }).click(); + await expect(page.locator('#prerendered')).toHaveText('yes'); + }); + + test('command remote function from client accounts for base path', async ({ + page, + javaScriptEnabled + }) => { + test.skip(!javaScriptEnabled); + + await page.goto('/basepath/remote'); + await expect(page.locator('#count')).toHaveText(''); + await page.locator('button', { hasText: 'reset' }).click(); + await expect(page.locator('#count')).toHaveText('0'); + }); + + test('form remote function from client accounts for base path', async ({ + page, + javaScriptEnabled + }) => { + test.skip(!javaScriptEnabled); + + await page.goto('/basepath/remote'); + await expect(page.locator('#count')).toHaveText(''); + await page.locator('input').fill('1'); + await page.locator('button', { hasText: 'submit' }).click(); + await expect(page.locator('#count')).toHaveText('1'); + }); }); test.describe('trailing slash', () => {