rivetkit 2.0.2 → 2.0.4

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 (246) hide show
  1. package/README.md +3 -5
  2. package/dist/schemas/actor-persist/v1.ts +225 -0
  3. package/dist/schemas/client-protocol/v1.ts +435 -0
  4. package/dist/schemas/file-system-driver/v1.ts +102 -0
  5. package/dist/tsup/actor/errors.cjs +77 -0
  6. package/dist/tsup/actor/errors.cjs.map +1 -0
  7. package/dist/tsup/actor/errors.d.cts +156 -0
  8. package/dist/tsup/actor/errors.d.ts +156 -0
  9. package/dist/tsup/actor/errors.js +77 -0
  10. package/dist/tsup/actor/errors.js.map +1 -0
  11. package/dist/tsup/chunk-3F2YSRJL.js +117 -0
  12. package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
  13. package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
  14. package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
  15. package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
  16. package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
  17. package/dist/tsup/chunk-6LJT3QRL.cjs +539 -0
  18. package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
  19. package/dist/tsup/chunk-GICQ3YCU.cjs +1792 -0
  20. package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
  21. package/dist/tsup/chunk-H26RP6GD.js +251 -0
  22. package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
  23. package/dist/tsup/chunk-HI3HWJRC.js +20 -0
  24. package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
  25. package/dist/tsup/chunk-HLLF4B4Q.js +1792 -0
  26. package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
  27. package/dist/tsup/chunk-IH6CKNDW.cjs +117 -0
  28. package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
  29. package/dist/tsup/chunk-LV2S3OU3.js +250 -0
  30. package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
  31. package/dist/tsup/chunk-LWNKVZG5.cjs +251 -0
  32. package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
  33. package/dist/tsup/chunk-NFU2BBT5.js +374 -0
  34. package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
  35. package/dist/tsup/chunk-PQY7KKTL.js +539 -0
  36. package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
  37. package/dist/tsup/chunk-QK72M5JB.js +45 -0
  38. package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
  39. package/dist/tsup/chunk-QNNXFOQV.cjs +45 -0
  40. package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
  41. package/dist/tsup/chunk-SBHHJ6QS.cjs +374 -0
  42. package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
  43. package/dist/tsup/chunk-TQ62L3X7.js +325 -0
  44. package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
  45. package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
  46. package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
  47. package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
  48. package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
  49. package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
  50. package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
  51. package/dist/tsup/client/mod.cjs +32 -0
  52. package/dist/tsup/client/mod.cjs.map +1 -0
  53. package/dist/tsup/client/mod.d.cts +20 -0
  54. package/dist/tsup/client/mod.d.ts +20 -0
  55. package/dist/tsup/client/mod.js +32 -0
  56. package/dist/tsup/client/mod.js.map +1 -0
  57. package/dist/tsup/common/log.cjs +21 -0
  58. package/dist/tsup/common/log.cjs.map +1 -0
  59. package/dist/tsup/common/log.d.cts +26 -0
  60. package/dist/tsup/common/log.d.ts +26 -0
  61. package/dist/tsup/common/log.js +21 -0
  62. package/dist/tsup/common/log.js.map +1 -0
  63. package/dist/tsup/common/websocket.cjs +10 -0
  64. package/dist/tsup/common/websocket.cjs.map +1 -0
  65. package/dist/tsup/common/websocket.d.cts +3 -0
  66. package/dist/tsup/common/websocket.d.ts +3 -0
  67. package/dist/tsup/common/websocket.js +10 -0
  68. package/dist/tsup/common/websocket.js.map +1 -0
  69. package/dist/tsup/common-CXCe7s6i.d.cts +218 -0
  70. package/dist/tsup/common-CXCe7s6i.d.ts +218 -0
  71. package/dist/tsup/connection-BI-6UIBJ.d.ts +2087 -0
  72. package/dist/tsup/connection-Dyd4NLGW.d.cts +2087 -0
  73. package/dist/tsup/driver-helpers/mod.cjs +30 -0
  74. package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
  75. package/dist/tsup/driver-helpers/mod.d.cts +17 -0
  76. package/dist/tsup/driver-helpers/mod.d.ts +17 -0
  77. package/dist/tsup/driver-helpers/mod.js +30 -0
  78. package/dist/tsup/driver-helpers/mod.js.map +1 -0
  79. package/dist/tsup/driver-test-suite/mod.cjs +3411 -0
  80. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
  81. package/dist/tsup/driver-test-suite/mod.d.cts +63 -0
  82. package/dist/tsup/driver-test-suite/mod.d.ts +63 -0
  83. package/dist/tsup/driver-test-suite/mod.js +3411 -0
  84. package/dist/tsup/driver-test-suite/mod.js.map +1 -0
  85. package/dist/tsup/inspector/mod.cjs +51 -0
  86. package/dist/tsup/inspector/mod.cjs.map +1 -0
  87. package/dist/tsup/inspector/mod.d.cts +408 -0
  88. package/dist/tsup/inspector/mod.d.ts +408 -0
  89. package/dist/tsup/inspector/mod.js +51 -0
  90. package/dist/tsup/inspector/mod.js.map +1 -0
  91. package/dist/tsup/mod.cjs +67 -0
  92. package/dist/tsup/mod.cjs.map +1 -0
  93. package/dist/tsup/mod.d.cts +105 -0
  94. package/dist/tsup/mod.d.ts +105 -0
  95. package/dist/tsup/mod.js +67 -0
  96. package/dist/tsup/mod.js.map +1 -0
  97. package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +65 -0
  98. package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +65 -0
  99. package/dist/tsup/test/mod.cjs +17 -0
  100. package/dist/tsup/test/mod.cjs.map +1 -0
  101. package/dist/tsup/test/mod.d.cts +26 -0
  102. package/dist/tsup/test/mod.d.ts +26 -0
  103. package/dist/tsup/test/mod.js +17 -0
  104. package/dist/tsup/test/mod.js.map +1 -0
  105. package/dist/tsup/utils-fwx3o3K9.d.cts +18 -0
  106. package/dist/tsup/utils-fwx3o3K9.d.ts +18 -0
  107. package/dist/tsup/utils.cjs +26 -0
  108. package/dist/tsup/utils.cjs.map +1 -0
  109. package/dist/tsup/utils.d.cts +36 -0
  110. package/dist/tsup/utils.d.ts +36 -0
  111. package/dist/tsup/utils.js +26 -0
  112. package/dist/tsup/utils.js.map +1 -0
  113. package/package.json +208 -5
  114. package/src/actor/action.ts +178 -0
  115. package/src/actor/config.ts +497 -0
  116. package/src/actor/connection.ts +257 -0
  117. package/src/actor/context.ts +168 -0
  118. package/src/actor/database.ts +23 -0
  119. package/src/actor/definition.ts +82 -0
  120. package/src/actor/driver.ts +84 -0
  121. package/src/actor/errors.ts +422 -0
  122. package/src/actor/generic-conn-driver.ts +246 -0
  123. package/src/actor/instance.ts +1844 -0
  124. package/src/actor/keys.test.ts +266 -0
  125. package/src/actor/keys.ts +89 -0
  126. package/src/actor/log.ts +6 -0
  127. package/src/actor/mod.ts +108 -0
  128. package/src/actor/persisted.ts +42 -0
  129. package/src/actor/protocol/old.ts +297 -0
  130. package/src/actor/protocol/serde.ts +131 -0
  131. package/src/actor/router-endpoints.ts +688 -0
  132. package/src/actor/router.ts +265 -0
  133. package/src/actor/schedule.ts +17 -0
  134. package/src/actor/unstable-react.ts +110 -0
  135. package/src/actor/utils.ts +102 -0
  136. package/src/client/actor-common.ts +30 -0
  137. package/src/client/actor-conn.ts +865 -0
  138. package/src/client/actor-handle.ts +268 -0
  139. package/src/client/actor-query.ts +65 -0
  140. package/src/client/client.ts +554 -0
  141. package/src/client/config.ts +44 -0
  142. package/src/client/errors.ts +42 -0
  143. package/src/client/log.ts +5 -0
  144. package/src/client/mod.ts +60 -0
  145. package/src/client/raw-utils.ts +149 -0
  146. package/src/client/test.ts +44 -0
  147. package/src/client/utils.ts +152 -0
  148. package/src/common/eventsource-interface.ts +47 -0
  149. package/src/common/eventsource.ts +80 -0
  150. package/src/common/fake-event-source.ts +267 -0
  151. package/src/common/inline-websocket-adapter2.ts +454 -0
  152. package/src/common/log-levels.ts +27 -0
  153. package/src/common/log.ts +214 -0
  154. package/src/common/logfmt.ts +219 -0
  155. package/src/common/network.ts +2 -0
  156. package/src/common/router.ts +80 -0
  157. package/src/common/utils.ts +336 -0
  158. package/src/common/versioned-data.ts +95 -0
  159. package/src/common/websocket-interface.ts +49 -0
  160. package/src/common/websocket.ts +42 -0
  161. package/src/driver-helpers/mod.ts +22 -0
  162. package/src/driver-helpers/utils.ts +17 -0
  163. package/src/driver-test-suite/log.ts +5 -0
  164. package/src/driver-test-suite/mod.ts +239 -0
  165. package/src/driver-test-suite/tests/action-features.ts +136 -0
  166. package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
  167. package/src/driver-test-suite/tests/actor-conn.ts +349 -0
  168. package/src/driver-test-suite/tests/actor-driver.ts +25 -0
  169. package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
  170. package/src/driver-test-suite/tests/actor-handle.ts +292 -0
  171. package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
  172. package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
  173. package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
  174. package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
  175. package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
  176. package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
  177. package/src/driver-test-suite/tests/actor-state.ts +54 -0
  178. package/src/driver-test-suite/tests/actor-vars.ts +93 -0
  179. package/src/driver-test-suite/tests/manager-driver.ts +367 -0
  180. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -0
  181. package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
  182. package/src/driver-test-suite/tests/raw-http.ts +347 -0
  183. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -0
  184. package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
  185. package/src/driver-test-suite/tests/request-access.ts +230 -0
  186. package/src/driver-test-suite/utils.ts +71 -0
  187. package/src/drivers/default.ts +34 -0
  188. package/src/drivers/engine/actor-driver.ts +369 -0
  189. package/src/drivers/engine/config.ts +31 -0
  190. package/src/drivers/engine/kv.ts +3 -0
  191. package/src/drivers/engine/log.ts +5 -0
  192. package/src/drivers/engine/mod.ts +35 -0
  193. package/src/drivers/file-system/actor.ts +91 -0
  194. package/src/drivers/file-system/global-state.ts +686 -0
  195. package/src/drivers/file-system/log.ts +5 -0
  196. package/src/drivers/file-system/manager.ts +329 -0
  197. package/src/drivers/file-system/mod.ts +48 -0
  198. package/src/drivers/file-system/utils.ts +109 -0
  199. package/src/globals.d.ts +6 -0
  200. package/src/inspector/actor.ts +298 -0
  201. package/src/inspector/config.ts +88 -0
  202. package/src/inspector/log.ts +5 -0
  203. package/src/inspector/manager.ts +86 -0
  204. package/src/inspector/mod.ts +2 -0
  205. package/src/inspector/protocol/actor.ts +10 -0
  206. package/src/inspector/protocol/common.ts +196 -0
  207. package/src/inspector/protocol/manager.ts +10 -0
  208. package/src/inspector/protocol/mod.ts +2 -0
  209. package/src/inspector/utils.ts +76 -0
  210. package/src/manager/driver.ts +88 -0
  211. package/src/manager/hono-websocket-adapter.ts +342 -0
  212. package/src/manager/log.ts +5 -0
  213. package/src/manager/mod.ts +2 -0
  214. package/src/manager/protocol/mod.ts +24 -0
  215. package/src/manager/protocol/query.ts +89 -0
  216. package/src/manager/router.ts +412 -0
  217. package/src/manager-api/routes/actors-create.ts +16 -0
  218. package/src/manager-api/routes/actors-delete.ts +4 -0
  219. package/src/manager-api/routes/actors-get-by-id.ts +7 -0
  220. package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
  221. package/src/manager-api/routes/actors-get.ts +7 -0
  222. package/src/manager-api/routes/common.ts +18 -0
  223. package/src/mod.ts +18 -0
  224. package/src/registry/config.ts +32 -0
  225. package/src/registry/log.ts +5 -0
  226. package/src/registry/mod.ts +157 -0
  227. package/src/registry/run-config.ts +52 -0
  228. package/src/registry/serve.ts +52 -0
  229. package/src/remote-manager-driver/actor-http-client.ts +72 -0
  230. package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
  231. package/src/remote-manager-driver/api-endpoints.ts +79 -0
  232. package/src/remote-manager-driver/api-utils.ts +43 -0
  233. package/src/remote-manager-driver/log.ts +5 -0
  234. package/src/remote-manager-driver/mod.ts +274 -0
  235. package/src/remote-manager-driver/ws-proxy.ts +180 -0
  236. package/src/schemas/actor-persist/mod.ts +1 -0
  237. package/src/schemas/actor-persist/versioned.ts +25 -0
  238. package/src/schemas/client-protocol/mod.ts +1 -0
  239. package/src/schemas/client-protocol/versioned.ts +63 -0
  240. package/src/schemas/file-system-driver/mod.ts +1 -0
  241. package/src/schemas/file-system-driver/versioned.ts +28 -0
  242. package/src/serde.ts +90 -0
  243. package/src/test/config.ts +16 -0
  244. package/src/test/log.ts +5 -0
  245. package/src/test/mod.ts +154 -0
  246. package/src/utils.ts +172 -0
@@ -0,0 +1,266 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ deserializeActorKey,
4
+ EMPTY_KEY,
5
+ KEY_SEPARATOR,
6
+ serializeActorKey,
7
+ } from "./keys";
8
+
9
+ describe("Key serialization and deserialization", () => {
10
+ // Test serialization
11
+ describe("serializeActorKey", () => {
12
+ test("serializes empty key array", () => {
13
+ expect(serializeActorKey([])).toBe(EMPTY_KEY);
14
+ });
15
+
16
+ test("serializes single key", () => {
17
+ expect(serializeActorKey(["test"])).toBe("test");
18
+ });
19
+
20
+ test("serializes multiple keys", () => {
21
+ expect(serializeActorKey(["a", "b", "c"])).toBe(
22
+ `a${KEY_SEPARATOR}b${KEY_SEPARATOR}c`,
23
+ );
24
+ });
25
+
26
+ test("escapes forward slashes in keys", () => {
27
+ expect(serializeActorKey(["a/b"])).toBe("a\\/b");
28
+ expect(serializeActorKey(["a/b", "c"])).toBe(`a\\/b${KEY_SEPARATOR}c`);
29
+ });
30
+
31
+ test("escapes empty key marker in keys", () => {
32
+ expect(serializeActorKey([EMPTY_KEY])).toBe(`\\${EMPTY_KEY}`);
33
+ });
34
+
35
+ test("handles complex keys", () => {
36
+ expect(serializeActorKey(["a/b", EMPTY_KEY, "c/d"])).toBe(
37
+ `a\\/b${KEY_SEPARATOR}\\${EMPTY_KEY}${KEY_SEPARATOR}c\\/d`,
38
+ );
39
+ });
40
+ });
41
+
42
+ // Test deserialization
43
+ describe("deserializeActorKey", () => {
44
+ test("deserializes empty string", () => {
45
+ expect(deserializeActorKey("")).toEqual([]);
46
+ });
47
+
48
+ test("deserializes undefined/null", () => {
49
+ expect(deserializeActorKey(undefined as unknown as string)).toEqual([]);
50
+ expect(deserializeActorKey(null as unknown as string)).toEqual([]);
51
+ });
52
+
53
+ test("deserializes empty key marker", () => {
54
+ expect(deserializeActorKey(EMPTY_KEY)).toEqual([]);
55
+ });
56
+
57
+ test("deserializes single key", () => {
58
+ expect(deserializeActorKey("test")).toEqual(["test"]);
59
+ });
60
+
61
+ test("deserializes multiple keys", () => {
62
+ expect(
63
+ deserializeActorKey(`a${KEY_SEPARATOR}b${KEY_SEPARATOR}c`),
64
+ ).toEqual(["a", "b", "c"]);
65
+ });
66
+
67
+ test("deserializes keys with escaped forward slashes", () => {
68
+ expect(deserializeActorKey("a\\/b")).toEqual(["a/b"]);
69
+ expect(deserializeActorKey(`a\\/b${KEY_SEPARATOR}c`)).toEqual([
70
+ "a/b",
71
+ "c",
72
+ ]);
73
+ });
74
+
75
+ test("deserializes keys with escaped empty key marker", () => {
76
+ expect(deserializeActorKey(`\\${EMPTY_KEY}`)).toEqual([EMPTY_KEY]);
77
+ });
78
+
79
+ test("deserializes complex keys", () => {
80
+ expect(
81
+ deserializeActorKey(
82
+ `a\\/b${KEY_SEPARATOR}\\${EMPTY_KEY}${KEY_SEPARATOR}c\\/d`,
83
+ ),
84
+ ).toEqual(["a/b", EMPTY_KEY, "c/d"]);
85
+ });
86
+ });
87
+
88
+ // Test edge cases
89
+ describe("edge cases", () => {
90
+ test("handles empty string parts", () => {
91
+ const testCases: Array<[string[], string]> = [
92
+ [[""], "\\0"],
93
+ [["a", "", "b"], "a/\\0/b"],
94
+ [["", "a"], "\\0/a"],
95
+ [["a", ""], "a/\\0"],
96
+ [["", "", ""], "\\0/\\0/\\0"],
97
+ [["", "a", "", "b", ""], "\\0/a/\\0/b/\\0"],
98
+ [[], "/"],
99
+ [["test"], "test"],
100
+ [["a", "b", "c"], "a/b/c"],
101
+ [["a/b", "c"], "a\\/b/c"],
102
+ [[EMPTY_KEY], "\\/"],
103
+ [["a/b", EMPTY_KEY, "c/d"], "a\\/b/\\//c\\/d"],
104
+ [
105
+ ["special\\chars", "more:complex,keys", "final key"],
106
+ "special\\\\chars/more:complex,keys/final key",
107
+ ],
108
+ ];
109
+
110
+ for (const [key, expectedSerialized] of testCases) {
111
+ const serialized = serializeActorKey(key);
112
+ expect(serialized).toBe(expectedSerialized);
113
+ const deserialized = deserializeActorKey(serialized);
114
+ expect(deserialized).toEqual(key);
115
+ }
116
+ });
117
+
118
+ test("differentiates empty array from array with empty string", () => {
119
+ const emptyArray: string[] = [];
120
+ const arrayWithEmptyString = [""];
121
+
122
+ const serialized1 = serializeActorKey(emptyArray);
123
+ const serialized2 = serializeActorKey(arrayWithEmptyString);
124
+
125
+ expect(serialized1).toBe(EMPTY_KEY); // Should be "/"
126
+ expect(serialized2).not.toBe(EMPTY_KEY); // Should NOT be "/"
127
+ expect(serialized2).toBe("\\0"); // Empty string becomes \0 marker
128
+
129
+ expect(deserializeActorKey(serialized1)).toEqual(emptyArray);
130
+ expect(deserializeActorKey(serialized2)).toEqual(arrayWithEmptyString);
131
+ });
132
+
133
+ test("handles mix of empty strings and forward slash (EMPTY_KEY)", () => {
134
+ const testCases: Array<[string[], string]> = [
135
+ [["", EMPTY_KEY, ""], "\\0/\\//\\0"],
136
+ [[EMPTY_KEY, ""], "\\//\\0"],
137
+ [["", EMPTY_KEY], "\\0/\\/"],
138
+ [["a", "", EMPTY_KEY, "", "b"], "a/\\0/\\//\\0/b"],
139
+ ];
140
+
141
+ for (const [key, expectedSerialized] of testCases) {
142
+ const serialized = serializeActorKey(key);
143
+ expect(serialized).toBe(expectedSerialized);
144
+ const deserialized = deserializeActorKey(serialized);
145
+ expect(deserialized).toEqual(key);
146
+ }
147
+ });
148
+
149
+ test("handles literal backslash-zero string", () => {
150
+ const testCases: Array<[string[], string]> = [
151
+ [["\\0"], "\\\\0"], // Literal \0 string
152
+ [["a\\0b"], "a\\\\0b"], // Literal \0 in middle
153
+ [["\\0", ""], "\\\\0/\\0"], // Literal \0 with empty string
154
+ [["", "\\0"], "\\0/\\\\0"], // Empty string with literal \0
155
+ ];
156
+
157
+ for (const [key, expectedSerialized] of testCases) {
158
+ const serialized = serializeActorKey(key);
159
+ expect(serialized).toBe(expectedSerialized);
160
+ const deserialized = deserializeActorKey(serialized);
161
+ expect(deserialized).toEqual(key);
162
+ }
163
+ });
164
+
165
+ test("handles backslash at the end", () => {
166
+ const key = ["abc\\"];
167
+ const serialized = serializeActorKey(key);
168
+ expect(serialized).toBe("abc\\\\");
169
+ const deserialized = deserializeActorKey(serialized);
170
+ expect(deserialized).toEqual(key);
171
+ });
172
+
173
+ test("handles backslashes in middle of string", () => {
174
+ const testCases: Array<[string[], string]> = [
175
+ [["abc\\def"], "abc\\\\def"],
176
+ [["abc\\\\def"], "abc\\\\\\\\def"],
177
+ [["path\\to\\file"], "path\\\\to\\\\file"],
178
+ ];
179
+
180
+ for (const [key, expectedSerialized] of testCases) {
181
+ const serialized = serializeActorKey(key);
182
+ expect(serialized).toBe(expectedSerialized);
183
+ const deserialized = deserializeActorKey(serialized);
184
+ expect(deserialized).toEqual(key);
185
+ }
186
+ });
187
+
188
+ test("handles forward slashes at the end of strings", () => {
189
+ const serialized = serializeActorKey(["abc\\/"]);
190
+ expect(deserializeActorKey(serialized)).toEqual(["abc\\/"]);
191
+ });
192
+
193
+ test("handles mixed backslashes and forward slashes", () => {
194
+ const testCases: Array<[string[], string]> = [
195
+ [["path\\to\\file/dir"], "path\\\\to\\\\file\\/dir"],
196
+ [["file\\with/slash"], "file\\\\with\\/slash"],
197
+ [["path\\to\\file", "with/slash"], "path\\\\to\\\\file/with\\/slash"],
198
+ ];
199
+
200
+ for (const [key, expectedSerialized] of testCases) {
201
+ const serialized = serializeActorKey(key);
202
+ expect(serialized).toBe(expectedSerialized);
203
+ const deserialized = deserializeActorKey(serialized);
204
+ expect(deserialized).toEqual(key);
205
+ }
206
+ });
207
+
208
+ test("handles multiple consecutive forward slashes", () => {
209
+ const key = ["a//b"];
210
+ const serialized = serializeActorKey(key);
211
+ expect(serialized).toBe("a\\/\\/b");
212
+ const deserialized = deserializeActorKey(serialized);
213
+ expect(deserialized).toEqual(key);
214
+ });
215
+
216
+ test("handles special characters", () => {
217
+ const key = ["a💻b", "c🔑d"];
218
+ const serialized = serializeActorKey(key);
219
+ expect(serialized).toBe("a💻b/c🔑d");
220
+ const deserialized = deserializeActorKey(serialized);
221
+ expect(deserialized).toEqual(key);
222
+ });
223
+
224
+ test("handles escaped forward slashes immediately after separator", () => {
225
+ const key = ["abc", "/def"];
226
+ const serialized = serializeActorKey(key);
227
+ expect(serialized).toBe(`abc${KEY_SEPARATOR}\\/def`);
228
+ expect(deserializeActorKey(serialized)).toEqual(key);
229
+ });
230
+ });
231
+
232
+ // Test exact key matching
233
+ describe("exact key matching", () => {
234
+ test("differentiates [a,b] from [a,b,c]", () => {
235
+ const key1 = ["a", "b"];
236
+ const key2 = ["a", "b", "c"];
237
+
238
+ const serialized1 = serializeActorKey(key1);
239
+ const serialized2 = serializeActorKey(key2);
240
+
241
+ expect(serialized1).not.toBe(serialized2);
242
+ });
243
+
244
+ test("differentiates [a,b] from [a]", () => {
245
+ const key1 = ["a", "b"];
246
+ const key2 = ["a"];
247
+
248
+ const serialized1 = serializeActorKey(key1);
249
+ const serialized2 = serializeActorKey(key2);
250
+
251
+ expect(serialized1).not.toBe(serialized2);
252
+ });
253
+
254
+ test("differentiates [a/b] from [a,b]", () => {
255
+ const key1 = ["a/b"];
256
+ const key2 = ["a", "b"];
257
+
258
+ const serialized1 = serializeActorKey(key1);
259
+ const serialized2 = serializeActorKey(key2);
260
+
261
+ expect(serialized1).not.toBe(serialized2);
262
+ expect(deserializeActorKey(serialized1)).toEqual(key1);
263
+ expect(deserializeActorKey(serialized2)).toEqual(key2);
264
+ });
265
+ });
266
+ });
@@ -0,0 +1,89 @@
1
+ import type { ActorKey } from "@/mod";
2
+
3
+ export const EMPTY_KEY = "/";
4
+ export const KEY_SEPARATOR = "/";
5
+
6
+ export function serializeActorKey(key: ActorKey): string {
7
+ // Use a special marker for empty key arrays
8
+ if (key.length === 0) {
9
+ return EMPTY_KEY;
10
+ }
11
+
12
+ // Escape each key part to handle the separator and the empty key marker
13
+ const escapedParts = key.map((part) => {
14
+ // Handle empty strings by using a special marker
15
+ if (part === "") {
16
+ return "\\0"; // Use \0 as a marker for empty strings
17
+ }
18
+
19
+ // Escape backslashes first to avoid conflicts with our markers
20
+ let escaped = part.replace(/\\/g, "\\\\");
21
+
22
+ // Then escape separators
23
+ escaped = escaped.replace(/\//g, `\\${KEY_SEPARATOR}`);
24
+
25
+ return escaped;
26
+ });
27
+
28
+ return escapedParts.join(KEY_SEPARATOR);
29
+ }
30
+
31
+ export function deserializeActorKey(keyString: string | undefined): ActorKey {
32
+ // Check for special empty key marker
33
+ if (
34
+ keyString === undefined ||
35
+ keyString === null ||
36
+ keyString === EMPTY_KEY
37
+ ) {
38
+ return [];
39
+ }
40
+
41
+ // Split by unescaped separators and unescape the escaped characters
42
+ const parts: string[] = [];
43
+ let currentPart = "";
44
+ let escaping = false;
45
+ let isEmptyStringMarker = false;
46
+
47
+ for (let i = 0; i < keyString.length; i++) {
48
+ const char = keyString[i];
49
+
50
+ if (escaping) {
51
+ // Handle special escape sequences
52
+ if (char === "0") {
53
+ // \0 represents an empty string marker
54
+ isEmptyStringMarker = true;
55
+ } else {
56
+ // This is an escaped character, add it directly
57
+ currentPart += char;
58
+ }
59
+ escaping = false;
60
+ } else if (char === "\\") {
61
+ // Start of an escape sequence
62
+ escaping = true;
63
+ } else if (char === KEY_SEPARATOR) {
64
+ // This is a separator
65
+ if (isEmptyStringMarker) {
66
+ parts.push("");
67
+ isEmptyStringMarker = false;
68
+ } else {
69
+ parts.push(currentPart);
70
+ }
71
+ currentPart = "";
72
+ } else {
73
+ // Regular character
74
+ currentPart += char;
75
+ }
76
+ }
77
+
78
+ // Add the last part
79
+ if (escaping) {
80
+ // Incomplete escape at the end - treat as literal backslash
81
+ parts.push(currentPart + "\\");
82
+ } else if (isEmptyStringMarker) {
83
+ parts.push("");
84
+ } else if (currentPart !== "" || parts.length > 0) {
85
+ parts.push(currentPart);
86
+ }
87
+
88
+ return parts;
89
+ }
@@ -0,0 +1,6 @@
1
+ import { getLogger } from "@/common/log";
2
+
3
+ /** Prever to use ActorInstance.rlog child logger. This does not provide context in the log, should only be used as a last resort if you cannot pass the actor's child logger. */
4
+ export function loggerWithoutContext() {
5
+ return getLogger("actor-runtime");
6
+ }
@@ -0,0 +1,108 @@
1
+ import {
2
+ type Actions,
3
+ type ActorConfig,
4
+ type ActorConfigInput,
5
+ ActorConfigSchema,
6
+ ActorTypes,
7
+ } from "./config";
8
+ import type { AnyDatabaseProvider } from "./database";
9
+ import { ActorDefinition } from "./definition";
10
+
11
+ export function actor<
12
+ TState,
13
+ TConnParams,
14
+ TConnState,
15
+ TVars,
16
+ TInput,
17
+ TDatabase extends AnyDatabaseProvider,
18
+ TActions extends Actions<
19
+ TState,
20
+ TConnParams,
21
+ TConnState,
22
+ TVars,
23
+ TInput,
24
+ TDatabase
25
+ >,
26
+ >(
27
+ input: ActorConfigInput<
28
+ TState,
29
+ TConnParams,
30
+ TConnState,
31
+ TVars,
32
+ TInput,
33
+ TDatabase,
34
+ TActions
35
+ >,
36
+ ): ActorDefinition<
37
+ TState,
38
+ TConnParams,
39
+ TConnState,
40
+ TVars,
41
+ TInput,
42
+ TDatabase,
43
+ TActions
44
+ > {
45
+ const config = ActorConfigSchema.parse(input) as ActorConfig<
46
+ TState,
47
+ TConnParams,
48
+ TConnState,
49
+ TVars,
50
+ TInput,
51
+ TDatabase
52
+ >;
53
+ return new ActorDefinition(config);
54
+ }
55
+ export type { Encoding } from "@/actor/protocol/serde";
56
+ export type {
57
+ UniversalErrorEvent,
58
+ UniversalEvent,
59
+ UniversalEventSource,
60
+ UniversalMessageEvent,
61
+ } from "@/common/eventsource-interface";
62
+ export type { UpgradeWebSocketArgs } from "@/common/inline-websocket-adapter2";
63
+ export type {
64
+ RivetCloseEvent,
65
+ RivetEvent,
66
+ RivetMessageEvent,
67
+ UniversalWebSocket,
68
+ } from "@/common/websocket-interface";
69
+ export type { ActorKey } from "@/manager/protocol/query";
70
+ export type { ActionContext } from "./action";
71
+ export type * from "./config";
72
+ export type {
73
+ Conn,
74
+ ConnectionDriver,
75
+ ConnectionStatus,
76
+ generateConnId,
77
+ generateConnToken,
78
+ } from "./connection";
79
+ export {
80
+ CONNECTION_DRIVER_HTTP,
81
+ CONNECTION_DRIVER_SSE,
82
+ CONNECTION_DRIVER_WEBSOCKET,
83
+ } from "./connection";
84
+ export type { ActorContext } from "./context";
85
+ export type {
86
+ ActionContextOf,
87
+ ActorContextOf,
88
+ ActorDefinition,
89
+ AnyActorDefinition,
90
+ } from "./definition";
91
+ export { lookupInRegistry } from "./definition";
92
+ export { UserError, type UserErrorOptions } from "./errors";
93
+ export {
94
+ createGenericConnDrivers,
95
+ GenericConnGlobalState,
96
+ } from "./generic-conn-driver";
97
+ export type { AnyActorInstance } from "./instance";
98
+ export {
99
+ type ActorRouter,
100
+ createActorRouter,
101
+ PATH_CONNECT_WEBSOCKET,
102
+ PATH_RAW_WEBSOCKET_PREFIX,
103
+ } from "./router";
104
+ export {
105
+ ALLOWED_PUBLIC_HEADERS,
106
+ handleRawWebSocketHandler,
107
+ handleWebSocketConnect,
108
+ } from "./router-endpoints";
@@ -0,0 +1,42 @@
1
+ import type { ConnectionDriver } from "./connection";
2
+
3
+ /** State object that gets automatically persisted to storage. */
4
+ export interface PersistedActor<S, CP, CS, I> {
5
+ input?: I;
6
+ hasInitiated: boolean;
7
+ state: S;
8
+ connections: PersistedConn<CP, CS>[];
9
+ scheduledEvents: PersistedScheduleEvent[];
10
+ }
11
+
12
+ /** Object representing connection that gets persisted to storage. */
13
+ export interface PersistedConn<CP, CS> {
14
+ connId: string;
15
+ token: string;
16
+ connDriver: ConnectionDriver;
17
+ connDriverState: unknown;
18
+ params: CP;
19
+ state: CS;
20
+ authData?: unknown;
21
+ subscriptions: PersistedSubscription[];
22
+ lastSeen: number;
23
+ }
24
+
25
+ export interface PersistedSubscription {
26
+ eventName: string;
27
+ }
28
+
29
+ export interface GenericPersistedScheduleEvent {
30
+ actionName: string;
31
+ args: ArrayBuffer | null;
32
+ }
33
+
34
+ export type PersistedScheduleEventKind = {
35
+ generic: GenericPersistedScheduleEvent;
36
+ };
37
+
38
+ export interface PersistedScheduleEvent {
39
+ eventId: string;
40
+ timestamp: number;
41
+ kind: PersistedScheduleEventKind;
42
+ }