@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
package/src/arbs.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  // Do not import to frontend
2
2
 
3
3
  import { faker } from "@faker-js/faker"
4
- import { type S } from "effect-app"
5
4
  import { setFaker } from "effect-app/faker"
5
+ import type * as S from "effect-app/Schema"
6
6
  import * as FastCheck from "effect/testing/FastCheck"
7
7
  import { Random } from "fast-check"
8
- import * as rand from "pure-rand"
8
+ import { congruential32 } from "pure-rand/generator/congruential32"
9
9
 
10
- const rnd = new Random(rand.congruential32(5))
10
+ const seed = 5
11
+ const rng = congruential32(seed)
12
+ const rnd = new Random(rng)
11
13
 
12
14
  setFaker(faker)
13
15
 
@@ -1,16 +1,18 @@
1
1
  import { CosmosClient as ComosClient_ } from "@azure/cosmos"
2
- import { Effect, Layer, ServiceMap } from "effect-app"
2
+ import * as Context from "effect-app/Context"
3
+ import * as Effect from "effect-app/Effect"
4
+ import * as Layer from "effect-app/Layer"
3
5
 
4
6
  const withClient = (url: string) => Effect.sync(() => new ComosClient_(url))
5
7
 
6
8
  export const makeCosmosClient = (url: string, dbName: string) =>
7
9
  Effect.map(withClient(url), (x) => ({ db: x.database(dbName) }))
8
10
 
9
- export class CosmosClient extends ServiceMap.Service<CosmosClient, {
11
+ export class CosmosClient extends Context.Service<CosmosClient, {
10
12
  readonly db: ReturnType<InstanceType<typeof ComosClient_>["database"]>
11
13
  }>()("@services/CosmosClient") {}
12
14
 
13
- export const db = CosmosClient.asEffect().pipe(Effect.map((_) => _.db))
15
+ export const db = CosmosClient.pipe(Effect.map((_) => _.db))
14
16
 
15
17
  export const CosmosClientLayer = (cosmosUrl: string, dbName: string) =>
16
18
  Layer.effect(CosmosClient, makeCosmosClient(cosmosUrl, dbName))
@@ -1,7 +1,9 @@
1
1
  import * as Sentry from "@sentry/node"
2
- import { Cause, Effect, type LogLevel } from "effect-app"
2
+ import * as Effect from "effect-app/Effect"
3
+ import { getRC } from "effect-app/setupRequest"
3
4
  import { dropUndefined, LogLevelToSentry } from "effect-app/utils"
4
- import { getRC } from "./api/setupRequest.js"
5
+ import * as Cause from "effect/Cause"
6
+ import type * as LogLevel from "effect/LogLevel"
5
7
  import { CauseException, tryToJson, tryToReport } from "./errors.js"
6
8
  import { InfraLogger } from "./logger.js"
7
9
 
@@ -13,47 +15,41 @@ const tryCauseException = <E>(cause: Cause.Cause<E>, name: string): CauseExcepti
13
15
  }
14
16
  }
15
17
 
16
- export function reportError(
17
- name: string
18
- ) {
19
- return (
20
- cause: Cause.Cause<unknown>,
21
- extras?: Record<string, unknown>,
22
- level: LogLevel.Severity = "Error"
23
- ) =>
24
- Effect
25
- .gen(function*() {
26
- if (Cause.hasInterruptsOnly(cause)) {
27
- yield* InfraLogger.logDebug("Interrupted").pipe(Effect.annotateLogs("extras", JSON.stringify(extras ?? {})))
28
- return
29
- }
30
- const error = tryCauseException(cause, name)
31
-
32
- yield* reportSentry(error, extras, LogLevelToSentry(level))
33
- yield* InfraLogger
34
- .logWithLevel(level, "Reporting error", cause)
35
- .pipe(
36
- Effect.annotateLogs(dropUndefined({
37
- extras,
38
- error: tryToReport(error),
39
- cause: tryToJson(cause),
40
- __error_name__: name
41
- }))
42
- )
43
- .pipe(
44
- Effect.catchCause((cause) => InfraLogger.logWarning("Failed to log error", cause)),
45
- Effect.catchCause(() => InfraLogger.logFatal("Failed to log error cause"))
46
- )
18
+ export function reportError(name: string) {
19
+ return Effect.fnUntraced(
20
+ function*(
21
+ cause: Cause.Cause<unknown>,
22
+ extras?: Record<string, unknown>,
23
+ level: LogLevel.Severity = "Error"
24
+ ) {
25
+ if (Cause.hasInterruptsOnly(cause)) {
26
+ yield* InfraLogger.logDebug("Interrupted").pipe(Effect.annotateLogs("extras", JSON.stringify(extras ?? {})))
27
+ return
28
+ }
29
+ const error = tryCauseException(cause, name)
47
30
 
48
- return error
49
- })
50
- .pipe(
51
- Effect.tapCause((cause) =>
52
- InfraLogger.logError("Failed to report error", cause).pipe(
53
- Effect.tapCause(() => InfraLogger.logFatal("Failed to log error cause"))
54
- )
31
+ yield* reportSentry(error, extras, LogLevelToSentry(level))
32
+ yield* InfraLogger
33
+ .logWithLevel(level, "Reporting error", cause)
34
+ .pipe(
35
+ Effect.annotateLogs(dropUndefined({
36
+ extras,
37
+ error: tryToReport(error),
38
+ cause: tryToJson(cause),
39
+ __error_name__: name
40
+ })),
41
+ Effect.catchCause((cause) => InfraLogger.logWarning("Failed to log error", cause)),
42
+ Effect.catchCause(() => InfraLogger.logFatal("Failed to log error cause"))
55
43
  )
56
- )
44
+
45
+ return error
46
+ },
47
+ (effect) =>
48
+ Effect.tapCause(effect, (cause) =>
49
+ InfraLogger.logError("Failed to report error", cause).pipe(
50
+ Effect.tapCause(() => InfraLogger.logFatal("Failed to log error cause"))
51
+ ))
52
+ )
57
53
  }
58
54
 
59
55
  function reportSentry(
@@ -66,45 +62,39 @@ function reportSentry(
66
62
  scope.setLevel(level)
67
63
  if (context) scope.setContext("context", { ...context })
68
64
  if (extras) scope.setContext("extras", extras)
69
- scope.setContext("error", { data: tryToReport(error) })
70
- scope.setContext("cause", { data: tryToJson(error.originalCause) })
65
+ const squashed = Cause.squash(error.originalCause)
66
+ scope.setContext("mainError", tryToJson(squashed))
67
+ scope.setContext("error", tryToReport(error))
68
+ scope.setContext("cause", tryToJson(error.originalCause))
71
69
  Sentry.captureException(error, scope)
72
70
  }))
73
71
  }
74
72
 
75
- export function logError<E>(
76
- name: string
77
- ) {
78
- return (cause: Cause.Cause<E>, extras?: Record<string, unknown>) =>
79
- Effect
80
- .gen(function*() {
81
- if (Cause.hasInterruptsOnly(cause)) {
82
- yield* InfraLogger.logDebug("Interrupted").pipe(Effect.annotateLogs(dropUndefined({ extras })))
83
- return
84
- }
85
- yield* InfraLogger
86
- .logWarning("Logging error", cause)
87
- .pipe(
88
- Effect.annotateLogs(dropUndefined({
89
- extras,
90
- cause: tryToJson(cause),
91
- __error_name__: name
92
- }))
93
- )
94
- })
95
- .pipe(
96
- Effect.tapCause(() => InfraLogger.logFatal("Failed to log error cause"))
97
- )
73
+ export function logError<E>(name: string) {
74
+ return Effect.fnUntraced(
75
+ function*(cause: Cause.Cause<E>, extras?: Record<string, unknown>) {
76
+ if (Cause.hasInterruptsOnly(cause)) {
77
+ yield* InfraLogger.logDebug("Interrupted").pipe(Effect.annotateLogs(dropUndefined({ extras })))
78
+ return
79
+ }
80
+ yield* InfraLogger
81
+ .logWarning("Logging error", cause)
82
+ .pipe(Effect.annotateLogs(dropUndefined({
83
+ extras,
84
+ cause: tryToJson(cause),
85
+ __error_name__: name
86
+ })))
87
+ },
88
+ (effect) => Effect.tapCause(effect, () => InfraLogger.logFatal("Failed to log error cause"))
89
+ )
98
90
  }
99
91
 
100
- export function reportMessage(message: string, extras?: Record<string, unknown>) {
101
- return Effect.gen(function*() {
102
- const context = yield* getRC
103
- const scope = new Sentry.Scope()
104
- if (context) scope.setContext("context", { ...context })
105
- if (extras) scope.setContext("extras", extras)
106
- Sentry.captureMessage(message, scope)
92
+ export const reportMessage = Effect.fnUntraced(function*(message: string, extras?: Record<string, unknown>) {
93
+ const context = yield* getRC
94
+ const scope = new Sentry.Scope()
95
+ if (context) scope.setContext("context", { ...context })
96
+ if (extras) scope.setContext("extras", extras)
97
+ Sentry.captureMessage(message, scope)
107
98
 
108
- console.warn(message, extras)
109
- })
110
- }
99
+ console.warn(message, extras)
100
+ })
package/src/fileUtil.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import crypto from "crypto"
2
- import { Effect } from "effect-app"
2
+ import * as Effect from "effect-app/Effect"
3
3
  import type { Abortable } from "events"
4
4
  import type { Mode, ObjectEncodingOptions, OpenMode } from "fs"
5
5
  import fs from "fs/promises"
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
- export * as Model from "./Model.js"
1
+ export * from "./logger.js"
2
+ export * from "./Store/index.js"
@@ -1,8 +1,10 @@
1
- import { Effect } from "effect-app"
1
+ import * as Effect from "effect-app/Effect"
2
2
  import { HttpMiddleware, HttpServerRequest, HttpServerResponse } from "effect-app/http"
3
+ import * as Layer from "effect-app/Layer"
4
+ import { Locale, LocaleRef, RequestContext, spanAttributes } from "effect-app/RequestContext"
3
5
  import { NonEmptyString255 } from "effect-app/Schema"
4
- import { Locale, RequestContext } from "../../RequestContext.js"
5
- import { setupRequestContext } from "../setupRequest.js"
6
+ import { provideOnRequestScope } from "effect-app/setupRequest"
7
+ import { ContextMapContainer, storeId } from "effect-app/Store"
6
8
 
7
9
  export const RequestContextMiddleware = (defaultLocale: Locale = "en") =>
8
10
  HttpMiddleware.make((app) =>
@@ -21,18 +23,33 @@ export const RequestContextMiddleware = (defaultLocale: Locale = "en") =>
21
23
  const namespace = NonEmptyString255((ns && (Array.isArray(ns) ? ns[0] : ns)) || "primary")
22
24
  const deviceId = req.headers["x-fe-device-id"]
23
25
 
24
- const requestContext = new RequestContext({
26
+ const requestContext = RequestContext.make({
25
27
  span: {
26
28
  traceId: currentSpan.traceId,
27
29
  spanId: currentSpan.spanId,
28
30
  sampled: currentSpan.sampled
29
31
  },
30
- name: NonEmptyString255(req.originalUrl), // set more detailed elsewhere
32
+ name: NonEmptyString255(`HTTP ${req.method} ${req.originalUrl.split("?")[0]}`), // set more detailed elsewhere
31
33
  locale,
32
34
  namespace,
33
35
  sourceId: deviceId ? NonEmptyString255(deviceId) : undefined
34
36
  })
35
- const res = yield* setupRequestContext(app, requestContext)
37
+ yield* Effect.annotateCurrentSpan(spanAttributes(requestContext))
38
+ const layer = Layer.mergeAll(
39
+ ContextMapContainer.layer,
40
+ Layer.succeed(LocaleRef, requestContext.locale),
41
+ Layer.succeed(storeId, requestContext.namespace)
42
+ )
43
+ // Bind layer to the request scope so ContextMap's finalizer (clear()) runs only
44
+ // after the response body is fully drained — not when `app` returns its
45
+ // HttpServerResponse value. Streaming RPC responses keep producing chunks (and
46
+ // using ContextMap-cached etags) after `app` returns; a sub-scope from
47
+ // `Effect.provide(layer)` would close too early and wipe etags mid-stream,
48
+ // causing spurious OptimisticConcurrencyException on later writes.
49
+ const res = yield* app.pipe(
50
+ Effect.withLogSpan(requestContext.name),
51
+ provideOnRequestScope(layer)
52
+ )
36
53
 
37
54
  // TODO: how to set also on errors?
38
55
  return HttpServerResponse.setHeaders(res, {
@@ -0,0 +1,272 @@
1
+ import * as Effect from "effect-app/Effect"
2
+ import { HttpHeaders, HttpMiddleware, HttpServerRequest, HttpServerResponse } from "effect-app/http"
3
+ import * as Option from "effect-app/Option"
4
+ import * as Data from "effect/Data"
5
+ import { createRemoteJWKSet, jwtVerify } from "jose"
6
+
7
+ const getHeaders = (error: string, description: string, scopes?: ReadonlyArray<string>) => ({
8
+ "WWW-Authenticate": `Bearer realm="api", error="${error}", error_description="${description.replace(/"/g, "'")}"${
9
+ scopes ? `, scope="${scopes.join(" ")}"` : ""
10
+ }`
11
+ })
12
+
13
+ export class UnauthorizedError extends Error {
14
+ readonly status: number = 401
15
+ readonly statusCode: number = 401
16
+ headers = { "WWW-Authenticate": "Bearer realm=\"api\"" }
17
+
18
+ constructor(message = "Unauthorized") {
19
+ super(message)
20
+ this.name = this.constructor.name
21
+ }
22
+ }
23
+
24
+ export class InvalidRequestError extends UnauthorizedError {
25
+ readonly code: string
26
+ override readonly status = 400
27
+ override readonly statusCode = 400
28
+
29
+ constructor(message = "Invalid Request", useErrorCode = true) {
30
+ super(message)
31
+ this.code = useErrorCode ? "invalid_request" : ""
32
+ if (useErrorCode) {
33
+ this.headers = getHeaders(this.code, this.message)
34
+ }
35
+ }
36
+ }
37
+
38
+ export class InvalidTokenError extends UnauthorizedError {
39
+ readonly code = "invalid_token"
40
+
41
+ constructor(message = "Invalid Token") {
42
+ super(message)
43
+ this.headers = getHeaders(this.code, this.message)
44
+ }
45
+ }
46
+
47
+ export class InsufficientScopeError extends UnauthorizedError {
48
+ readonly code = "insufficient_scope"
49
+ override readonly status = 403
50
+ override readonly statusCode = 403
51
+
52
+ constructor(scopes?: ReadonlyArray<string>, message = "Insufficient Scope") {
53
+ super(message)
54
+ this.headers = getHeaders(this.code, this.message, scopes)
55
+ }
56
+ }
57
+
58
+ export interface JwtVerifierOptions {
59
+ readonly audience?: string | Array<string> | ReadonlyArray<string>
60
+ readonly clockTolerance?: number
61
+ readonly issuer?: string
62
+ readonly issuerBaseURL?: string
63
+ readonly jwksUri?: string
64
+ readonly maxTokenAge?: number
65
+ readonly secret?: string
66
+ readonly strict?: boolean
67
+ readonly tokenSigningAlg?: string
68
+ }
69
+
70
+ export interface AuthOptions extends JwtVerifierOptions {
71
+ readonly authRequired?: boolean
72
+ }
73
+
74
+ type Config = AuthOptions
75
+
76
+ type JwtError = InsufficientScopeError | InvalidRequestError | InvalidTokenError | UnauthorizedError
77
+
78
+ type ResolvedConfigBase = {
79
+ readonly audience: string | Array<string> | undefined
80
+ readonly clockTolerance: number
81
+ readonly issuer: string | undefined
82
+ readonly maxTokenAge: number | undefined
83
+ readonly strict: boolean
84
+ readonly tokenSigningAlg: string | undefined
85
+ }
86
+
87
+ type ResolvedConfig =
88
+ & ResolvedConfigBase
89
+ & (
90
+ | {
91
+ readonly key: ReturnType<typeof createRemoteJWKSet>
92
+ readonly keyType: "jwks"
93
+ }
94
+ | {
95
+ readonly key: Uint8Array
96
+ readonly keyType: "secret"
97
+ }
98
+ )
99
+
100
+ const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null
101
+
102
+ const getErrorMessage = (error: unknown) => error instanceof Error ? error.message : String(error)
103
+
104
+ const normalizeAudience = (audience: Config["audience"]): string | Array<string> | undefined =>
105
+ Array.isArray(audience) ? Array.from(audience) : audience as string | undefined
106
+
107
+ const buildDiscoveryUrl = (issuerBaseURL: string) => {
108
+ const url = new URL(issuerBaseURL)
109
+ if (!url.pathname.includes("/.well-known/")) {
110
+ url.pathname = url.pathname.endsWith("/")
111
+ ? `${url.pathname}.well-known/openid-configuration`
112
+ : `${url.pathname}/.well-known/openid-configuration`
113
+ }
114
+ url.search = ""
115
+ url.hash = ""
116
+ return url
117
+ }
118
+
119
+ const fetchDiscoveryDocumentPromise = async (issuerBaseURL: string) => {
120
+ const response = await fetch(buildDiscoveryUrl(issuerBaseURL))
121
+ if (!response.ok) {
122
+ throw new Error(`Failed to fetch authorization server metadata: ${response.status}`)
123
+ }
124
+ const json = await response.json()
125
+ if (!isRecord(json) || typeof json["issuer"] !== "string" || typeof json["jwks_uri"] !== "string") {
126
+ throw new Error("Invalid authorization server metadata")
127
+ }
128
+ return { issuer: json["issuer"], jwksUri: json["jwks_uri"] }
129
+ }
130
+
131
+ const getAuthorizationToken = (headers: HttpHeaders.Headers, authRequired: boolean) => {
132
+ const authorization = HttpHeaders.get(headers, "authorization")
133
+ if (Option.isNone(authorization)) {
134
+ return authRequired ? Effect.fail(new UnauthorizedError()) : Effect.succeed(Option.none<string>())
135
+ }
136
+
137
+ const [scheme, token] = authorization.value.split(" ")
138
+ if (!scheme || !token || scheme.toLowerCase() !== "bearer") {
139
+ return Effect.fail(new InvalidRequestError("", false))
140
+ }
141
+
142
+ return Effect.succeed(Option.some(token))
143
+ }
144
+
145
+ const makeResolveConfig = (config: Config) => {
146
+ let cached: Promise<ResolvedConfig> | undefined
147
+
148
+ return Effect.tryPromise({
149
+ try: () => {
150
+ if (!cached) {
151
+ cached = (async (): Promise<ResolvedConfig> => {
152
+ const discovery = config.issuerBaseURL
153
+ ? await fetchDiscoveryDocumentPromise(config.issuerBaseURL)
154
+ : undefined
155
+
156
+ const issuer = config.issuer ?? discovery?.issuer
157
+ const jwksUri = config.jwksUri ?? discovery?.jwksUri
158
+ const secret = config.secret
159
+ const base = {
160
+ audience: normalizeAudience(config.audience),
161
+ clockTolerance: config.clockTolerance ?? 5,
162
+ issuer,
163
+ maxTokenAge: config.maxTokenAge,
164
+ strict: config.strict ?? false,
165
+ tokenSigningAlg: config.tokenSigningAlg
166
+ } satisfies ResolvedConfigBase
167
+
168
+ if (!issuer && !secret) {
169
+ throw new InvalidRequestError("JWT config requires 'issuer', 'issuerBaseURL', or 'secret'")
170
+ }
171
+
172
+ if (!secret) {
173
+ if (!jwksUri) {
174
+ throw new InvalidRequestError("JWT config requires 'jwksUri', 'issuerBaseURL', or 'secret'")
175
+ }
176
+
177
+ return {
178
+ ...base,
179
+ key: createRemoteJWKSet(new URL(jwksUri)),
180
+ keyType: "jwks"
181
+ }
182
+ }
183
+
184
+ return {
185
+ ...base,
186
+ key: new TextEncoder().encode(secret),
187
+ keyType: "secret"
188
+ }
189
+ })()
190
+ }
191
+
192
+ return cached
193
+ },
194
+ catch: (error) =>
195
+ error instanceof InvalidRequestError || error instanceof InvalidTokenError
196
+ ? error
197
+ : new InvalidTokenError(getErrorMessage(error))
198
+ })
199
+ }
200
+
201
+ const verifyToken =
202
+ (resolveConfig: Effect.Effect<ResolvedConfig, InvalidRequestError | InvalidTokenError>) => (token: string) =>
203
+ resolveConfig.pipe(
204
+ Effect.flatMap((config) => {
205
+ const options = {
206
+ clockTolerance: config.clockTolerance,
207
+ ...(config.tokenSigningAlg ? { algorithms: [config.tokenSigningAlg] } : {}),
208
+ ...(config.audience !== undefined ? { audience: config.audience } : {}),
209
+ ...(config.issuer !== undefined ? { issuer: config.issuer } : {}),
210
+ ...(config.maxTokenAge !== undefined ? { maxTokenAge: config.maxTokenAge } : {})
211
+ }
212
+ const verified = config.keyType === "jwks"
213
+ ? Effect.tryPromise({
214
+ try: () => jwtVerify(token, config.key, options).then(({ protectedHeader }) => ({ protectedHeader })),
215
+ catch: (error) => new InvalidTokenError(getErrorMessage(error))
216
+ })
217
+ : Effect.tryPromise({
218
+ try: () => jwtVerify(token, config.key, options).then(({ protectedHeader }) => ({ protectedHeader })),
219
+ catch: (error) => new InvalidTokenError(getErrorMessage(error))
220
+ })
221
+
222
+ return verified.pipe(
223
+ Effect.flatMap(({ protectedHeader }) => {
224
+ const typ = protectedHeader.typ?.toLowerCase().replace(/^application\//, "")
225
+ return config.strict && typ !== "at+jwt"
226
+ ? Effect.fail(new InvalidTokenError("Unexpected 'typ' value"))
227
+ : Effect.void
228
+ })
229
+ )
230
+ })
231
+ )
232
+
233
+ export const checkJWTI = (config: Config) => {
234
+ const resolveConfig = makeResolveConfig(config)
235
+ const verify = verifyToken(resolveConfig)
236
+
237
+ return Effect.fnUntraced(function*(headers: HttpHeaders.Headers) {
238
+ const token = yield* getAuthorizationToken(headers, config.authRequired !== false)
239
+ if (Option.isNone(token)) {
240
+ return
241
+ }
242
+
243
+ yield* verify(token.value)
244
+ })
245
+ }
246
+
247
+ export const checkJwt = (config: Config) => {
248
+ const check = checkJWTI(config)
249
+ return HttpMiddleware.make((app) =>
250
+ Effect.gen(function*() {
251
+ const req = yield* HttpServerRequest.HttpServerRequest
252
+ const response = yield* check(req.headers).pipe(
253
+ Effect.catch((error: JwtError) =>
254
+ HttpServerResponse.json({ message: error.message }, {
255
+ status: error.status,
256
+ headers: HttpHeaders.fromInput(error.headers)
257
+ })
258
+ )
259
+ )
260
+
261
+ if (response) {
262
+ return response
263
+ }
264
+
265
+ return yield* app
266
+ })
267
+ )
268
+ }
269
+
270
+ export class JWTError extends Data.TaggedClass("JWTError")<{
271
+ error: JwtError
272
+ }> {}
@@ -1,7 +1,13 @@
1
- import { Duration, Effect, pipe, S, Schedule, Stream } from "effect-app"
1
+ import * as Effect from "effect-app/Effect"
2
2
  import { HttpHeaders, HttpServerResponse } from "effect-app/http"
3
- import { reportError } from "../../errorReporter.js"
4
- import { setupRequestContextFromCurrent } from "../setupRequest.js"
3
+ import * as S from "effect-app/Schema"
4
+ import { setupStreamingRequestContextFromCurrent } from "effect-app/setupRequest"
5
+ import { storeId } from "effect-app/Store"
6
+ import * as Duration from "effect/Duration"
7
+ import { pipe } from "effect/Function"
8
+ import * as Schedule from "effect/Schedule"
9
+ import * as Stream from "effect/Stream"
10
+ import { reportError } from "../errorReporter.js"
5
11
 
6
12
  // Tell the client to retry every 10 seconds if connectivity is lost
7
13
  const setRetry = Stream.succeed("retry: 10000")
@@ -9,29 +15,32 @@ const keepAlive = Stream.fromEffectSchedule(Effect.succeed(":keep-alive"), Sched
9
15
 
10
16
  let connId = BigInt(0)
11
17
 
12
- export const makeSSE = <A extends { id: any }, SI, SR>(
13
- schema: S.Codec<A, SI, SR>
18
+ export const makeSSE = <A extends { id: any }, SI, SRD, SRE>(
19
+ schema: S.Codec<A, SI, SRD, SRE>
14
20
  ) =>
15
21
  <E, R>(events: Stream.Stream<{ evt: A; namespace: string }, E, R>) =>
16
22
  Effect
17
23
  .gen(function*() {
18
24
  const id = connId++
19
- const ctx = yield* Effect.services<R | SR>()
25
+ const ctx = yield* Effect.context<R | SRD | SRE>()
20
26
  const res = HttpServerResponse.stream(
21
27
  // workaround for different scoped behaviour for streams in Bun
22
28
  // https://discord.com/channels/795981131316985866/1098177242598756412/1389646879675125861
23
29
  Effect
24
30
  .gen(function*() {
25
- yield* Effect.annotateCurrentSpan({ connectionId: id.toString() })
26
- yield* Effect.logInfo("$ start listening to events, id: " + id.toString())
27
- yield* Effect.addFinalizer(() => Effect.logInfo("$ end listening to events, id: " + id.toString()))
31
+ const ns = yield* storeId
32
+ yield* Effect.annotateCurrentSpan({ "network.connection.id": id.toString() })
33
+ yield* Effect.logInfo("$ start listening to events, id: " + id.toString() + ", ns: " + ns)
34
+ yield* Effect.addFinalizer(() =>
35
+ Effect.logInfo("$ end listening to events, id: " + id.toString() + ", ns: " + ns)
36
+ )
28
37
 
29
38
  const enc = new TextEncoder()
30
39
 
31
- const encode = S.encodeEffect(S.fromJsonString(schema))
40
+ const encode = S.encodeEffect(S.fromJsonString(S.toCodecJson(schema)))
32
41
 
33
42
  const eventStream = Stream.mapEffect(
34
- events,
43
+ Stream.filter(events, (_) => _.namespace === ns),
35
44
  (_) =>
36
45
  encode(_.evt)
37
46
  .pipe(Effect.map((data) => `id: ${_.evt.id}\ndata: ${data}`))
@@ -42,7 +51,7 @@ export const makeSSE = <A extends { id: any }, SI, SR>(
42
51
  Stream.merge(keepAlive),
43
52
  // Keep this unary so pipe receives a function, not a Stream value.
44
53
  (self) => Stream.merge(self, eventStream, { haltStrategy: "either" }),
45
- Stream.tapCause((cause) => Effect.logError("SSE error", cause)),
54
+ Stream.tapCause((cause) => Effect.logError("SSE error, id: " + id.toString() + ", ns: " + ns, cause)),
46
55
  Stream.map((_) => enc.encode(_ + "\n\n"))
47
56
  )
48
57
 
@@ -65,4 +74,4 @@ export const makeSSE = <A extends { id: any }, SI, SR>(
65
74
  )
66
75
  return res
67
76
  })
68
- .pipe(Effect.tapCause(reportError("Request")), setupRequestContextFromCurrent("events"))
77
+ .pipe(Effect.tapCause(reportError("Request")), setupStreamingRequestContextFromCurrent("events"))