UNPKG

@rivetkit/core

Version:

1,383 lines (1,369 loc) 83.9 kB
import { z } from 'zod'; import * as hono from 'hono'; import { Env, Context, Hono } from 'hono'; import { WebSocket as WebSocket$1 } from 'ws'; import { Logger } from './common/log.js'; import { UpgradeWebSocket } from './utils.js'; import * as nanoevents from 'nanoevents'; import { g as Connection, h as RealtimeEvent } from './common-CXCe7s6i.js'; import { SSEStreamingApi } from 'hono/streaming'; import { WSContext } from 'hono/ws'; declare const ToClientSchema: z.ZodObject<{ b: z.ZodUnion<[z.ZodObject<{ i: z.ZodObject<{ ai: z.ZodString; ci: z.ZodString; ct: z.ZodString; }, "strip", z.ZodTypeAny, { ai: string; ci: string; ct: string; }, { ai: string; ci: string; ct: string; }>; }, "strip", z.ZodTypeAny, { i: { ai: string; ci: string; ct: string; }; }, { i: { ai: string; ci: string; ct: string; }; }>, z.ZodObject<{ e: z.ZodObject<{ c: z.ZodString; m: z.ZodString; md: z.ZodOptional<z.ZodUnknown>; ai: z.ZodOptional<z.ZodNumber>; }, "strip", z.ZodTypeAny, { c: string; m: string; ai?: number | undefined; md?: unknown; }, { c: string; m: string; ai?: number | undefined; md?: unknown; }>; }, "strip", z.ZodTypeAny, { e: { c: string; m: string; ai?: number | undefined; md?: unknown; }; }, { e: { c: string; m: string; ai?: number | undefined; md?: unknown; }; }>, z.ZodObject<{ ar: z.ZodObject<{ i: z.ZodNumber; o: z.ZodUnknown; }, "strip", z.ZodTypeAny, { i: number; o?: unknown; }, { i: number; o?: unknown; }>; }, "strip", z.ZodTypeAny, { ar: { i: number; o?: unknown; }; }, { ar: { i: number; o?: unknown; }; }>, z.ZodObject<{ ev: z.ZodObject<{ n: z.ZodString; a: z.ZodArray<z.ZodUnknown, "many">; }, "strip", z.ZodTypeAny, { n: string; a: unknown[]; }, { n: string; a: unknown[]; }>; }, "strip", z.ZodTypeAny, { ev: { n: string; a: unknown[]; }; }, { ev: { n: string; a: unknown[]; }; }>]>; }, "strip", z.ZodTypeAny, { b: { i: { ai: string; ci: string; ct: string; }; } | { e: { c: string; m: string; ai?: number | undefined; md?: unknown; }; } | { ar: { i: number; o?: unknown; }; } | { ev: { n: string; a: unknown[]; }; }; }, { b: { i: { ai: string; ci: string; ct: string; }; } | { e: { c: string; m: string; ai?: number | undefined; md?: unknown; }; } | { ar: { i: number; o?: unknown; }; } | { ev: { n: string; a: unknown[]; }; }; }>; type ToClient = z.infer<typeof ToClientSchema>; type InferDatabaseClient<DBProvider extends AnyDatabaseProvider> = DBProvider extends DatabaseProvider<any> ? Awaited<ReturnType<DBProvider["createClient"]>> : never; type AnyDatabaseProvider = DatabaseProvider<any> | undefined; type DatabaseProvider<DB extends { execute: (query: string) => any; }> = { /** * Creates a new database client for the actor. * The result is passed to the actor context as `c.db`. * @experimental */ createClient: (ctx: { getDatabase: () => Promise<string | unknown>; }) => Promise<DB>; /** * Runs before the actor has started. * Use this to run migrations or other setup tasks. * @experimental */ onMigrate: (client: DB) => void | Promise<void>; }; /** Data that's been serialized. */ type OutputData = string | Uint8Array; declare const EncodingSchema: z.ZodEnum<["json", "cbor"]>; /** * Encoding used to communicate between the client & actor. */ type Encoding = z.infer<typeof EncodingSchema>; /** * Helper class that helps serialize data without re-serializing for the same encoding. */ declare class CachedSerializer<T> { #private; constructor(data: T); get rawData(): T; serialize(encoding: Encoding): OutputData; } declare const ActorsSchema: z.ZodRecord<z.ZodString, z.ZodType<ActorDefinition<any, any, any, any, any, any, any, any>, z.ZodTypeDef, ActorDefinition<any, any, any, any, any, any, any, any>>>; type RegistryActors = z.infer<typeof ActorsSchema>; /** Base config used for the actor config across all platforms. */ declare const RegistryConfigSchema: z.ZodObject<{ use: z.ZodRecord<z.ZodString, z.ZodType<AnyActorDefinition, z.ZodTypeDef, AnyActorDefinition>>; /** * Test configuration. * * DO NOT MANUALLY ENABLE. THIS IS USED INTERNALLY. * @internal **/ test: z.ZodDefault<z.ZodOptional<z.ZodObject<{ enabled: z.ZodBoolean; }, "strip", z.ZodTypeAny, { enabled: boolean; }, { enabled: boolean; }>>>; }, "strip", z.ZodTypeAny, { use: Record<string, AnyActorDefinition>; test: { enabled: boolean; }; }, { use: Record<string, AnyActorDefinition>; test?: { enabled: boolean; } | undefined; }>; type RegistryConfig = z.infer<typeof RegistryConfigSchema>; type RegistryConfigInput<A extends RegistryActors> = Omit<z.input<typeof RegistryConfigSchema>, "use"> & { use: A; }; interface RivetEvent { type: string; target?: any; currentTarget?: any; } interface RivetMessageEvent extends RivetEvent { data: any; } interface RivetCloseEvent extends RivetEvent { code: number; reason: string; wasClean: boolean; } /** * Common WebSocket interface that can be implemented by different WebSocket-like classes * This is compatible with the standard WebSocket API but allows for custom implementations */ interface UniversalWebSocket { readonly CONNECTING: 0; readonly OPEN: 1; readonly CLOSING: 2; readonly CLOSED: 3; readonly readyState: 0 | 1 | 2 | 3; binaryType: "arraybuffer" | "blob"; readonly bufferedAmount: number; readonly extensions: string; readonly protocol: string; readonly url: string; send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void; close(code?: number, reason?: string): void; addEventListener(type: string, listener: (event: any) => void): void; removeEventListener(type: string, listener: (event: any) => void): void; dispatchEvent(event: RivetEvent): boolean; onopen?: ((event: RivetEvent) => void) | null; onclose?: ((event: RivetCloseEvent) => void) | null; onerror?: ((event: RivetEvent) => void) | null; onmessage?: ((event: RivetMessageEvent) => void) | null; } type ManagerDriverBuilder = (registryConfig: RegistryConfig, runConfig: RunConfig) => ManagerDriver; interface ManagerDriver { getForId(input: GetForIdInput): Promise<ActorOutput | undefined>; getWithKey(input: GetWithKeyInput): Promise<ActorOutput | undefined>; getOrCreateWithKey(input: GetOrCreateWithKeyInput): Promise<ActorOutput>; createActor(input: CreateInput): Promise<ActorOutput>; sendRequest(actorId: string, actorRequest: Request): Promise<Response>; openWebSocket(path: string, actorId: string, encoding: Encoding, params: unknown): Promise<WebSocket>; proxyRequest(c: Context, actorRequest: Request, actorId: string): Promise<Response>; proxyWebSocket(c: Context, path: string, actorId: string, encoding: Encoding, params: unknown, authData: unknown): Promise<Response>; extraStartupLog?: () => Record<string, unknown>; modifyManagerRouter?: (registryConfig: RegistryConfig, router: Hono) => void; } interface GetForIdInput<E extends Env = any> { c?: Context | undefined; actorId: string; } interface GetWithKeyInput<E extends Env = any> { c?: Context | undefined; name: string; key: ActorKey; } interface GetOrCreateWithKeyInput<E extends Env = any> { c?: Context | undefined; name: string; key: ActorKey; input?: unknown; region?: string; } interface CreateInput<E extends Env = any> { c?: Context | undefined; name: string; key: ActorKey; input?: unknown; region?: string; } interface ActorOutput { actorId: string; name: string; key: ActorKey; } type GetUpgradeWebSocket = () => UpgradeWebSocket; declare const DriverConfigSchema: z.ZodObject<{ /** Machine-readable name to identify this driver by. */ name: z.ZodString; manager: z.ZodType<ManagerDriverBuilder, z.ZodTypeDef, ManagerDriverBuilder>; actor: z.ZodType<ActorDriverBuilder, z.ZodTypeDef, ActorDriverBuilder>; }, "strip", z.ZodTypeAny, { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; }, { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; }>; type DriverConfig = z.infer<typeof DriverConfigSchema>; /** Base config used for the actor config across all platforms. */ declare const RunConfigSchema: z.ZodDefault<z.ZodObject<{ driver: z.ZodDefault<z.ZodOptional<z.ZodObject<{ /** Machine-readable name to identify this driver by. */ name: z.ZodString; manager: z.ZodType<ManagerDriverBuilder, z.ZodTypeDef, ManagerDriverBuilder>; actor: z.ZodType<ActorDriverBuilder, z.ZodTypeDef, ActorDriverBuilder>; }, "strip", z.ZodTypeAny, { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; }, { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; }>>>; getUpgradeWebSocket: z.ZodOptional<z.ZodType<GetUpgradeWebSocket, z.ZodTypeDef, GetUpgradeWebSocket>>; /** CORS configuration for the router. Uses Hono's CORS middleware options. */ cors: z.ZodOptional<z.ZodType<{ origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }, z.ZodTypeDef, { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }>>; maxIncomingMessageSize: z.ZodDefault<z.ZodOptional<z.ZodNumber>>; studio: z.ZodDefault<z.ZodOptional<z.ZodObject<{ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>; cors: z.ZodDefault<z.ZodOptional<z.ZodType<{ origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }, z.ZodTypeDef, { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }>>>; token: z.ZodDefault<z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodString>>>; defaultEndpoint: z.ZodOptional<z.ZodString>; }, "strip", z.ZodTypeAny, { enabled: boolean; cors: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }; token: (...args: unknown[]) => string; defaultEndpoint?: string | undefined; }, { enabled?: boolean | undefined; cors?: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; } | undefined; token?: ((...args: unknown[]) => string) | undefined; defaultEndpoint?: string | undefined; }>>>; /** * Base path for the router. This is used to prefix all routes. * For example, if the base path is `/api`, then the route `/actors` will be * available at `/api/actors`. */ basePath: z.ZodDefault<z.ZodOptional<z.ZodString>>; }, "strip", z.ZodTypeAny, { driver: { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; }; maxIncomingMessageSize: number; studio: { enabled: boolean; cors: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; }; token: (...args: unknown[]) => string; defaultEndpoint?: string | undefined; }; basePath: string; cors?: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; } | undefined; getUpgradeWebSocket?: GetUpgradeWebSocket | undefined; }, { cors?: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; } | undefined; driver?: { name: string; actor: ActorDriverBuilder; manager: ManagerDriverBuilder; } | undefined; getUpgradeWebSocket?: GetUpgradeWebSocket | undefined; maxIncomingMessageSize?: number | undefined; studio?: { enabled?: boolean | undefined; cors?: { origin: string | string[] | ((origin: string, c: hono.Context) => string | undefined | null); allowMethods?: string[] | ((origin: string, c: hono.Context) => string[]); allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; } | undefined; token?: ((...args: unknown[]) => string) | undefined; defaultEndpoint?: string | undefined; } | undefined; basePath?: string | undefined; }>>; type RunConfig = z.infer<typeof RunConfigSchema>; type RunConfigInput = z.input<typeof RunConfigSchema>; interface ServerOutput<A extends Registry<any>> { client: Client<A>; hono: Hono; handler: (req: Request) => Promise<Response>; serve: (hono?: Hono) => void; } interface ActorNodeOutput { hono: Hono<any>; handler: (req: Request) => Promise<Response>; serve: (hono?: Hono) => void; } declare class Registry<A extends RegistryActors> { #private; get config(): RegistryConfig; constructor(config: RegistryConfig); /** * Runs the registry for a server. */ createServer(inputConfig?: RunConfigInput): ServerOutput<this>; /** * Runs the registry as a standalone server. */ runServer(inputConfig?: RunConfigInput): Promise<void>; /** * Creates a worker for the registry. */ createWorker(inputConfig?: RunConfigInput): ActorNodeOutput; /** * Runs the standalone worker. */ runWorker(inputConfig?: RunConfigInput): Promise<void>; } declare function setup<A extends RegistryActors>(input: RegistryConfigInput<A>): Registry<A>; declare const ToServerSchema: z.ZodObject<{ b: z.ZodUnion<[z.ZodObject<{ ar: z.ZodObject<{ i: z.ZodNumber; n: z.ZodString; a: z.ZodArray<z.ZodUnknown, "many">; }, "strip", z.ZodTypeAny, { i: number; n: string; a: unknown[]; }, { i: number; n: string; a: unknown[]; }>; }, "strip", z.ZodTypeAny, { ar: { i: number; n: string; a: unknown[]; }; }, { ar: { i: number; n: string; a: unknown[]; }; }>, z.ZodObject<{ sr: z.ZodObject<{ e: z.ZodString; s: z.ZodBoolean; }, "strip", z.ZodTypeAny, { e: string; s: boolean; }, { e: string; s: boolean; }>; }, "strip", z.ZodTypeAny, { sr: { e: string; s: boolean; }; }, { sr: { e: string; s: boolean; }; }>]>; }, "strip", z.ZodTypeAny, { b: { ar: { i: number; n: string; a: unknown[]; }; } | { sr: { e: string; s: boolean; }; }; }, { b: { ar: { i: number; n: string; a: unknown[]; }; } | { sr: { e: string; s: boolean; }; }; }>; type ToServer = z.infer<typeof ToServerSchema>; interface ActorInspectorAccessors { isStateEnabled: () => Promise<boolean>; getState: () => Promise<unknown>; setState: (state: unknown) => Promise<void>; isDbEnabled: () => Promise<boolean>; getDb: () => Promise<InferDatabaseClient<AnyDatabaseProvider>>; getRpcs: () => Promise<string[]>; getConnections: () => Promise<Connection[]>; } interface ActorInspectorEmitterEvents { stateUpdated: (state: unknown) => void; connectionUpdated: () => void; eventFired: (event: RealtimeEvent) => void; } /** * Provides a unified interface for inspecting actor external and internal state. */ declare class ActorInspector { #private; readonly accessors: ActorInspectorAccessors; readonly emitter: nanoevents.Emitter<ActorInspectorEmitterEvents>; get lastRealtimeEvents(): (({ type: "action"; name: string; args: any[]; connId: string; } | { type: "broadcast"; eventName: string; args: any[]; } | { type: "subscribe"; eventName: string; connId: string; } | { type: "unsubscribe"; eventName: string; connId: string; } | { type: "event"; eventName: string; args: any[]; connId: string; }) & { id: string; timestamp: number; })[]; constructor(accessors: () => ActorInspectorAccessors); } declare class Schedule { #private; constructor(actor: AnyActorInstance); after(duration: number, fn: string, ...args: unknown[]): Promise<void>; at(timestamp: number, fn: string, ...args: unknown[]): Promise<void>; } /** * Options for the `_saveState` method. */ interface SaveStateOptions { /** * Forces the state to be saved immediately. This function will return when the state has saved successfully. */ immediate?: boolean; } /** Actor type alias with all `any` types. Used for `extends` in classes referencing this actor. */ type AnyActorInstance = ActorInstance<any, any, any, any, any, any, any>; declare class ActorInstance<S, CP, CS, V, I, AD, DB extends AnyDatabaseProvider> { #private; actorContext: ActorContext<S, CP, CS, V, I, AD, DB>; isStopping: boolean; get id(): string; get inlineClient(): Client<Registry<any>>; get inspector(): ActorInspector; /** * This constructor should never be used directly. * * Constructed in {@link ActorInstance.start}. * * @private */ constructor(config: ActorConfig<S, CP, CS, V, I, AD, DB>); start(connectionDrivers: ConnDrivers, actorDriver: ActorDriver, inlineClient: Client<Registry<any>>, actorId: string, name: string, key: ActorKey, region: string): Promise<void>; scheduleEvent(timestamp: number, fn: string, args: unknown[]): Promise<void>; onAlarm(): Promise<void>; get stateEnabled(): boolean; __getConnForId(id: string): Conn<S, CP, CS, V, I, AD, DB> | undefined; /** * Removes a connection and cleans up its resources. */ __removeConn(conn: Conn<S, CP, CS, V, I, AD, DB> | undefined): void; prepareConn(params: any, request?: Request): Promise<CS>; __getConnDriver(driverId: string): ConnDriver; /** * Called after establishing a connection handshake. */ createConn(connectionId: string, connectionToken: string, params: CP, state: CS, driverId: string, driverState: unknown, authData: unknown): Promise<Conn<S, CP, CS, V, I, AD, DB>>; processMessage(message: ToServer, conn: Conn<S, CP, CS, V, I, AD, DB>): Promise<void>; /** * Check if the actor is ready to handle requests. */ isReady(): boolean; /** * Returns a list of action methods available on this actor. */ get actions(): string[]; /** * Handles raw HTTP requests to the actor. */ handleFetch(request: Request, opts: { auth: AD; }): Promise<Response>; /** * Handles raw WebSocket connections to the actor. */ handleWebSocket(websocket: UniversalWebSocket, opts: { request: Request; auth: AD; }): Promise<void>; /** * Gets the logger instance. */ get log(): Logger; /** * Gets the name. */ get name(): string; /** * Gets the key. */ get key(): ActorKey; /** * Gets the region. */ get region(): string; /** * Gets the scheduler. */ get schedule(): Schedule; /** * Gets the map of connections. */ get conns(): Map<ConnId, Conn<S, CP, CS, V, I, AD, DB>>; /** * Gets the current state. * * Changing properties of this value will automatically be persisted. */ get state(): S; /** * Gets the database. * @experimental * @throws {DatabaseNotEnabled} If the database is not enabled. */ get db(): InferDatabaseClient<DB>; /** * Sets the current state. * * This property will automatically be persisted. */ set state(value: S); get vars(): V; /** * Broadcasts an event to all connected clients. * @param name - The name of the event. * @param args - The arguments to send with the event. */ _broadcast<Args extends Array<unknown>>(name: string, ...args: Args): void; /** * Runs a promise in the background. * * This allows the actor runtime to ensure that a promise completes while * returning from an action request early. * * @param promise - The promise to run in the background. */ _runInBackground(promise: Promise<void>): void; /** * Forces the state to get saved. * * This is helpful if running a long task that may fail later or when * running a background job that updates the state. * * @param opts - Options for saving the state. */ saveState(opts: SaveStateOptions): Promise<void>; stop(): Promise<void>; } /** * ActorContext class that provides access to actor methods and state */ declare class ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase extends AnyDatabaseProvider> { #private; constructor(actor: ActorInstance<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>); /** * Get the actor state */ get state(): TState; /** * Get the actor variables */ get vars(): TVars; /** * Broadcasts an event to all connected clients. * @param name - The name of the event. * @param args - The arguments to send with the event. */ broadcast<Args extends Array<unknown>>(name: string, ...args: Args): void; /** * Gets the logger instance. */ get log(): Logger; /** * Gets actor ID. */ get actorId(): string; /** * Gets the actor name. */ get name(): string; /** * Gets the actor key. */ get key(): ActorKey; /** * Gets the region. */ get region(): string; /** * Gets the scheduler. */ get schedule(): Schedule; /** * Gets the map of connections. */ get conns(): Map<ConnId, Conn<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>>; /** * Returns the client for the given registry. */ client<R extends Registry<any>>(): Client<R>; /** * Gets the database. * @experimental * @throws {DatabaseNotEnabled} If the database is not enabled. */ get db(): InferDatabaseClient<TDatabase>; /** * Forces the state to get saved. * * @param opts - Options for saving the state. */ saveState(opts: SaveStateOptions): Promise<void>; /** * Runs a promise in the background. * * @param promise - The promise to run in the background. */ runInBackground(promise: Promise<void>): void; } type InitContext = ActorContext<undefined, undefined, undefined, undefined, undefined, undefined, undefined>; interface ActorTypes<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase extends AnyDatabaseProvider> { state?: TState; connParams?: TConnParams; connState?: TConnState; vars?: TVars; input?: TInput; authData?: TAuthData; database?: TDatabase; } declare const ActorConfigSchema: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodObject<{ onAuth: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onCreate: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onStart: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onStateChange: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onBeforeConnect: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onConnect: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onDisconnect: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onBeforeActionResponse: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onFetch: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; onWebSocket: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; actions: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>>; state: z.ZodOptional<z.ZodAny>; createState: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; connState: z.ZodOptional<z.ZodAny>; createConnState: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; vars: z.ZodOptional<z.ZodAny>; db: z.ZodOptional<z.ZodAny>; createVars: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>; options: z.ZodDefault<z.ZodObject<{ lifecycle: z.ZodDefault<z.ZodObject<{ createVarsTimeout: z.ZodDefault<z.ZodNumber>; createConnStateTimeout: z.ZodDefault<z.ZodNumber>; onConnectTimeout: z.ZodDefault<z.ZodNumber>; }, "strict", z.ZodTypeAny, { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }, { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; }>>; state: z.ZodDefault<z.ZodObject<{ saveInterval: z.ZodDefault<z.ZodNumber>; }, "strict", z.ZodTypeAny, { saveInterval: number; }, { saveInterval?: number | undefined; }>>; action: z.ZodDefault<z.ZodObject<{ timeout: z.ZodDefault<z.ZodNumber>; }, "strict", z.ZodTypeAny, { timeout: number; }, { timeout?: number | undefined; }>>; }, "strict", z.ZodTypeAny, { state: { saveInterval: number; }; action: { timeout: number; }; lifecycle: { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }; }, { state?: { saveInterval?: number | undefined; } | undefined; action?: { timeout?: number | undefined; } | undefined; lifecycle?: { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; } | undefined; }>>; }, "strict", z.ZodTypeAny, { options: { state: { saveInterval: number; }; action: { timeout: number; }; lifecycle: { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }; }; actions: Record<string, (...args: unknown[]) => unknown>; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }, { options?: { state?: { saveInterval?: number | undefined; } | undefined; action?: { timeout?: number | undefined; } | undefined; lifecycle?: { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; } | undefined; } | undefined; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; actions?: Record<string, (...args: unknown[]) => unknown> | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }>, { options: { state: { saveInterval: number; }; action: { timeout: number; }; lifecycle: { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }; }; actions: Record<string, (...args: unknown[]) => unknown>; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }, { options?: { state?: { saveInterval?: number | undefined; } | undefined; action?: { timeout?: number | undefined; } | undefined; lifecycle?: { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; } | undefined; } | undefined; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; actions?: Record<string, (...args: unknown[]) => unknown> | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }>, { options: { state: { saveInterval: number; }; action: { timeout: number; }; lifecycle: { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }; }; actions: Record<string, (...args: unknown[]) => unknown>; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }, { options?: { state?: { saveInterval?: number | undefined; } | undefined; action?: { timeout?: number | undefined; } | undefined; lifecycle?: { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; } | undefined; } | undefined; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; actions?: Record<string, (...args: unknown[]) => unknown> | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }>, { options: { state: { saveInterval: number; }; action: { timeout: number; }; lifecycle: { createVarsTimeout: number; createConnStateTimeout: number; onConnectTimeout: number; }; }; actions: Record<string, (...args: unknown[]) => unknown>; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }, { options?: { state?: { saveInterval?: number | undefined; } | undefined; action?: { timeout?: number | undefined; } | undefined; lifecycle?: { createVarsTimeout?: number | undefined; createConnStateTimeout?: number | undefined; onConnectTimeout?: number | undefined; } | undefined; } | undefined; state?: any; db?: any; onAuth?: ((...args: unknown[]) => unknown) | undefined; onCreate?: ((...args: unknown[]) => unknown) | undefined; onStart?: ((...args: unknown[]) => unknown) | undefined; onStateChange?: ((...args: unknown[]) => unknown) | undefined; onBeforeConnect?: ((...args: unknown[]) => unknown) | undefined; onConnect?: ((...args: unknown[]) => unknown) | undefined; onDisconnect?: ((...args: unknown[]) => unknown) | undefined; onBeforeActionResponse?: ((...args: unknown[]) => unknown) | undefined; onFetch?: ((...args: unknown[]) => unknown) | undefined; onWebSocket?: ((...args: unknown[]) => unknown) | undefined; actions?: Record<string, (...args: unknown[]) => unknown> | undefined; createState?: ((...args: unknown[]) => unknown) | undefined; connState?: any; createConnState?: ((...args: unknown[]) => unknown) | undefined; vars?: any; createVars?: ((...args: unknown[]) => unknown) | undefined; }>; interface OnConnectOptions { /** * The request object associated with the connection. * * @experimental */ request?: Request; } type CreateState<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase> = { state: TState; } | { createState: (c: InitContext, input: TInput) => TState | Promise<TState>; } | Record<never, never>; type CreateConnState<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase> = { connState: TConnState; } | { createConnState: (c: InitContext, opts: OnConnectOptions, params: TConnParams) => TConnState | Promise<TConnState>; } | Record<never, never>; /** * @experimental */ type CreateVars<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase> = { /** * @experimental */ vars: TVars; } | { /** * @experimental */ createVars: (c: InitContext, driverCtx: any) => TVars | Promise<TVars>; } | Record<never, never>; type OnAuth<TConnParams, TAuthData> = { /** * Called on the HTTP server before clients can interact with the actor. * * Only called for public endpoints. Calls to actors from within the backend * do not trigger this handler. * * Data returned from this handler will be available on `c.conn.auth`. * * This function is required for any public HTTP endpoint access. Use this hook * to validate client credentials and return authentication data that will be * available on connections. This runs on the HTTP server (not the actor) * in order to reduce load on the actor & prevent denial of server attacks * against individual actors. * * If you need access to actor state for authentication, use onBeforeConnect * with an empty onAuth function instead. * * You can also provide your own authentication middleware on your router if you * choose, then use onAuth to pass the authentication data (e.g. user ID) to the * actor itself. * * @param opts Authentication options including request and intent * @returns Authentication data to attach to connections (must be serializable) * @throws Throw an error to deny access to the actor */ onAuth: (opts: OnAuthOptions, params: TConnParams) => TAuthData | Promise<TAuthData>; } | Record<never, never>; interface Actions<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase extends AnyDatabaseProvider> { [Action: string]: (c: ActionContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, ...args: any[]) => any; } /** * @experimental */ type AuthIntent = "get" | "create" | "connect" | "action" | "message"; interface OnAuthOptions { request: Request; /** * @experimental */ intents: Set<AuthIntent>; } interface BaseActorConfig<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase extends AnyDatabaseProvider, TActions extends Actions<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>> { /** * Called when the actor is first initialized. * * Use this hook to initialize your actor's state. * This is called before any other lifecycle hooks. */ onCreate?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, input: TInput) => void | Promise<void>; /** * Called when the actor is started and ready to receive connections and action. * * Use this hook to initialize resources needed for the actor's operation * (timers, external connections, etc.) * * @returns Void or a Promise that resolves when startup is complete */ onStart?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>) => void | Promise<void>; /** * Called when the actor's state changes. * * Use this hook to react to state changes, such as updating * external systems or triggering events. * * @param newState The updated state */ onStateChange?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, newState: TState) => void; /** * Called before a client connects to the actor. * * Unlike onAuth, this handler is still called for both internal and * public clients. * * Use this hook to determine if a connection should be accepted * and to initialize connection-specific state. Unlike onAuth, this runs * on the actor and has access to actor state, but uses slightly * more resources on the actor rather than authenticating with onAuth. * * For authentication without actor state access, prefer onAuth. * * For authentication with actor state, use onBeforeConnect with an empty * onAuth handler. * * @param opts Connection parameters including client-provided data * @returns The initial connection state or a Promise that resolves to it * @throws Throw an error to reject the connection */ onBeforeConnect?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, opts: OnConnectOptions, params: TConnParams) => void | Promise<void>; /** * Called when a client successfully connects to the actor. * * Use this hook to perform actions when a connection is established, * such as sending initial data or updating the actor's state. * * @param conn The connection object * @returns Void or a Promise that resolves when connection handling is complete */ onConnect?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, conn: Conn<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>) => void | Promise<void>; /** * Called when a client disconnects from the actor. * * Use this hook to clean up resources associated with the connection * or update the actor's state. * * @param conn The connection that is being closed * @returns Void or a Promise that resolves when disconnect handling is complete */ onDisconnect?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, conn: Conn<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>) => void | Promise<void>; /** * Called before sending an action response to the client. * * Use this hook to modify or transform the output of an action before it's sent * to the client. This is useful for formatting responses, adding metadata, * or applying transformations to the output. * * @param name The name of the action that was called * @param args The arguments that were passed to the action * @param output The output that will be sent to the client * @returns The modified output to send to the client */ onBeforeActionResponse?: <Out>(c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, name: string, args: unknown[], output: Out) => Out | Promise<Out>; /** * Called when a raw HTTP request is made to the actor. * * This handler receives raw HTTP requests made to `/actors/{actorName}/http/*` endpoints. * Use this hook to handle custom HTTP patterns, REST APIs, or other HTTP-based protocols. * * @param request The raw HTTP request object * @returns A Response object to send back, or void to continue with default routing */ onFetch?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, request: Request, opts: { auth: TAuthData; }) => Response | Promise<Response>; /** * Called when a raw WebSocket connection is established to the actor. * * This handler receives WebSocket connections made to `/actors/{actorName}/websocket/*` endpoints. * Use this hook to handle custom WebSocket protocols, binary streams, or other WebSocket-based communication. * * @param websocket The raw WebSocket connection * @param request The original HTTP upgrade request */ onWebSocket?: (c: ActorContext<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase>, websocket: UniversalWebSocket, opts: { request: Request; auth: TAuthData; }) => void | Promise<void>; actions: TActions; } type ActorDatabaseConfig<TDatabase extends AnyDatabaseProvider> = { /** * @experimental */ db: TDatabase; } | Record<never, never>; type ActorConfig<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase extends AnyDatabaseProvider> = Omit<z.infer<typeof ActorConfigSchema>, "actions" | "onAuth" | "onCreate" | "onStart" | "onStateChange" | "onBeforeConnect" | "onConnect" | "onDisconnect" | "onBeforeActionResponse" | "onFetch" | "onWebSocket" | "state" | "createState" | "connState" | "createConnState" | "vars" | "createVars" | "db"> & BaseActorConfig<TState, TConnParams, TConnState, TVars, TInput, TAuthData, TDatabase, Actions<TState, TConnParams, TConnState, TVars, TInput, T