rivetkit 2.0.2 → 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
@@ -0,0 +1,591 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { ActorError } from "@/client/errors";
3
+ import type { DriverTestConfig } from "../mod";
4
+ import { setupDriverTest } from "../utils";
5
+
6
+ export function runActorAuthTests(driverTestConfig: DriverTestConfig) {
7
+ describe("Actor Authentication Tests", () => {
8
+ describe("Basic Authentication", () => {
9
+ test("should allow access with valid auth", async (c) => {
10
+ const { client } = await setupDriverTest(c, driverTestConfig);
11
+
12
+ // Create client with valid auth params
13
+ const instance = client.authActor.getOrCreate(undefined, {
14
+ params: { apiKey: "valid-api-key" },
15
+ });
16
+
17
+ // This should succeed with valid API key
18
+ const authData = await instance.getUserAuth();
19
+ if (driverTestConfig.clientType === "inline") {
20
+ // Inline clients don't have auth data
21
+ expect(authData).toBeUndefined();
22
+ } else {
23
+ // HTTP clients should have auth data
24
+ expect(authData).toEqual({
25
+ userId: "user123",
26
+ token: "valid-api-key",
27
+ });
28
+ }
29
+
30
+ // Should be able to call actions
31
+ const requests = await instance.getRequests();
32
+ expect(requests).toBe(1);
33
+ });
34
+
35
+ test("should deny access with invalid auth", async (c) => {
36
+ const { client } = await setupDriverTest(c, driverTestConfig);
37
+
38
+ // This should fail without proper authorization
39
+ const instance = client.authActor.getOrCreate();
40
+
41
+ if (driverTestConfig.clientType === "inline") {
42
+ // Inline clients bypass authentication
43
+ const requests = await instance.getRequests();
44
+ expect(typeof requests).toBe("number");
45
+ } else {
46
+ // HTTP clients should enforce authentication
47
+ try {
48
+ await instance.getRequests();
49
+ expect.fail("Expected authentication error");
50
+ } catch (error) {
51
+ expect((error as ActorError).code).toBe("missing_auth");
52
+ }
53
+ }
54
+ });
55
+
56
+ test("should expose auth data on connection", async (c) => {
57
+ const { client } = await setupDriverTest(c, driverTestConfig);
58
+
59
+ const instance = client.authActor.getOrCreate(undefined, {
60
+ params: { apiKey: "valid-api-key" },
61
+ });
62
+
63
+ // Auth data should be available via c.conn.auth
64
+ const authData = await instance.getUserAuth();
65
+ if (driverTestConfig.clientType === "inline") {
66
+ // Inline clients don't have auth data
67
+ expect(authData).toBeUndefined();
68
+ } else {
69
+ // HTTP clients should have auth data
70
+ expect(authData).toBeDefined();
71
+ expect((authData as any).userId).toBe("user123");
72
+ expect((authData as any).token).toBe("valid-api-key");
73
+ }
74
+ });
75
+ });
76
+
77
+ describe("Intent-Based Authentication", () => {
78
+ test("should allow get operations for any role", async (c) => {
79
+ const { client } = await setupDriverTest(c, driverTestConfig);
80
+
81
+ const createdInstance = await client.intentAuthActor.create(["foo"], {
82
+ params: { role: "admin" },
83
+ });
84
+ const actorId = await createdInstance.resolve();
85
+
86
+ if (driverTestConfig.clientType === "inline") {
87
+ // Inline clients bypass authentication
88
+ const instance = client.intentAuthActor.getForId(actorId);
89
+ const value = await instance.getValue();
90
+ expect(value).toBe(0);
91
+ } else {
92
+ // HTTP clients - actions require user or admin role
93
+ const instance = client.intentAuthActor.getForId(actorId, {
94
+ params: { role: "user" }, // Actions require user or admin role
95
+ });
96
+ const value = await instance.getValue();
97
+ expect(value).toBe(0);
98
+ }
99
+ });
100
+
101
+ test("should require admin role for create operations", async (c) => {
102
+ const { client } = await setupDriverTest(c, driverTestConfig);
103
+
104
+ if (driverTestConfig.clientType === "inline") {
105
+ // Inline clients bypass authentication - should succeed
106
+ const instance = client.intentAuthActor.getOrCreate(undefined, {
107
+ params: { role: "user" },
108
+ });
109
+ const value = await instance.getValue();
110
+ expect(value).toBe(0);
111
+ } else {
112
+ // HTTP clients should enforce authentication
113
+ try {
114
+ const instance = client.intentAuthActor.getOrCreate(undefined, {
115
+ params: { role: "user" },
116
+ });
117
+ await instance.getValue();
118
+ expect.fail("Expected permission error for create operation");
119
+ } catch (error) {
120
+ expect((error as ActorError).code).toBe("insufficient_permissions");
121
+ expect((error as ActorError).message).toContain(
122
+ "Admin role required",
123
+ );
124
+ }
125
+ }
126
+ });
127
+
128
+ test("should allow actions for user and admin roles", async (c) => {
129
+ const { client } = await setupDriverTest(c, driverTestConfig);
130
+
131
+ const createdInstance = await client.intentAuthActor.create(["foo"], {
132
+ params: { role: "admin" },
133
+ });
134
+ const actorId = await createdInstance.resolve();
135
+
136
+ // This should fail - actions require user or admin role
137
+ const instance = client.intentAuthActor.getForId(actorId, {
138
+ params: { role: "guest" },
139
+ });
140
+
141
+ if (driverTestConfig.clientType === "inline") {
142
+ // Inline clients bypass authentication - should succeed
143
+ const result = await instance.setValue(42);
144
+ expect(result).toBe(42);
145
+ } else {
146
+ // HTTP clients should enforce authentication
147
+ try {
148
+ await instance.setValue(42);
149
+ expect.fail("Expected permission error for action");
150
+ } catch (error) {
151
+ expect((error as ActorError).code).toBe("insufficient_permissions");
152
+ expect((error as ActorError).message).toContain(
153
+ "User or admin role required",
154
+ );
155
+ }
156
+ }
157
+ });
158
+ });
159
+
160
+ describe("Public Access", () => {
161
+ test("should allow access with empty onAuth", async (c) => {
162
+ const { client } = await setupDriverTest(c, driverTestConfig);
163
+
164
+ // Public actor should allow access without authentication
165
+ const instance = client.publicActor.getOrCreate();
166
+
167
+ const visitors = await instance.visit();
168
+ expect(visitors).toBe(1);
169
+
170
+ // Should be able to call multiple times
171
+ const visitors2 = await instance.visit();
172
+ expect(visitors2).toBe(2);
173
+ });
174
+
175
+ test("should deny access without onAuth defined", async (c) => {
176
+ const { client } = await setupDriverTest(c, driverTestConfig);
177
+
178
+ // Actor without onAuth should be blocked
179
+ const instance = client.noAuthActor.getOrCreate();
180
+
181
+ if (driverTestConfig.clientType === "inline") {
182
+ // Inline clients bypass authentication - should succeed
183
+ const value = await instance.getValue();
184
+ expect(value).toBe(42);
185
+ } else {
186
+ // HTTP clients should enforce authentication
187
+ try {
188
+ await instance.getValue();
189
+ expect.fail(
190
+ "Expected access to be denied for actor without onAuth",
191
+ );
192
+ } catch (error) {
193
+ expect((error as ActorError).code).toBe("forbidden");
194
+ }
195
+ }
196
+ });
197
+ });
198
+
199
+ describe("Async Authentication", () => {
200
+ test("should handle promise-based auth", async (c) => {
201
+ const { client } = await setupDriverTest(c, driverTestConfig);
202
+
203
+ const instance = client.asyncAuthActor.getOrCreate(undefined, {
204
+ params: { token: "valid" },
205
+ });
206
+
207
+ // Should succeed with valid token
208
+ const result = await instance.increment();
209
+ expect(result).toBe(1);
210
+
211
+ // Auth data should be available
212
+ const authData = await instance.getAuthData();
213
+ if (driverTestConfig.clientType === "inline") {
214
+ // Inline clients don't have auth data
215
+ expect(authData).toBeUndefined();
216
+ } else {
217
+ // HTTP clients should have auth data
218
+ expect(authData).toBeDefined();
219
+ expect((authData as any).userId).toBe("user-valid");
220
+ expect((authData as any).validated).toBe(true);
221
+ }
222
+ });
223
+
224
+ test("should handle async auth failures", async (c) => {
225
+ const { client } = await setupDriverTest(c, driverTestConfig);
226
+
227
+ const instance = client.asyncAuthActor.getOrCreate();
228
+
229
+ if (driverTestConfig.clientType === "inline") {
230
+ // Inline clients bypass authentication - should succeed
231
+ const result = await instance.increment();
232
+ expect(result).toBe(1);
233
+ } else {
234
+ // HTTP clients should enforce authentication
235
+ try {
236
+ await instance.increment();
237
+ expect.fail("Expected async auth failure");
238
+ } catch (error) {
239
+ expect((error as ActorError).code).toBe("missing_token");
240
+ }
241
+ }
242
+ });
243
+ });
244
+
245
+ describe("Authentication Across Transports", () => {
246
+ if (driverTestConfig.transport === "websocket") {
247
+ test("should authenticate WebSocket connections", async (c) => {
248
+ const { client } = await setupDriverTest(c, driverTestConfig);
249
+
250
+ // Test WebSocket connection auth
251
+ const instance = client.authActor.getOrCreate(undefined, {
252
+ params: { apiKey: "valid-api-key" },
253
+ });
254
+
255
+ // Should be able to establish connection and call actions
256
+ const authData = await instance.getUserAuth();
257
+ expect(authData).toBeDefined();
258
+ expect((authData as any).userId).toBe("user123");
259
+ });
260
+ }
261
+
262
+ test("should authenticate HTTP actions", async (c) => {
263
+ const { client } = await setupDriverTest(c, driverTestConfig);
264
+
265
+ // Test HTTP action auth
266
+ const instance = client.authActor.getOrCreate(undefined, {
267
+ params: { apiKey: "valid-api-key" },
268
+ });
269
+
270
+ // Actions should require authentication
271
+ const requests = await instance.getRequests();
272
+ expect(typeof requests).toBe("number");
273
+ });
274
+ });
275
+
276
+ describe("Error Handling", () => {
277
+ test("should handle auth errors gracefully", async (c) => {
278
+ const { client } = await setupDriverTest(c, driverTestConfig);
279
+
280
+ const instance = client.authActor.getOrCreate();
281
+
282
+ if (driverTestConfig.clientType === "inline") {
283
+ // Inline clients bypass authentication - should succeed
284
+ const requests = await instance.getRequests();
285
+ expect(typeof requests).toBe("number");
286
+ } else {
287
+ // HTTP clients should enforce authentication
288
+ try {
289
+ await instance.getRequests();
290
+ expect.fail("Expected authentication error");
291
+ } catch (error) {
292
+ // Error should be properly structured
293
+ const actorError = error as ActorError;
294
+ expect(actorError.code).toBeDefined();
295
+ expect(actorError.message).toBeDefined();
296
+ }
297
+ }
298
+ });
299
+
300
+ test("should preserve error details for debugging", async (c) => {
301
+ const { client } = await setupDriverTest(c, driverTestConfig);
302
+
303
+ const instance = client.asyncAuthActor.getOrCreate();
304
+
305
+ if (driverTestConfig.clientType === "inline") {
306
+ // Inline clients bypass authentication - should succeed
307
+ const result = await instance.increment();
308
+ expect(result).toBe(1);
309
+ } else {
310
+ // HTTP clients should enforce authentication
311
+ try {
312
+ await instance.increment();
313
+ expect.fail("Expected token error");
314
+ } catch (error) {
315
+ const actorError = error as ActorError;
316
+ expect(actorError.code).toBe("missing_token");
317
+ expect(actorError.message).toBe("Token required");
318
+ }
319
+ }
320
+ });
321
+ });
322
+
323
+ describe("Raw HTTP Authentication", () => {
324
+ test("should allow raw HTTP access with valid auth", async (c) => {
325
+ const { client } = await setupDriverTest(c, driverTestConfig);
326
+
327
+ // Create actor with valid auth
328
+ const instance = client.rawHttpAuthActor.getOrCreate(undefined, {
329
+ params: { apiKey: "valid-api-key" },
330
+ });
331
+
332
+ // Raw HTTP request should succeed
333
+ const response = await instance.fetch("api/auth-info");
334
+ expect(response.ok).toBe(true);
335
+
336
+ const data = (await response.json()) as any;
337
+ expect(data.message).toBe("Authenticated request");
338
+ expect(data.requestCount).toBe(1);
339
+
340
+ // Regular actions should also work
341
+ const count = await instance.getRequestCount();
342
+ expect(count).toBe(1);
343
+ });
344
+
345
+ test("should deny raw HTTP access without auth", async (c) => {
346
+ const { client } = await setupDriverTest(c, driverTestConfig);
347
+
348
+ // Create actor without auth
349
+ const instance = client.rawHttpAuthActor.getOrCreate();
350
+
351
+ // All clients should now enforce authentication for raw endpoints
352
+ const response = await instance.fetch("api/protected");
353
+ if (driverTestConfig.clientType === "inline") {
354
+ expect(response.ok).toBe(true);
355
+ expect(response.status).toBe(200);
356
+ } else {
357
+ expect(response.ok).toBe(false);
358
+ expect(response.status).toBe(400);
359
+ }
360
+
361
+ // Check error details
362
+ try {
363
+ const errorData = (await response.json()) as any;
364
+ expect(errorData.c || errorData.code).toBe("missing_auth");
365
+ } catch {
366
+ // Response might be CBOR encoded, status code check is sufficient
367
+ }
368
+ });
369
+
370
+ test("should deny raw HTTP for actors without onAuth", async (c) => {
371
+ const { client } = await setupDriverTest(c, driverTestConfig);
372
+
373
+ const instance = client.rawHttpNoAuthActor.getOrCreate();
374
+
375
+ // All clients should now enforce authentication for raw endpoints
376
+ const response = await instance.fetch("api/test");
377
+ if (driverTestConfig.clientType === "inline") {
378
+ expect(response.ok).toBe(true);
379
+ expect(response.status).toBe(200);
380
+ } else {
381
+ expect(response.ok).toBe(false);
382
+ expect(response.status).toBe(403);
383
+ }
384
+
385
+ // Check error details
386
+ try {
387
+ const errorData = (await response.json()) as any;
388
+ expect(errorData.c || errorData.code).toBe("forbidden");
389
+ } catch {
390
+ // Response might be CBOR encoded, status code check is sufficient
391
+ }
392
+ });
393
+
394
+ test("should allow public raw HTTP access", async (c) => {
395
+ const { client } = await setupDriverTest(c, driverTestConfig);
396
+
397
+ const instance = client.rawHttpPublicActor.getOrCreate();
398
+
399
+ // Should work without auth
400
+ const response = await instance.fetch("api/visit");
401
+ expect(response.ok).toBe(true);
402
+
403
+ const data = (await response.json()) as any;
404
+ expect(data.message).toBe("Welcome visitor!");
405
+ expect(data.count).toBe(1);
406
+
407
+ // Second request
408
+ const response2 = await instance.fetch("api/visit");
409
+ const data2 = (await response2.json()) as any;
410
+ expect(data2.count).toBe(2);
411
+ });
412
+
413
+ test("should handle custom auth in onFetch", async (c) => {
414
+ const { client } = await setupDriverTest(c, driverTestConfig);
415
+
416
+ const instance = client.rawHttpCustomAuthActor.getOrCreate();
417
+
418
+ // Request without auth should fail
419
+ const response1 = await instance.fetch("api/data");
420
+ expect(response1.ok).toBe(false);
421
+ expect(response1.status).toBe(401);
422
+
423
+ const error1 = (await response1.json()) as any;
424
+ expect(error1.error).toBe("Unauthorized");
425
+
426
+ // Request with wrong token should fail
427
+ const response2 = await instance.fetch("api/data", {
428
+ headers: {
429
+ Authorization: "Bearer wrong-token",
430
+ },
431
+ });
432
+ expect(response2.ok).toBe(false);
433
+ expect(response2.status).toBe(403);
434
+
435
+ // Request with correct token should succeed
436
+ const response3 = await instance.fetch("api/data", {
437
+ headers: {
438
+ Authorization: "Bearer custom-token",
439
+ },
440
+ });
441
+ expect(response3.ok).toBe(true);
442
+
443
+ const data = (await response3.json()) as any;
444
+ expect(data.message).toBe("Authorized!");
445
+ expect(data.authorized).toBe(1);
446
+
447
+ // Check stats
448
+ const stats = await instance.getStats();
449
+ expect(stats.authorized).toBe(1);
450
+ expect(stats.unauthorized).toBe(2);
451
+ });
452
+ });
453
+
454
+ describe("Raw WebSocket Authentication", () => {
455
+ test("should allow raw WebSocket access with valid auth", async (c) => {
456
+ const { client } = await setupDriverTest(c, driverTestConfig);
457
+
458
+ // Create actor with valid auth
459
+ const instance = client.rawWebSocketAuthActor.getOrCreate(undefined, {
460
+ params: { apiKey: "valid-api-key" },
461
+ });
462
+
463
+ const ws = await instance.websocket();
464
+
465
+ // Wait for welcome message
466
+ const welcomePromise = new Promise((resolve, reject) => {
467
+ ws.addEventListener("message", (event: any) => {
468
+ const data = JSON.parse(event.data);
469
+ if (data.type === "welcome") {
470
+ resolve(data);
471
+ }
472
+ });
473
+ ws.addEventListener("close", () => reject("closed"));
474
+ });
475
+
476
+ const welcomeData = (await welcomePromise) as any;
477
+ expect(welcomeData.message).toBe("Authenticated WebSocket connection");
478
+ expect(welcomeData.connectionCount).toBe(1);
479
+
480
+ ws.close();
481
+ });
482
+
483
+ test("should deny raw WebSocket access without auth", async (c) => {
484
+ const { client } = await setupDriverTest(c, driverTestConfig);
485
+
486
+ const instance = client.rawWebSocketAuthActor.getOrCreate();
487
+
488
+ // All clients should now enforce authentication for raw endpoints
489
+ try {
490
+ await instance.websocket();
491
+ expect.fail("Expected authentication error");
492
+ } catch (error) {
493
+ // WebSocket connection failures may not always have structured error codes
494
+ expect(error).toBeDefined();
495
+ }
496
+ });
497
+
498
+ test("should deny raw WebSocket for actors without onAuth", async (c) => {
499
+ const { client } = await setupDriverTest(c, driverTestConfig);
500
+
501
+ const instance = client.rawWebSocketNoAuthActor.getOrCreate();
502
+
503
+ // All clients should now enforce authentication for raw endpoints
504
+ try {
505
+ await instance.websocket();
506
+ expect.fail("Expected forbidden error");
507
+ } catch (error) {
508
+ // WebSocket connection failures may not always have structured error codes
509
+ expect(error).toBeDefined();
510
+ }
511
+ });
512
+
513
+ test("should allow public raw WebSocket access", async (c) => {
514
+ const { client } = await setupDriverTest(c, driverTestConfig);
515
+
516
+ const instance = client.rawWebSocketPublicActor.getOrCreate();
517
+
518
+ // Should work without auth
519
+ const ws = await instance.websocket();
520
+
521
+ const welcomePromise = new Promise((resolve, reject) => {
522
+ ws.addEventListener("message", (event: any) => {
523
+ const data = JSON.parse(event.data);
524
+ if (data.type === "welcome") {
525
+ resolve(data);
526
+ }
527
+ });
528
+ ws.addEventListener("close", reject);
529
+ });
530
+
531
+ const welcomeData = (await welcomePromise) as any;
532
+ expect(welcomeData.message).toBe("Public WebSocket connection");
533
+ expect(welcomeData.visitorNumber).toBe(1);
534
+
535
+ ws.close();
536
+ });
537
+
538
+ test("should handle custom auth in onWebSocket", async (c) => {
539
+ const { client } = await setupDriverTest(c, driverTestConfig);
540
+
541
+ const instance = client.rawWebSocketCustomAuthActor.getOrCreate();
542
+
543
+ // WebSocket without token should be rejected
544
+ try {
545
+ const ws1 = await instance.websocket();
546
+
547
+ // Listen for error message before close
548
+ const errorPromise = new Promise((resolve, reject) => {
549
+ ws1.addEventListener("message", (event: any) => {
550
+ const data = JSON.parse(event.data);
551
+ if (data.type === "error") {
552
+ resolve(data);
553
+ }
554
+ });
555
+ ws1.addEventListener("close", reject);
556
+ });
557
+
558
+ const errorData = (await errorPromise) as any;
559
+ expect(errorData.type).toBe("error");
560
+ expect(errorData.message).toBe("Unauthorized");
561
+ } catch (error) {
562
+ // Some drivers might reject the connection immediately
563
+ expect(error).toBeDefined();
564
+ }
565
+
566
+ // WebSocket with correct token should succeed
567
+ const ws2 = await instance.websocket("?token=custom-ws-token");
568
+
569
+ const authPromise = new Promise((resolve, reject) => {
570
+ ws2.addEventListener("message", (event: any) => {
571
+ const data = JSON.parse(event.data);
572
+ if (data.type === "authorized") {
573
+ resolve(data);
574
+ }
575
+ });
576
+ ws2.addEventListener("close", reject);
577
+ });
578
+
579
+ const authData = (await authPromise) as any;
580
+ expect(authData.message).toBe("Welcome authenticated user!");
581
+
582
+ ws2.close();
583
+
584
+ // Check stats
585
+ const stats = await instance.getStats();
586
+ expect(stats.authorized).toBeGreaterThanOrEqual(1);
587
+ expect(stats.unauthorized).toBeGreaterThanOrEqual(1);
588
+ });
589
+ });
590
+ });
591
+ }