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/kind-parents-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: better error when `.remote.ts` files are used without the `experimental.remoteFunctions` flag
18 changes: 15 additions & 3 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -619,16 +620,27 @@ 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) => {
return `${' '.repeat(i + 1)}${id}`;
})
.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\`.`;

Expand Down Expand Up @@ -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'
);
Expand Down
6 changes: 2 additions & 4 deletions packages/kit/src/exports/vite/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,11 @@ 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}
\`\`\`
`
);
}
20 changes: 5 additions & 15 deletions packages/kit/src/exports/vite/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@ 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: {
adapter: true
}
\`\`\`
`
);
});
Expand All @@ -62,27 +60,24 @@ 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: {
experimental: {
instrumentation: {
server: true
}
}
}
\`\`\`
`
);
});

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: {
b: {
c: {
Expand All @@ -92,21 +87,18 @@ 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: {
someFeature: false
}
\`\`\`
`
);
});
Expand All @@ -116,13 +108,11 @@ 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: {
special: { enabled: true }
}
\`\`\`
`
);
});
4 changes: 1 addition & 3 deletions packages/kit/src/runtime/app/server/remote/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/** @import { RemoteInfo, MaybePromise } from 'types' */
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
import { get_request_store } from '@sveltejs/kit/internal/server';
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.
Expand Down Expand Up @@ -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;

Expand Down
4 changes: 1 addition & 3 deletions packages/kit/src/runtime/app/server/remote/form.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @import { RemoteForm } from '@sveltejs/kit' */
/** @import { RemoteInfo, MaybePromise } from 'types' */
import { get_request_store } from '@sveltejs/kit/internal/server';
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 `<form>` element.
Expand All @@ -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]
*/
Expand Down
3 changes: 0 additions & 3 deletions packages/kit/src/runtime/app/server/remote/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { get_request_store } from '@sveltejs/kit/internal/server';
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,
Expand Down Expand Up @@ -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} */
Expand Down
9 changes: 1 addition & 8 deletions packages/kit/src/runtime/app/server/remote/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
import { get_request_store } from '@sveltejs/kit/internal/server';
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.
Expand Down Expand Up @@ -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;

Expand Down
9 changes: 0 additions & 9 deletions packages/kit/src/runtime/app/server/remote/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading