@rikalabs/akter 0.1.0-alpha.0

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 (603) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +8 -0
  4. package/README.md +116 -0
  5. package/dist/actor/codecs.d.ts +77 -0
  6. package/dist/actor/codecs.js +87 -0
  7. package/dist/actor/connections.d.ts +34 -0
  8. package/dist/actor/connections.js +145 -0
  9. package/dist/actor/definition.d.ts +893 -0
  10. package/dist/actor/definition.js +147 -0
  11. package/dist/actor/descriptor.d.ts +172 -0
  12. package/dist/actor/descriptor.js +367 -0
  13. package/dist/actor/handles.d.ts +77 -0
  14. package/dist/actor/handles.js +265 -0
  15. package/dist/actor/jobs.d.ts +10 -0
  16. package/dist/actor/jobs.js +137 -0
  17. package/dist/actor/layers.d.ts +41 -0
  18. package/dist/actor/layers.js +177 -0
  19. package/dist/actor/reads.d.ts +47 -0
  20. package/dist/actor/reads.js +224 -0
  21. package/dist/actor/served.d.ts +120 -0
  22. package/dist/actor/served.js +72 -0
  23. package/dist/actor/turns.d.ts +13 -0
  24. package/dist/actor/turns.js +332 -0
  25. package/dist/actor/workflows.d.ts +16 -0
  26. package/dist/actor/workflows.js +37 -0
  27. package/dist/client/calls.d.ts +47 -0
  28. package/dist/client/calls.js +425 -0
  29. package/dist/client/clock.d.ts +56 -0
  30. package/dist/client/clock.js +119 -0
  31. package/dist/client/fleet-page.d.ts +15 -0
  32. package/dist/client/fleet-page.js +13 -0
  33. package/dist/client/fleet.d.ts +29 -0
  34. package/dist/client/fleet.js +51 -0
  35. package/dist/client/index.d.ts +17 -0
  36. package/dist/client/index.js +6 -0
  37. package/dist/client/make.d.ts +157 -0
  38. package/dist/client/make.js +221 -0
  39. package/dist/client/offline/queue.d.ts +118 -0
  40. package/dist/client/offline/queue.js +292 -0
  41. package/dist/client/offline/store.d.ts +74 -0
  42. package/dist/client/offline/store.js +78 -0
  43. package/dist/client/optimistic.d.ts +57 -0
  44. package/dist/client/optimistic.js +136 -0
  45. package/dist/client/report.d.ts +2 -0
  46. package/dist/client/report.js +8 -0
  47. package/dist/client/sessions/connection.d.ts +118 -0
  48. package/dist/client/sessions/connection.js +162 -0
  49. package/dist/client/sessions/feed.d.ts +42 -0
  50. package/dist/client/sessions/feed.js +43 -0
  51. package/dist/client/sessions/sse.d.ts +47 -0
  52. package/dist/client/sessions/sse.js +112 -0
  53. package/dist/client/sessions/stream.d.ts +28 -0
  54. package/dist/client/sessions/stream.js +35 -0
  55. package/dist/client/sessions/watch.d.ts +34 -0
  56. package/dist/client/sessions/watch.js +40 -0
  57. package/dist/client/transport.d.ts +37 -0
  58. package/dist/client/transport.js +66 -0
  59. package/dist/contexts/command.d.ts +132 -0
  60. package/dist/contexts/command.js +20 -0
  61. package/dist/contexts/connection.d.ts +68 -0
  62. package/dist/contexts/connection.js +0 -0
  63. package/dist/contexts/job.d.ts +49 -0
  64. package/dist/contexts/job.js +0 -0
  65. package/dist/contexts/workflow.d.ts +147 -0
  66. package/dist/contexts/workflow.js +22 -0
  67. package/dist/errors/actor.d.ts +200 -0
  68. package/dist/errors/actor.js +271 -0
  69. package/dist/errors/content.d.ts +19 -0
  70. package/dist/errors/content.js +14 -0
  71. package/dist/errors/database.d.ts +22 -0
  72. package/dist/errors/database.js +23 -0
  73. package/dist/errors/events.d.ts +17 -0
  74. package/dist/errors/events.js +14 -0
  75. package/dist/errors/subscription.d.ts +12 -0
  76. package/dist/errors/subscription.js +8 -0
  77. package/dist/errors/workflow.d.ts +28 -0
  78. package/dist/errors/workflow.js +17 -0
  79. package/dist/handles/actors.d.ts +17 -0
  80. package/dist/handles/actors.js +7 -0
  81. package/dist/handles/content.d.ts +59 -0
  82. package/dist/handles/content.js +36 -0
  83. package/dist/handles/intents.d.ts +164 -0
  84. package/dist/handles/intents.js +214 -0
  85. package/dist/handles/run.d.ts +31 -0
  86. package/dist/handles/run.js +21 -0
  87. package/dist/handles/workflow.d.ts +27 -0
  88. package/dist/handles/workflow.js +23 -0
  89. package/dist/identity/caller.d.ts +105 -0
  90. package/dist/identity/caller.js +68 -0
  91. package/dist/identity/child.d.ts +18 -0
  92. package/dist/identity/child.js +39 -0
  93. package/dist/identity/command.d.ts +19 -0
  94. package/dist/identity/command.js +21 -0
  95. package/dist/identity/connection.d.ts +24 -0
  96. package/dist/identity/connection.js +29 -0
  97. package/dist/identity/content.d.ts +18 -0
  98. package/dist/identity/content.js +12 -0
  99. package/dist/identity/digest.d.ts +4 -0
  100. package/dist/identity/digest.js +5 -0
  101. package/dist/identity/execution.d.ts +32 -0
  102. package/dist/identity/execution.js +63 -0
  103. package/dist/identity/mint.d.ts +51 -0
  104. package/dist/identity/mint.js +76 -0
  105. package/dist/identity/version.d.ts +2 -0
  106. package/dist/identity/version.js +3 -0
  107. package/dist/index.d.ts +159 -0
  108. package/dist/index.js +97 -0
  109. package/dist/members/blob.d.ts +43 -0
  110. package/dist/members/blob.js +29 -0
  111. package/dist/members/command.d.ts +109 -0
  112. package/dist/members/command.js +61 -0
  113. package/dist/members/connection.d.ts +55 -0
  114. package/dist/members/connection.js +49 -0
  115. package/dist/members/event.d.ts +36 -0
  116. package/dist/members/event.js +24 -0
  117. package/dist/members/job.d.ts +157 -0
  118. package/dist/members/job.js +67 -0
  119. package/dist/members/payload.d.ts +93 -0
  120. package/dist/members/payload.js +145 -0
  121. package/dist/members/reducer.d.ts +64 -0
  122. package/dist/members/reducer.js +27 -0
  123. package/dist/members/stream.d.ts +36 -0
  124. package/dist/members/stream.js +14 -0
  125. package/dist/members/subscription.d.ts +182 -0
  126. package/dist/members/subscription.js +91 -0
  127. package/dist/members/workflow.d.ts +99 -0
  128. package/dist/members/workflow.js +2 -0
  129. package/dist/policies/access.d.ts +35 -0
  130. package/dist/policies/access.js +6 -0
  131. package/dist/policies/command.d.ts +127 -0
  132. package/dist/policies/command.js +45 -0
  133. package/dist/policies/job.d.ts +28 -0
  134. package/dist/policies/job.js +60 -0
  135. package/dist/policies/schedules.d.ts +33 -0
  136. package/dist/policies/schedules.js +131 -0
  137. package/dist/protocol/frames.d.ts +66 -0
  138. package/dist/protocol/frames.js +55 -0
  139. package/dist/protocol/inspection.d.ts +807 -0
  140. package/dist/protocol/inspection.js +243 -0
  141. package/dist/protocol/wire.d.ts +184 -0
  142. package/dist/protocol/wire.js +150 -0
  143. package/dist/runtime/actors.d.ts +155 -0
  144. package/dist/runtime/actors.js +4 -0
  145. package/dist/runtime/admission.d.ts +34 -0
  146. package/dist/runtime/admission.js +72 -0
  147. package/dist/runtime/adoption/backfill.d.ts +27 -0
  148. package/dist/runtime/adoption/backfill.js +144 -0
  149. package/dist/runtime/adoption/enforce.d.ts +55 -0
  150. package/dist/runtime/adoption/enforce.js +241 -0
  151. package/dist/runtime/adoption/observe.d.ts +43 -0
  152. package/dist/runtime/adoption/observe.js +139 -0
  153. package/dist/runtime/adoption/plan.d.ts +45 -0
  154. package/dist/runtime/adoption/plan.js +192 -0
  155. package/dist/runtime/adoption/startup.d.ts +32 -0
  156. package/dist/runtime/adoption/startup.js +76 -0
  157. package/dist/runtime/adoption/status.d.ts +23 -0
  158. package/dist/runtime/adoption/status.js +47 -0
  159. package/dist/runtime/adoption/target.d.ts +33 -0
  160. package/dist/runtime/adoption/target.js +49 -0
  161. package/dist/runtime/connections/holder.d.ts +221 -0
  162. package/dist/runtime/connections/holder.js +816 -0
  163. package/dist/runtime/connections/owner.d.ts +263 -0
  164. package/dist/runtime/connections/owner.js +896 -0
  165. package/dist/runtime/connections/protocol.d.ts +441 -0
  166. package/dist/runtime/connections/protocol.js +222 -0
  167. package/dist/runtime/connections/reads.d.ts +24 -0
  168. package/dist/runtime/connections/reads.js +19 -0
  169. package/dist/runtime/connections/streams.d.ts +62 -0
  170. package/dist/runtime/connections/streams.js +128 -0
  171. package/dist/runtime/connections/transport.d.ts +40 -0
  172. package/dist/runtime/connections/transport.js +68 -0
  173. package/dist/runtime/connections/watch.d.ts +52 -0
  174. package/dist/runtime/connections/watch.js +159 -0
  175. package/dist/runtime/content/grant.d.ts +34 -0
  176. package/dist/runtime/content/grant.js +58 -0
  177. package/dist/runtime/content/store.d.ts +63 -0
  178. package/dist/runtime/content/store.js +294 -0
  179. package/dist/runtime/cron/key.d.ts +2 -0
  180. package/dist/runtime/cron/key.js +2 -0
  181. package/dist/runtime/cron/schedule.d.ts +69 -0
  182. package/dist/runtime/cron/schedule.js +144 -0
  183. package/dist/runtime/database/bounded.d.ts +43 -0
  184. package/dist/runtime/database/bounded.js +108 -0
  185. package/dist/runtime/database/connection.d.ts +8 -0
  186. package/dist/runtime/database/connection.js +18 -0
  187. package/dist/runtime/database/coordination.d.ts +19 -0
  188. package/dist/runtime/database/coordination.js +72 -0
  189. package/dist/runtime/database/flock.d.ts +10 -0
  190. package/dist/runtime/database/flock.js +60 -0
  191. package/dist/runtime/database/gate.d.ts +26 -0
  192. package/dist/runtime/database/gate.js +54 -0
  193. package/dist/runtime/database/keepalive.d.ts +11 -0
  194. package/dist/runtime/database/keepalive.js +22 -0
  195. package/dist/runtime/database/migrations.d.ts +177 -0
  196. package/dist/runtime/database/migrations.js +1018 -0
  197. package/dist/runtime/database/neki/migrations.d.ts +31 -0
  198. package/dist/runtime/database/neki/migrations.js +276 -0
  199. package/dist/runtime/database/neki/session.d.ts +23 -0
  200. package/dist/runtime/database/neki/session.js +31 -0
  201. package/dist/runtime/database/pglite.d.ts +21 -0
  202. package/dist/runtime/database/pglite.js +74 -0
  203. package/dist/runtime/database/replica.d.ts +41 -0
  204. package/dist/runtime/database/replica.js +51 -0
  205. package/dist/runtime/database/shards.d.ts +21 -0
  206. package/dist/runtime/database/shards.js +37 -0
  207. package/dist/runtime/database/snapshot.d.ts +7 -0
  208. package/dist/runtime/database/snapshot.js +7 -0
  209. package/dist/runtime/database/tenancy.d.ts +69 -0
  210. package/dist/runtime/database/tenancy.js +145 -0
  211. package/dist/runtime/database/transient.d.ts +10 -0
  212. package/dist/runtime/database/transient.js +25 -0
  213. package/dist/runtime/drain.d.ts +132 -0
  214. package/dist/runtime/drain.js +109 -0
  215. package/dist/runtime/entity/mailbox.d.ts +86 -0
  216. package/dist/runtime/entity/mailbox.js +121 -0
  217. package/dist/runtime/entity/register.d.ts +424 -0
  218. package/dist/runtime/entity/register.js +669 -0
  219. package/dist/runtime/events/append.d.ts +192 -0
  220. package/dist/runtime/events/append.js +128 -0
  221. package/dist/runtime/events/cursor.d.ts +2 -0
  222. package/dist/runtime/events/cursor.js +5 -0
  223. package/dist/runtime/events/replay.d.ts +20 -0
  224. package/dist/runtime/events/replay.js +45 -0
  225. package/dist/runtime/feeds.d.ts +26 -0
  226. package/dist/runtime/feeds.js +100 -0
  227. package/dist/runtime/fleet/checks.d.ts +17 -0
  228. package/dist/runtime/fleet/checks.js +106 -0
  229. package/dist/runtime/fleet/maintainer.d.ts +38 -0
  230. package/dist/runtime/fleet/maintainer.js +383 -0
  231. package/dist/runtime/fleet/pgoutput.d.ts +41 -0
  232. package/dist/runtime/fleet/pgoutput.js +102 -0
  233. package/dist/runtime/fleet/setup.d.ts +36 -0
  234. package/dist/runtime/fleet/setup.js +58 -0
  235. package/dist/runtime/fleet/subscribe.d.ts +42 -0
  236. package/dist/runtime/fleet/subscribe.js +147 -0
  237. package/dist/runtime/index.d.ts +66 -0
  238. package/dist/runtime/index.js +37 -0
  239. package/dist/runtime/inspector/http.d.ts +19 -0
  240. package/dist/runtime/inspector/http.js +36 -0
  241. package/dist/runtime/inspector/layer.d.ts +46 -0
  242. package/dist/runtime/inspector/layer.js +180 -0
  243. package/dist/runtime/inspector/queries.d.ts +711 -0
  244. package/dist/runtime/inspector/queries.js +494 -0
  245. package/dist/runtime/jobs/attempt.d.ts +254 -0
  246. package/dist/runtime/jobs/attempt.js +413 -0
  247. package/dist/runtime/jobs/isolation.d.ts +20 -0
  248. package/dist/runtime/jobs/isolation.js +10 -0
  249. package/dist/runtime/jobs/progress.d.ts +95 -0
  250. package/dist/runtime/jobs/progress.js +144 -0
  251. package/dist/runtime/layer.d.ts +260 -0
  252. package/dist/runtime/layer.js +876 -0
  253. package/dist/runtime/members.d.ts +381 -0
  254. package/dist/runtime/members.js +8 -0
  255. package/dist/runtime/operators/audit.d.ts +64 -0
  256. package/dist/runtime/operators/audit.js +56 -0
  257. package/dist/runtime/operators/auth.d.ts +29 -0
  258. package/dist/runtime/operators/auth.js +42 -0
  259. package/dist/runtime/operators/export.d.ts +68 -0
  260. package/dist/runtime/operators/export.js +137 -0
  261. package/dist/runtime/operators/grants.d.ts +45 -0
  262. package/dist/runtime/operators/grants.js +40 -0
  263. package/dist/runtime/operators/repair.d.ts +206 -0
  264. package/dist/runtime/operators/repair.js +226 -0
  265. package/dist/runtime/operators/routes.d.ts +35 -0
  266. package/dist/runtime/operators/routes.js +190 -0
  267. package/dist/runtime/operators/seed.d.ts +123 -0
  268. package/dist/runtime/operators/seed.js +123 -0
  269. package/dist/runtime/payloads/versions.d.ts +65 -0
  270. package/dist/runtime/payloads/versions.js +240 -0
  271. package/dist/runtime/peering/authority.d.ts +42 -0
  272. package/dist/runtime/peering/authority.js +132 -0
  273. package/dist/runtime/peering/credentials.d.ts +21 -0
  274. package/dist/runtime/peering/credentials.js +13 -0
  275. package/dist/runtime/peering/transport.d.ts +51 -0
  276. package/dist/runtime/peering/transport.js +175 -0
  277. package/dist/runtime/queries.d.ts +18 -0
  278. package/dist/runtime/queries.js +169 -0
  279. package/dist/runtime/readiness.d.ts +36 -0
  280. package/dist/runtime/readiness.js +44 -0
  281. package/dist/runtime/registration.d.ts +58 -0
  282. package/dist/runtime/registration.js +186 -0
  283. package/dist/runtime/request.d.ts +158 -0
  284. package/dist/runtime/request.js +102 -0
  285. package/dist/runtime/retry.d.ts +8 -0
  286. package/dist/runtime/retry.js +11 -0
  287. package/dist/runtime/runner.d.ts +93 -0
  288. package/dist/runtime/runner.js +122 -0
  289. package/dist/runtime/storage/codec.d.ts +39 -0
  290. package/dist/runtime/storage/codec.js +41 -0
  291. package/dist/runtime/storage/generation.d.ts +69 -0
  292. package/dist/runtime/storage/generation.js +49 -0
  293. package/dist/runtime/storage/placements.d.ts +15 -0
  294. package/dist/runtime/storage/placements.js +38 -0
  295. package/dist/runtime/storage/platform.d.ts +6 -0
  296. package/dist/runtime/storage/platform.js +9 -0
  297. package/dist/runtime/storage/retention.d.ts +73 -0
  298. package/dist/runtime/storage/retention.js +158 -0
  299. package/dist/runtime/subscriptions/identity.d.ts +31 -0
  300. package/dist/runtime/subscriptions/identity.js +45 -0
  301. package/dist/runtime/subscriptions/relay.d.ts +175 -0
  302. package/dist/runtime/subscriptions/relay.js +763 -0
  303. package/dist/runtime/subscriptions/storage.d.ts +40 -0
  304. package/dist/runtime/subscriptions/storage.js +98 -0
  305. package/dist/runtime/sweeps.d.ts +39 -0
  306. package/dist/runtime/sweeps.js +54 -0
  307. package/dist/runtime/telemetry/defects.d.ts +57 -0
  308. package/dist/runtime/telemetry/defects.js +43 -0
  309. package/dist/runtime/telemetry/metrics.d.ts +52 -0
  310. package/dist/runtime/telemetry/metrics.js +138 -0
  311. package/dist/runtime/telemetry/routes.d.ts +19 -0
  312. package/dist/runtime/telemetry/routes.js +18 -0
  313. package/dist/runtime/telemetry/sampler.d.ts +26 -0
  314. package/dist/runtime/telemetry/sampler.js +101 -0
  315. package/dist/runtime/telemetry/spans.d.ts +38 -0
  316. package/dist/runtime/telemetry/spans.js +44 -0
  317. package/dist/runtime/telemetry/usage.d.ts +52 -0
  318. package/dist/runtime/telemetry/usage.js +30 -0
  319. package/dist/runtime/topology/admission.d.ts +13 -0
  320. package/dist/runtime/topology/admission.js +36 -0
  321. package/dist/runtime/topology/locks.d.ts +56 -0
  322. package/dist/runtime/topology/locks.js +81 -0
  323. package/dist/runtime/topology/messages.d.ts +15 -0
  324. package/dist/runtime/topology/messages.js +32 -0
  325. package/dist/runtime/turn/admission.d.ts +22 -0
  326. package/dist/runtime/turn/admission.js +41 -0
  327. package/dist/runtime/turn/blobs.d.ts +38 -0
  328. package/dist/runtime/turn/blobs.js +215 -0
  329. package/dist/runtime/turn/execute.d.ts +208 -0
  330. package/dist/runtime/turn/execute.js +972 -0
  331. package/dist/runtime/turn/group.d.ts +165 -0
  332. package/dist/runtime/turn/group.js +326 -0
  333. package/dist/runtime/turn/hooks.d.ts +44 -0
  334. package/dist/runtime/turn/hooks.js +28 -0
  335. package/dist/runtime/turn/outbox.d.ts +159 -0
  336. package/dist/runtime/turn/outbox.js +269 -0
  337. package/dist/runtime/turn/pipeline.d.ts +68 -0
  338. package/dist/runtime/turn/pipeline.js +83 -0
  339. package/dist/runtime/turn/receipt.d.ts +81 -0
  340. package/dist/runtime/turn/receipt.js +32 -0
  341. package/dist/runtime/turn/relay.d.ts +179 -0
  342. package/dist/runtime/turn/relay.js +685 -0
  343. package/dist/runtime/turn/rows.d.ts +43 -0
  344. package/dist/runtime/turn/rows.js +592 -0
  345. package/dist/runtime/workflows/compatibility.d.ts +125 -0
  346. package/dist/runtime/workflows/compatibility.js +285 -0
  347. package/dist/runtime/workflows/engine.d.ts +107 -0
  348. package/dist/runtime/workflows/engine.js +826 -0
  349. package/dist/runtime/workflows/manifest.d.ts +34 -0
  350. package/dist/runtime/workflows/manifest.js +39 -0
  351. package/dist/runtime/workflows/steps.d.ts +33 -0
  352. package/dist/runtime/workflows/steps.js +152 -0
  353. package/dist/serve/api.d.ts +99 -0
  354. package/dist/serve/api.js +403 -0
  355. package/dist/serve/assertion/binding.d.ts +41 -0
  356. package/dist/serve/assertion/binding.js +92 -0
  357. package/dist/serve/assertion/verify.d.ts +93 -0
  358. package/dist/serve/assertion/verify.js +189 -0
  359. package/dist/serve/auth.d.ts +200 -0
  360. package/dist/serve/auth.js +92 -0
  361. package/dist/serve/clock.d.ts +10 -0
  362. package/dist/serve/clock.js +25 -0
  363. package/dist/serve/jwt.d.ts +65 -0
  364. package/dist/serve/jwt.js +202 -0
  365. package/dist/serve/layer.d.ts +98 -0
  366. package/dist/serve/layer.js +809 -0
  367. package/dist/serve/mcp/endpoint.d.ts +39 -0
  368. package/dist/serve/mcp/endpoint.js +187 -0
  369. package/dist/serve/mcp/tools.d.ts +37 -0
  370. package/dist/serve/mcp/tools.js +125 -0
  371. package/dist/serve/origin.d.ts +6 -0
  372. package/dist/serve/origin.js +21 -0
  373. package/dist/serve/sessions/feed.d.ts +79 -0
  374. package/dist/serve/sessions/feed.js +115 -0
  375. package/dist/serve/sessions/socket.d.ts +56 -0
  376. package/dist/serve/sessions/socket.js +212 -0
  377. package/dist/serve/sessions/sse.d.ts +27 -0
  378. package/dist/serve/sessions/sse.js +26 -0
  379. package/dist/serve/sessions/stream.d.ts +9 -0
  380. package/dist/serve/sessions/stream.js +9 -0
  381. package/dist/serve/sessions/watch.d.ts +12 -0
  382. package/dist/serve/sessions/watch.js +11 -0
  383. package/dist/serve/wire.d.ts +16 -0
  384. package/dist/serve/wire.js +50 -0
  385. package/dist/state/blob.d.ts +71 -0
  386. package/dist/state/blob.js +0 -0
  387. package/dist/state/migration.d.ts +53 -0
  388. package/dist/state/migration.js +29 -0
  389. package/dist/tables/fleet.d.ts +170 -0
  390. package/dist/tables/fleet.js +214 -0
  391. package/dist/tables/owned.d.ts +250 -0
  392. package/dist/tables/owned.js +233 -0
  393. package/dist/testing/actor-test.d.ts +360 -0
  394. package/dist/testing/actor-test.js +337 -0
  395. package/dist/testing/cluster.d.ts +93 -0
  396. package/dist/testing/cluster.js +296 -0
  397. package/dist/testing/conformance/access.d.ts +5 -0
  398. package/dist/testing/conformance/access.js +531 -0
  399. package/dist/testing/conformance/admission.d.ts +11 -0
  400. package/dist/testing/conformance/admission.js +182 -0
  401. package/dist/testing/conformance/adoption.d.ts +2 -0
  402. package/dist/testing/conformance/adoption.js +1019 -0
  403. package/dist/testing/conformance/assertions.d.ts +202 -0
  404. package/dist/testing/conformance/assertions.js +849 -0
  405. package/dist/testing/conformance/batches.d.ts +41 -0
  406. package/dist/testing/conformance/batches.js +388 -0
  407. package/dist/testing/conformance/blobs.d.ts +14 -0
  408. package/dist/testing/conformance/blobs.js +405 -0
  409. package/dist/testing/conformance/capacity.d.ts +8 -0
  410. package/dist/testing/conformance/capacity.js +433 -0
  411. package/dist/testing/conformance/client.d.ts +5 -0
  412. package/dist/testing/conformance/client.js +719 -0
  413. package/dist/testing/conformance/cold-serve.d.ts +16 -0
  414. package/dist/testing/conformance/cold-serve.js +254 -0
  415. package/dist/testing/conformance/connections/actors.d.ts +1143 -0
  416. package/dist/testing/conformance/connections/actors.js +180 -0
  417. package/dist/testing/conformance/connections/harness.d.ts +1754 -0
  418. package/dist/testing/conformance/connections/harness.js +142 -0
  419. package/dist/testing/conformance/connections/holders.d.ts +4 -0
  420. package/dist/testing/conformance/connections/holders.js +165 -0
  421. package/dist/testing/conformance/connections/lifecycle.d.ts +4 -0
  422. package/dist/testing/conformance/connections/lifecycle.js +113 -0
  423. package/dist/testing/conformance/connections/limits.d.ts +4 -0
  424. package/dist/testing/conformance/connections/limits.js +127 -0
  425. package/dist/testing/conformance/connections/reauthorization.d.ts +4 -0
  426. package/dist/testing/conformance/connections/reauthorization.js +170 -0
  427. package/dist/testing/conformance/connections/resync.d.ts +4 -0
  428. package/dist/testing/conformance/connections/resync.js +360 -0
  429. package/dist/testing/conformance/connections/takeover.d.ts +4 -0
  430. package/dist/testing/conformance/connections/takeover.js +287 -0
  431. package/dist/testing/conformance/connections.d.ts +4 -0
  432. package/dist/testing/conformance/connections.js +15 -0
  433. package/dist/testing/conformance/content-blobs.d.ts +16 -0
  434. package/dist/testing/conformance/content-blobs.js +534 -0
  435. package/dist/testing/conformance/counter.d.ts +16 -0
  436. package/dist/testing/conformance/counter.js +813 -0
  437. package/dist/testing/conformance/cron.d.ts +5 -0
  438. package/dist/testing/conformance/cron.js +665 -0
  439. package/dist/testing/conformance/drain.d.ts +26 -0
  440. package/dist/testing/conformance/drain.js +540 -0
  441. package/dist/testing/conformance/effect-control.d.ts +38 -0
  442. package/dist/testing/conformance/effect-control.js +1059 -0
  443. package/dist/testing/conformance/effects.d.ts +23 -0
  444. package/dist/testing/conformance/effects.js +432 -0
  445. package/dist/testing/conformance/events.d.ts +28 -0
  446. package/dist/testing/conformance/events.js +335 -0
  447. package/dist/testing/conformance/export.d.ts +2 -0
  448. package/dist/testing/conformance/export.js +368 -0
  449. package/dist/testing/conformance/fleet.d.ts +444 -0
  450. package/dist/testing/conformance/fleet.js +1009 -0
  451. package/dist/testing/conformance/groups.d.ts +7 -0
  452. package/dist/testing/conformance/groups.js +353 -0
  453. package/dist/testing/conformance/heap.d.ts +3 -0
  454. package/dist/testing/conformance/heap.js +149 -0
  455. package/dist/testing/conformance/http.d.ts +2809 -0
  456. package/dist/testing/conformance/http.js +1234 -0
  457. package/dist/testing/conformance/inspection-views.d.ts +8 -0
  458. package/dist/testing/conformance/inspection-views.js +272 -0
  459. package/dist/testing/conformance/inspector.d.ts +7 -0
  460. package/dist/testing/conformance/inspector.js +650 -0
  461. package/dist/testing/conformance/mint.d.ts +58 -0
  462. package/dist/testing/conformance/mint.js +692 -0
  463. package/dist/testing/conformance/multi-runner.d.ts +8 -0
  464. package/dist/testing/conformance/multi-runner.js +403 -0
  465. package/dist/testing/conformance/neki/plan.d.ts +19 -0
  466. package/dist/testing/conformance/neki/plan.js +30 -0
  467. package/dist/testing/conformance/observability.d.ts +3 -0
  468. package/dist/testing/conformance/observability.js +343 -0
  469. package/dist/testing/conformance/offline.d.ts +4 -0
  470. package/dist/testing/conformance/offline.js +474 -0
  471. package/dist/testing/conformance/operator-harness.d.ts +57 -0
  472. package/dist/testing/conformance/operator-harness.js +78 -0
  473. package/dist/testing/conformance/operator.d.ts +3 -0
  474. package/dist/testing/conformance/operator.js +379 -0
  475. package/dist/testing/conformance/outbox-cross-shard.d.ts +14 -0
  476. package/dist/testing/conformance/outbox-cross-shard.js +160 -0
  477. package/dist/testing/conformance/outbox.d.ts +36 -0
  478. package/dist/testing/conformance/outbox.js +437 -0
  479. package/dist/testing/conformance/payload-migrations.d.ts +3 -0
  480. package/dist/testing/conformance/payload-migrations.js +612 -0
  481. package/dist/testing/conformance/pipeline.d.ts +3 -0
  482. package/dist/testing/conformance/pipeline.js +1040 -0
  483. package/dist/testing/conformance/placement.d.ts +22 -0
  484. package/dist/testing/conformance/placement.js +539 -0
  485. package/dist/testing/conformance/platform.d.ts +40 -0
  486. package/dist/testing/conformance/platform.js +101 -0
  487. package/dist/testing/conformance/progress.d.ts +39 -0
  488. package/dist/testing/conformance/progress.js +666 -0
  489. package/dist/testing/conformance/properties.d.ts +6 -0
  490. package/dist/testing/conformance/properties.js +295 -0
  491. package/dist/testing/conformance/protocols.d.ts +4 -0
  492. package/dist/testing/conformance/protocols.js +618 -0
  493. package/dist/testing/conformance/provider/advertise.d.ts +21 -0
  494. package/dist/testing/conformance/provider/advertise.js +44 -0
  495. package/dist/testing/conformance/read-your-writes.d.ts +20 -0
  496. package/dist/testing/conformance/read-your-writes.js +192 -0
  497. package/dist/testing/conformance/reducers.d.ts +8 -0
  498. package/dist/testing/conformance/reducers.js +258 -0
  499. package/dist/testing/conformance/relay.d.ts +42 -0
  500. package/dist/testing/conformance/relay.js +1115 -0
  501. package/dist/testing/conformance/restore.d.ts +43 -0
  502. package/dist/testing/conformance/restore.js +341 -0
  503. package/dist/testing/conformance/retention.d.ts +14 -0
  504. package/dist/testing/conformance/retention.js +463 -0
  505. package/dist/testing/conformance/rls.d.ts +24 -0
  506. package/dist/testing/conformance/rls.js +576 -0
  507. package/dist/testing/conformance/simulation.d.ts +31 -0
  508. package/dist/testing/conformance/simulation.js +167 -0
  509. package/dist/testing/conformance/single-shard.d.ts +2 -0
  510. package/dist/testing/conformance/single-shard.js +125 -0
  511. package/dist/testing/conformance/singleton.d.ts +3 -0
  512. package/dist/testing/conformance/singleton.js +293 -0
  513. package/dist/testing/conformance/statements.d.ts +60 -0
  514. package/dist/testing/conformance/statements.js +108 -0
  515. package/dist/testing/conformance/streams.d.ts +7 -0
  516. package/dist/testing/conformance/streams.js +280 -0
  517. package/dist/testing/conformance/subscriptions/access.d.ts +4 -0
  518. package/dist/testing/conformance/subscriptions/access.js +98 -0
  519. package/dist/testing/conformance/subscriptions/actors.d.ts +4910 -0
  520. package/dist/testing/conformance/subscriptions/actors.js +372 -0
  521. package/dist/testing/conformance/subscriptions/cluster.d.ts +4 -0
  522. package/dist/testing/conformance/subscriptions/cluster.js +89 -0
  523. package/dist/testing/conformance/subscriptions/delivery.d.ts +4 -0
  524. package/dist/testing/conformance/subscriptions/delivery.js +253 -0
  525. package/dist/testing/conformance/subscriptions/deploys.d.ts +4 -0
  526. package/dist/testing/conformance/subscriptions/deploys.js +162 -0
  527. package/dist/testing/conformance/subscriptions/epochs.d.ts +4 -0
  528. package/dist/testing/conformance/subscriptions/epochs.js +169 -0
  529. package/dist/testing/conformance/subscriptions/failures.d.ts +4 -0
  530. package/dist/testing/conformance/subscriptions/failures.js +108 -0
  531. package/dist/testing/conformance/subscriptions/feeds.d.ts +4 -0
  532. package/dist/testing/conformance/subscriptions/feeds.js +218 -0
  533. package/dist/testing/conformance/subscriptions/harness.d.ts +124 -0
  534. package/dist/testing/conformance/subscriptions/harness.js +143 -0
  535. package/dist/testing/conformance/subscriptions/operator.d.ts +4 -0
  536. package/dist/testing/conformance/subscriptions/operator.js +128 -0
  537. package/dist/testing/conformance/subscriptions/retention.d.ts +4 -0
  538. package/dist/testing/conformance/subscriptions/retention.js +288 -0
  539. package/dist/testing/conformance/subscriptions/routing.d.ts +4 -0
  540. package/dist/testing/conformance/subscriptions/routing.js +179 -0
  541. package/dist/testing/conformance/subscriptions.d.ts +4 -0
  542. package/dist/testing/conformance/subscriptions.js +19 -0
  543. package/dist/testing/conformance/tables.d.ts +125 -0
  544. package/dist/testing/conformance/tables.js +664 -0
  545. package/dist/testing/conformance/transports/actors.d.ts +1907 -0
  546. package/dist/testing/conformance/transports/actors.js +163 -0
  547. package/dist/testing/conformance/transports/client.d.ts +3 -0
  548. package/dist/testing/conformance/transports/client.js +237 -0
  549. package/dist/testing/conformance/transports/feeds.d.ts +3 -0
  550. package/dist/testing/conformance/transports/feeds.js +232 -0
  551. package/dist/testing/conformance/transports/harness.d.ts +93 -0
  552. package/dist/testing/conformance/transports/harness.js +84 -0
  553. package/dist/testing/conformance/transports/streams.d.ts +3 -0
  554. package/dist/testing/conformance/transports/streams.js +96 -0
  555. package/dist/testing/conformance/transports/websocket.d.ts +3 -0
  556. package/dist/testing/conformance/transports/websocket.js +384 -0
  557. package/dist/testing/conformance/transports/wire.d.ts +141 -0
  558. package/dist/testing/conformance/transports/wire.js +204 -0
  559. package/dist/testing/conformance/transports.d.ts +3 -0
  560. package/dist/testing/conformance/transports.js +11 -0
  561. package/dist/testing/conformance/watch.d.ts +59 -0
  562. package/dist/testing/conformance/watch.js +879 -0
  563. package/dist/testing/conformance/workflow-engine.d.ts +97 -0
  564. package/dist/testing/conformance/workflow-engine.js +253 -0
  565. package/dist/testing/conformance/workflow-versions.d.ts +3 -0
  566. package/dist/testing/conformance/workflow-versions.js +545 -0
  567. package/dist/testing/conformance/workflows/access.d.ts +4 -0
  568. package/dist/testing/conformance/workflows/access.js +147 -0
  569. package/dist/testing/conformance/workflows/actors.d.ts +2317 -0
  570. package/dist/testing/conformance/workflows/actors.js +305 -0
  571. package/dist/testing/conformance/workflows/basics.d.ts +4 -0
  572. package/dist/testing/conformance/workflows/basics.js +144 -0
  573. package/dist/testing/conformance/workflows/engine.d.ts +4 -0
  574. package/dist/testing/conformance/workflows/engine.js +80 -0
  575. package/dist/testing/conformance/workflows/guards.d.ts +4 -0
  576. package/dist/testing/conformance/workflows/guards.js +172 -0
  577. package/dist/testing/conformance/workflows/harness.d.ts +14 -0
  578. package/dist/testing/conformance/workflows/harness.js +44 -0
  579. package/dist/testing/conformance/workflows/recovery.d.ts +4 -0
  580. package/dist/testing/conformance/workflows/recovery.js +181 -0
  581. package/dist/testing/conformance/workflows/starts.d.ts +4 -0
  582. package/dist/testing/conformance/workflows/starts.js +57 -0
  583. package/dist/testing/conformance/workflows/suspension.d.ts +4 -0
  584. package/dist/testing/conformance/workflows/suspension.js +106 -0
  585. package/dist/testing/conformance/workflows/waits.d.ts +4 -0
  586. package/dist/testing/conformance/workflows/waits.js +284 -0
  587. package/dist/testing/conformance/workflows.d.ts +4 -0
  588. package/dist/testing/conformance/workflows.js +19 -0
  589. package/dist/testing/conformance.d.ts +330 -0
  590. package/dist/testing/conformance.js +364 -0
  591. package/dist/testing/database.d.ts +31 -0
  592. package/dist/testing/database.js +70 -0
  593. package/dist/testing/foundation.d.ts +41 -0
  594. package/dist/testing/foundation.js +517 -0
  595. package/dist/testing/index.d.ts +20 -0
  596. package/dist/testing/index.js +12 -0
  597. package/dist/testing/property.d.ts +40 -0
  598. package/dist/testing/property.js +95 -0
  599. package/dist/testing/simulate-cluster.d.ts +112 -0
  600. package/dist/testing/simulate-cluster.js +257 -0
  601. package/dist/testing/simulate.d.ts +90 -0
  602. package/dist/testing/simulate.js +127 -0
  603. package/package.json +1 -0
@@ -0,0 +1,292 @@
1
+ import { Deferred, Duration, Effect, Match, Option, Schema } from "effect";
2
+ import { ActorError, CommandConflict, CommandExpired, Timeout, Unauthorized, } from "../../errors/actor.js";
3
+ import { retryDeadline } from "../clock.js";
4
+ import { OfflineStoreError } from "./store.js";
5
+ import { reportError } from "../report.js";
6
+ /** How long to wait before asking again after a retryable failure that names no delay. */
7
+ const IDLE_RETRY_MS = 5_000;
8
+ const isFramework = Schema.is(ActorError);
9
+ const isExpired = (failure) => isFramework(failure) && Schema.is(CommandExpired)(failure.reason);
10
+ const isCredentialFailure = (failure) => isFramework(failure) && Schema.is(Unauthorized)(failure.reason) && failure.reason.isCredential;
11
+ const decodeBody = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Json));
12
+ const noop = () => undefined;
13
+ const report = (error) => Effect.sync(() => reportError(error));
14
+ const guard = (operation, work) => Effect.tryPromise({ try: work, catch: (cause) => OfflineStoreError.make({ operation, cause }) });
15
+ const expiredFailure = (commandId) => ActorError.make({ reason: CommandExpired.make({ commandId }) });
16
+ const viewOf = (principal) => ({ command, failure }) => ({
17
+ commandId: command.commandId,
18
+ target: command.target,
19
+ member: command.member,
20
+ input: command.body === undefined ? undefined : Option.getOrUndefined(decodeBody(command.body)),
21
+ status: command.status === "queued" && command.principal !== principal ? "held" : command.status,
22
+ failure,
23
+ });
24
+ /**
25
+ * The queue behind a client's `offline` option. It keeps each actor's commands
26
+ * in the order they were called and sends one at a time, so a later command
27
+ * never overtakes an earlier one that is still waiting for the network;
28
+ * different actors are delivered independently. A command that expires or is
29
+ * rejected for good does not hold back those after it.
30
+ *
31
+ * Each command is saved under the principal the client ran as, and only
32
+ * commands of the current principal are sent: another's are `held`, so a
33
+ * shared store never sends one user's commands with another's credential.
34
+ *
35
+ * Ids are minted by the caller and stored with the command, so a replay after
36
+ * a lost reply, a reload, or a second tab is a retry the receipt answers, never
37
+ * a second execution. Tabs sharing one store each deliver what they read, and
38
+ * only the order within a tab is kept.
39
+ */
40
+ export const openCommandQueue = (options) => {
41
+ const slots = new Map();
42
+ const listeners = new Set();
43
+ const wakers = new Set();
44
+ const draining = new Set();
45
+ const parked = new Set();
46
+ const loading = Deferred.makeUnsafe();
47
+ let snapshot = [];
48
+ let principal = undefined;
49
+ let sequence = 0;
50
+ let loaded = false;
51
+ let closed = false;
52
+ let tail = Deferred.makeUnsafe();
53
+ Deferred.doneUnsafe(tail, Effect.void);
54
+ const publish = () => {
55
+ snapshot = Array.from(slots.values(), viewOf(principal));
56
+ for (const listener of listeners)
57
+ try {
58
+ listener(snapshot);
59
+ }
60
+ catch (error) {
61
+ reportError(error);
62
+ }
63
+ };
64
+ const slotOf = (command) => {
65
+ const failure = Match.value(command.status).pipe(Match.withReturnType(), Match.when("expired", () => expiredFailure(command.commandId)), Match.when("failed", () => options.failureOf(command)), Match.orElse(() => undefined));
66
+ return {
67
+ command,
68
+ failure,
69
+ discarded: false,
70
+ settled: Deferred.makeUnsafe(),
71
+ };
72
+ };
73
+ const awaitWake = Effect.callback((resume) => {
74
+ const wake = () => resume(Effect.void);
75
+ wakers.add(wake);
76
+ return Effect.sync(() => {
77
+ wakers.delete(wake);
78
+ });
79
+ });
80
+ /** Reads the current principal, and republishes when it changed, since that moves commands in and out of `held`. */
81
+ const current = Effect.gen(function* () {
82
+ const next = yield* options.principal;
83
+ if (next !== principal) {
84
+ principal = next;
85
+ publish();
86
+ }
87
+ return next;
88
+ });
89
+ const sleep = (ms) => Effect.raceFirst(Effect.sleep(Duration.millis(ms)), awaitWake);
90
+ const stop = (slot, status, failure, answer) => Effect.gen(function* () {
91
+ slot.command = { ...slot.command, status, answer };
92
+ slot.failure = failure;
93
+ yield* Deferred.fail(slot.settled, failure);
94
+ publish();
95
+ yield* guard("save", () => options.store.save(slot.command)).pipe(Effect.catch(report));
96
+ return "settled";
97
+ });
98
+ const expire = (slot) => stop(slot, "expired", expiredFailure(slot.command.commandId), undefined);
99
+ const commit = (slot, value) => Effect.gen(function* () {
100
+ const { commandId } = slot.command;
101
+ slots.delete(commandId);
102
+ yield* Deferred.succeed(slot.settled, value);
103
+ publish();
104
+ yield* guard("remove", () => options.store.remove(commandId)).pipe(Effect.catch(report));
105
+ return "settled";
106
+ });
107
+ /**
108
+ * Attempts one command until the server answers, its id can no longer be
109
+ * used, or it must wait for the application. A retry never leaves the
110
+ * command's own id, and a retry that would run past the id's window is not
111
+ * made: the command expires instead.
112
+ */
113
+ const deliver = (slot) => Effect.gen(function* () {
114
+ const { commandId, target } = slot.command;
115
+ const attempt = options.begin(slot.command);
116
+ const deadline = retryDeadline(commandId);
117
+ while (true) {
118
+ if (slot.command.principal !== (yield* current))
119
+ return "held";
120
+ if (deadline !== undefined && options.now() >= deadline)
121
+ return yield* expire(slot);
122
+ const outcome = yield* Effect.match(attempt, {
123
+ onSuccess: (value) => ({ answered: true, value }),
124
+ onFailure: (refused) => ({ answered: false, refused }),
125
+ });
126
+ if (closed || slot.discarded)
127
+ return "stopped";
128
+ if (outcome.answered)
129
+ return yield* commit(slot, outcome.value);
130
+ const { failure, retryAfterMs, answer } = outcome.refused;
131
+ slot.failure = failure;
132
+ publish();
133
+ if (Option.isNone(retryAfterMs)) {
134
+ if (isExpired(failure))
135
+ return yield* expire(slot);
136
+ if (isCredentialFailure(failure)) {
137
+ parked.add(target);
138
+ return "parked";
139
+ }
140
+ if (!(isFramework(failure) && failure.isRetryable))
141
+ return yield* stop(slot, "failed", failure, answer);
142
+ }
143
+ const delay = Option.getOrElse(retryAfterMs, () => IDLE_RETRY_MS);
144
+ if (deadline !== undefined && options.now() + delay >= deadline)
145
+ return yield* expire(slot);
146
+ yield* sleep(delay);
147
+ if (closed || slot.discarded)
148
+ return "stopped";
149
+ }
150
+ });
151
+ const drain = (target) => {
152
+ if (closed || !loaded || draining.has(target) || parked.has(target))
153
+ return;
154
+ draining.add(target);
155
+ const deliverAll = Effect.gen(function* () {
156
+ while (true) {
157
+ const running = yield* current;
158
+ let head = undefined;
159
+ for (const slot of slots.values())
160
+ if (slot.command.target === target &&
161
+ slot.command.status === "queued" &&
162
+ slot.command.principal === running) {
163
+ head = slot;
164
+ break;
165
+ }
166
+ if (head === undefined || (yield* deliver(head)) !== "settled")
167
+ return;
168
+ }
169
+ });
170
+ Effect.runFork(deliverAll.pipe(Effect.catchCause((cause) => Effect.sync(() => {
171
+ reportError(cause);
172
+ parked.add(target);
173
+ })), Effect.ensuring(Effect.sync(() => {
174
+ draining.delete(target);
175
+ }))));
176
+ };
177
+ const drainQueued = () => {
178
+ for (const slot of slots.values())
179
+ if (slot.command.status === "queued")
180
+ drain(slot.command.target);
181
+ };
182
+ const load = Effect.gen(function* () {
183
+ const saved = yield* guard("entries", () => options.store.entries());
184
+ const prefix = `/actors/${options.actor}`;
185
+ for (const command of saved) {
186
+ sequence = Math.max(sequence, command.sequence + 1);
187
+ if (command.baseUrl === options.baseUrl &&
188
+ (command.target === prefix || command.target.startsWith(`${prefix}/`)))
189
+ slots.set(command.commandId, slotOf(command));
190
+ }
191
+ loaded = true;
192
+ principal = Option.getOrUndefined(yield* options.principal.pipe(Effect.asSome, Effect.catchCause(() => Effect.succeedNone)));
193
+ publish();
194
+ drainQueued();
195
+ yield* Effect.forkDetach(options.warm);
196
+ });
197
+ Effect.runFork(load.pipe(Deferred.into(loading)));
198
+ const ready = Effect.runPromise(Deferred.await(loading));
199
+ ready.catch(noop);
200
+ const append = (input) => Effect.gen(function* () {
201
+ const existing = slots.get(input.commandId);
202
+ if (existing !== undefined) {
203
+ const { command } = existing;
204
+ if (command.target !== input.target ||
205
+ command.member !== input.member ||
206
+ command.body !== input.body ||
207
+ command.principal !== (yield* current))
208
+ return yield* ActorError.make({
209
+ reason: CommandConflict.make({ commandId: input.commandId }),
210
+ });
211
+ parked.delete(command.target);
212
+ drain(command.target);
213
+ return {
214
+ settled: command.status === "queued"
215
+ ? Deferred.await(existing.settled)
216
+ : Effect.fail(existing.failure ?? expiredFailure(command.commandId)),
217
+ };
218
+ }
219
+ const command = {
220
+ ...input,
221
+ baseUrl: options.baseUrl,
222
+ principal: yield* current,
223
+ sequence,
224
+ status: "queued",
225
+ answer: undefined,
226
+ };
227
+ yield* guard("save", () => options.store.save(command));
228
+ sequence += 1;
229
+ const slot = slotOf(command);
230
+ slots.set(command.commandId, slot);
231
+ parked.delete(command.target);
232
+ publish();
233
+ drain(command.target);
234
+ return { settled: Deferred.await(slot.settled) };
235
+ });
236
+ const submit = (make, signal) => {
237
+ const previous = tail;
238
+ const mine = Deferred.makeUnsafe();
239
+ const aborted = () => signal?.aborted === true;
240
+ tail = mine;
241
+ return Effect.runPromise(Deferred.await(previous).pipe(Effect.andThen(Deferred.await(loading)), Effect.andThen(Effect.gen(function* () {
242
+ if (aborted())
243
+ return undefined;
244
+ const command = yield* make;
245
+ return aborted() ? undefined : yield* append(command);
246
+ })), Effect.ensuring(Deferred.succeed(mine, undefined))));
247
+ };
248
+ const flush = () => {
249
+ if (closed)
250
+ return;
251
+ parked.clear();
252
+ for (const wake of wakers)
253
+ wake();
254
+ drainQueued();
255
+ };
256
+ const isOnlineEmitter = "addEventListener" in globalThis;
257
+ if (isOnlineEmitter)
258
+ globalThis.addEventListener("online", flush);
259
+ return {
260
+ ready,
261
+ get pending() {
262
+ return snapshot;
263
+ },
264
+ subscribe: (listener) => {
265
+ listeners.add(listener);
266
+ return () => {
267
+ listeners.delete(listener);
268
+ };
269
+ },
270
+ flush,
271
+ discard: (commandId) => Effect.runPromise(Effect.gen(function* () {
272
+ yield* Deferred.await(loading);
273
+ const slot = slots.get(commandId);
274
+ if (slot === undefined)
275
+ return;
276
+ slot.discarded = true;
277
+ slots.delete(commandId);
278
+ yield* Deferred.fail(slot.settled, ActorError.make({ reason: Timeout.make({ commandId }) }));
279
+ publish();
280
+ yield* guard("remove", () => options.store.remove(commandId));
281
+ })),
282
+ close: () => {
283
+ closed = true;
284
+ for (const wake of wakers)
285
+ wake();
286
+ listeners.clear();
287
+ if (isOnlineEmitter)
288
+ globalThis.removeEventListener("online", flush);
289
+ },
290
+ submit,
291
+ };
292
+ };
@@ -0,0 +1,74 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * A command a client saved before its first attempt. Everything here is plain
4
+ * data, so an adapter can keep it in any structured store; credentials are
5
+ * never part of it, since headers are read again for each attempt. It names
6
+ * the principal it was queued under, so it is never sent as anyone else.
7
+ */
8
+ export interface QueuedCommand {
9
+ /** The id minted once for this command; every attempt, in any session, sends it unchanged. */
10
+ readonly commandId: string;
11
+ /** Position in the queue; commands of one actor are delivered in this order. */
12
+ readonly sequence: number;
13
+ /** The client's `baseUrl`; a client delivers only the commands saved under its own. */
14
+ readonly baseUrl: string;
15
+ /**
16
+ * Who queued the command: the client's `identity`, never a credential. A
17
+ * client delivers only the commands saved under the principal it runs as.
18
+ */
19
+ readonly principal: string;
20
+ /** The actor's route under `baseUrl`, such as `/actors/Room/r1`. */
21
+ readonly target: string;
22
+ /** The member's name. */
23
+ readonly member: string;
24
+ /** The JSON text every attempt sends, encoded once when the command was called. */
25
+ readonly body: string | undefined;
26
+ /**
27
+ * `queued` until an answer settles it. `expired` means the id's window
28
+ * passed before an answer arrived and `failed` that the server answered with
29
+ * a terminal failure; both stay saved until the application discards them.
30
+ */
31
+ readonly status: "queued" | "expired" | "failed";
32
+ /** The server's terminal answer to a `failed` command, kept so a later session can decode it. */
33
+ readonly answer: {
34
+ readonly status: number;
35
+ readonly text: string;
36
+ } | undefined;
37
+ }
38
+ /**
39
+ * Where queued commands survive a reload. `save` resolves only once the
40
+ * command is durable, because a client sends nothing before then.
41
+ */
42
+ export interface OfflineStore {
43
+ /** Every saved command, in the order they were queued. */
44
+ readonly entries: () => Promise<ReadonlyArray<QueuedCommand>>;
45
+ /** Saves `command`, replacing the one with the same id. */
46
+ readonly save: (command: QueuedCommand) => Promise<void>;
47
+ /** Forgets the command with this id; forgetting an unknown id succeeds. */
48
+ readonly remove: (commandId: string) => Promise<void>;
49
+ }
50
+ declare const OfflineStoreError_base: Schema.Class<OfflineStoreError, Schema.TaggedStruct<"OfflineStoreError", {
51
+ readonly operation: Schema.Literals<readonly ["entries", "save", "remove"]>;
52
+ readonly cause: Schema.Defect;
53
+ }>, import("effect/Cause").YieldableError>;
54
+ /**
55
+ * An offline store could not read or write a queued command. A command whose
56
+ * `save` failed was never sent, so nothing about it is unknown.
57
+ */
58
+ export declare class OfflineStoreError extends OfflineStoreError_base {
59
+ }
60
+ /** Keeps commands in memory, for tests and for pages that need the queue but not a reload. */
61
+ declare const memory: () => OfflineStore;
62
+ /**
63
+ * Keeps commands in an IndexedDB database named `akter:<name>`, one
64
+ * record per command. The database opens on first use, so building a client
65
+ * on a server, where there is none, fails only when a command is queued.
66
+ * Writes ask for strict durability: a record is on disk when `save` resolves.
67
+ */
68
+ declare const indexedDb: (name: string) => OfflineStore;
69
+ /** The storage adapters a client's `offline` option accepts. */
70
+ export declare const Offline: {
71
+ indexedDb: typeof indexedDb;
72
+ memory: typeof memory;
73
+ };
74
+ export {};
@@ -0,0 +1,78 @@
1
+ import { Deferred, Effect, Schema } from "effect";
2
+ /**
3
+ * An offline store could not read or write a queued command. A command whose
4
+ * `save` failed was never sent, so nothing about it is unknown.
5
+ */
6
+ export class OfflineStoreError extends Schema.TaggedError()("OfflineStoreError", { operation: Schema.Literals(["entries", "save", "remove"]), cause: Schema.Defect() }) {
7
+ }
8
+ /** An IndexedDB store could not be opened; `cause` is the browser's error when it gave one. */
9
+ class IndexedDbUnavailable extends Schema.TaggedError()("IndexedDbUnavailable", { reason: Schema.Literals(["absent", "blocked", "failed"]), cause: Schema.Defect() }) {
10
+ }
11
+ const bySequence = (left, right) => left.sequence - right.sequence;
12
+ /** Keeps commands in memory, for tests and for pages that need the queue but not a reload. */
13
+ const memory = () => {
14
+ const commands = new Map();
15
+ return {
16
+ entries: () => Promise.resolve(Array.from(commands.values(), (command) => structuredClone(command)).sort(bySequence)),
17
+ save: (command) => {
18
+ commands.set(command.commandId, structuredClone(command));
19
+ return Promise.resolve();
20
+ },
21
+ remove: (commandId) => {
22
+ commands.delete(commandId);
23
+ return Promise.resolve();
24
+ },
25
+ };
26
+ };
27
+ const COMMANDS = "commands";
28
+ /**
29
+ * Keeps commands in an IndexedDB database named `akter:<name>`, one
30
+ * record per command. The database opens on first use, so building a client
31
+ * on a server, where there is none, fails only when a command is queued.
32
+ * Writes ask for strict durability: a record is on disk when `save` resolves.
33
+ */
34
+ const indexedDb = (name) => {
35
+ let opening;
36
+ const openDatabase = Effect.callback((resume) => {
37
+ if (!("indexedDB" in globalThis))
38
+ return resume(Effect.fail(IndexedDbUnavailable.make({ reason: "absent", cause: undefined })));
39
+ const request = globalThis.indexedDB.open(`akter:${name}`, 1);
40
+ request.onupgradeneeded = () => {
41
+ request.result.createObjectStore(COMMANDS, { keyPath: "commandId" });
42
+ };
43
+ request.onsuccess = () => {
44
+ const opened = request.result;
45
+ opened.onversionchange = () => {
46
+ opened.close();
47
+ opening = undefined;
48
+ };
49
+ resume(Effect.succeed(opened));
50
+ };
51
+ request.onerror = () => resume(Effect.fail(IndexedDbUnavailable.make({ reason: "failed", cause: request.error })));
52
+ request.onblocked = () => resume(Effect.fail(IndexedDbUnavailable.make({ reason: "blocked", cause: undefined })));
53
+ });
54
+ const database = Effect.suspend(() => {
55
+ if (opening !== undefined)
56
+ return Deferred.await(opening);
57
+ const attempt = Deferred.makeUnsafe();
58
+ opening = attempt;
59
+ return openDatabase.pipe(Deferred.into(attempt), Effect.andThen(Deferred.await(attempt)), Effect.tapError(() => Effect.sync(() => {
60
+ if (opening === attempt)
61
+ opening = undefined;
62
+ })));
63
+ });
64
+ const transact = (mode, run) => Effect.runPromise(database.pipe(Effect.flatMap((connection) => Effect.callback((resume) => {
65
+ const transaction = connection.transaction(COMMANDS, mode, { durability: "strict" });
66
+ const request = run(transaction.objectStore(COMMANDS));
67
+ transaction.oncomplete = () => resume(Effect.succeed(request.result));
68
+ transaction.onerror = () => resume(Effect.fail(transaction.error ?? request.error));
69
+ transaction.onabort = () => resume(Effect.fail(transaction.error ?? request.error));
70
+ }))));
71
+ return {
72
+ entries: () => transact("readonly", (store) => store.getAll()).then((commands) => commands.sort(bySequence)),
73
+ save: (command) => transact("readwrite", (store) => store.put(command)).then(() => undefined),
74
+ remove: (commandId) => transact("readwrite", (store) => store.delete(commandId)).then(() => undefined),
75
+ };
76
+ };
77
+ /** The storage adapters a client's `offline` option accepts. */
78
+ export const Offline = { indexedDb, memory };
@@ -0,0 +1,57 @@
1
+ import type { OptimisticReducer, StateValue } from "../actor/served.ts";
2
+ /** A reducer input applied ahead of its receipt. */
3
+ export interface PendingInput {
4
+ readonly member: string;
5
+ readonly input: unknown;
6
+ }
7
+ interface Entry extends PendingInput {
8
+ readonly reducer: OptimisticReducer;
9
+ }
10
+ /**
11
+ * One actor's state as a client sees it: the committed state it last learned
12
+ * and the reducer inputs still waiting for receipts, applied in call order.
13
+ * A listener that throws goes to `reportError`, as a DOM event listener's
14
+ * would, and the rest still run.
15
+ */
16
+ export declare class Optimistic {
17
+ private committed;
18
+ private entries;
19
+ private view;
20
+ private readonly listeners;
21
+ /** Settles when the last reducer call sent here has; reducer calls send one at a time. */
22
+ private queue;
23
+ /** `reducer` is any of the actor's reducers; its state schema copies what goes in and out. */
24
+ private readonly reducer;
25
+ constructor(reducer: OptimisticReducer | undefined);
26
+ /** Committed state with pending inputs applied; undefined until committed state is known. */
27
+ get state(): StateValue | undefined;
28
+ /** Copies of the inputs still waiting for receipts, in call order. */
29
+ get pending(): ReadonlyArray<PendingInput>;
30
+ /** Nothing pending and nobody listening, so dropping it loses nothing. */
31
+ get isIdle(): boolean;
32
+ /** Calls `listener` with the view after each change; returns the unsubscribe. */
33
+ subscribe(listener: (state: StateValue | undefined) => void): () => void;
34
+ /** Replaces the committed state and reapplies pending inputs. */
35
+ reconcile(committed: StateValue): void;
36
+ /**
37
+ * Applies `entry` to the view ahead of its receipt and settles it with
38
+ * `outcome`: a reply confirms it, a failure drops it. The call that decides
39
+ * `outcome` is the caller's; this only reflects it.
40
+ */
41
+ follow(entry: Entry, outcome: Promise<unknown>): void;
42
+ /**
43
+ * Sends `entry` once every reducer call sent here before it has settled,
44
+ * so each reply is the committed state before every later pending input,
45
+ * and follows it. `send` receives what its first attempt waits for.
46
+ */
47
+ sendInOrder<A>(entry: Entry, send: (after: Promise<void>) => Promise<A>): Promise<A>;
48
+ /**
49
+ * Its receipt succeeded. A reducer's reply is the committed state; a
50
+ * commutative reducer replies nothing, so it is applied to committed state here.
51
+ */
52
+ private confirm;
53
+ /** Its call failed, so the input comes out of the view. */
54
+ private drop;
55
+ private publish;
56
+ }
57
+ export {};
@@ -0,0 +1,136 @@
1
+ import { Data, Effect, Exit, Option, Predicate, Result, Schema } from "effect";
2
+ import { reportError } from "./report.js";
3
+ class Rejected extends Data.TaggedError("Rejected") {
4
+ }
5
+ const copiers = new WeakMap();
6
+ /** Round-trips state through its JSON codec: a private copy, and a check that it fits the schema. */
7
+ const copierOf = (reducer) => {
8
+ const existing = copiers.get(reducer);
9
+ if (existing !== undefined)
10
+ return existing;
11
+ const json = Schema.toCodecJson(reducer.state);
12
+ const encode = Schema.encodeEffect(json);
13
+ const decode = Schema.decodeEffect(json);
14
+ const copy = (state) => encode(state).pipe(Effect.map((encoded) => structuredClone(encoded)), Effect.flatMap(decode));
15
+ copiers.set(reducer, copy);
16
+ return copy;
17
+ };
18
+ /** `entry`'s reducer over a copy of `state`; none when it fails, throws, or returns an invalid state. */
19
+ const apply = (entry, state) => {
20
+ const copy = copierOf(entry.reducer);
21
+ const exit = Effect.runSyncExit(Effect.gen(function* () {
22
+ const given = yield* copy(state);
23
+ const reduced = yield* Effect.try({
24
+ try: () => entry.reducer.reduce(given, entry.input),
25
+ catch: () => new Rejected(),
26
+ });
27
+ if (Result.isFailure(reduced))
28
+ return yield* new Rejected();
29
+ return yield* copy(reduced.success);
30
+ }));
31
+ return Exit.isSuccess(exit) ? Option.some(exit.value) : Option.none();
32
+ };
33
+ const applyOrKeep = (state, entry) => Option.getOrElse(apply(entry, state), () => state);
34
+ /** A private copy of `state`, or `state` itself when it does not fit the schema. */
35
+ const own = (reducer, state) => {
36
+ if (reducer === undefined)
37
+ return state;
38
+ const exit = Effect.runSyncExit(copierOf(reducer)(state));
39
+ return Exit.isSuccess(exit) ? exit.value : state;
40
+ };
41
+ /**
42
+ * One actor's state as a client sees it: the committed state it last learned
43
+ * and the reducer inputs still waiting for receipts, applied in call order.
44
+ * A listener that throws goes to `reportError`, as a DOM event listener's
45
+ * would, and the rest still run.
46
+ */
47
+ export class Optimistic {
48
+ committed = Option.none();
49
+ entries = [];
50
+ view = undefined;
51
+ listeners = new Set();
52
+ /** Settles when the last reducer call sent here has; reducer calls send one at a time. */
53
+ queue = Promise.resolve();
54
+ /** `reducer` is any of the actor's reducers; its state schema copies what goes in and out. */
55
+ reducer;
56
+ constructor(reducer) {
57
+ this.reducer = reducer;
58
+ }
59
+ /** Committed state with pending inputs applied; undefined until committed state is known. */
60
+ get state() {
61
+ return this.view;
62
+ }
63
+ /** Copies of the inputs still waiting for receipts, in call order. */
64
+ get pending() {
65
+ return this.entries.map(({ member, input }) => ({ member, input: structuredClone(input) }));
66
+ }
67
+ /** Nothing pending and nobody listening, so dropping it loses nothing. */
68
+ get isIdle() {
69
+ return this.entries.length === 0 && this.listeners.size === 0;
70
+ }
71
+ /** Calls `listener` with the view after each change; returns the unsubscribe. */
72
+ subscribe(listener) {
73
+ this.listeners.add(listener);
74
+ return () => {
75
+ this.listeners.delete(listener);
76
+ };
77
+ }
78
+ /** Replaces the committed state and reapplies pending inputs. */
79
+ reconcile(committed) {
80
+ this.committed = Option.some(own(this.reducer, committed));
81
+ this.publish();
82
+ }
83
+ /**
84
+ * Applies `entry` to the view ahead of its receipt and settles it with
85
+ * `outcome`: a reply confirms it, a failure drops it. The call that decides
86
+ * `outcome` is the caller's; this only reflects it.
87
+ */
88
+ follow(entry, outcome) {
89
+ void outcome.then((reply) => {
90
+ this.confirm(entry, entry.reducer.commutative || !Predicate.isObject(reply) ? undefined : reply);
91
+ }, () => {
92
+ this.drop(entry);
93
+ });
94
+ this.entries = [...this.entries, entry];
95
+ this.publish();
96
+ }
97
+ /**
98
+ * Sends `entry` once every reducer call sent here before it has settled,
99
+ * so each reply is the committed state before every later pending input,
100
+ * and follows it. `send` receives what its first attempt waits for.
101
+ */
102
+ sendInOrder(entry, send) {
103
+ const previous = this.queue;
104
+ const settled = send(previous);
105
+ this.queue = Promise.allSettled([previous, settled]).then(() => undefined);
106
+ this.follow(entry, settled);
107
+ return settled;
108
+ }
109
+ /**
110
+ * Its receipt succeeded. A reducer's reply is the committed state; a
111
+ * commutative reducer replies nothing, so it is applied to committed state here.
112
+ */
113
+ confirm(entry, reply) {
114
+ this.entries = this.entries.filter((pending) => pending !== entry);
115
+ this.committed =
116
+ reply !== undefined
117
+ ? Option.some(own(this.reducer, reply))
118
+ : Option.map(this.committed, (committed) => applyOrKeep(committed, entry));
119
+ this.publish();
120
+ }
121
+ /** Its call failed, so the input comes out of the view. */
122
+ drop(entry) {
123
+ this.entries = this.entries.filter((pending) => pending !== entry);
124
+ this.publish();
125
+ }
126
+ publish() {
127
+ this.view = Option.getOrUndefined(Option.map(this.committed, (committed) => own(this.reducer, this.entries.reduce(applyOrKeep, committed))));
128
+ for (const listener of this.listeners)
129
+ try {
130
+ listener(this.view);
131
+ }
132
+ catch (error) {
133
+ reportError(error);
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,2 @@
1
+ /** Reports listener failures without interrupting notification; Node lacks the browser's global reporter. */
2
+ export declare const reportError: typeof globalThis.reportError;
@@ -0,0 +1,8 @@
1
+ import { Effect } from "effect";
2
+ /** Reports listener failures without interrupting notification; Node lacks the browser's global reporter. */
3
+ export const reportError = (error) => {
4
+ if (globalThis.reportError !== undefined)
5
+ globalThis.reportError(error);
6
+ else
7
+ Effect.runSync(Effect.logError(error));
8
+ };