@sveltejs/kit
Version:
SvelteKit is the fastest way to build Svelte apps
104 lines (90 loc) • 3.38 kB
JavaScript
/** @import { RemoteCommand } from '@sveltejs/kit' */
/** @import { MaybePromise, RemoteCommandInternals } from 'types' */
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
import { get_request_store } from '@sveltejs/kit/internal/server';
import { create_validator, run_remote_function } from './shared.js';
import { MUTATIVE_METHODS } from '../../../../constants.js';
/**
* Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call.
*
* See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
*
* @template Output
* @overload
* @param {() => MaybePromise<Output>} fn
* @returns {RemoteCommand<void, Output>}
* @since 2.27
*/
/**
* Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call.
*
* See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
*
* @template Input
* @template Output
* @overload
* @param {'unchecked'} validate
* @param {(arg: Input) => MaybePromise<Output>} fn
* @returns {RemoteCommand<Input, Output>}
* @since 2.27
*/
/**
* Creates a remote command. When called from the browser, the function will be invoked on the server via a `fetch` call.
*
* See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
*
* @template {StandardSchemaV1} Schema
* @template Output
* @overload
* @param {Schema} validate
* @param {(arg: StandardSchemaV1.InferOutput<Schema>) => MaybePromise<Output>} fn
* @returns {RemoteCommand<StandardSchemaV1.InferInput<Schema>, Output>}
* @since 2.27
*/
/**
* @template Input
* @template Output
* @param {any} validate_or_fn
* @param {(arg?: Input) => MaybePromise<Output>} [maybe_fn]
* @returns {RemoteCommand<Input, Output>}
* @since 2.27
*/
/*@__NO_SIDE_EFFECTS__*/
export function command(validate_or_fn, maybe_fn) {
/** @type {(arg?: Input) => MaybePromise<Output>} */
const fn = maybe_fn ?? validate_or_fn;
/** @type {(arg?: any) => MaybePromise<Input>} */
const validate = create_validator(validate_or_fn, maybe_fn);
/** @type {RemoteCommandInternals} */
const __ = { type: 'command', id: '', name: '' };
/** @type {RemoteCommand<Input, Output> & { __: RemoteCommandInternals }} */
const wrapper = (arg) => {
const { event, state } = get_request_store();
if (!MUTATIVE_METHODS.includes(event.request.method)) {
throw new Error(
`Cannot call a command (\`${__.name}(${maybe_fn ? '...' : ''})\`) from a ${event.request.method} handler`
);
}
if (state.is_in_render) {
throw new Error(
`Cannot call a command (\`${__.name}(${maybe_fn ? '...' : ''})\`) during server-side rendering`
);
}
state.remote.refreshes ??= new Map();
state.remote.reconnects ??= new Map();
const promise = Promise.resolve(
run_remote_function(event, state, true, () => validate(arg), fn)
);
// @ts-expect-error
promise.updates = () => {
throw new Error(`Cannot call '${__.name}(...).updates(...)' on the server`);
};
return /** @type {ReturnType<RemoteCommand<Input, Output>>} */ (promise);
};
Object.defineProperty(wrapper, '__', { value: __ });
// On the server, pending is always 0
Object.defineProperty(wrapper, 'pending', {
get: () => 0
});
return wrapper;
}