From 412783b30b1b4676040dcfb4bf121d5766ccb968 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 21:49:04 -0400 Subject: [PATCH 1/2] fix: better error when `.remote.ts` files are used without the `experimental.remoteFunctions` flag --- .changeset/kind-parents-melt.md | 5 +++++ packages/kit/src/exports/vite/index.js | 18 +++++++++++++++--- packages/kit/src/exports/vite/utils.js | 4 ++-- packages/kit/src/exports/vite/utils.spec.js | 10 +++++----- .../src/runtime/app/server/remote/command.js | 4 +--- .../kit/src/runtime/app/server/remote/form.js | 4 +--- .../src/runtime/app/server/remote/prerender.js | 3 --- .../kit/src/runtime/app/server/remote/query.js | 9 +-------- .../src/runtime/app/server/remote/shared.js | 9 --------- 9 files changed, 30 insertions(+), 36 deletions(-) create mode 100644 .changeset/kind-parents-melt.md diff --git a/.changeset/kind-parents-melt.md b/.changeset/kind-parents-melt.md new file mode 100644 index 000000000000..feb8b9e2037a --- /dev/null +++ b/.changeset/kind-parents-melt.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: better error when `.remote.ts` files are used without the `experimental.remoteFunctions` flag diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index bbaf6686a63a..f05ec3dc045a 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -609,6 +609,7 @@ async function kit({ svelte_config }) { const chain = [normalized]; let current = normalized; + let includes_remote_file = false; while (true) { const importers = import_map.get(current); @@ -619,9 +620,11 @@ async function kit({ svelte_config }) { chain.push((current = candidates[0])); - if (entrypoints.has(current)) { - let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; + includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { + return current.endsWith(`.remote${ext}`); + }); + if (entrypoints.has(current)) { const pyramid = chain .reverse() .map((id, i) => { @@ -629,6 +632,15 @@ async function kit({ svelte_config }) { }) .join(' imports\n'); + if (includes_remote_file) { + error_for_missing_config( + 'remote functions', + 'kit.experimental.remoteFunctions', + 'true' + ); + } + + let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; message += `\n\n${pyramid}`; message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; @@ -794,7 +806,7 @@ async function kit({ svelte_config }) { } if (!kit.experimental.instrumentation.server) { error_for_missing_config( - 'instrumentation.server.js', + '`instrumentation.server.js`', 'kit.experimental.instrumentation.server', 'true' ); diff --git a/packages/kit/src/exports/vite/utils.js b/packages/kit/src/exports/vite/utils.js index 3eb71b0e0852..e01c1ca84498 100644 --- a/packages/kit/src/exports/vite/utils.js +++ b/packages/kit/src/exports/vite/utils.js @@ -206,9 +206,9 @@ export function error_for_missing_config(feature_name, path, value) { return acc.replace(hole, `${indent}${part}: ${rhs}`); }, hole); - throw new Error( + throw stackless( dedent`\ - To enable \`${feature_name}\`, add the following to your \`svelte.config.js\`: + To enable ${feature_name}, add the following to your \`svelte.config.js\`: \`\`\`js ${result} diff --git a/packages/kit/src/exports/vite/utils.spec.js b/packages/kit/src/exports/vite/utils.spec.js index bf13485390ad..5e12b96c0aa4 100644 --- a/packages/kit/src/exports/vite/utils.spec.js +++ b/packages/kit/src/exports/vite/utils.spec.js @@ -42,7 +42,7 @@ test('transform kit.alias to resolve.alias', () => { test('error_for_missing_config - simple single level config', () => { expect(() => error_for_missing_config('feature', 'kit.adapter', 'true')).toThrow( dedent` - To enable \`feature\`, add the following to your \`svelte.config.js\`: + To enable feature, add the following to your \`svelte.config.js\`: \`\`\`js kit: { @@ -62,7 +62,7 @@ test('error_for_missing_config - nested config', () => { ) ).toThrow( dedent` - To enable \`instrumentation.server.js\`, add the following to your \`svelte.config.js\`: + To enable instrumentation.server.js, add the following to your \`svelte.config.js\`: \`\`\`js kit: { @@ -80,7 +80,7 @@ test('error_for_missing_config - nested config', () => { test('error_for_missing_config - deeply nested config', () => { expect(() => error_for_missing_config('deep feature', 'a.b.c.d.e', '"value"')).toThrow( dedent` - To enable \`deep feature\`, add the following to your \`svelte.config.js\`: + To enable deep feature, add the following to your \`svelte.config.js\`: \`\`\`js a: { @@ -100,7 +100,7 @@ test('error_for_missing_config - deeply nested config', () => { test('error_for_missing_config - two level config', () => { expect(() => error_for_missing_config('some feature', 'kit.someFeature', 'false')).toThrow( dedent` - To enable \`some feature\`, add the following to your \`svelte.config.js\`: + To enable some feature, add the following to your \`svelte.config.js\`: \`\`\`js kit: { @@ -116,7 +116,7 @@ test('error_for_missing_config - handles special characters in feature name', () error_for_missing_config('special-feature.js', 'kit.special', '{ enabled: true }') ).toThrow( dedent` - To enable \`special-feature.js\`, add the following to your \`svelte.config.js\`: + To enable special-feature.js, add the following to your \`svelte.config.js\`: \`\`\`js kit: { diff --git a/packages/kit/src/runtime/app/server/remote/command.js b/packages/kit/src/runtime/app/server/remote/command.js index e96025e802b2..eebe03af5f9c 100644 --- a/packages/kit/src/runtime/app/server/remote/command.js +++ b/packages/kit/src/runtime/app/server/remote/command.js @@ -2,7 +2,7 @@ /** @import { RemoteInfo, MaybePromise } from 'types' */ /** @import { StandardSchemaV1 } from '@standard-schema/spec' */ import { get_request_store } from '@sveltejs/kit/internal'; -import { check_experimental, create_validator, run_remote_function } from './shared.js'; +import { create_validator, run_remote_function } from './shared.js'; /** * Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call. @@ -51,8 +51,6 @@ import { check_experimental, create_validator, run_remote_function } from './sha */ /*@__NO_SIDE_EFFECTS__*/ export function command(validate_or_fn, maybe_fn) { - check_experimental('command'); - /** @type {(arg?: Input) => Output} */ const fn = maybe_fn ?? validate_or_fn; diff --git a/packages/kit/src/runtime/app/server/remote/form.js b/packages/kit/src/runtime/app/server/remote/form.js index caa1f3120ddc..08d4b2717288 100644 --- a/packages/kit/src/runtime/app/server/remote/form.js +++ b/packages/kit/src/runtime/app/server/remote/form.js @@ -1,7 +1,7 @@ /** @import { RemoteForm } from '@sveltejs/kit' */ /** @import { RemoteInfo, MaybePromise } from 'types' */ import { get_request_store } from '@sveltejs/kit/internal'; -import { check_experimental, run_remote_function } from './shared.js'; +import { run_remote_function } from './shared.js'; /** * Creates a form object that can be spread onto a `
` element. @@ -16,8 +16,6 @@ import { check_experimental, run_remote_function } from './shared.js'; /*@__NO_SIDE_EFFECTS__*/ // @ts-ignore we don't want to prefix `fn` with an underscore, as that will be user-visible export function form(fn) { - check_experimental('form'); - /** * @param {string | number | boolean} [key] */ diff --git a/packages/kit/src/runtime/app/server/remote/prerender.js b/packages/kit/src/runtime/app/server/remote/prerender.js index 46489e7a0555..42ff28cdfa5c 100644 --- a/packages/kit/src/runtime/app/server/remote/prerender.js +++ b/packages/kit/src/runtime/app/server/remote/prerender.js @@ -7,7 +7,6 @@ import { get_request_store } from '@sveltejs/kit/internal'; import { create_remote_cache_key, stringify, stringify_remote_arg } from '../../../shared.js'; import { app_dir, base } from '__sveltekit/paths'; import { - check_experimental, create_validator, get_response, parse_remote_response, @@ -65,8 +64,6 @@ import { */ /*@__NO_SIDE_EFFECTS__*/ export function prerender(validate_or_fn, fn_or_options, maybe_options) { - check_experimental('prerender'); - const maybe_fn = typeof fn_or_options === 'function' ? fn_or_options : undefined; /** @type {typeof maybe_options} */ diff --git a/packages/kit/src/runtime/app/server/remote/query.js b/packages/kit/src/runtime/app/server/remote/query.js index 4fb38995916a..7bb54c20e5cc 100644 --- a/packages/kit/src/runtime/app/server/remote/query.js +++ b/packages/kit/src/runtime/app/server/remote/query.js @@ -4,12 +4,7 @@ import { get_request_store } from '@sveltejs/kit/internal'; import { create_remote_cache_key, stringify_remote_arg } from '../../../shared.js'; import { prerendering } from '__sveltekit/environment'; -import { - check_experimental, - create_validator, - get_response, - run_remote_function -} from './shared.js'; +import { create_validator, get_response, run_remote_function } from './shared.js'; /** * Creates a remote query. When called from the browser, the function will be invoked on the server via a `fetch` call. @@ -58,8 +53,6 @@ import { */ /*@__NO_SIDE_EFFECTS__*/ export function query(validate_or_fn, maybe_fn) { - check_experimental('query'); - /** @type {(arg?: Input) => Output} */ const fn = maybe_fn ?? validate_or_fn; diff --git a/packages/kit/src/runtime/app/server/remote/shared.js b/packages/kit/src/runtime/app/server/remote/shared.js index 431a219b7f1e..6ec750b3fb94 100644 --- a/packages/kit/src/runtime/app/server/remote/shared.js +++ b/packages/kit/src/runtime/app/server/remote/shared.js @@ -74,15 +74,6 @@ export function get_response(id, arg, state, get_result) { return ((state.remote_data ??= {})[cache_key] ??= get_result()); } -/** @param {string} feature */ -export function check_experimental(feature) { - if (!__SVELTEKIT_EXPERIMENTAL__REMOTE_FUNCTIONS__) { - throw new Error( - `Cannot use \`${feature}\` from \`$app/server\` without the experimental flag set to true. Please set kit.experimental.remoteFunctions to \`true\` in your config.` - ); - } -} - /** * @param {any} data * @param {ServerHooks['transport']} transport From 8383f17af4dd3c1749bdb72cab1733ec6d7c82a6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 16 Aug 2025 11:27:19 -0400 Subject: [PATCH 2/2] remove fence --- packages/kit/src/exports/vite/utils.js | 2 -- packages/kit/src/exports/vite/utils.spec.js | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/packages/kit/src/exports/vite/utils.js b/packages/kit/src/exports/vite/utils.js index e01c1ca84498..864080b09a7b 100644 --- a/packages/kit/src/exports/vite/utils.js +++ b/packages/kit/src/exports/vite/utils.js @@ -210,9 +210,7 @@ export function error_for_missing_config(feature_name, path, value) { dedent`\ To enable ${feature_name}, add the following to your \`svelte.config.js\`: - \`\`\`js ${result} - \`\`\` ` ); } diff --git a/packages/kit/src/exports/vite/utils.spec.js b/packages/kit/src/exports/vite/utils.spec.js index 5e12b96c0aa4..90c9ee0c91e1 100644 --- a/packages/kit/src/exports/vite/utils.spec.js +++ b/packages/kit/src/exports/vite/utils.spec.js @@ -44,11 +44,9 @@ test('error_for_missing_config - simple single level config', () => { dedent` To enable feature, add the following to your \`svelte.config.js\`: - \`\`\`js kit: { adapter: true } - \`\`\` ` ); }); @@ -64,7 +62,6 @@ test('error_for_missing_config - nested config', () => { dedent` To enable instrumentation.server.js, add the following to your \`svelte.config.js\`: - \`\`\`js kit: { experimental: { instrumentation: { @@ -72,7 +69,6 @@ test('error_for_missing_config - nested config', () => { } } } - \`\`\` ` ); }); @@ -82,7 +78,6 @@ test('error_for_missing_config - deeply nested config', () => { dedent` To enable deep feature, add the following to your \`svelte.config.js\`: - \`\`\`js a: { b: { c: { @@ -92,7 +87,6 @@ test('error_for_missing_config - deeply nested config', () => { } } } - \`\`\` ` ); }); @@ -102,11 +96,9 @@ test('error_for_missing_config - two level config', () => { dedent` To enable some feature, add the following to your \`svelte.config.js\`: - \`\`\`js kit: { someFeature: false } - \`\`\` ` ); }); @@ -118,11 +110,9 @@ test('error_for_missing_config - handles special characters in feature name', () dedent` To enable special-feature.js, add the following to your \`svelte.config.js\`: - \`\`\`js kit: { special: { enabled: true } } - \`\`\` ` ); });