Skip to content

Commit f69dce5

Browse files
committed
chore(rivetkit): make actions optional
1 parent 4b0cbc8 commit f69dce5

File tree

4 files changed

+206
-53
lines changed

4 files changed

+206
-53
lines changed

rivetkit-typescript/packages/rivetkit/scripts/manager-openapi-gen.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import * as fs from "node:fs/promises";
22
import { resolve } from "node:path";
33
import { z } from "zod";
44
import { createFileSystemOrMemoryDriver } from "@/drivers/file-system/mod";
5-
import type {
6-
ManagerDriver,
7-
} from "@/manager/driver";
5+
import type { ManagerDriver } from "@/manager/driver";
86
import { buildManagerRouter } from "@/manager/router";
97
import { type RegistryConfig, RegistryConfigSchema } from "@/registry/config";
108
import { VERSION } from "@/utils";
@@ -22,19 +20,20 @@ async function main() {
2220
// const registry = setup(registryConfig);
2321

2422
const managerDriver: ManagerDriver = {
25-
getForId: unimplemented,
26-
getWithKey: unimplemented,
27-
getOrCreateWithKey: unimplemented,
28-
createActor: unimplemented,
29-
listActors: unimplemented,
30-
sendRequest: unimplemented,
31-
openWebSocket: unimplemented,
32-
proxyRequest: unimplemented,
33-
proxyWebSocket: unimplemented,
34-
displayInformation: unimplemented,
35-
setGetUpgradeWebSocket: unimplemented,
36-
kvGet: unimplemented,
37-
};
23+
getForId: unimplemented,
24+
getWithKey: unimplemented,
25+
getOrCreateWithKey: unimplemented,
26+
createActor: unimplemented,
27+
listActors: unimplemented,
28+
sendRequest: unimplemented,
29+
openWebSocket: unimplemented,
30+
proxyRequest: unimplemented,
31+
proxyWebSocket: unimplemented,
32+
displayInformation: unimplemented,
33+
setGetUpgradeWebSocket: unimplemented,
34+
buildGatewayUrl: unimplemented,
35+
kvGet: unimplemented,
36+
};
3837

3938
// const client = createClientWithDriver(
4039
// managerDriver,
@@ -207,4 +206,5 @@ function unimplemented(): never {
207206
throw new Error("UNIMPLEMENTED");
208207
}
209208

209+
// biome-ignore lint/nursery/noFloatingPromises: main
210210
main();

rivetkit-typescript/packages/rivetkit/src/actor/config.ts

Lines changed: 183 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,14 @@ export const ActorConfigSchema = z
132132
// This must have only one or the other or else TState will not be able to be inferred
133133
//
134134
// Data returned from this handler will be available on `c.state`.
135-
type CreateState<TState, TConnParams, TConnState, TVars, TInput, TDatabase extends AnyDatabaseProvider> =
135+
type CreateState<
136+
TState,
137+
TConnParams,
138+
TConnState,
139+
TVars,
140+
TInput,
141+
TDatabase extends AnyDatabaseProvider,
142+
> =
136143
| { state: TState }
137144
| {
138145
createState: (
@@ -458,7 +465,7 @@ interface BaseActorConfig<
458465
websocket: UniversalWebSocket,
459466
) => void | Promise<void>;
460467

461-
actions: TActions;
468+
actions?: TActions;
462469
}
463470

464471
type ActorDatabaseConfig<TDatabase extends AnyDatabaseProvider> =
@@ -620,43 +627,185 @@ export function test<
620627

621628
export const DocActorOptionsSchema = z
622629
.object({
623-
createVarsTimeout: z.number().optional().describe("Timeout in ms for createVars handler. Default: 5000"),
624-
createConnStateTimeout: z.number().optional().describe("Timeout in ms for createConnState handler. Default: 5000"),
625-
onConnectTimeout: z.number().optional().describe("Timeout in ms for onConnect handler. Default: 5000"),
626-
onSleepTimeout: z.number().optional().describe("Timeout in ms for onSleep handler. Must be less than ACTOR_STOP_THRESHOLD_MS. Default: 5000"),
627-
onDestroyTimeout: z.number().optional().describe("Timeout in ms for onDestroy handler. Default: 5000"),
628-
stateSaveInterval: z.number().optional().describe("Interval in ms between automatic state saves. Default: 10000"),
629-
actionTimeout: z.number().optional().describe("Timeout in ms for action handlers. Default: 60000"),
630-
waitUntilTimeout: z.number().optional().describe("Max time in ms to wait for waitUntil background promises during shutdown. Default: 15000"),
631-
connectionLivenessTimeout: z.number().optional().describe("Timeout in ms for connection liveness checks. Default: 2500"),
632-
connectionLivenessInterval: z.number().optional().describe("Interval in ms between connection liveness checks. Default: 5000"),
633-
noSleep: z.boolean().optional().describe("If true, the actor will never sleep. Default: false"),
634-
sleepTimeout: z.number().optional().describe("Time in ms of inactivity before the actor sleeps. Default: 30000"),
635-
canHibernateWebSocket: z.boolean().optional().describe("Whether WebSockets using onWebSocket can be hibernated. WebSockets using actions/events are hibernatable by default. Default: false"),
630+
createVarsTimeout: z
631+
.number()
632+
.optional()
633+
.describe("Timeout in ms for createVars handler. Default: 5000"),
634+
createConnStateTimeout: z
635+
.number()
636+
.optional()
637+
.describe(
638+
"Timeout in ms for createConnState handler. Default: 5000",
639+
),
640+
onConnectTimeout: z
641+
.number()
642+
.optional()
643+
.describe("Timeout in ms for onConnect handler. Default: 5000"),
644+
onSleepTimeout: z
645+
.number()
646+
.optional()
647+
.describe(
648+
"Timeout in ms for onSleep handler. Must be less than ACTOR_STOP_THRESHOLD_MS. Default: 5000",
649+
),
650+
onDestroyTimeout: z
651+
.number()
652+
.optional()
653+
.describe("Timeout in ms for onDestroy handler. Default: 5000"),
654+
stateSaveInterval: z
655+
.number()
656+
.optional()
657+
.describe(
658+
"Interval in ms between automatic state saves. Default: 10000",
659+
),
660+
actionTimeout: z
661+
.number()
662+
.optional()
663+
.describe("Timeout in ms for action handlers. Default: 60000"),
664+
waitUntilTimeout: z
665+
.number()
666+
.optional()
667+
.describe(
668+
"Max time in ms to wait for waitUntil background promises during shutdown. Default: 15000",
669+
),
670+
connectionLivenessTimeout: z
671+
.number()
672+
.optional()
673+
.describe(
674+
"Timeout in ms for connection liveness checks. Default: 2500",
675+
),
676+
connectionLivenessInterval: z
677+
.number()
678+
.optional()
679+
.describe(
680+
"Interval in ms between connection liveness checks. Default: 5000",
681+
),
682+
noSleep: z
683+
.boolean()
684+
.optional()
685+
.describe("If true, the actor will never sleep. Default: false"),
686+
sleepTimeout: z
687+
.number()
688+
.optional()
689+
.describe(
690+
"Time in ms of inactivity before the actor sleeps. Default: 30000",
691+
),
692+
canHibernateWebSocket: z
693+
.boolean()
694+
.optional()
695+
.describe(
696+
"Whether WebSockets using onWebSocket can be hibernated. WebSockets using actions/events are hibernatable by default. Default: false",
697+
),
636698
})
637699
.describe("Actor options for timeouts and behavior configuration.");
638700

639701
export const DocActorConfigSchema = z
640702
.object({
641-
state: z.unknown().optional().describe("Initial state value for the actor. Cannot be used with createState."),
642-
createState: z.unknown().optional().describe("Function to create initial state. Receives context and input. Cannot be used with state."),
643-
connState: z.unknown().optional().describe("Initial connection state value. Cannot be used with createConnState."),
644-
createConnState: z.unknown().optional().describe("Function to create connection state. Receives context and connection params. Cannot be used with connState."),
645-
vars: z.unknown().optional().describe("Initial ephemeral variables value. Cannot be used with createVars."),
646-
createVars: z.unknown().optional().describe("Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars."),
647-
db: z.unknown().optional().describe("Database provider instance for the actor."),
648-
onCreate: z.unknown().optional().describe("Called when the actor is first initialized. Use to initialize state."),
649-
onDestroy: z.unknown().optional().describe("Called when the actor is destroyed."),
650-
onWake: z.unknown().optional().describe("Called when the actor wakes up and is ready to receive connections and actions."),
651-
onSleep: z.unknown().optional().describe("Called when the actor is stopping or sleeping. Use to clean up resources."),
652-
onStateChange: z.unknown().optional().describe("Called when the actor's state changes. State changes within this hook won't trigger recursion."),
653-
onBeforeConnect: z.unknown().optional().describe("Called before a client connects. Throw an error to reject the connection."),
654-
onConnect: z.unknown().optional().describe("Called when a client successfully connects."),
655-
onDisconnect: z.unknown().optional().describe("Called when a client disconnects."),
656-
onBeforeActionResponse: z.unknown().optional().describe("Called before sending an action response. Use to transform output."),
657-
onRequest: z.unknown().optional().describe("Called for raw HTTP requests to /actors/{name}/http/* endpoints."),
658-
onWebSocket: z.unknown().optional().describe("Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints."),
659-
actions: z.record(z.string(), z.unknown()).optional().describe("Map of action name to handler function."),
703+
state: z
704+
.unknown()
705+
.optional()
706+
.describe(
707+
"Initial state value for the actor. Cannot be used with createState.",
708+
),
709+
createState: z
710+
.unknown()
711+
.optional()
712+
.describe(
713+
"Function to create initial state. Receives context and input. Cannot be used with state.",
714+
),
715+
connState: z
716+
.unknown()
717+
.optional()
718+
.describe(
719+
"Initial connection state value. Cannot be used with createConnState.",
720+
),
721+
createConnState: z
722+
.unknown()
723+
.optional()
724+
.describe(
725+
"Function to create connection state. Receives context and connection params. Cannot be used with connState.",
726+
),
727+
vars: z
728+
.unknown()
729+
.optional()
730+
.describe(
731+
"Initial ephemeral variables value. Cannot be used with createVars.",
732+
),
733+
createVars: z
734+
.unknown()
735+
.optional()
736+
.describe(
737+
"Function to create ephemeral variables. Receives context and driver context. Cannot be used with vars.",
738+
),
739+
db: z
740+
.unknown()
741+
.optional()
742+
.describe("Database provider instance for the actor."),
743+
onCreate: z
744+
.unknown()
745+
.optional()
746+
.describe(
747+
"Called when the actor is first initialized. Use to initialize state.",
748+
),
749+
onDestroy: z
750+
.unknown()
751+
.optional()
752+
.describe("Called when the actor is destroyed."),
753+
onWake: z
754+
.unknown()
755+
.optional()
756+
.describe(
757+
"Called when the actor wakes up and is ready to receive connections and actions.",
758+
),
759+
onSleep: z
760+
.unknown()
761+
.optional()
762+
.describe(
763+
"Called when the actor is stopping or sleeping. Use to clean up resources.",
764+
),
765+
onStateChange: z
766+
.unknown()
767+
.optional()
768+
.describe(
769+
"Called when the actor's state changes. State changes within this hook won't trigger recursion.",
770+
),
771+
onBeforeConnect: z
772+
.unknown()
773+
.optional()
774+
.describe(
775+
"Called before a client connects. Throw an error to reject the connection.",
776+
),
777+
onConnect: z
778+
.unknown()
779+
.optional()
780+
.describe("Called when a client successfully connects."),
781+
onDisconnect: z
782+
.unknown()
783+
.optional()
784+
.describe("Called when a client disconnects."),
785+
onBeforeActionResponse: z
786+
.unknown()
787+
.optional()
788+
.describe(
789+
"Called before sending an action response. Use to transform output.",
790+
),
791+
onRequest: z
792+
.unknown()
793+
.optional()
794+
.describe(
795+
"Called for raw HTTP requests to /actors/{name}/http/* endpoints.",
796+
),
797+
onWebSocket: z
798+
.unknown()
799+
.optional()
800+
.describe(
801+
"Called for raw WebSocket connections to /actors/{name}/websocket/* endpoints.",
802+
),
803+
actions: z
804+
.record(z.string(), z.unknown())
805+
.optional()
806+
.describe(
807+
"Map of action name to handler function. Defaults to an empty object.",
808+
),
660809
options: DocActorOptionsSchema.optional(),
661810
})
662811
.describe("Actor configuration passed to the actor() function.");

rivetkit-typescript/packages/rivetkit/src/actor/instance/mod.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export class ActorInstance<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
203203
}
204204

205205
get actions(): string[] {
206-
return Object.keys(this.#config.actions);
206+
return Object.keys(this.#config.actions ?? {});
207207
}
208208

209209
get config(): ActorConfig<S, CP, CS, V, I, DB> {
@@ -516,12 +516,13 @@ export class ActorInstance<S, CP, CS, V, I, DB extends AnyDatabaseProvider> {
516516
): Promise<unknown> {
517517
this.assertReady();
518518

519-
if (!(actionName in this.#config.actions)) {
519+
const actions = this.#config.actions ?? {};
520+
if (!(actionName in actions)) {
520521
this.#rLog.warn({ msg: "action does not exist", actionName });
521522
throw new errors.ActionNotFound(actionName);
522523
}
523524

524-
const actionFunction = this.#config.actions[actionName];
525+
const actionFunction = actions[actionName];
525526
if (typeof actionFunction !== "function") {
526527
this.#rLog.warn({
527528
msg: "action is not a function",

rivetkit-typescript/packages/rivetkit/src/driver-test-suite/test-inline-client-driver.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ export function createTestInlineClientDriver(
237237
);
238238
return upgradeWebSocket(() => wsHandler)(c, noopNext());
239239
},
240+
async buildGatewayUrl(actorId: string): Promise<string> {
241+
return `${endpoint}/gateway/${actorId}`;
242+
},
240243
displayInformation(): ManagerDisplayInformation {
241244
return { properties: {} };
242245
},

0 commit comments

Comments
 (0)