rivetkit 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/schemas/actor-persist/v1.ts +228 -0
  2. package/dist/schemas/client-protocol/v1.ts +429 -0
  3. package/dist/schemas/file-system-driver/v1.ts +102 -0
  4. package/dist/tsup/actor/errors.cjs +69 -0
  5. package/dist/tsup/actor/errors.cjs.map +1 -0
  6. package/dist/tsup/actor/errors.d.cts +143 -0
  7. package/dist/tsup/actor/errors.d.ts +143 -0
  8. package/dist/tsup/actor/errors.js +69 -0
  9. package/dist/tsup/actor/errors.js.map +1 -0
  10. package/dist/tsup/chunk-2CRLFV6Z.cjs +202 -0
  11. package/dist/tsup/chunk-2CRLFV6Z.cjs.map +1 -0
  12. package/dist/tsup/chunk-3H7O2A7I.js +525 -0
  13. package/dist/tsup/chunk-3H7O2A7I.js.map +1 -0
  14. package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
  15. package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
  16. package/dist/tsup/chunk-4NSUQZ2H.js +1790 -0
  17. package/dist/tsup/chunk-4NSUQZ2H.js.map +1 -0
  18. package/dist/tsup/chunk-6PDXBYI5.js +132 -0
  19. package/dist/tsup/chunk-6PDXBYI5.js.map +1 -0
  20. package/dist/tsup/chunk-6WKQDDUD.cjs +1790 -0
  21. package/dist/tsup/chunk-6WKQDDUD.cjs.map +1 -0
  22. package/dist/tsup/chunk-CTBOSFUH.cjs +116 -0
  23. package/dist/tsup/chunk-CTBOSFUH.cjs.map +1 -0
  24. package/dist/tsup/chunk-EGVZZFE2.js +2857 -0
  25. package/dist/tsup/chunk-EGVZZFE2.js.map +1 -0
  26. package/dist/tsup/chunk-FCCPJNMA.cjs +132 -0
  27. package/dist/tsup/chunk-FCCPJNMA.cjs.map +1 -0
  28. package/dist/tsup/chunk-FLMTTN27.js +244 -0
  29. package/dist/tsup/chunk-FLMTTN27.js.map +1 -0
  30. package/dist/tsup/chunk-GIR3AFFI.cjs +315 -0
  31. package/dist/tsup/chunk-GIR3AFFI.cjs.map +1 -0
  32. package/dist/tsup/chunk-INGJP237.js +315 -0
  33. package/dist/tsup/chunk-INGJP237.js.map +1 -0
  34. package/dist/tsup/chunk-KJCJLKRM.js +116 -0
  35. package/dist/tsup/chunk-KJCJLKRM.js.map +1 -0
  36. package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
  37. package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
  38. package/dist/tsup/chunk-O2MBYIXO.cjs +2857 -0
  39. package/dist/tsup/chunk-O2MBYIXO.cjs.map +1 -0
  40. package/dist/tsup/chunk-OGAPU3UG.cjs +525 -0
  41. package/dist/tsup/chunk-OGAPU3UG.cjs.map +1 -0
  42. package/dist/tsup/chunk-OV6AYD4S.js +4406 -0
  43. package/dist/tsup/chunk-OV6AYD4S.js.map +1 -0
  44. package/dist/tsup/chunk-PO4VLDWA.js +47 -0
  45. package/dist/tsup/chunk-PO4VLDWA.js.map +1 -0
  46. package/dist/tsup/chunk-R2OPSKIV.cjs +244 -0
  47. package/dist/tsup/chunk-R2OPSKIV.cjs.map +1 -0
  48. package/dist/tsup/chunk-TZJKSBUQ.cjs +47 -0
  49. package/dist/tsup/chunk-TZJKSBUQ.cjs.map +1 -0
  50. package/dist/tsup/chunk-UBUC5C3G.cjs +189 -0
  51. package/dist/tsup/chunk-UBUC5C3G.cjs.map +1 -0
  52. package/dist/tsup/chunk-UIM22YJL.cjs +4406 -0
  53. package/dist/tsup/chunk-UIM22YJL.cjs.map +1 -0
  54. package/dist/tsup/chunk-URVFQMYI.cjs +230 -0
  55. package/dist/tsup/chunk-URVFQMYI.cjs.map +1 -0
  56. package/dist/tsup/chunk-UVUPOS46.js +230 -0
  57. package/dist/tsup/chunk-UVUPOS46.js.map +1 -0
  58. package/dist/tsup/chunk-VRRHBNJC.js +189 -0
  59. package/dist/tsup/chunk-VRRHBNJC.js.map +1 -0
  60. package/dist/tsup/chunk-XFSS33EQ.js +202 -0
  61. package/dist/tsup/chunk-XFSS33EQ.js.map +1 -0
  62. package/dist/tsup/client/mod.cjs +32 -0
  63. package/dist/tsup/client/mod.cjs.map +1 -0
  64. package/dist/tsup/client/mod.d.cts +26 -0
  65. package/dist/tsup/client/mod.d.ts +26 -0
  66. package/dist/tsup/client/mod.js +32 -0
  67. package/dist/tsup/client/mod.js.map +1 -0
  68. package/dist/tsup/common/log.cjs +13 -0
  69. package/dist/tsup/common/log.cjs.map +1 -0
  70. package/dist/tsup/common/log.d.cts +20 -0
  71. package/dist/tsup/common/log.d.ts +20 -0
  72. package/dist/tsup/common/log.js +13 -0
  73. package/dist/tsup/common/log.js.map +1 -0
  74. package/dist/tsup/common/websocket.cjs +10 -0
  75. package/dist/tsup/common/websocket.cjs.map +1 -0
  76. package/dist/tsup/common/websocket.d.cts +3 -0
  77. package/dist/tsup/common/websocket.d.ts +3 -0
  78. package/dist/tsup/common/websocket.js +10 -0
  79. package/dist/tsup/common/websocket.js.map +1 -0
  80. package/dist/tsup/common-CpqORuCq.d.cts +218 -0
  81. package/dist/tsup/common-CpqORuCq.d.ts +218 -0
  82. package/dist/tsup/connection-BR_Ve4ku.d.cts +2117 -0
  83. package/dist/tsup/connection-BwUMoe6n.d.ts +2117 -0
  84. package/dist/tsup/driver-helpers/mod.cjs +33 -0
  85. package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
  86. package/dist/tsup/driver-helpers/mod.d.cts +18 -0
  87. package/dist/tsup/driver-helpers/mod.d.ts +18 -0
  88. package/dist/tsup/driver-helpers/mod.js +33 -0
  89. package/dist/tsup/driver-helpers/mod.js.map +1 -0
  90. package/dist/tsup/driver-test-suite/mod.cjs +4619 -0
  91. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
  92. package/dist/tsup/driver-test-suite/mod.d.cts +57 -0
  93. package/dist/tsup/driver-test-suite/mod.d.ts +57 -0
  94. package/dist/tsup/driver-test-suite/mod.js +4619 -0
  95. package/dist/tsup/driver-test-suite/mod.js.map +1 -0
  96. package/dist/tsup/inspector/mod.cjs +53 -0
  97. package/dist/tsup/inspector/mod.cjs.map +1 -0
  98. package/dist/tsup/inspector/mod.d.cts +408 -0
  99. package/dist/tsup/inspector/mod.d.ts +408 -0
  100. package/dist/tsup/inspector/mod.js +53 -0
  101. package/dist/tsup/inspector/mod.js.map +1 -0
  102. package/dist/tsup/mod.cjs +73 -0
  103. package/dist/tsup/mod.cjs.map +1 -0
  104. package/dist/tsup/mod.d.cts +100 -0
  105. package/dist/tsup/mod.d.ts +100 -0
  106. package/dist/tsup/mod.js +73 -0
  107. package/dist/tsup/mod.js.map +1 -0
  108. package/dist/tsup/router-endpoints-AYkXG8Tl.d.cts +66 -0
  109. package/dist/tsup/router-endpoints-DAbqVFx2.d.ts +66 -0
  110. package/dist/tsup/test/mod.cjs +21 -0
  111. package/dist/tsup/test/mod.cjs.map +1 -0
  112. package/dist/tsup/test/mod.d.cts +27 -0
  113. package/dist/tsup/test/mod.d.ts +27 -0
  114. package/dist/tsup/test/mod.js +21 -0
  115. package/dist/tsup/test/mod.js.map +1 -0
  116. package/dist/tsup/utils-CT0cv4jd.d.cts +17 -0
  117. package/dist/tsup/utils-CT0cv4jd.d.ts +17 -0
  118. package/dist/tsup/utils.cjs +26 -0
  119. package/dist/tsup/utils.cjs.map +1 -0
  120. package/dist/tsup/utils.d.cts +36 -0
  121. package/dist/tsup/utils.d.ts +36 -0
  122. package/dist/tsup/utils.js +26 -0
  123. package/dist/tsup/utils.js.map +1 -0
  124. package/package.json +208 -5
  125. package/src/actor/action.ts +182 -0
  126. package/src/actor/config.ts +765 -0
  127. package/src/actor/connection.ts +260 -0
  128. package/src/actor/context.ts +171 -0
  129. package/src/actor/database.ts +23 -0
  130. package/src/actor/definition.ts +86 -0
  131. package/src/actor/driver.ts +84 -0
  132. package/src/actor/errors.ts +360 -0
  133. package/src/actor/generic-conn-driver.ts +234 -0
  134. package/src/actor/instance.ts +1800 -0
  135. package/src/actor/log.ts +15 -0
  136. package/src/actor/mod.ts +113 -0
  137. package/src/actor/persisted.ts +42 -0
  138. package/src/actor/protocol/old.ts +281 -0
  139. package/src/actor/protocol/serde.ts +131 -0
  140. package/src/actor/router-endpoints.ts +685 -0
  141. package/src/actor/router.ts +263 -0
  142. package/src/actor/schedule.ts +17 -0
  143. package/src/actor/unstable-react.ts +110 -0
  144. package/src/actor/utils.ts +98 -0
  145. package/src/client/actor-common.ts +30 -0
  146. package/src/client/actor-conn.ts +804 -0
  147. package/src/client/actor-handle.ts +208 -0
  148. package/src/client/client.ts +623 -0
  149. package/src/client/errors.ts +41 -0
  150. package/src/client/http-client-driver.ts +326 -0
  151. package/src/client/log.ts +7 -0
  152. package/src/client/mod.ts +56 -0
  153. package/src/client/raw-utils.ts +92 -0
  154. package/src/client/test.ts +44 -0
  155. package/src/client/utils.ts +150 -0
  156. package/src/common/eventsource-interface.ts +47 -0
  157. package/src/common/eventsource.ts +80 -0
  158. package/src/common/fake-event-source.ts +266 -0
  159. package/src/common/inline-websocket-adapter2.ts +445 -0
  160. package/src/common/log-levels.ts +27 -0
  161. package/src/common/log.ts +139 -0
  162. package/src/common/logfmt.ts +228 -0
  163. package/src/common/network.ts +2 -0
  164. package/src/common/router.ts +87 -0
  165. package/src/common/utils.ts +322 -0
  166. package/src/common/versioned-data.ts +95 -0
  167. package/src/common/websocket-interface.ts +49 -0
  168. package/src/common/websocket.ts +43 -0
  169. package/src/driver-helpers/mod.ts +22 -0
  170. package/src/driver-helpers/utils.ts +17 -0
  171. package/src/driver-test-suite/log.ts +7 -0
  172. package/src/driver-test-suite/mod.ts +213 -0
  173. package/src/driver-test-suite/test-inline-client-driver.ts +402 -0
  174. package/src/driver-test-suite/tests/action-features.ts +136 -0
  175. package/src/driver-test-suite/tests/actor-auth.ts +591 -0
  176. package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
  177. package/src/driver-test-suite/tests/actor-conn.ts +349 -0
  178. package/src/driver-test-suite/tests/actor-driver.ts +25 -0
  179. package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
  180. package/src/driver-test-suite/tests/actor-handle.ts +259 -0
  181. package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
  182. package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
  183. package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
  184. package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
  185. package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
  186. package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
  187. package/src/driver-test-suite/tests/actor-state.ts +54 -0
  188. package/src/driver-test-suite/tests/actor-vars.ts +93 -0
  189. package/src/driver-test-suite/tests/manager-driver.ts +365 -0
  190. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +226 -0
  191. package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
  192. package/src/driver-test-suite/tests/raw-http.ts +347 -0
  193. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +392 -0
  194. package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
  195. package/src/driver-test-suite/tests/request-access.ts +244 -0
  196. package/src/driver-test-suite/utils.ts +68 -0
  197. package/src/drivers/default.ts +31 -0
  198. package/src/drivers/engine/actor-driver.ts +360 -0
  199. package/src/drivers/engine/api-endpoints.ts +128 -0
  200. package/src/drivers/engine/api-utils.ts +70 -0
  201. package/src/drivers/engine/config.ts +39 -0
  202. package/src/drivers/engine/keys.test.ts +266 -0
  203. package/src/drivers/engine/keys.ts +89 -0
  204. package/src/drivers/engine/kv.ts +3 -0
  205. package/src/drivers/engine/log.ts +7 -0
  206. package/src/drivers/engine/manager-driver.ts +391 -0
  207. package/src/drivers/engine/mod.ts +36 -0
  208. package/src/drivers/engine/ws-proxy.ts +170 -0
  209. package/src/drivers/file-system/actor.ts +91 -0
  210. package/src/drivers/file-system/global-state.ts +673 -0
  211. package/src/drivers/file-system/log.ts +7 -0
  212. package/src/drivers/file-system/manager.ts +306 -0
  213. package/src/drivers/file-system/mod.ts +48 -0
  214. package/src/drivers/file-system/utils.ts +109 -0
  215. package/src/globals.d.ts +6 -0
  216. package/src/inline-client-driver/log.ts +7 -0
  217. package/src/inline-client-driver/mod.ts +385 -0
  218. package/src/inspector/actor.ts +298 -0
  219. package/src/inspector/config.ts +83 -0
  220. package/src/inspector/log.ts +5 -0
  221. package/src/inspector/manager.ts +86 -0
  222. package/src/inspector/mod.ts +2 -0
  223. package/src/inspector/protocol/actor.ts +10 -0
  224. package/src/inspector/protocol/common.ts +196 -0
  225. package/src/inspector/protocol/manager.ts +10 -0
  226. package/src/inspector/protocol/mod.ts +2 -0
  227. package/src/inspector/utils.ts +76 -0
  228. package/src/manager/auth.ts +121 -0
  229. package/src/manager/driver.ts +80 -0
  230. package/src/manager/hono-websocket-adapter.ts +333 -0
  231. package/src/manager/log.ts +7 -0
  232. package/src/manager/mod.ts +2 -0
  233. package/src/manager/protocol/mod.ts +24 -0
  234. package/src/manager/protocol/query.ts +89 -0
  235. package/src/manager/router.ts +1792 -0
  236. package/src/mod.ts +20 -0
  237. package/src/registry/config.ts +32 -0
  238. package/src/registry/log.ts +7 -0
  239. package/src/registry/mod.ts +124 -0
  240. package/src/registry/run-config.ts +54 -0
  241. package/src/registry/serve.ts +53 -0
  242. package/src/schemas/actor-persist/mod.ts +1 -0
  243. package/src/schemas/actor-persist/versioned.ts +25 -0
  244. package/src/schemas/client-protocol/mod.ts +1 -0
  245. package/src/schemas/client-protocol/versioned.ts +63 -0
  246. package/src/schemas/file-system-driver/mod.ts +1 -0
  247. package/src/schemas/file-system-driver/versioned.ts +28 -0
  248. package/src/serde.ts +84 -0
  249. package/src/test/config.ts +16 -0
  250. package/src/test/log.ts +7 -0
  251. package/src/test/mod.ts +153 -0
  252. package/src/utils.ts +172 -0
  253. package/README.md +0 -13
package/src/mod.ts ADDED
@@ -0,0 +1,20 @@
1
+ export { generateConnId, generateConnToken } from "@/actor/connection";
2
+ export * from "@/actor/mod";
3
+ export {
4
+ type AnyClient,
5
+ type Client,
6
+ type ClientDriver,
7
+ createClientWithDriver,
8
+ } from "@/client/client";
9
+ export { InlineWebSocketAdapter2 } from "@/common/inline-websocket-adapter2";
10
+ export { noopNext } from "@/common/utils";
11
+ export { createEngineDriver } from "@/drivers/engine/mod";
12
+ export {
13
+ createFileSystemDriver,
14
+ createMemoryDriver,
15
+ } from "@/drivers/file-system/mod";
16
+ export { createInlineClientDriver } from "@/inline-client-driver/mod";
17
+ // Re-export important protocol types and utilities needed by drivers
18
+ export type { ActorQuery } from "@/manager/protocol/query";
19
+ export * from "@/registry/mod";
20
+ export { toUint8Array } from "@/utils";
@@ -0,0 +1,32 @@
1
+ //! These configs configs hold anything that's not platform-specific about running actors.
2
+
3
+ import { z } from "zod";
4
+ import type { ActorDefinition, AnyActorDefinition } from "@/actor/definition";
5
+
6
+ export const ActorsSchema = z.record(
7
+ z.string(),
8
+ z.custom<ActorDefinition<any, any, any, any, any, any, any, any>>(),
9
+ );
10
+ export type RegistryActors = z.infer<typeof ActorsSchema>;
11
+
12
+ export const TestConfigSchema = z.object({ enabled: z.boolean() });
13
+ export type TestConfig = z.infer<typeof TestConfigSchema>;
14
+
15
+ /** Base config used for the actor config across all platforms. */
16
+ export const RegistryConfigSchema = z.object({
17
+ use: z.record(z.string(), z.custom<AnyActorDefinition>()),
18
+
19
+ // TODO: Find a better way of passing around the test config
20
+ /**
21
+ * Test configuration.
22
+ *
23
+ * DO NOT MANUALLY ENABLE. THIS IS USED INTERNALLY.
24
+ * @internal
25
+ **/
26
+ test: TestConfigSchema.optional().default({ enabled: false }),
27
+ });
28
+ export type RegistryConfig = z.infer<typeof RegistryConfigSchema>;
29
+ export type RegistryConfigInput<A extends RegistryActors> = Omit<
30
+ z.input<typeof RegistryConfigSchema>,
31
+ "use"
32
+ > & { use: A };
@@ -0,0 +1,7 @@
1
+ import { getLogger } from "@/common//log";
2
+
3
+ export const LOGGER_NAME = "registry";
4
+
5
+ export function logger() {
6
+ return getLogger(LOGGER_NAME);
7
+ }
@@ -0,0 +1,124 @@
1
+ import type { Hono } from "hono";
2
+ import { createActorRouter } from "@/actor/router";
3
+ import { type Client, createClientWithDriver } from "@/client/client";
4
+ import { chooseDefaultDriver } from "@/drivers/default";
5
+ import { createInlineClientDriver } from "@/inline-client-driver/mod";
6
+ import { getInspectorUrl } from "@/inspector/utils";
7
+ import { createManagerRouter } from "@/manager/router";
8
+ import {
9
+ type RegistryActors,
10
+ type RegistryConfig,
11
+ type RegistryConfigInput,
12
+ RegistryConfigSchema,
13
+ } from "./config";
14
+ import { logger } from "./log";
15
+ import {
16
+ type DriverConfig,
17
+ type RunConfig,
18
+ type RunConfigInput,
19
+ RunConfigSchema,
20
+ } from "./run-config";
21
+ import { crossPlatformServe } from "./serve";
22
+
23
+ interface ServerOutput<A extends Registry<any>> {
24
+ client: Client<A>;
25
+ hono: Hono;
26
+ handler: (req: Request) => Promise<Response>;
27
+ serve: (hono?: Hono) => void;
28
+ }
29
+
30
+ export class Registry<A extends RegistryActors> {
31
+ #config: RegistryConfig;
32
+
33
+ public get config(): RegistryConfig {
34
+ return this.#config;
35
+ }
36
+
37
+ constructor(config: RegistryConfig) {
38
+ this.#config = config;
39
+ }
40
+
41
+ /**
42
+ * Runs the registry for a server.
43
+ */
44
+ public createServer(inputConfig?: RunConfigInput): ServerOutput<this> {
45
+ const config = RunConfigSchema.parse(inputConfig);
46
+
47
+ // Choose the driver based on configuration
48
+ const driver = chooseDefaultDriver(config);
49
+
50
+ // Configure getUpgradeWebSocket lazily so we can assign it in crossPlatformServe
51
+ let upgradeWebSocket: any;
52
+ if (!config.getUpgradeWebSocket) {
53
+ config.getUpgradeWebSocket = () => upgradeWebSocket!;
54
+ }
55
+
56
+ // Create router
57
+ const managerDriver = driver.manager(this.#config, config);
58
+ const clientDriver = createInlineClientDriver(managerDriver);
59
+ const { router: hono } = createManagerRouter(
60
+ this.#config,
61
+ config,
62
+ clientDriver,
63
+ managerDriver,
64
+ false,
65
+ );
66
+
67
+ // Create client
68
+ const client = createClientWithDriver<this>(clientDriver);
69
+
70
+ const driverLog = managerDriver.extraStartupLog?.() ?? {};
71
+ logger().info("rivetkit ready", {
72
+ driver: driver.name,
73
+ definitions: Object.keys(this.#config.use).length,
74
+ ...driverLog,
75
+ });
76
+ if (config.inspector?.enabled) {
77
+ logger().info("inspector ready", {
78
+ url: getInspectorUrl(config),
79
+ });
80
+ }
81
+
82
+ // Create runner
83
+ if (config.role === "all" || config.role === "runner") {
84
+ const inlineClient = createClientWithDriver(
85
+ createInlineClientDriver(managerDriver),
86
+ );
87
+ const _actorDriver = driver.actor(
88
+ this.#config,
89
+ config,
90
+ managerDriver,
91
+ inlineClient,
92
+ );
93
+ // TODO: What do we do with the actor driver here?
94
+ }
95
+
96
+ return {
97
+ client,
98
+ hono,
99
+ handler: async (req: Request) => await hono.fetch(req),
100
+ serve: async (app) => {
101
+ const out = await crossPlatformServe(hono, app);
102
+ upgradeWebSocket = out.upgradeWebSocket;
103
+ },
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Runs the registry as a standalone server.
109
+ */
110
+ public async runServer(inputConfig?: RunConfigInput) {
111
+ const { serve } = this.createServer(inputConfig);
112
+ serve();
113
+ }
114
+ }
115
+
116
+ export function setup<A extends RegistryActors>(
117
+ input: RegistryConfigInput<A>,
118
+ ): Registry<A> {
119
+ const config = RegistryConfigSchema.parse(input);
120
+ return new Registry(config);
121
+ }
122
+
123
+ export type { RegistryConfig, RegistryActors, RunConfig, DriverConfig };
124
+ export { RegistryConfigSchema };
@@ -0,0 +1,54 @@
1
+ import type { cors } from "hono/cors";
2
+ import { z } from "zod";
3
+ import type { ActorDriverBuilder } from "@/actor/driver";
4
+ import { InspectorConfigSchema } from "@/inspector/config";
5
+ import type { ManagerDriverBuilder } from "@/manager/driver";
6
+ import type { UpgradeWebSocket } from "@/utils";
7
+
8
+ type CorsOptions = NonNullable<Parameters<typeof cors>[0]>;
9
+
10
+ export type GetUpgradeWebSocket = () => UpgradeWebSocket;
11
+
12
+ export const DriverConfigSchema = z.object({
13
+ /** Machine-readable name to identify this driver by. */
14
+ name: z.string(),
15
+ manager: z.custom<ManagerDriverBuilder>(),
16
+ actor: z.custom<ActorDriverBuilder>(),
17
+ });
18
+
19
+ export type DriverConfig = z.infer<typeof DriverConfigSchema>;
20
+
21
+ /** Base config used for the actor config across all platforms. */
22
+ export const RunConfigSchema = z
23
+ .object({
24
+ driver: DriverConfigSchema.optional(),
25
+
26
+ /** Endpoint to connect to the Rivet engine. Can be configured via RIVET_ENGINE env var. */
27
+ engine: z.string().optional(),
28
+
29
+ // This is a function to allow for lazy configuration of upgradeWebSocket on the
30
+ // fly. This is required since the dependencies that profie upgradeWebSocket
31
+ // (specifically Node.js) can sometimes only be specified after the router is
32
+ // created or must be imported async using `await import(...)`
33
+ getUpgradeWebSocket: z.custom<GetUpgradeWebSocket>().optional(),
34
+
35
+ role: z.enum(["all", "server", "runner"]).optional().default("all"),
36
+
37
+ /** CORS configuration for the router. Uses Hono's CORS middleware options. */
38
+ cors: z.custom<CorsOptions>().optional(),
39
+
40
+ maxIncomingMessageSize: z.number().optional().default(65_536),
41
+
42
+ inspector: InspectorConfigSchema,
43
+
44
+ /**
45
+ * Base path for the router. This is used to prefix all routes.
46
+ * For example, if the base path is `/api`, then the route `/actors` will be
47
+ * available at `/api/actors`.
48
+ */
49
+ basePath: z.string().optional().default("/"),
50
+ })
51
+ .default({});
52
+
53
+ export type RunConfig = z.infer<typeof RunConfigSchema>;
54
+ export type RunConfigInput = z.input<typeof RunConfigSchema>;
@@ -0,0 +1,53 @@
1
+ import { Hono } from "hono";
2
+ import { getEnvUniversal } from "@/utils";
3
+ import { logger } from "./log";
4
+
5
+ export async function crossPlatformServe(
6
+ rivetKitRouter: Hono<any>,
7
+ userRouter: Hono | undefined,
8
+ ) {
9
+ const app = userRouter ?? new Hono();
10
+
11
+ // Import @hono/node-server
12
+ let serve: any;
13
+ try {
14
+ const dep = await import("@hono/node-server");
15
+ serve = dep.serve;
16
+ } catch (err) {
17
+ logger().error(
18
+ "failed to import @hono/node-server. please run 'npm install @hono/node-server @hono/node-ws'",
19
+ );
20
+ process.exit(1);
21
+ }
22
+
23
+ // Mount registry
24
+ app.route("/registry", rivetKitRouter);
25
+
26
+ // Import @hono/node-ws
27
+ let createNodeWebSocket: any;
28
+ try {
29
+ const dep = await import("@hono/node-ws");
30
+ createNodeWebSocket = dep.createNodeWebSocket;
31
+ } catch (err) {
32
+ logger().error(
33
+ "failed to import @hono/node-ws. please run 'npm install @hono/node-server @hono/node-ws'",
34
+ );
35
+ process.exit(1);
36
+ }
37
+
38
+ // Inject WS
39
+ const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({
40
+ app,
41
+ });
42
+
43
+ // Start server
44
+ const port = Number.parseInt(
45
+ getEnvUniversal("PORT") ?? getEnvUniversal("PORT_HTTP") ?? "8080",
46
+ );
47
+ const server = serve({ fetch: app.fetch, port }, () =>
48
+ logger().info("server listening", { port }),
49
+ );
50
+ injectWebSocket(server);
51
+
52
+ return { upgradeWebSocket };
53
+ }
@@ -0,0 +1 @@
1
+ export * from "../../../dist/schemas/actor-persist/v1";
@@ -0,0 +1,25 @@
1
+ import {
2
+ createVersionedDataHandler,
3
+ type MigrationFn,
4
+ } from "@/common/versioned-data";
5
+ import * as v1 from "../../../dist/schemas/actor-persist/v1";
6
+
7
+ export const CURRENT_VERSION = 1;
8
+
9
+ export type CurrentPersistedActor = v1.PersistedActor;
10
+ export type CurrentPersistedConnection = v1.PersistedConnection;
11
+ export type CurrentPersistedSubscription = v1.PersistedSubscription;
12
+ export type CurrentGenericPersistedScheduleEvent =
13
+ v1.GenericPersistedScheduleEvent;
14
+ export type CurrentPersistedScheduleEventKind = v1.PersistedScheduleEventKind;
15
+ export type CurrentPersistedScheduleEvent = v1.PersistedScheduleEvent;
16
+
17
+ const migrations = new Map<number, MigrationFn<any, any>>();
18
+
19
+ export const PERSISTED_ACTOR_VERSIONED =
20
+ createVersionedDataHandler<CurrentPersistedActor>({
21
+ currentVersion: CURRENT_VERSION,
22
+ migrations,
23
+ serializeVersion: (data) => v1.encodePersistedActor(data),
24
+ deserializeVersion: (bytes) => v1.decodePersistedActor(bytes),
25
+ });
@@ -0,0 +1 @@
1
+ export * from "../../../dist/schemas/client-protocol/v1";
@@ -0,0 +1,63 @@
1
+ import {
2
+ createVersionedDataHandler,
3
+ type MigrationFn,
4
+ } from "@/common/versioned-data";
5
+ import * as v1 from "../../../dist/schemas/client-protocol/v1";
6
+
7
+ export const CURRENT_VERSION = 1;
8
+
9
+ const migrations = new Map<number, MigrationFn<any, any>>();
10
+
11
+ export const TO_SERVER_VERSIONED = createVersionedDataHandler<v1.ToServer>({
12
+ currentVersion: CURRENT_VERSION,
13
+ migrations,
14
+ serializeVersion: (data) => v1.encodeToServer(data),
15
+ deserializeVersion: (bytes) => v1.decodeToServer(bytes),
16
+ });
17
+
18
+ export const TO_CLIENT_VERSIONED = createVersionedDataHandler<v1.ToClient>({
19
+ currentVersion: CURRENT_VERSION,
20
+ migrations,
21
+ serializeVersion: (data) => v1.encodeToClient(data),
22
+ deserializeVersion: (bytes) => v1.decodeToClient(bytes),
23
+ });
24
+
25
+ export const HTTP_ACTION_REQUEST_VERSIONED =
26
+ createVersionedDataHandler<v1.HttpActionRequest>({
27
+ currentVersion: CURRENT_VERSION,
28
+ migrations,
29
+ serializeVersion: (data) => v1.encodeHttpActionRequest(data),
30
+ deserializeVersion: (bytes) => v1.decodeHttpActionRequest(bytes),
31
+ });
32
+
33
+ export const HTTP_ACTION_RESPONSE_VERSIONED =
34
+ createVersionedDataHandler<v1.HttpActionResponse>({
35
+ currentVersion: CURRENT_VERSION,
36
+ migrations,
37
+ serializeVersion: (data) => v1.encodeHttpActionResponse(data),
38
+ deserializeVersion: (bytes) => v1.decodeHttpActionResponse(bytes),
39
+ });
40
+
41
+ export const HTTP_RESPONSE_ERROR_VERSIONED =
42
+ createVersionedDataHandler<v1.HttpResponseError>({
43
+ currentVersion: CURRENT_VERSION,
44
+ migrations,
45
+ serializeVersion: (data) => v1.encodeHttpResponseError(data),
46
+ deserializeVersion: (bytes) => v1.decodeHttpResponseError(bytes),
47
+ });
48
+
49
+ export const HTTP_RESOLVE_REQUEST_VERSIONED =
50
+ createVersionedDataHandler<v1.HttpResolveRequest>({
51
+ currentVersion: CURRENT_VERSION,
52
+ migrations,
53
+ serializeVersion: (_) => new Uint8Array(),
54
+ deserializeVersion: (bytes) => null,
55
+ });
56
+
57
+ export const HTTP_RESOLVE_RESPONSE_VERSIONED =
58
+ createVersionedDataHandler<v1.HttpResolveResponse>({
59
+ currentVersion: CURRENT_VERSION,
60
+ migrations,
61
+ serializeVersion: (data) => v1.encodeHttpResolveResponse(data),
62
+ deserializeVersion: (bytes) => v1.decodeHttpResolveResponse(bytes),
63
+ });
@@ -0,0 +1 @@
1
+ export * from "../../../dist/schemas/file-system-driver/v1";
@@ -0,0 +1,28 @@
1
+ import {
2
+ createVersionedDataHandler,
3
+ type MigrationFn,
4
+ } from "@/common/versioned-data";
5
+ import * as v1 from "../../../dist/schemas/file-system-driver/v1";
6
+
7
+ export const CURRENT_VERSION = 1;
8
+
9
+ export type CurrentActorState = v1.ActorState;
10
+ export type CurrentActorAlarm = v1.ActorAlarm;
11
+
12
+ const migrations = new Map<number, MigrationFn<any, any>>();
13
+
14
+ export const ACTOR_STATE_VERSIONED =
15
+ createVersionedDataHandler<CurrentActorState>({
16
+ currentVersion: CURRENT_VERSION,
17
+ migrations,
18
+ serializeVersion: (data) => v1.encodeActorState(data),
19
+ deserializeVersion: (bytes) => v1.decodeActorState(bytes),
20
+ });
21
+
22
+ export const ACTOR_ALARM_VERSIONED =
23
+ createVersionedDataHandler<CurrentActorAlarm>({
24
+ currentVersion: CURRENT_VERSION,
25
+ migrations,
26
+ serializeVersion: (data) => v1.encodeActorAlarm(data),
27
+ deserializeVersion: (bytes) => v1.decodeActorAlarm(bytes),
28
+ });
package/src/serde.ts ADDED
@@ -0,0 +1,84 @@
1
+ import * as cbor from "cbor-x";
2
+ import invariant from "invariant";
3
+ import { assertUnreachable } from "@/common/utils";
4
+ import type { VersionedDataHandler } from "@/common/versioned-data";
5
+ import type { Encoding } from "@/mod";
6
+ import { jsonStringifyCompat } from "./actor/protocol/serde";
7
+
8
+ export function encodingIsBinary(encoding: Encoding): boolean {
9
+ if (encoding === "json") {
10
+ return false;
11
+ } else if (encoding === "cbor" || encoding === "bare") {
12
+ return true;
13
+ } else {
14
+ assertUnreachable(encoding);
15
+ }
16
+ }
17
+
18
+ export function contentTypeForEncoding(encoding: Encoding): string {
19
+ if (encoding === "json") {
20
+ return "application/json";
21
+ } else if (encoding === "cbor" || encoding === "bare") {
22
+ return "application/octet-stream";
23
+ } else {
24
+ assertUnreachable(encoding);
25
+ }
26
+ }
27
+
28
+ export function wsBinaryTypeForEncoding(
29
+ encoding: Encoding,
30
+ ): "arraybuffer" | "blob" {
31
+ if (encoding === "json") {
32
+ return "blob";
33
+ } else if (encoding === "cbor" || encoding === "bare") {
34
+ return "arraybuffer";
35
+ } else {
36
+ assertUnreachable(encoding);
37
+ }
38
+ }
39
+
40
+ export function serializeWithEncoding<T>(
41
+ encoding: Encoding,
42
+ value: T,
43
+ versionedDataHandler: VersionedDataHandler<T>,
44
+ ): Uint8Array | string {
45
+ if (encoding === "json") {
46
+ return jsonStringifyCompat(value);
47
+ } else if (encoding === "cbor") {
48
+ return cbor.encode(value);
49
+ } else if (encoding === "bare") {
50
+ return versionedDataHandler.serializeWithEmbeddedVersion(value);
51
+ } else {
52
+ assertUnreachable(encoding);
53
+ }
54
+ }
55
+
56
+ export function deserializeWithEncoding<T>(
57
+ encoding: Encoding,
58
+ buffer: Uint8Array | string,
59
+ versionedDataHandler: VersionedDataHandler<T>,
60
+ ): T {
61
+ if (encoding === "json") {
62
+ if (typeof buffer === "string") {
63
+ return JSON.parse(buffer);
64
+ } else {
65
+ const decoder = new TextDecoder("utf-8");
66
+ const jsonString = decoder.decode(buffer);
67
+ return JSON.parse(jsonString);
68
+ }
69
+ } else if (encoding === "cbor") {
70
+ invariant(
71
+ typeof buffer !== "string",
72
+ "buffer cannot be string for cbor encoding",
73
+ );
74
+ return cbor.decode(buffer);
75
+ } else if (encoding === "bare") {
76
+ invariant(
77
+ typeof buffer !== "string",
78
+ "buffer cannot be string for bare encoding",
79
+ );
80
+ return versionedDataHandler.deserializeWithEmbeddedVersion(buffer);
81
+ } else {
82
+ assertUnreachable(encoding);
83
+ }
84
+ }
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+ import { RunConfigSchema } from "@/registry/run-config";
3
+
4
+ export const ConfigSchema = RunConfigSchema.removeDefault()
5
+ .extend({
6
+ hostname: z
7
+ .string()
8
+ .optional()
9
+ .default(process.env.HOSTNAME ?? "127.0.0.1"),
10
+ port: z
11
+ .number()
12
+ .optional()
13
+ .default(Number.parseInt(process.env.PORT ?? "8080")),
14
+ })
15
+ .default({});
16
+ export type InputConfig = z.input<typeof ConfigSchema>;
@@ -0,0 +1,7 @@
1
+ import { getLogger } from "@/common/log";
2
+
3
+ export const LOGGER_NAME = "nodejs";
4
+
5
+ export function logger() {
6
+ return getLogger(LOGGER_NAME);
7
+ }
@@ -0,0 +1,153 @@
1
+ import { createServer } from "node:net";
2
+ import { serve as honoServe, type ServerType } from "@hono/node-server";
3
+ import { createNodeWebSocket } from "@hono/node-ws";
4
+ import { type TestContext, vi } from "vitest";
5
+ import { type Client, createClient } from "@/client/mod";
6
+ import { chooseDefaultDriver } from "@/drivers/default";
7
+ import { createFileSystemOrMemoryDriver } from "@/drivers/file-system/mod";
8
+ import { createInlineClientDriver } from "@/inline-client-driver/mod";
9
+ import { getInspectorUrl } from "@/inspector/utils";
10
+ import { createManagerRouter } from "@/manager/router";
11
+ import type { Registry } from "@/registry/mod";
12
+ import { RunConfigSchema } from "@/registry/run-config";
13
+ import { ConfigSchema, type InputConfig } from "./config";
14
+ import { logger } from "./log";
15
+
16
+ function serve(registry: Registry<any>, inputConfig?: InputConfig): ServerType {
17
+ // Configure default configuration
18
+ inputConfig ??= {};
19
+
20
+ const config = ConfigSchema.parse(inputConfig);
21
+
22
+ let upgradeWebSocket: any;
23
+ if (!config.getUpgradeWebSocket) {
24
+ config.getUpgradeWebSocket = () => upgradeWebSocket!;
25
+ }
26
+
27
+ // Create router
28
+ const runConfig = RunConfigSchema.parse(inputConfig);
29
+ const driver = inputConfig.driver ?? createFileSystemOrMemoryDriver(false);
30
+ const managerDriver = driver.manager(registry.config, config);
31
+ const inlineClientDriver = createInlineClientDriver(managerDriver);
32
+ const { router } = createManagerRouter(
33
+ registry.config,
34
+ runConfig,
35
+ inlineClientDriver,
36
+ managerDriver,
37
+ false,
38
+ );
39
+
40
+ // Inject WebSocket
41
+ const nodeWebSocket = createNodeWebSocket({ app: router });
42
+ upgradeWebSocket = nodeWebSocket.upgradeWebSocket;
43
+
44
+ const server = honoServe({
45
+ fetch: router.fetch,
46
+ hostname: config.hostname,
47
+ port: config.port,
48
+ });
49
+ nodeWebSocket.injectWebSocket(server);
50
+
51
+ logger().info("rivetkit started", {
52
+ hostname: config.hostname,
53
+ port: config.port,
54
+ definitions: Object.keys(registry.config.use).length,
55
+ });
56
+
57
+ return server;
58
+ }
59
+
60
+ export interface SetupTestResult<A extends Registry<any>> {
61
+ client: Client<A>;
62
+ mockDriver: {
63
+ actorDriver: {
64
+ setCreateVarsContext: (ctx: any) => void;
65
+ };
66
+ };
67
+ }
68
+
69
+ // Must use `TestContext` since global hooks do not work when running concurrently
70
+ export async function setupTest<A extends Registry<any>>(
71
+ c: TestContext,
72
+ registry: A,
73
+ ): Promise<SetupTestResult<A>> {
74
+ vi.useFakeTimers();
75
+
76
+ // Set up mock driver for testing createVars context
77
+ const mockDriverContext: any = {};
78
+ const setDriverContextFn = (ctx: any) => {
79
+ mockDriverContext.current = ctx;
80
+ };
81
+
82
+ // We don't need to modify the driver context anymore since we're testing with the actual context
83
+
84
+ // Start server with a random port
85
+ const port = await getPort();
86
+ const server = serve(registry, { port });
87
+ c.onTestFinished(
88
+ async () => await new Promise((resolve) => server.close(() => resolve())),
89
+ );
90
+
91
+ // Create client
92
+ const client = createClient<A>(`http://127.0.0.1:${port}`);
93
+ c.onTestFinished(async () => await client.dispose());
94
+
95
+ return {
96
+ client,
97
+ mockDriver: {
98
+ actorDriver: {
99
+ setCreateVarsContext: setDriverContextFn,
100
+ },
101
+ },
102
+ };
103
+ }
104
+
105
+ export async function getPort(): Promise<number> {
106
+ // Pick random port between 10000 and 65535 (avoiding well-known and registered ports)
107
+ const MIN_PORT = 10000;
108
+ const MAX_PORT = 65535;
109
+ const getRandomPort = () =>
110
+ Math.floor(Math.random() * (MAX_PORT - MIN_PORT + 1)) + MIN_PORT;
111
+
112
+ let port = getRandomPort();
113
+ let maxAttempts = 10;
114
+
115
+ while (maxAttempts > 0) {
116
+ try {
117
+ // Try to create a server on the port to check if it's available
118
+ const server = await new Promise<any>((resolve, reject) => {
119
+ const server = createServer();
120
+
121
+ server.once("error", (err: Error & { code?: string }) => {
122
+ if (err.code === "EADDRINUSE") {
123
+ reject(new Error(`Port ${port} is in use`));
124
+ } else {
125
+ reject(err);
126
+ }
127
+ });
128
+
129
+ server.once("listening", () => {
130
+ resolve(server);
131
+ });
132
+
133
+ server.listen(port);
134
+ });
135
+
136
+ // Close the server since we're just checking availability
137
+ await new Promise<void>((resolve) => {
138
+ server.close(() => resolve());
139
+ });
140
+
141
+ return port;
142
+ } catch (err) {
143
+ // If port is in use, try a different one
144
+ maxAttempts--;
145
+ if (maxAttempts <= 0) {
146
+ break;
147
+ }
148
+ port = getRandomPort();
149
+ }
150
+ }
151
+
152
+ throw new Error("Could not find an available port after multiple attempts");
153
+ }