import type { RemoteFormInput, RemoteQuery, RemoteQueryOverride } from "@sveltejs/kit"; import type { EffectRemoteCommandCall as ClientEffectRemoteCommandCall, EffectRemoteForm as ClientEffectRemoteForm, EffectRemoteQueryUpdateBrand as ClientEffectRemoteQueryUpdateBrand } from "../remote/client.js"; import type { Effect, Layer, ManagedRuntime, Schema, Stream } from "effect"; import type { create_form_error, RemoteFailure } from "../remote/shared.js"; import type { RemoteLiveStream } from "../live.js"; /** * Effect-like values accepted by remote helper wrappers. * * @example * ```ts * const value: EffectLike = Effect.succeed(1); * ``` * * @since 2.0.0 */ export type EffectLike = Effect.Effect | Effect.gen.Return; /** * Effect-producing callback adapted by {@link Handler} to a native SvelteKit * server handler. The callback must resolve every typed failure before the * server boundary, while its service requirements are supplied by * {@link ServerRuntime}. * * @example * ```ts * import type { RequestHandler } from "./$types"; * * const get_post: EffectHandler = ({ params }) => * Posts.get(params.slug).pipe( * Effect.map((post) => Response.json(post)), * ); * ``` * * @since 4.0.0 */ export type EffectHandler unknown, R = unknown> = (...arguments_: Parameters) => EffectLike>, never, R>; /** * Handler shape accepted by query, command, and prerender helpers. * * @example * ```ts * const handler: RemoteHandler<{ id: string }, string> = ({ id }) => * Effect.succeed(id); * ``` * * @since 2.0.0 */ export type RemoteHandler = (input: Input) => EffectLike; /** * Source shape accepted by no-argument live query helpers. * * @example * ```ts * const source: RemoteLiveSource = Stream.make(1, 2, 3); * ``` * * @since 3.4.8 */ export type RemoteLiveSource = Stream.Stream; /** * Handler shape accepted by input-bearing live query helpers. * * @example * ```ts * const handler: RemoteLiveHandler = (id) => * Stream.make(id.length); * ``` * * @since 2.0.0 */ export type RemoteLiveHandler = (input: Input) => Stream.Stream; /** * Handler shape accepted by batch query helpers. The handler receives the * validated inputs collected by SvelteKit and returns an Effect-producing * resolver for each requested input. * * @example * ```ts * const handler: EffectRemoteBatchHandler = (ids) => * Effect.succeed((id) => ids.includes(id)); * ``` * * @since 2.0.0 */ export type EffectRemoteBatchHandler = (inputs: readonly Input[]) => EffectLike<(input: Input, index: number) => A, E, R>; /** * Handler shape accepted by the form helper. * * @example * ```ts * const handler: RemoteFormHandler<{ email: string }, { ok: true }> = ( * { data }, * ) => Effect.succeed({ ok: data.email.length > 0 }); * ``` * * @since 2.0.0 */ export type RemoteFormHandler = (input: { readonly data: Input; readonly invalid: FormInvalid; readonly issue: unknown; }) => EffectLike; /** * Proxy callable used to create typed form validation failures. * * @example * ```ts * const fail: Effect.Effect = invalid.email( * "Use an email address.", * ); * ``` * * @since 2.0.0 */ export type FormInvalid = FormInvalidFunctionChildren & FormInvalidChildren & { (message: string): Effect.Effect>; }; type FormInvalidFunctionChildren = { readonly apply: FormInvalid; readonly bind: FormInvalid; readonly call: FormInvalid; readonly length: FormInvalid; readonly name: FormInvalid; readonly toString: FormInvalid; }; type FormInvalidChildren = IsUnknown extends true ? { readonly [key: string]: FormInvalid; } : NonNullable extends readonly (infer Item)[] ? { readonly [index: number]: FormInvalid; } : NonNullable extends object ? { readonly [Key in keyof NonNullable]-?: FormInvalid[Key]>; } : Record; type IsUnknown = unknown extends Value ? ([Value] extends [unknown] ? true : false) : false; /** * Options accepted by the prerender helper. * * @example * ```ts * const options: PrerenderOptions = { * inputs: () => Effect.succeed(["first-post", "second-post"]), * dynamic: true, * }; * ``` * * @since 2.0.0 */ export type PrerenderOptions = { readonly inputs?: PrerenderInputs; readonly dynamic?: boolean; }; /** * Effect-producing input generator for a prerendered remote function. * * @since 4.0.0 * @returns The caller inputs SvelteKit should prerender. */ export type PrerenderInputs = () => EffectLike; /** * Minimal Standard Schema shape accepted by SvelteKit remote helpers. * * @example * ```ts * const schema: StandardSchema = { * "~standard": { * validate: (input) => ({ value: input }), * }, * }; * ``` * * @since 2.0.0 */ export type StandardSchema = { readonly "~standard": { readonly types?: { readonly input: unknown; readonly output: unknown; }; readonly validate: (input: unknown) => unknown; }; }; /** * Extracts the input type from an Effect Schema. * * @example * ```ts * type Input = SchemaInput; * ``` * * @since 2.0.0 */ export type SchemaInput = S extends Schema.Top ? Schema.Schema.Type : unknown; /** * Extracts the encoded caller input type from an Effect Schema. * * @example * ```ts * type Input = SchemaEncodedInput; * ``` * * @since 2.4.2 */ export type SchemaEncodedInput = S extends Schema.Top ? S["Encoded"] : unknown; /** * Extracts the encoded input type from a Standard Schema. * * @example * ```ts * type Input = StandardSchemaInput; * ``` * * @since 3.0.0 */ export type StandardSchemaInput = S extends { readonly "~standard": { readonly types: { readonly input: infer Input; }; }; } ? Input : unknown; /** * Extracts the decoded handler input type from a Standard Schema. * * @example * ```ts * type Output = StandardSchemaOutput; * ``` * * @since 3.0.0 */ export type StandardSchemaOutput = S extends { readonly "~standard": { readonly types: { readonly output: infer Output; }; }; } ? Output : StandardSchemaInput; /** * Root and server export shape for building the server-side runtime. * * @example * ```ts * const runtime = ServerRuntime.make(); * ``` * * @since 2.0.0 */ export interface ServerRuntimeFactory { /** * Builds and caches the server-side Effect runtime. * * @param layer - Optional Effect layer to provide to remote handlers. * @returns The managed runtime used by server-side SER helpers. */ make(layer?: Layer.Layer): ManagedRuntime.ManagedRuntime; } /** * Root and server export shape for query helpers. * * @example * ```ts * export const GetUser = Query(Schema.Struct({ id: Schema.String }), ({ id }) => * Effect.succeed({ id }) * ); * ``` * * @since 2.0.0 */ export interface QueryFactory { (validate_or_handler: EffectLike | RemoteHandler): EffectRemoteQueryFunction; (validate_or_handler: "unchecked", maybe_handler: RemoteHandler): EffectRemoteQueryFunction; , A, E = never, R = never>(validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>): EffectRemoteQueryFunction, A, E>; (validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>): EffectRemoteQueryFunction, A, E>; readonly batch: QueryBatchFactory; readonly live: QueryLiveFactory; } /** * Root and server export shape for batched query helpers. * * @example * ```ts * export const HasUser = Query.batch(Schema.String, (ids) => * Effect.succeed((id) => ids.includes(id)) * ); * ``` * * @since 2.0.0 */ export interface QueryBatchFactory { (validate_or_handler: "unchecked", maybe_handler: EffectRemoteBatchHandler): EffectRemoteQueryFunction; , A, E = never, R = never>(validate_or_handler: S, maybe_handler: EffectRemoteBatchHandler, A, E, R>): EffectRemoteQueryFunction, A, E>; (validate_or_handler: S, maybe_handler: EffectRemoteBatchHandler, A, E, R>): EffectRemoteQueryFunction, A, E>; } /** * Root and server export shape for live query helpers. * * @example * ```ts * export const Clock = Query.live(() => Stream.repeatValue(new Date())); * ``` * * @since 2.0.0 */ export interface QueryLiveFactory { (validate_or_handler: RemoteLiveSource | RemoteLiveHandler): EffectRemoteLiveQueryFunction; (validate_or_handler: "unchecked", maybe_handler: RemoteLiveHandler): EffectRemoteLiveQueryFunction; , A, E = never, R = never>(validate_or_handler: S, maybe_handler: RemoteLiveHandler, A, E, R>): EffectRemoteLiveQueryFunction, A, E>; (validate_or_handler: S, maybe_handler: RemoteLiveHandler, A, E, R>): EffectRemoteLiveQueryFunction, A, E>; } /** * Root and server export shape for command helpers. * * @example * ```ts * export const SaveUser = Command( * Schema.Struct({ id: Schema.String }), * ({ id }) => Effect.succeed({ id, saved: true }), * ); * ``` * * @since 2.0.0 */ export interface CommandFactory { (validate_or_handler: EffectLike | RemoteHandler): EffectRemoteCommand; (validate_or_handler: "unchecked", maybe_handler: RemoteHandler): EffectRemoteCommand; , A, E = never, R = never>(validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>): EffectRemoteCommand, A, E>; (validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>): EffectRemoteCommand, A, E>; } /** * Root and server export shape for form helpers. * * @example * ```ts * export const SignIn = Form( * Schema.Struct({ email: Schema.String }), * ({ data }) => Effect.succeed({ ok: data.email.length > 0 }), * ); * ``` * * @since 2.0.0 */ export interface FormFactory { (validate_or_handler: EffectLike | RemoteFormHandler): EffectRemoteForm; (validate_or_handler: "unchecked", maybe_handler: RemoteFormHandler): EffectRemoteForm; (validate_or_handler: S, maybe_handler: RemoteFormHandler, A, E, R>): EffectRemoteForm, A, E>; (validate_or_handler: S, maybe_handler: RemoteFormHandler, A, E, R>): EffectRemoteForm, A, E>; } /** * Root and server export shape for prerender helpers. * * @example * ```ts * export const GetBuildInfo = Prerender(() => Effect.succeed("ready")); * ``` * * @since 2.0.0 */ export interface PrerenderFactory { (validate_or_handler: EffectLike | RemoteHandler, maybe_options?: PrerenderOptions): EffectRemotePrerenderFunction; (validate_or_handler: "unchecked", maybe_handler: RemoteHandler, maybe_options?: PrerenderOptions): EffectRemotePrerenderFunction; , A, E = never, R = never>(validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>, maybe_options?: PrerenderOptions>): EffectRemotePrerenderFunction, A, E>; (validate_or_handler: S, maybe_handler: RemoteHandler, A, E, R>, maybe_options?: PrerenderOptions>): EffectRemotePrerenderFunction, A, E>; } /** * Base Effect-returning function type used by remote commands. * * @example * ```ts * const SavePost: EffectRemoteFunction = (id) => * Effect.succeed({ saved: true }); * ``` * * @since 2.0.0 */ export type EffectRemoteFunction = [Input] extends [void] ? () => Effect.Effect, never> : undefined extends Input ? (input?: Input) => Effect.Effect, never> : (input: Input) => Effect.Effect, never>; /** * Effect-returning prerender resource with SvelteKit's read-only state * preserved. * * @since 4.0.0 */ export type EffectRemotePrerender = Effect.Effect, never> & { readonly current: A | undefined; readonly error: unknown; readonly loading: boolean; readonly ready: boolean; }; /** * Effect-returning prerender function whose resource state remains readable. * * @since 4.0.0 */ export type EffectRemotePrerenderFunction = [Input] extends [void] ? () => EffectRemotePrerender : undefined extends Input ? (input?: Input) => EffectRemotePrerender : (input: Input) => EffectRemotePrerender; /** * Effect-returning query resource with SvelteKit cache update methods * preserved. * * @example * ```ts * const posts = GetPosts(); * yield* posts.refresh(); * ``` * * @since 2.0.0 */ export type EffectRemoteQuery = ClientEffectRemoteQueryUpdateBrand & Effect.Effect, never> & Pick, "set"> & { readonly current: A | undefined; readonly error: unknown; readonly loading: boolean; readonly ready: boolean; readonly refresh: () => Effect.Effect; readonly withOverride: (update: (current: A) => A) => RemoteQueryOverride; }; /** * Effect-returning remote query function with SvelteKit query resource methods * preserved on the returned Effect. * * @example * ```ts * const posts = GetPosts(); * yield* posts; * yield* posts.refresh(); * ``` * * @since 2.0.0 */ export type EffectRemoteQueryFunction = [Input] extends [void] ? () => EffectRemoteQuery : undefined extends Input ? (input?: Input) => EffectRemoteQuery : (input: Input) => EffectRemoteQuery; /** * Remote live query stream. * * @example * ```ts * const clock = getClock(); * const first = yield* Stream.runHead(clock); * ``` * * @since 3.4.8 */ export type EffectRemoteLiveQuery = RemoteLiveStream; /** * Remote live query function returning an Effect Stream. * * @example * ```ts * const clock = getClock(); * ``` * * @since 3.4.8 */ export type EffectRemoteLiveQueryFunction = [Input] extends [void] ? () => EffectRemoteLiveQuery : undefined extends Input ? (input?: Input) => EffectRemoteLiveQuery : (input: Input) => EffectRemoteLiveQuery; /** * Effect returned by a command invocation, including SvelteKit's per-call * query update selection. * * @since 4.0.0 */ export type EffectRemoteCommandCall = ClientEffectRemoteCommandCall; /** * Effect-returning command type with SvelteKit's pending counter and per-call * updates preserved. * * @since 2.0.0 */ export type EffectRemoteCommand = ([Input] extends [void] ? () => EffectRemoteCommandCall : undefined extends Input ? (input?: Input) => EffectRemoteCommandCall : (input: Input) => EffectRemoteCommandCall) & { readonly pending: number; }; /** * Effect-returning form type with SvelteKit form helpers preserved. * * @example * ```ts * const signIn: EffectRemoteForm<{ email: string }, { ok: true }> = * Form(Schema.Struct({ email: Schema.String }), ({ data }) => * Effect.succeed({ ok: data.email.length > 0 }) * ); * ``` * * @since 2.0.0 * @template Input - Data shape submitted by the remote form. * @template A - Successful value produced by the form handler. */ export type EffectRemoteForm = ClientEffectRemoteForm; type FormSchemaEncodedInput = S extends Schema.Top ? FormRemoteInput : never; type FormRemoteInput = NormalizeFormEncoded extends RemoteFormInput ? NormalizeFormEncoded : never; type FormStandardSchemaInput = StandardSchemaInput extends RemoteFormInput ? StandardSchemaInput : RemoteFormInput; type FormScalar = string | number | boolean | File; type NormalizeFormEncoded = Value extends FormScalar ? Value : Value extends ReadonlyArray ? Array> : Value extends object ? NormalizeFormObject : Value; type NormalizeFormObject = { readonly [Key in keyof Value]: Key extends OptionalFormKeys ? NormalizeFormEncoded> : NormalizeFormEncoded; }; type OptionalFormKeys = { [Key in keyof Value]-?: Record extends Pick ? Key : never; }[keyof Value]; export {};