@effect-app/infra 4.0.0-beta.26 → 4.0.0-beta.261

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 (505) hide show
  1. package/CHANGELOG.md +1973 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +30 -11
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +35 -14
  6. package/dist/ClusterCosmos.d.ts +64 -0
  7. package/dist/ClusterCosmos.d.ts.map +1 -0
  8. package/dist/ClusterCosmos.js +501 -0
  9. package/dist/ClusterServiceBus.d.ts +67 -0
  10. package/dist/ClusterServiceBus.d.ts.map +1 -0
  11. package/dist/ClusterServiceBus.js +82 -0
  12. package/dist/ContextProvider.d.ts +34 -0
  13. package/dist/ContextProvider.d.ts.map +1 -0
  14. package/dist/ContextProvider.js +40 -0
  15. package/dist/Emailer/Sendgrid.d.ts +111 -147
  16. package/dist/Emailer/Sendgrid.d.ts.map +1 -1
  17. package/dist/Emailer/Sendgrid.js +24 -19
  18. package/dist/Emailer/fake.d.ts +2 -2
  19. package/dist/Emailer/fake.d.ts.map +1 -1
  20. package/dist/Emailer/fake.js +4 -4
  21. package/dist/MainFiberSet.d.ts +12 -9
  22. package/dist/MainFiberSet.d.ts.map +1 -1
  23. package/dist/MainFiberSet.js +10 -6
  24. package/dist/QueueMaker/SQLQueue.d.ts +8 -9
  25. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  26. package/dist/QueueMaker/SQLQueue.js +138 -120
  27. package/dist/QueueMaker/errors.d.ts +5 -3
  28. package/dist/QueueMaker/errors.d.ts.map +1 -1
  29. package/dist/QueueMaker/errors.js +4 -2
  30. package/dist/QueueMaker/memQueue.d.ts +10 -6
  31. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  32. package/dist/QueueMaker/memQueue.js +84 -68
  33. package/dist/QueueMaker/sbqueue.d.ts +9 -5
  34. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  35. package/dist/QueueMaker/sbqueue.js +60 -58
  36. package/dist/RequestFiberSet.d.ts +10 -7
  37. package/dist/RequestFiberSet.d.ts.map +1 -1
  38. package/dist/RequestFiberSet.js +13 -8
  39. package/dist/SQL/Model.d.ts +468 -0
  40. package/dist/SQL/Model.d.ts.map +1 -0
  41. package/dist/SQL/Model.js +469 -0
  42. package/dist/SQL.d.ts +2 -0
  43. package/dist/SQL.d.ts.map +1 -0
  44. package/dist/{adapters/SQL.js → SQL.js} +1 -1
  45. package/dist/ServiceBus.d.ts +61 -0
  46. package/dist/ServiceBus.d.ts.map +1 -0
  47. package/dist/ServiceBus.js +108 -0
  48. package/dist/Store/Cosmos/query.d.ts +15 -4
  49. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  50. package/dist/Store/Cosmos/query.js +179 -41
  51. package/dist/Store/Cosmos.d.ts +3 -3
  52. package/dist/Store/Cosmos.d.ts.map +1 -1
  53. package/dist/Store/Cosmos.js +344 -246
  54. package/dist/Store/Disk.d.ts +5 -5
  55. package/dist/Store/Disk.d.ts.map +1 -1
  56. package/dist/Store/Disk.js +78 -38
  57. package/dist/Store/Memory.d.ts +7 -10
  58. package/dist/Store/Memory.d.ts.map +1 -1
  59. package/dist/Store/Memory.js +326 -66
  60. package/dist/Store/SQL/Pg.d.ts +4 -0
  61. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  62. package/dist/Store/SQL/Pg.js +232 -0
  63. package/dist/Store/SQL/query.d.ts +49 -0
  64. package/dist/Store/SQL/query.d.ts.map +1 -0
  65. package/dist/Store/SQL/query.js +527 -0
  66. package/dist/Store/SQL.d.ts +21 -0
  67. package/dist/Store/SQL.d.ts.map +1 -0
  68. package/dist/Store/SQL.js +449 -0
  69. package/dist/Store/codeFilter.d.ts +5 -5
  70. package/dist/Store/codeFilter.d.ts.map +1 -1
  71. package/dist/Store/codeFilter.js +6 -3
  72. package/dist/Store/index.d.ts +7 -5
  73. package/dist/Store/index.d.ts.map +1 -1
  74. package/dist/Store/index.js +18 -5
  75. package/dist/Store/utils.d.ts +4 -3
  76. package/dist/Store/utils.d.ts.map +1 -1
  77. package/dist/Store/utils.js +5 -5
  78. package/dist/WorkflowEngineCosmos.d.ts +29 -0
  79. package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
  80. package/dist/WorkflowEngineCosmos.js +521 -0
  81. package/dist/WorkflowEngineSqlite.d.ts +24 -0
  82. package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
  83. package/dist/WorkflowEngineSqlite.js +550 -0
  84. package/dist/arbs.d.ts +2 -2
  85. package/dist/arbs.d.ts.map +1 -1
  86. package/dist/arbs.js +5 -3
  87. package/dist/codec.d.ts +5 -0
  88. package/dist/codec.d.ts.map +1 -0
  89. package/dist/codec.js +5 -0
  90. package/dist/cosmos-client.d.ts +16 -0
  91. package/dist/cosmos-client.d.ts.map +1 -0
  92. package/dist/cosmos-client.js +11 -0
  93. package/dist/errorReporter.d.ts +7 -5
  94. package/dist/errorReporter.d.ts.map +1 -1
  95. package/dist/errorReporter.js +23 -27
  96. package/dist/errors.d.ts +1 -1
  97. package/dist/fileUtil.d.ts +2 -2
  98. package/dist/fileUtil.d.ts.map +1 -1
  99. package/dist/fileUtil.js +2 -2
  100. package/dist/index.d.ts +3 -2
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +3 -2
  103. package/dist/internal/RequestContextMiddleware.d.ts +5 -0
  104. package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
  105. package/dist/internal/RequestContextMiddleware.js +45 -0
  106. package/dist/internal/auth.d.ts +53 -0
  107. package/dist/internal/auth.d.ts.map +1 -0
  108. package/dist/internal/auth.js +180 -0
  109. package/dist/internal/events.d.ts +11 -0
  110. package/dist/internal/events.d.ts.map +1 -0
  111. package/dist/internal/events.js +49 -0
  112. package/dist/internal/health.d.ts +3 -0
  113. package/dist/internal/health.d.ts.map +1 -0
  114. package/dist/internal/health.js +5 -0
  115. package/dist/layerUtils.d.ts +32 -0
  116. package/dist/layerUtils.d.ts.map +1 -0
  117. package/dist/layerUtils.js +17 -0
  118. package/dist/logger/jsonLogger.d.ts +2 -2
  119. package/dist/logger/jsonLogger.d.ts.map +1 -1
  120. package/dist/logger/jsonLogger.js +5 -3
  121. package/dist/logger/logFmtLogger.d.ts +2 -2
  122. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  123. package/dist/logger/logFmtLogger.js +3 -3
  124. package/dist/logger/shared.d.ts +3 -3
  125. package/dist/logger/shared.d.ts.map +1 -1
  126. package/dist/logger/shared.js +5 -5
  127. package/dist/logger.d.ts +1 -1
  128. package/dist/logger.d.ts.map +1 -1
  129. package/dist/memQueue.d.ts +15 -0
  130. package/dist/memQueue.d.ts.map +1 -0
  131. package/dist/memQueue.js +21 -0
  132. package/dist/middlewares.d.ts +10 -0
  133. package/dist/middlewares.d.ts.map +1 -0
  134. package/dist/{api/middlewares.js → middlewares.js} +1 -1
  135. package/dist/mongo-client.d.ts +11 -0
  136. package/dist/mongo-client.d.ts.map +1 -0
  137. package/dist/mongo-client.js +15 -0
  138. package/dist/otel.d.ts +75 -0
  139. package/dist/otel.d.ts.map +1 -0
  140. package/dist/otel.js +65 -0
  141. package/dist/rateLimit.d.ts +12 -4
  142. package/dist/rateLimit.d.ts.map +1 -1
  143. package/dist/rateLimit.js +7 -12
  144. package/dist/redis-client.d.ts +42 -0
  145. package/dist/redis-client.d.ts.map +1 -0
  146. package/dist/redis-client.js +98 -0
  147. package/dist/reportError.d.ts +4 -0
  148. package/dist/reportError.d.ts.map +1 -0
  149. package/dist/reportError.js +28 -0
  150. package/dist/routing/middleware/RouterMiddleware.d.ts +16 -0
  151. package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  152. package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
  153. package/dist/routing/middleware/middleware.d.ts +48 -0
  154. package/dist/routing/middleware/middleware.d.ts.map +1 -0
  155. package/dist/routing/middleware/middleware.js +128 -0
  156. package/dist/routing/middleware.d.ts +3 -0
  157. package/dist/routing/middleware.d.ts.map +1 -0
  158. package/dist/{api/routing → routing}/middleware.js +1 -2
  159. package/dist/routing/schema/jwt.d.ts +4 -0
  160. package/dist/routing/schema/jwt.d.ts.map +1 -0
  161. package/dist/routing/schema/jwt.js +13 -0
  162. package/dist/routing/tsort.d.ts +8 -0
  163. package/dist/routing/tsort.d.ts.map +1 -0
  164. package/dist/routing/tsort.js +51 -0
  165. package/dist/routing/utils.d.ts +19 -0
  166. package/dist/routing/utils.d.ts.map +1 -0
  167. package/dist/routing/utils.js +45 -0
  168. package/dist/routing.d.ts +184 -0
  169. package/dist/routing.d.ts.map +1 -0
  170. package/dist/routing.js +236 -0
  171. package/dist/test.d.ts +3 -3
  172. package/dist/test.d.ts.map +1 -1
  173. package/dist/test.js +2 -2
  174. package/dist/util.d.ts +3 -0
  175. package/dist/util.d.ts.map +1 -0
  176. package/dist/util.js +14 -0
  177. package/dist/vitest.d.ts +1 -1
  178. package/docs/cluster-storage.md +26 -0
  179. package/docs/workflow-engine.md +262 -0
  180. package/examples/query.ts +47 -39
  181. package/package.json +31 -345
  182. package/run.sh +1 -0
  183. package/src/CUPS.ts +52 -13
  184. package/src/ClusterCosmos.ts +984 -0
  185. package/src/ClusterServiceBus.ts +242 -0
  186. package/src/{api/ContextProvider.ts → ContextProvider.ts} +19 -16
  187. package/src/Emailer/Sendgrid.ts +82 -59
  188. package/src/Emailer/fake.ts +3 -3
  189. package/src/MainFiberSet.ts +12 -10
  190. package/src/QueueMaker/SQLQueue.ts +153 -156
  191. package/src/QueueMaker/errors.ts +3 -1
  192. package/src/QueueMaker/memQueue.ts +113 -107
  193. package/src/QueueMaker/sbqueue.ts +78 -90
  194. package/src/RequestFiberSet.ts +13 -8
  195. package/src/{adapters/SQL → SQL}/Model.ts +42 -41
  196. package/src/ServiceBus.ts +219 -0
  197. package/src/Store/Cosmos/query.ts +216 -52
  198. package/src/Store/Cosmos.ts +493 -353
  199. package/src/Store/Disk.ts +109 -69
  200. package/src/Store/Memory.ts +365 -96
  201. package/src/Store/SQL/Pg.ts +363 -0
  202. package/src/Store/SQL/query.ts +603 -0
  203. package/src/Store/SQL.ts +735 -0
  204. package/src/Store/codeFilter.ts +8 -5
  205. package/src/Store/index.ts +21 -6
  206. package/src/Store/utils.ts +26 -24
  207. package/src/WorkflowEngineCosmos.ts +719 -0
  208. package/src/WorkflowEngineSqlite.ts +813 -0
  209. package/src/arbs.ts +5 -3
  210. package/src/{adapters/cosmos-client.ts → cosmos-client.ts} +5 -3
  211. package/src/errorReporter.ts +66 -76
  212. package/src/fileUtil.ts +1 -1
  213. package/src/index.ts +2 -1
  214. package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
  215. package/src/internal/auth.ts +272 -0
  216. package/src/{api/internal → internal}/events.ts +22 -13
  217. package/src/{api/layerUtils.ts → layerUtils.ts} +14 -10
  218. package/src/logger/jsonLogger.ts +4 -2
  219. package/src/logger/logFmtLogger.ts +2 -2
  220. package/src/logger/shared.ts +5 -4
  221. package/src/{adapters/memQueue.ts → memQueue.ts} +5 -4
  222. package/src/{adapters/mongo-client.ts → mongo-client.ts} +4 -2
  223. package/src/otel.ts +152 -0
  224. package/src/rateLimit.ts +34 -23
  225. package/src/{adapters/redis-client.ts → redis-client.ts} +7 -3
  226. package/src/{api/reportError.ts → reportError.ts} +3 -2
  227. package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +5 -4
  228. package/src/{api/routing → routing}/middleware/middleware.ts +62 -17
  229. package/src/routing/middleware.ts +4 -0
  230. package/src/{api/routing → routing}/schema/jwt.ts +2 -1
  231. package/src/{api/routing → routing}/utils.ts +2 -1
  232. package/src/routing.ts +768 -0
  233. package/src/test.ts +2 -2
  234. package/test/auth.test.ts +101 -0
  235. package/test/cluster-cosmos.test.ts +590 -0
  236. package/test/cluster-servicebus.test.ts +180 -0
  237. package/test/cluster-sqlite.test.ts +207 -0
  238. package/test/contextProvider.test.ts +15 -12
  239. package/test/controller.test.ts +28 -32
  240. package/test/cosmos-query.test.ts +159 -0
  241. package/test/dist/_check-agg-infer.test-d.d.ts +2 -0
  242. package/test/dist/_check-agg-infer.test-d.d.ts.map +1 -0
  243. package/test/dist/_check-agg-infer.test-d.js +19 -0
  244. package/test/dist/_check-proj-infer.test-d.d.ts +2 -0
  245. package/test/dist/_check-proj-infer.test-d.d.ts.map +1 -0
  246. package/test/dist/_check-proj-infer.test-d.js +16 -0
  247. package/test/dist/_check-tighten.test-d.d.ts +2 -0
  248. package/test/dist/_check-tighten.test-d.d.ts.map +1 -0
  249. package/test/dist/_check-tighten.test-d.js +21 -0
  250. package/test/dist/auth.test.d.ts.map +1 -0
  251. package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
  252. package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
  253. package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
  254. package/test/dist/contextProvider.test.d.ts.map +1 -1
  255. package/test/dist/controller.test.d.ts.map +1 -1
  256. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  257. package/test/dist/date-query.test.d.ts.map +1 -0
  258. package/test/dist/fixtures.d.ts +30 -12
  259. package/test/dist/fixtures.d.ts.map +1 -1
  260. package/test/dist/fixtures.js +17 -10
  261. package/test/dist/query.test.d.ts.map +1 -1
  262. package/test/dist/rawQuery.test.d.ts.map +1 -1
  263. package/test/dist/repository-ext.test.d.ts.map +1 -0
  264. package/test/dist/requires.test.d.ts.map +1 -1
  265. package/test/dist/router-generator.test.d.ts.map +1 -0
  266. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  267. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  268. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  269. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  270. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  271. package/test/dist/sql-store.test.d.ts.map +1 -0
  272. package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
  273. package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
  274. package/test/fixtures.ts +16 -9
  275. package/test/layerUtils.test.ts +2 -2
  276. package/test/query.test.ts +905 -40
  277. package/test/rawQuery.test.ts +340 -22
  278. package/test/repository-ext.test.ts +62 -0
  279. package/test/requires.test.ts +10 -5
  280. package/test/router-generator.test.ts +187 -0
  281. package/test/routing-interruptibility.test.ts +66 -0
  282. package/test/rpc-context-map-streaming.test.ts +262 -0
  283. package/test/rpc-e2e-invalidation.test.ts +256 -0
  284. package/test/rpc-multi-middleware.test.ts +85 -10
  285. package/test/rpc-stream-fullstack.test.ts +304 -0
  286. package/test/sql-store.test.ts +1711 -0
  287. package/test/validateSample.test.ts +26 -14
  288. package/test/workflow-engine-cosmos.test.ts +354 -0
  289. package/test/workflow-engine-sqlite.test.ts +299 -0
  290. package/tsconfig.examples.json +1 -1
  291. package/tsconfig.json +2 -1
  292. package/tsconfig.json.bak +2 -2
  293. package/tsconfig.src.json +35 -35
  294. package/tsconfig.test.json +2 -2
  295. package/dist/Emailer/service.d.ts +0 -55
  296. package/dist/Emailer/service.d.ts.map +0 -1
  297. package/dist/Emailer/service.js +0 -6
  298. package/dist/Emailer.d.ts +0 -2
  299. package/dist/Emailer.d.ts.map +0 -1
  300. package/dist/Emailer.js +0 -2
  301. package/dist/Model/Repository/ext.d.ts +0 -41
  302. package/dist/Model/Repository/ext.d.ts.map +0 -1
  303. package/dist/Model/Repository/ext.js +0 -65
  304. package/dist/Model/Repository/internal/internal.d.ts +0 -59
  305. package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
  306. package/dist/Model/Repository/internal/internal.js +0 -316
  307. package/dist/Model/Repository/legacy.d.ts +0 -19
  308. package/dist/Model/Repository/legacy.d.ts.map +0 -1
  309. package/dist/Model/Repository/legacy.js +0 -2
  310. package/dist/Model/Repository/makeRepo.d.ts +0 -49
  311. package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
  312. package/dist/Model/Repository/makeRepo.js +0 -24
  313. package/dist/Model/Repository/service.d.ts +0 -89
  314. package/dist/Model/Repository/service.d.ts.map +0 -1
  315. package/dist/Model/Repository/service.js +0 -2
  316. package/dist/Model/Repository/validation.d.ts +0 -42
  317. package/dist/Model/Repository/validation.d.ts.map +0 -1
  318. package/dist/Model/Repository/validation.js +0 -32
  319. package/dist/Model/Repository.d.ts +0 -6
  320. package/dist/Model/Repository.d.ts.map +0 -1
  321. package/dist/Model/Repository.js +0 -6
  322. package/dist/Model/dsl.d.ts +0 -32
  323. package/dist/Model/dsl.d.ts.map +0 -1
  324. package/dist/Model/dsl.js +0 -44
  325. package/dist/Model/filter/filterApi.d.ts +0 -30
  326. package/dist/Model/filter/filterApi.d.ts.map +0 -1
  327. package/dist/Model/filter/filterApi.js +0 -2
  328. package/dist/Model/filter/types/errors.d.ts +0 -29
  329. package/dist/Model/filter/types/errors.d.ts.map +0 -1
  330. package/dist/Model/filter/types/errors.js +0 -2
  331. package/dist/Model/filter/types/fields.d.ts +0 -15
  332. package/dist/Model/filter/types/fields.d.ts.map +0 -1
  333. package/dist/Model/filter/types/fields.js +0 -2
  334. package/dist/Model/filter/types/path/common.d.ts +0 -316
  335. package/dist/Model/filter/types/path/common.d.ts.map +0 -1
  336. package/dist/Model/filter/types/path/common.js +0 -2
  337. package/dist/Model/filter/types/path/eager.d.ts +0 -95
  338. package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
  339. package/dist/Model/filter/types/path/eager.js +0 -31
  340. package/dist/Model/filter/types/path/index.d.ts +0 -4
  341. package/dist/Model/filter/types/path/index.d.ts.map +0 -1
  342. package/dist/Model/filter/types/path/index.js +0 -3
  343. package/dist/Model/filter/types/utils.d.ts +0 -79
  344. package/dist/Model/filter/types/utils.d.ts.map +0 -1
  345. package/dist/Model/filter/types/utils.js +0 -2
  346. package/dist/Model/filter/types/validator.d.ts +0 -30
  347. package/dist/Model/filter/types/validator.d.ts.map +0 -1
  348. package/dist/Model/filter/types/validator.js +0 -2
  349. package/dist/Model/filter/types.d.ts +0 -5
  350. package/dist/Model/filter/types.d.ts.map +0 -1
  351. package/dist/Model/filter/types.js +0 -7
  352. package/dist/Model/query/dsl.d.ts +0 -248
  353. package/dist/Model/query/dsl.d.ts.map +0 -1
  354. package/dist/Model/query/dsl.js +0 -104
  355. package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
  356. package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
  357. package/dist/Model/query/new-kid-interpreter.js +0 -165
  358. package/dist/Model/query.d.ts +0 -15
  359. package/dist/Model/query.d.ts.map +0 -1
  360. package/dist/Model/query.js +0 -3
  361. package/dist/Model.d.ts +0 -4
  362. package/dist/Model.d.ts.map +0 -1
  363. package/dist/Model.js +0 -4
  364. package/dist/Operations.d.ts +0 -55
  365. package/dist/Operations.d.ts.map +0 -1
  366. package/dist/Operations.js +0 -102
  367. package/dist/OperationsRepo.d.ts +0 -41
  368. package/dist/OperationsRepo.d.ts.map +0 -1
  369. package/dist/OperationsRepo.js +0 -14
  370. package/dist/QueueMaker/service.d.ts +0 -11
  371. package/dist/QueueMaker/service.d.ts.map +0 -1
  372. package/dist/QueueMaker/service.js +0 -4
  373. package/dist/RequestContext.d.ts +0 -63
  374. package/dist/RequestContext.d.ts.map +0 -1
  375. package/dist/RequestContext.js +0 -49
  376. package/dist/Store/ContextMapContainer.d.ts +0 -14
  377. package/dist/Store/ContextMapContainer.d.ts.map +0 -1
  378. package/dist/Store/ContextMapContainer.js +0 -16
  379. package/dist/Store/service.d.ts +0 -108
  380. package/dist/Store/service.d.ts.map +0 -1
  381. package/dist/Store/service.js +0 -71
  382. package/dist/Store.d.ts +0 -2
  383. package/dist/Store.d.ts.map +0 -1
  384. package/dist/Store.js +0 -2
  385. package/dist/adapters/SQL/Model.d.ts +0 -479
  386. package/dist/adapters/SQL/Model.d.ts.map +0 -1
  387. package/dist/adapters/SQL/Model.js +0 -478
  388. package/dist/adapters/SQL.d.ts +0 -2
  389. package/dist/adapters/SQL.d.ts.map +0 -1
  390. package/dist/adapters/ServiceBus.d.ts +0 -58
  391. package/dist/adapters/ServiceBus.d.ts.map +0 -1
  392. package/dist/adapters/ServiceBus.js +0 -99
  393. package/dist/adapters/cosmos-client.d.ts +0 -14
  394. package/dist/adapters/cosmos-client.d.ts.map +0 -1
  395. package/dist/adapters/cosmos-client.js +0 -9
  396. package/dist/adapters/index.d.ts +0 -2
  397. package/dist/adapters/index.d.ts.map +0 -1
  398. package/dist/adapters/index.js +0 -2
  399. package/dist/adapters/logger.d.ts +0 -9
  400. package/dist/adapters/logger.d.ts.map +0 -1
  401. package/dist/adapters/logger.js +0 -3
  402. package/dist/adapters/memQueue.d.ts +0 -13
  403. package/dist/adapters/memQueue.d.ts.map +0 -1
  404. package/dist/adapters/memQueue.js +0 -20
  405. package/dist/adapters/mongo-client.d.ts +0 -10
  406. package/dist/adapters/mongo-client.d.ts.map +0 -1
  407. package/dist/adapters/mongo-client.js +0 -13
  408. package/dist/adapters/redis-client.d.ts +0 -39
  409. package/dist/adapters/redis-client.d.ts.map +0 -1
  410. package/dist/adapters/redis-client.js +0 -94
  411. package/dist/api/ContextProvider.d.ts +0 -31
  412. package/dist/api/ContextProvider.d.ts.map +0 -1
  413. package/dist/api/ContextProvider.js +0 -38
  414. package/dist/api/codec.d.ts +0 -5
  415. package/dist/api/codec.d.ts.map +0 -1
  416. package/dist/api/codec.js +0 -5
  417. package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
  418. package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
  419. package/dist/api/internal/RequestContextMiddleware.js +0 -35
  420. package/dist/api/internal/auth.d.ts +0 -15
  421. package/dist/api/internal/auth.d.ts.map +0 -1
  422. package/dist/api/internal/auth.js +0 -47
  423. package/dist/api/internal/events.d.ts +0 -9
  424. package/dist/api/internal/events.d.ts.map +0 -1
  425. package/dist/api/internal/events.js +0 -42
  426. package/dist/api/internal/health.d.ts +0 -3
  427. package/dist/api/internal/health.d.ts.map +0 -1
  428. package/dist/api/internal/health.js +0 -5
  429. package/dist/api/layerUtils.d.ts +0 -24
  430. package/dist/api/layerUtils.d.ts.map +0 -1
  431. package/dist/api/layerUtils.js +0 -16
  432. package/dist/api/middlewares.d.ts +0 -10
  433. package/dist/api/middlewares.d.ts.map +0 -1
  434. package/dist/api/reportError.d.ts +0 -4
  435. package/dist/api/reportError.d.ts.map +0 -1
  436. package/dist/api/reportError.js +0 -27
  437. package/dist/api/routing/middleware/RouterMiddleware.d.ts +0 -15
  438. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
  439. package/dist/api/routing/middleware/middleware.d.ts +0 -9
  440. package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
  441. package/dist/api/routing/middleware/middleware.js +0 -92
  442. package/dist/api/routing/middleware.d.ts +0 -4
  443. package/dist/api/routing/middleware.d.ts.map +0 -1
  444. package/dist/api/routing/schema/jwt.d.ts +0 -4
  445. package/dist/api/routing/schema/jwt.d.ts.map +0 -1
  446. package/dist/api/routing/schema/jwt.js +0 -12
  447. package/dist/api/routing/tsort.d.ts +0 -8
  448. package/dist/api/routing/tsort.d.ts.map +0 -1
  449. package/dist/api/routing/tsort.js +0 -51
  450. package/dist/api/routing/utils.d.ts +0 -19
  451. package/dist/api/routing/utils.d.ts.map +0 -1
  452. package/dist/api/routing/utils.js +0 -44
  453. package/dist/api/routing.d.ts +0 -138
  454. package/dist/api/routing.d.ts.map +0 -1
  455. package/dist/api/routing.js +0 -166
  456. package/dist/api/setupRequest.d.ts +0 -12
  457. package/dist/api/setupRequest.d.ts.map +0 -1
  458. package/dist/api/setupRequest.js +0 -44
  459. package/dist/api/util.d.ts +0 -3
  460. package/dist/api/util.d.ts.map +0 -1
  461. package/dist/api/util.js +0 -14
  462. package/eslint.config.mjs +0 -24
  463. package/src/Emailer/service.ts +0 -52
  464. package/src/Emailer.ts +0 -1
  465. package/src/Model/Repository/ext.ts +0 -283
  466. package/src/Model/Repository/internal/internal.ts +0 -577
  467. package/src/Model/Repository/legacy.ts +0 -27
  468. package/src/Model/Repository/makeRepo.ts +0 -139
  469. package/src/Model/Repository/service.ts +0 -627
  470. package/src/Model/Repository/validation.ts +0 -31
  471. package/src/Model/Repository.ts +0 -5
  472. package/src/Model/dsl.ts +0 -128
  473. package/src/Model/filter/filterApi.ts +0 -60
  474. package/src/Model/filter/types/errors.ts +0 -47
  475. package/src/Model/filter/types/fields.ts +0 -50
  476. package/src/Model/filter/types/path/common.ts +0 -404
  477. package/src/Model/filter/types/path/eager.ts +0 -298
  478. package/src/Model/filter/types/path/index.ts +0 -4
  479. package/src/Model/filter/types/utils.ts +0 -128
  480. package/src/Model/filter/types/validator.ts +0 -46
  481. package/src/Model/filter/types.ts +0 -6
  482. package/src/Model/query/dsl.ts +0 -2110
  483. package/src/Model/query/new-kid-interpreter.ts +0 -210
  484. package/src/Model/query.ts +0 -13
  485. package/src/Model.ts +0 -3
  486. package/src/Operations.ts +0 -235
  487. package/src/OperationsRepo.ts +0 -16
  488. package/src/QueueMaker/service.ts +0 -17
  489. package/src/RequestContext.ts +0 -63
  490. package/src/Store/ContextMapContainer.ts +0 -20
  491. package/src/Store/service.ts +0 -184
  492. package/src/Store.ts +0 -1
  493. package/src/adapters/ServiceBus.ts +0 -209
  494. package/src/adapters/index.ts +0 -0
  495. package/src/adapters/logger.ts +0 -3
  496. package/src/api/internal/auth.ts +0 -68
  497. package/src/api/routing/middleware.ts +0 -6
  498. package/src/api/routing.ts +0 -598
  499. package/src/api/setupRequest.ts +0 -84
  500. /package/src/{adapters/SQL.ts → SQL.ts} +0 -0
  501. /package/src/{api/codec.ts → codec.ts} +0 -0
  502. /package/src/{api/internal → internal}/health.ts +0 -0
  503. /package/src/{api/middlewares.ts → middlewares.ts} +0 -0
  504. /package/src/{api/routing → routing}/tsort.ts +0 -0
  505. /package/src/{api/util.ts → util.ts} +0 -0
@@ -1,9 +1,14 @@
1
- import { Effect, S } from "effect-app"
1
+ import * as Effect from "effect-app/Effect"
2
+ import * as Layer from "effect-app/Layer"
3
+ import { makeRepo, ValidationError, ValidationResult } from "effect-app/Model/Repository"
4
+ import { RepositoryRegistryLive } from "effect-app/Model/Repository/Registry"
5
+ import * as S from "effect-app/Schema"
6
+ import { setupRequestContextFromCurrent } from "effect-app/setupRequest"
2
7
  import { describe, expect, it } from "vitest"
3
- import { setupRequestContextFromCurrent } from "../src/api/setupRequest.js"
4
- import { makeRepo, ValidationError, ValidationResult } from "../src/Model/Repository.js"
5
8
  import { MemoryStoreLive } from "../src/Store/Memory.js"
6
9
 
10
+ const TestStoreLive = Layer.merge(MemoryStoreLive, RepositoryRegistryLive)
11
+
7
12
  // simple schema for valid items
8
13
  class SimpleItem extends S.Class<SimpleItem>("SimpleItem")({
9
14
  id: S.String,
@@ -25,15 +30,16 @@ describe("validateSample", () => {
25
30
 
26
31
  const result = yield* repo.validateSample({ percentage: 1.0 }) // 100%
27
32
 
28
- expect(result).toBeInstanceOf(ValidationResult)
33
+ expect(S.is(ValidationResult)(result)).toBe(true)
29
34
  expect(result.total).toBe(3)
30
35
  expect(result.sampled).toBe(3)
31
36
  expect(result.valid).toBe(3)
32
37
  expect(result.errors).toHaveLength(0)
33
38
  })
34
39
  .pipe(
35
- Effect.provide(MemoryStoreLive),
40
+ Effect.provide(TestStoreLive),
36
41
  setupRequestContextFromCurrent(),
42
+ Effect.scoped,
37
43
  Effect.runPromise
38
44
  ))
39
45
 
@@ -59,7 +65,7 @@ describe("validateSample", () => {
59
65
 
60
66
  const result = yield* repo.validateSample({ percentage: 1.0 }) // 100%
61
67
 
62
- expect(result).toBeInstanceOf(ValidationResult)
68
+ expect(S.is(ValidationResult)(result)).toBe(true)
63
69
  expect(result.total).toBe(3)
64
70
  expect(result.sampled).toBe(3)
65
71
  expect(result.valid).toBe(1)
@@ -67,7 +73,7 @@ describe("validateSample", () => {
67
73
 
68
74
  // verify error structure
69
75
  for (const error of result.errors) {
70
- expect(error).toBeInstanceOf(ValidationError)
76
+ expect(S.is(ValidationError)(error)).toBe(true)
71
77
  expect(error.id).toBeDefined()
72
78
  expect(error.rawData).toBeDefined()
73
79
  expect(error.jitMResult).toBeDefined()
@@ -80,8 +86,9 @@ describe("validateSample", () => {
80
86
  expect(failingIds).toContain("3")
81
87
  })
82
88
  .pipe(
83
- Effect.provide(MemoryStoreLive),
89
+ Effect.provide(TestStoreLive),
84
90
  setupRequestContextFromCurrent(),
91
+ Effect.scoped,
85
92
  Effect.runPromise
86
93
  ))
87
94
 
@@ -98,8 +105,9 @@ describe("validateSample", () => {
98
105
  expect(result.errors).toHaveLength(0)
99
106
  })
100
107
  .pipe(
101
- Effect.provide(MemoryStoreLive),
108
+ Effect.provide(TestStoreLive),
102
109
  setupRequestContextFromCurrent(),
110
+ Effect.scoped,
103
111
  Effect.runPromise
104
112
  ))
105
113
 
@@ -127,8 +135,9 @@ describe("validateSample", () => {
127
135
  expect(result.errors).toHaveLength(0)
128
136
  })
129
137
  .pipe(
130
- Effect.provide(MemoryStoreLive),
138
+ Effect.provide(TestStoreLive),
131
139
  setupRequestContextFromCurrent(),
140
+ Effect.scoped,
132
141
  Effect.runPromise
133
142
  ))
134
143
 
@@ -138,7 +147,7 @@ describe("validateSample", () => {
138
147
  // schema that expects a 'status' field
139
148
  class ItemWithStatus extends S.Class<ItemWithStatus>("ItemWithStatus")({
140
149
  id: S.String,
141
- status: S.Literal("active", "inactive")
150
+ status: S.Literals(["active", "inactive"])
142
151
  }) {}
143
152
 
144
153
  // jitM that adds default status for items
@@ -161,8 +170,9 @@ describe("validateSample", () => {
161
170
  expect(result.errors).toHaveLength(0)
162
171
  })
163
172
  .pipe(
164
- Effect.provide(MemoryStoreLive),
173
+ Effect.provide(TestStoreLive),
165
174
  setupRequestContextFromCurrent(),
175
+ Effect.scoped,
166
176
  Effect.runPromise
167
177
  ))
168
178
 
@@ -208,8 +218,9 @@ describe("validateSample", () => {
208
218
  expect((error.error as any)._tag).toBe("SchemaError")
209
219
  })
210
220
  .pipe(
211
- Effect.provide(MemoryStoreLive),
221
+ Effect.provide(TestStoreLive),
212
222
  setupRequestContextFromCurrent(),
223
+ Effect.scoped,
213
224
  Effect.runPromise
214
225
  ))
215
226
 
@@ -230,8 +241,9 @@ describe("validateSample", () => {
230
241
  expect(result.errors).toHaveLength(0)
231
242
  })
232
243
  .pipe(
233
- Effect.provide(MemoryStoreLive),
244
+ Effect.provide(TestStoreLive),
234
245
  setupRequestContextFromCurrent(),
246
+ Effect.scoped,
235
247
  Effect.runPromise
236
248
  ))
237
249
  })
@@ -0,0 +1,354 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * Workflow engine conformance tests.
4
+ *
5
+ * The `runSuite` body is engine-agnostic: it runs against
6
+ * `WorkflowEngine.layerMemory` (fast, always) and — when `COSMOS_TEST_URL`
7
+ * is set — against the Cosmos adapter (`layerCosmos`) pointed at a Cosmos
8
+ * emulator. Both must satisfy the same observable contract: idempotent
9
+ * execution, activity replay (no double side effects), suspend → durable-
10
+ * deferred completion → resume with a correctly decoded result, interrupt
11
+ * propagation, and first-writer-wins deferred completion.
12
+ *
13
+ * A second describe block (Cosmos emulator only) exercises adapter
14
+ * internals — the recovery poller (driving execs whose lease has lapsed)
15
+ * and the clock poller (firing past-due clocks) — by seeding rows
16
+ * directly against the Cosmos container.
17
+ */
18
+ import { assert, describe, it } from "@effect/vitest"
19
+ import { Context, Duration, Effect, Exit, Layer, Option, Redacted, Schema } from "effect"
20
+ import { Activity, DurableDeferred, Workflow, WorkflowEngine } from "effect/unstable/workflow"
21
+ import { CosmosClient, CosmosClientLayer } from "../src/cosmos-client.js"
22
+ import { layerCosmos } from "../src/WorkflowEngineCosmos.js"
23
+
24
+ // --- Shared mutable counter for activity-side-effect assertions --------
25
+
26
+ class CounterRef extends Context.Service<CounterRef, { count: number }>()("CounterRef") {
27
+ static readonly layer = Layer.effect(CounterRef, Effect.sync(() => ({ count: 0 })))
28
+ }
29
+
30
+ // --- Workflow definitions ----------------------------------------------
31
+
32
+ const IncrementWorkflow = Workflow.make({
33
+ name: "WorkflowEngineCosmos/IncrementWorkflow",
34
+ payload: { value: Schema.Number },
35
+ success: Schema.Number,
36
+ idempotencyKey: ({ value }) => String(value)
37
+ })
38
+
39
+ const IncrementHandler = IncrementWorkflow.toLayer(({ value }) => Effect.succeed(value + 1))
40
+
41
+ // Counts activity body invocations across re-executes so the test can
42
+ // prove side-effects don't repeat when a persisted result is available.
43
+ const CounterWorkflow = Workflow.make({
44
+ name: "WorkflowEngineCosmos/CounterWorkflow",
45
+ payload: { id: Schema.String },
46
+ success: Schema.Number,
47
+ idempotencyKey: ({ id }) => id
48
+ })
49
+
50
+ const CounterHandler = CounterWorkflow.toLayer(Effect.fn(function*() {
51
+ const counter = yield* CounterRef
52
+ return yield* Activity.make({
53
+ name: "Bump",
54
+ success: Schema.Number,
55
+ execute: Effect.sync(() => {
56
+ counter.count++
57
+ return counter.count
58
+ })
59
+ })
60
+ }))
61
+
62
+ // Suspends on a deferred, then composes the persisted activity result
63
+ // with the resumed deferred value. Exercises Result/Exit round-trip.
64
+ const Trigger = DurableDeferred.make("WorkflowEngineCosmos/Trigger", { success: Schema.String })
65
+
66
+ const SuspendWorkflow = Workflow.make({
67
+ name: "WorkflowEngineCosmos/SuspendWorkflow",
68
+ payload: { id: Schema.String },
69
+ success: Schema.String,
70
+ idempotencyKey: ({ id }) => id
71
+ })
72
+
73
+ const SuspendHandler = SuspendWorkflow.toLayer(Effect.fn(function*({ id }) {
74
+ const n = yield* Activity.make({
75
+ name: "step",
76
+ success: Schema.Number,
77
+ execute: Effect.succeed(1)
78
+ })
79
+ const v = yield* DurableDeferred.await(Trigger)
80
+ return `${id}:${n}:${v}`
81
+ }))
82
+
83
+ // Plain durable-deferred await — used to assert first-writer-wins on done().
84
+ const AwaitOnly = Workflow.make({
85
+ name: "WorkflowEngineCosmos/AwaitOnly",
86
+ payload: { id: Schema.String },
87
+ success: Schema.String,
88
+ idempotencyKey: ({ id }) => id
89
+ })
90
+
91
+ const AwaitOnlyHandler = AwaitOnly.toLayer(Effect.fn(function*() {
92
+ return yield* DurableDeferred.await(Trigger)
93
+ }))
94
+
95
+ const Handlers = Layer.mergeAll(IncrementHandler, SuspendHandler, CounterHandler, AwaitOnlyHandler)
96
+
97
+ // Helper that polls until the workflow completes (or `maxIterations` elapse).
98
+ const waitForComplete = (
99
+ workflow: { readonly poll: (id: string) => Effect.Effect<Option.Option<Workflow.Result<any, any>>, never, any> },
100
+ executionId: string,
101
+ step = Duration.millis(10),
102
+ maxIterations = 200
103
+ ) =>
104
+ Effect.gen(function*() {
105
+ for (let i = 0; i < maxIterations; i++) {
106
+ const polled = yield* workflow.poll(executionId)
107
+ if (Option.isSome(polled) && polled.value._tag === "Complete") {
108
+ return polled.value
109
+ }
110
+ yield* Effect.sleep(step)
111
+ }
112
+ return undefined
113
+ })
114
+
115
+ const runSuite = (engineLayer: Layer.Layer<WorkflowEngine.WorkflowEngine>) => {
116
+ const TestLayer = Handlers.pipe(
117
+ Layer.provideMerge(CounterRef.layer),
118
+ Layer.provideMerge(engineLayer)
119
+ )
120
+
121
+ it.live("executes a workflow and polls the result", () =>
122
+ Effect
123
+ .gen(function*() {
124
+ const executionId = yield* IncrementWorkflow.execute({ value: 41 }, { discard: true })
125
+ const result = yield* IncrementWorkflow.execute({ value: 41 })
126
+ const polled = yield* IncrementWorkflow.poll(executionId)
127
+
128
+ assert.strictEqual(result, 42)
129
+ assert(
130
+ Option.isSome(polled)
131
+ && polled.value._tag === "Complete"
132
+ && Exit.isSuccess(polled.value.exit)
133
+ )
134
+ assert.strictEqual(polled.value.exit.value, 42)
135
+ })
136
+ .pipe(Effect.provide(TestLayer)))
137
+
138
+ it.live("re-executing the same id is idempotent", () =>
139
+ Effect
140
+ .gen(function*() {
141
+ const a = yield* IncrementWorkflow.execute({ value: 7 })
142
+ const b = yield* IncrementWorkflow.execute({ value: 7 })
143
+ assert.strictEqual(a, b)
144
+ })
145
+ .pipe(Effect.provide(TestLayer)))
146
+
147
+ it.live("activity side effects run once across re-executions", () =>
148
+ Effect
149
+ .gen(function*() {
150
+ const counter = yield* CounterRef
151
+ yield* CounterWorkflow.execute({ id: "once" })
152
+ yield* CounterWorkflow.execute({ id: "once" })
153
+ yield* CounterWorkflow.execute({ id: "once" })
154
+ assert.strictEqual(counter.count, 1)
155
+ })
156
+ .pipe(Effect.provide(TestLayer)))
157
+
158
+ it.live("suspends on a durable deferred, then resumes with the decoded result", () =>
159
+ Effect
160
+ .gen(function*() {
161
+ // The execution suspends on `Trigger`; completing the deferred resumes
162
+ // it (the workflow body replays, the `step` activity is served from its
163
+ // persisted result), and the final value round-trips through the engine.
164
+ const executionId = yield* SuspendWorkflow.execute({ id: "abc" }, { discard: true })
165
+
166
+ const token = yield* DurableDeferred.tokenFromPayload(Trigger, {
167
+ workflow: SuspendWorkflow,
168
+ payload: { id: "abc" }
169
+ })
170
+ yield* DurableDeferred.done(Trigger, { token, exit: Exit.succeed("ok") })
171
+
172
+ const done = yield* waitForComplete(SuspendWorkflow, executionId)
173
+ assert(done && Exit.isSuccess(done.exit))
174
+ assert.strictEqual(done.exit.value, "abc:1:ok")
175
+ })
176
+ .pipe(Effect.provide(TestLayer)))
177
+
178
+ it.live("deferredDone is idempotent (first-writer-wins)", () =>
179
+ Effect
180
+ .gen(function*() {
181
+ const executionId = yield* AwaitOnly.execute({ id: "dup" }, { discard: true })
182
+ const token = yield* DurableDeferred.tokenFromPayload(Trigger, {
183
+ workflow: AwaitOnly,
184
+ payload: { id: "dup" }
185
+ })
186
+ yield* DurableDeferred.done(Trigger, { token, exit: Exit.succeed("first") })
187
+ // Second completion must lose; the workflow body sees "first".
188
+ yield* DurableDeferred.done(Trigger, { token, exit: Exit.succeed("second") })
189
+
190
+ const done = yield* waitForComplete(AwaitOnly, executionId)
191
+ assert(done && Exit.isSuccess(done.exit))
192
+ assert.strictEqual(done.exit.value, "first")
193
+ })
194
+ .pipe(Effect.provide(TestLayer)))
195
+
196
+ it.live("interrupt eventually completes a suspended execution", () =>
197
+ Effect
198
+ .gen(function*() {
199
+ const executionId = yield* AwaitOnly.execute({ id: "int" }, { discard: true })
200
+ // Give the workflow time to suspend on the deferred.
201
+ yield* Effect.sleep(Duration.millis(50))
202
+ yield* AwaitOnly.interrupt(executionId)
203
+
204
+ // The execution should stop reporting as "running" — a subsequent poll
205
+ // returns either Complete (engine collapses the interrupt into a
206
+ // completion) or None (engine surfaces it as not-yet-complete and the
207
+ // wrapper sleep loop eventually ends). Both are acceptable as long as
208
+ // the workflow no longer makes forward progress.
209
+ yield* Effect.sleep(Duration.millis(150))
210
+ const polled = yield* AwaitOnly.poll(executionId)
211
+ if (Option.isSome(polled)) {
212
+ assert.strictEqual(polled.value._tag, "Complete")
213
+ }
214
+ })
215
+ .pipe(Effect.provide(TestLayer)))
216
+ }
217
+
218
+ describe("WorkflowEngine (in-memory)", () => {
219
+ runSuite(WorkflowEngine.layerMemory)
220
+ })
221
+
222
+ // --- Cosmos-emulator-only adapter tests --------------------------------
223
+ //
224
+ // Opt-in. Run with e.g.
225
+ // COSMOS_TEST_URL="https://localhost:8081" COSMOS_TEST_DB="workflow-test" \
226
+ // NODE_TLS_REJECT_UNAUTHORIZED=0 pnpm vitest run workflow-engine-cosmos
227
+ const cosmosUrl = process.env["COSMOS_TEST_URL"]
228
+ const cosmosDb = process.env["COSMOS_TEST_DB"] ?? "workflow-test"
229
+
230
+ describe.skipIf(!cosmosUrl)("WorkflowEngine (Cosmos) — conformance", () => {
231
+ runSuite(
232
+ layerCosmos({
233
+ url: Redacted.make(cosmosUrl ?? ""),
234
+ dbName: cosmosDb,
235
+ prefix: `test-${Date.now()}-`,
236
+ // Tight cadences so the suite doesn't wait on the background pollers.
237
+ recoveryInterval: Duration.seconds(2),
238
+ clockPollInterval: Duration.seconds(1)
239
+ })
240
+ )
241
+ })
242
+
243
+ describe.skipIf(!cosmosUrl)("WorkflowEngine (Cosmos) — adapter internals", () => {
244
+ // Each test gets its own container prefix so seeded docs don't leak.
245
+ const prefixFor = (label: string) => `test-${Date.now()}-${label}-`
246
+
247
+ const adapterLayer = (prefix: string) =>
248
+ Layer
249
+ .mergeAll(
250
+ IncrementHandler,
251
+ AwaitOnlyHandler,
252
+ CounterRef.layer,
253
+ CosmosClientLayer(cosmosUrl ?? "", cosmosDb)
254
+ )
255
+ .pipe(
256
+ Layer.provideMerge(
257
+ layerCosmos({
258
+ url: Redacted.make(cosmosUrl ?? ""),
259
+ dbName: cosmosDb,
260
+ prefix,
261
+ recoveryInterval: Duration.millis(500),
262
+ clockPollInterval: Duration.millis(500)
263
+ })
264
+ )
265
+ )
266
+
267
+ it.live("recovery poller drives execs with stale leases", () => {
268
+ const prefix = prefixFor("recovery")
269
+ const containerId = `${prefix}workflow-engine`
270
+ return Effect
271
+ .gen(function*() {
272
+ const { db } = yield* CosmosClient
273
+ const container = db.container(containerId)
274
+ // Pre-seed a running exec whose lease has already expired and whose
275
+ // payload is the schema-encoded form of `{ value: 99 }`.
276
+ yield* Effect.promise(() =>
277
+ container.items.upsert({
278
+ id: "exec",
279
+ _partitionKey: "recover-1",
280
+ type: "exec",
281
+ workflowName: IncrementWorkflow.name,
282
+ payload: JSON.stringify({ value: 99 }),
283
+ status: "running",
284
+ suspended: false,
285
+ interrupted: false,
286
+ worker: "ghost",
287
+ leaseExpiresAt: new Date(Date.now() - 60_000).toISOString(),
288
+ etag: "seed"
289
+ })
290
+ )
291
+
292
+ // Wait for the recovery poller (500ms cadence) to drive it.
293
+ yield* Effect.sleep(Duration.seconds(2))
294
+
295
+ const polled = yield* IncrementWorkflow.poll("recover-1")
296
+ assert(
297
+ Option.isSome(polled)
298
+ && polled.value._tag === "Complete"
299
+ && Exit.isSuccess(polled.value.exit)
300
+ )
301
+ assert.strictEqual(polled.value.exit.value, 100)
302
+ })
303
+ .pipe(Effect.provide(adapterLayer(prefix)))
304
+ })
305
+
306
+ it.live("clock poller fires past-due clocks", () => {
307
+ const prefix = prefixFor("clocks")
308
+ const containerId = `${prefix}workflow-engine`
309
+ return Effect
310
+ .gen(function*() {
311
+ const { db } = yield* CosmosClient
312
+ const container = db.container(containerId)
313
+ // Seed an exec + a clock that fired in the past. No in-process timer
314
+ // exists (we never called scheduleClock), so only the poller can
315
+ // resolve the deferred.
316
+ yield* Effect.promise(() =>
317
+ container.items.upsert({
318
+ id: "exec",
319
+ _partitionKey: "exec-clock",
320
+ type: "exec",
321
+ workflowName: AwaitOnly.name,
322
+ payload: JSON.stringify({ id: "wake" }),
323
+ status: "running",
324
+ suspended: false,
325
+ interrupted: false,
326
+ etag: "seed"
327
+ })
328
+ )
329
+ yield* Effect.promise(() =>
330
+ container.items.upsert({
331
+ id: "clock::wake",
332
+ _partitionKey: "exec-clock",
333
+ type: "clock",
334
+ workflowName: AwaitOnly.name,
335
+ deferredName: Trigger.name,
336
+ fireAt: new Date(Date.now() - 60_000).toISOString()
337
+ })
338
+ )
339
+
340
+ yield* Effect.sleep(Duration.seconds(2))
341
+
342
+ // The clock fire is a deferred-complete; assert the deferred row
343
+ // now exists for this execution.
344
+ const deferred = yield* Effect.promise(() =>
345
+ container.item(`deferred::${Trigger.name}`, "exec-clock").read<{ exit: string }>()
346
+ )
347
+ assert(deferred.resource !== undefined)
348
+ // And the clock doc has been deleted.
349
+ const clockGone = yield* Effect.promise(() => container.item("clock::wake", "exec-clock").read())
350
+ assert.strictEqual(clockGone.statusCode, 404)
351
+ })
352
+ .pipe(Effect.provide(adapterLayer(prefix)))
353
+ })
354
+ })