@effect-app/infra 4.0.0-beta.25 → 4.0.0-beta.251

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 (467) hide show
  1. package/CHANGELOG.md +1900 -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/ContextProvider.d.ts +34 -0
  7. package/dist/ContextProvider.d.ts.map +1 -0
  8. package/dist/ContextProvider.js +40 -0
  9. package/dist/Emailer/Sendgrid.d.ts +111 -147
  10. package/dist/Emailer/Sendgrid.d.ts.map +1 -1
  11. package/dist/Emailer/Sendgrid.js +24 -19
  12. package/dist/Emailer/fake.d.ts +2 -2
  13. package/dist/Emailer/fake.d.ts.map +1 -1
  14. package/dist/Emailer/fake.js +4 -4
  15. package/dist/MainFiberSet.d.ts +12 -9
  16. package/dist/MainFiberSet.d.ts.map +1 -1
  17. package/dist/MainFiberSet.js +10 -6
  18. package/dist/QueueMaker/SQLQueue.d.ts +8 -9
  19. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  20. package/dist/QueueMaker/SQLQueue.js +138 -120
  21. package/dist/QueueMaker/errors.d.ts +5 -3
  22. package/dist/QueueMaker/errors.d.ts.map +1 -1
  23. package/dist/QueueMaker/errors.js +4 -2
  24. package/dist/QueueMaker/memQueue.d.ts +10 -6
  25. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  26. package/dist/QueueMaker/memQueue.js +84 -68
  27. package/dist/QueueMaker/sbqueue.d.ts +9 -5
  28. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  29. package/dist/QueueMaker/sbqueue.js +60 -58
  30. package/dist/RequestFiberSet.d.ts +10 -7
  31. package/dist/RequestFiberSet.d.ts.map +1 -1
  32. package/dist/RequestFiberSet.js +13 -8
  33. package/dist/SQL/Model.d.ts +468 -0
  34. package/dist/SQL/Model.d.ts.map +1 -0
  35. package/dist/SQL/Model.js +469 -0
  36. package/dist/SQL.d.ts +2 -0
  37. package/dist/SQL.d.ts.map +1 -0
  38. package/dist/{adapters/SQL.js → SQL.js} +1 -1
  39. package/dist/ServiceBus.d.ts +61 -0
  40. package/dist/ServiceBus.d.ts.map +1 -0
  41. package/dist/ServiceBus.js +108 -0
  42. package/dist/Store/Cosmos/query.d.ts +15 -4
  43. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  44. package/dist/Store/Cosmos/query.js +179 -41
  45. package/dist/Store/Cosmos.d.ts +3 -3
  46. package/dist/Store/Cosmos.d.ts.map +1 -1
  47. package/dist/Store/Cosmos.js +344 -246
  48. package/dist/Store/Disk.d.ts +5 -5
  49. package/dist/Store/Disk.d.ts.map +1 -1
  50. package/dist/Store/Disk.js +78 -38
  51. package/dist/Store/Memory.d.ts +7 -10
  52. package/dist/Store/Memory.d.ts.map +1 -1
  53. package/dist/Store/Memory.js +326 -66
  54. package/dist/Store/SQL/Pg.d.ts +4 -0
  55. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  56. package/dist/Store/SQL/Pg.js +232 -0
  57. package/dist/Store/SQL/query.d.ts +49 -0
  58. package/dist/Store/SQL/query.d.ts.map +1 -0
  59. package/dist/Store/SQL/query.js +527 -0
  60. package/dist/Store/SQL.d.ts +21 -0
  61. package/dist/Store/SQL.d.ts.map +1 -0
  62. package/dist/Store/SQL.js +449 -0
  63. package/dist/Store/codeFilter.d.ts +5 -5
  64. package/dist/Store/codeFilter.d.ts.map +1 -1
  65. package/dist/Store/codeFilter.js +6 -3
  66. package/dist/Store/index.d.ts +7 -5
  67. package/dist/Store/index.d.ts.map +1 -1
  68. package/dist/Store/index.js +18 -5
  69. package/dist/Store/utils.d.ts +4 -3
  70. package/dist/Store/utils.d.ts.map +1 -1
  71. package/dist/Store/utils.js +5 -5
  72. package/dist/arbs.d.ts +2 -2
  73. package/dist/arbs.d.ts.map +1 -1
  74. package/dist/arbs.js +5 -3
  75. package/dist/codec.d.ts +5 -0
  76. package/dist/codec.d.ts.map +1 -0
  77. package/dist/codec.js +5 -0
  78. package/dist/cosmos-client.d.ts +16 -0
  79. package/dist/cosmos-client.d.ts.map +1 -0
  80. package/dist/cosmos-client.js +11 -0
  81. package/dist/errorReporter.d.ts +7 -5
  82. package/dist/errorReporter.d.ts.map +1 -1
  83. package/dist/errorReporter.js +23 -27
  84. package/dist/errors.d.ts +1 -1
  85. package/dist/fileUtil.d.ts +2 -2
  86. package/dist/fileUtil.d.ts.map +1 -1
  87. package/dist/fileUtil.js +2 -2
  88. package/dist/index.d.ts +3 -2
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +3 -2
  91. package/dist/internal/RequestContextMiddleware.d.ts +5 -0
  92. package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
  93. package/dist/internal/RequestContextMiddleware.js +45 -0
  94. package/dist/internal/auth.d.ts +53 -0
  95. package/dist/internal/auth.d.ts.map +1 -0
  96. package/dist/internal/auth.js +180 -0
  97. package/dist/internal/events.d.ts +11 -0
  98. package/dist/internal/events.d.ts.map +1 -0
  99. package/dist/internal/events.js +49 -0
  100. package/dist/internal/health.d.ts +3 -0
  101. package/dist/internal/health.d.ts.map +1 -0
  102. package/dist/internal/health.js +5 -0
  103. package/dist/layerUtils.d.ts +32 -0
  104. package/dist/layerUtils.d.ts.map +1 -0
  105. package/dist/layerUtils.js +17 -0
  106. package/dist/logger/jsonLogger.d.ts +2 -2
  107. package/dist/logger/jsonLogger.d.ts.map +1 -1
  108. package/dist/logger/jsonLogger.js +5 -3
  109. package/dist/logger/logFmtLogger.d.ts +2 -2
  110. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  111. package/dist/logger/logFmtLogger.js +3 -3
  112. package/dist/logger/shared.d.ts +3 -3
  113. package/dist/logger/shared.d.ts.map +1 -1
  114. package/dist/logger/shared.js +5 -5
  115. package/dist/logger.d.ts +1 -1
  116. package/dist/logger.d.ts.map +1 -1
  117. package/dist/memQueue.d.ts +15 -0
  118. package/dist/memQueue.d.ts.map +1 -0
  119. package/dist/memQueue.js +21 -0
  120. package/dist/middlewares.d.ts +10 -0
  121. package/dist/middlewares.d.ts.map +1 -0
  122. package/dist/{api/middlewares.js → middlewares.js} +1 -1
  123. package/dist/mongo-client.d.ts +11 -0
  124. package/dist/mongo-client.d.ts.map +1 -0
  125. package/dist/mongo-client.js +15 -0
  126. package/dist/otel.d.ts +75 -0
  127. package/dist/otel.d.ts.map +1 -0
  128. package/dist/otel.js +65 -0
  129. package/dist/rateLimit.d.ts +12 -4
  130. package/dist/rateLimit.d.ts.map +1 -1
  131. package/dist/rateLimit.js +7 -12
  132. package/dist/redis-client.d.ts +42 -0
  133. package/dist/redis-client.d.ts.map +1 -0
  134. package/dist/redis-client.js +98 -0
  135. package/dist/reportError.d.ts +4 -0
  136. package/dist/reportError.d.ts.map +1 -0
  137. package/dist/reportError.js +28 -0
  138. package/dist/routing/middleware/RouterMiddleware.d.ts +16 -0
  139. package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  140. package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
  141. package/dist/routing/middleware/middleware.d.ts +48 -0
  142. package/dist/routing/middleware/middleware.d.ts.map +1 -0
  143. package/dist/routing/middleware/middleware.js +128 -0
  144. package/dist/routing/middleware.d.ts +3 -0
  145. package/dist/routing/middleware.d.ts.map +1 -0
  146. package/dist/{api/routing → routing}/middleware.js +1 -2
  147. package/dist/routing/schema/jwt.d.ts +4 -0
  148. package/dist/routing/schema/jwt.d.ts.map +1 -0
  149. package/dist/routing/schema/jwt.js +13 -0
  150. package/dist/routing/tsort.d.ts +8 -0
  151. package/dist/routing/tsort.d.ts.map +1 -0
  152. package/dist/routing/tsort.js +51 -0
  153. package/dist/routing/utils.d.ts +19 -0
  154. package/dist/routing/utils.d.ts.map +1 -0
  155. package/dist/routing/utils.js +45 -0
  156. package/dist/routing.d.ts +184 -0
  157. package/dist/routing.d.ts.map +1 -0
  158. package/dist/routing.js +236 -0
  159. package/dist/test.d.ts +3 -3
  160. package/dist/test.d.ts.map +1 -1
  161. package/dist/test.js +2 -2
  162. package/dist/util.d.ts +3 -0
  163. package/dist/util.d.ts.map +1 -0
  164. package/dist/util.js +14 -0
  165. package/dist/vitest.d.ts +1 -1
  166. package/examples/query.ts +47 -39
  167. package/package.json +119 -234
  168. package/src/CUPS.ts +52 -13
  169. package/src/{api/ContextProvider.ts → ContextProvider.ts} +19 -16
  170. package/src/Emailer/Sendgrid.ts +82 -59
  171. package/src/Emailer/fake.ts +3 -3
  172. package/src/MainFiberSet.ts +12 -10
  173. package/src/QueueMaker/SQLQueue.ts +153 -156
  174. package/src/QueueMaker/errors.ts +3 -1
  175. package/src/QueueMaker/memQueue.ts +113 -107
  176. package/src/QueueMaker/sbqueue.ts +78 -90
  177. package/src/RequestFiberSet.ts +13 -8
  178. package/src/{adapters/SQL → SQL}/Model.ts +42 -41
  179. package/src/ServiceBus.ts +219 -0
  180. package/src/Store/Cosmos/query.ts +216 -52
  181. package/src/Store/Cosmos.ts +493 -353
  182. package/src/Store/Disk.ts +109 -69
  183. package/src/Store/Memory.ts +365 -96
  184. package/src/Store/SQL/Pg.ts +363 -0
  185. package/src/Store/SQL/query.ts +603 -0
  186. package/src/Store/SQL.ts +735 -0
  187. package/src/Store/codeFilter.ts +8 -5
  188. package/src/Store/index.ts +21 -6
  189. package/src/Store/utils.ts +26 -24
  190. package/src/arbs.ts +5 -3
  191. package/src/{adapters/cosmos-client.ts → cosmos-client.ts} +5 -3
  192. package/src/errorReporter.ts +66 -76
  193. package/src/fileUtil.ts +1 -1
  194. package/src/index.ts +2 -1
  195. package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
  196. package/src/internal/auth.ts +272 -0
  197. package/src/{api/internal → internal}/events.ts +22 -13
  198. package/src/{api/layerUtils.ts → layerUtils.ts} +14 -10
  199. package/src/logger/jsonLogger.ts +4 -2
  200. package/src/logger/logFmtLogger.ts +2 -2
  201. package/src/logger/shared.ts +5 -4
  202. package/src/{adapters/memQueue.ts → memQueue.ts} +5 -4
  203. package/src/{adapters/mongo-client.ts → mongo-client.ts} +4 -2
  204. package/src/otel.ts +152 -0
  205. package/src/rateLimit.ts +34 -23
  206. package/src/{adapters/redis-client.ts → redis-client.ts} +7 -3
  207. package/src/{api/reportError.ts → reportError.ts} +3 -2
  208. package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +5 -4
  209. package/src/{api/routing → routing}/middleware/middleware.ts +62 -17
  210. package/src/routing/middleware.ts +4 -0
  211. package/src/{api/routing → routing}/schema/jwt.ts +2 -1
  212. package/src/{api/routing → routing}/utils.ts +2 -1
  213. package/src/routing.ts +768 -0
  214. package/src/test.ts +2 -2
  215. package/test/auth.test.ts +101 -0
  216. package/test/contextProvider.test.ts +15 -12
  217. package/test/controller.test.ts +28 -32
  218. package/test/cosmos-query.test.ts +159 -0
  219. package/test/dist/auth.test.d.ts.map +1 -0
  220. package/test/dist/contextProvider.test.d.ts.map +1 -1
  221. package/test/dist/controller.test.d.ts.map +1 -1
  222. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  223. package/test/dist/date-query.test.d.ts.map +1 -0
  224. package/test/dist/fixtures.d.ts +30 -12
  225. package/test/dist/fixtures.d.ts.map +1 -1
  226. package/test/dist/fixtures.js +17 -10
  227. package/test/dist/query.test.d.ts.map +1 -1
  228. package/test/dist/rawQuery.test.d.ts.map +1 -1
  229. package/test/dist/repository-ext.test.d.ts.map +1 -0
  230. package/test/dist/requires.test.d.ts.map +1 -1
  231. package/test/dist/router-generator.test.d.ts.map +1 -0
  232. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  233. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  234. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  235. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  236. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  237. package/test/dist/sql-store.test.d.ts.map +1 -0
  238. package/test/fixtures.ts +16 -9
  239. package/test/layerUtils.test.ts +2 -2
  240. package/test/query.test.ts +903 -40
  241. package/test/rawQuery.test.ts +340 -22
  242. package/test/repository-ext.test.ts +62 -0
  243. package/test/requires.test.ts +10 -5
  244. package/test/router-generator.test.ts +187 -0
  245. package/test/routing-interruptibility.test.ts +66 -0
  246. package/test/rpc-context-map-streaming.test.ts +262 -0
  247. package/test/rpc-e2e-invalidation.test.ts +256 -0
  248. package/test/rpc-multi-middleware.test.ts +85 -10
  249. package/test/rpc-stream-fullstack.test.ts +304 -0
  250. package/test/sql-store.test.ts +1711 -0
  251. package/test/validateSample.test.ts +19 -14
  252. package/tsconfig.examples.json +1 -1
  253. package/tsconfig.json +2 -1
  254. package/tsconfig.json.bak +2 -2
  255. package/tsconfig.src.json +35 -35
  256. package/tsconfig.test.json +2 -2
  257. package/dist/Emailer/service.d.ts +0 -55
  258. package/dist/Emailer/service.d.ts.map +0 -1
  259. package/dist/Emailer/service.js +0 -6
  260. package/dist/Emailer.d.ts +0 -2
  261. package/dist/Emailer.d.ts.map +0 -1
  262. package/dist/Emailer.js +0 -2
  263. package/dist/Model/Repository/ext.d.ts +0 -41
  264. package/dist/Model/Repository/ext.d.ts.map +0 -1
  265. package/dist/Model/Repository/ext.js +0 -65
  266. package/dist/Model/Repository/internal/internal.d.ts +0 -59
  267. package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
  268. package/dist/Model/Repository/internal/internal.js +0 -316
  269. package/dist/Model/Repository/legacy.d.ts +0 -19
  270. package/dist/Model/Repository/legacy.d.ts.map +0 -1
  271. package/dist/Model/Repository/legacy.js +0 -2
  272. package/dist/Model/Repository/makeRepo.d.ts +0 -49
  273. package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
  274. package/dist/Model/Repository/makeRepo.js +0 -24
  275. package/dist/Model/Repository/service.d.ts +0 -89
  276. package/dist/Model/Repository/service.d.ts.map +0 -1
  277. package/dist/Model/Repository/service.js +0 -2
  278. package/dist/Model/Repository/validation.d.ts +0 -42
  279. package/dist/Model/Repository/validation.d.ts.map +0 -1
  280. package/dist/Model/Repository/validation.js +0 -32
  281. package/dist/Model/Repository.d.ts +0 -6
  282. package/dist/Model/Repository.d.ts.map +0 -1
  283. package/dist/Model/Repository.js +0 -6
  284. package/dist/Model/dsl.d.ts +0 -32
  285. package/dist/Model/dsl.d.ts.map +0 -1
  286. package/dist/Model/dsl.js +0 -44
  287. package/dist/Model/filter/filterApi.d.ts +0 -30
  288. package/dist/Model/filter/filterApi.d.ts.map +0 -1
  289. package/dist/Model/filter/filterApi.js +0 -2
  290. package/dist/Model/filter/types/errors.d.ts +0 -29
  291. package/dist/Model/filter/types/errors.d.ts.map +0 -1
  292. package/dist/Model/filter/types/errors.js +0 -2
  293. package/dist/Model/filter/types/fields.d.ts +0 -15
  294. package/dist/Model/filter/types/fields.d.ts.map +0 -1
  295. package/dist/Model/filter/types/fields.js +0 -2
  296. package/dist/Model/filter/types/path/common.d.ts +0 -316
  297. package/dist/Model/filter/types/path/common.d.ts.map +0 -1
  298. package/dist/Model/filter/types/path/common.js +0 -2
  299. package/dist/Model/filter/types/path/eager.d.ts +0 -95
  300. package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
  301. package/dist/Model/filter/types/path/eager.js +0 -31
  302. package/dist/Model/filter/types/path/index.d.ts +0 -4
  303. package/dist/Model/filter/types/path/index.d.ts.map +0 -1
  304. package/dist/Model/filter/types/path/index.js +0 -3
  305. package/dist/Model/filter/types/utils.d.ts +0 -79
  306. package/dist/Model/filter/types/utils.d.ts.map +0 -1
  307. package/dist/Model/filter/types/utils.js +0 -2
  308. package/dist/Model/filter/types/validator.d.ts +0 -30
  309. package/dist/Model/filter/types/validator.d.ts.map +0 -1
  310. package/dist/Model/filter/types/validator.js +0 -2
  311. package/dist/Model/filter/types.d.ts +0 -5
  312. package/dist/Model/filter/types.d.ts.map +0 -1
  313. package/dist/Model/filter/types.js +0 -7
  314. package/dist/Model/query/dsl.d.ts +0 -248
  315. package/dist/Model/query/dsl.d.ts.map +0 -1
  316. package/dist/Model/query/dsl.js +0 -104
  317. package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
  318. package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
  319. package/dist/Model/query/new-kid-interpreter.js +0 -165
  320. package/dist/Model/query.d.ts +0 -15
  321. package/dist/Model/query.d.ts.map +0 -1
  322. package/dist/Model/query.js +0 -3
  323. package/dist/Model.d.ts +0 -4
  324. package/dist/Model.d.ts.map +0 -1
  325. package/dist/Model.js +0 -4
  326. package/dist/Operations.d.ts +0 -55
  327. package/dist/Operations.d.ts.map +0 -1
  328. package/dist/Operations.js +0 -102
  329. package/dist/OperationsRepo.d.ts +0 -41
  330. package/dist/OperationsRepo.d.ts.map +0 -1
  331. package/dist/OperationsRepo.js +0 -14
  332. package/dist/QueueMaker/service.d.ts +0 -11
  333. package/dist/QueueMaker/service.d.ts.map +0 -1
  334. package/dist/QueueMaker/service.js +0 -4
  335. package/dist/RequestContext.d.ts +0 -63
  336. package/dist/RequestContext.d.ts.map +0 -1
  337. package/dist/RequestContext.js +0 -49
  338. package/dist/Store/ContextMapContainer.d.ts +0 -14
  339. package/dist/Store/ContextMapContainer.d.ts.map +0 -1
  340. package/dist/Store/ContextMapContainer.js +0 -16
  341. package/dist/Store/service.d.ts +0 -108
  342. package/dist/Store/service.d.ts.map +0 -1
  343. package/dist/Store/service.js +0 -71
  344. package/dist/Store.d.ts +0 -2
  345. package/dist/Store.d.ts.map +0 -1
  346. package/dist/Store.js +0 -2
  347. package/dist/adapters/SQL/Model.d.ts +0 -479
  348. package/dist/adapters/SQL/Model.d.ts.map +0 -1
  349. package/dist/adapters/SQL/Model.js +0 -478
  350. package/dist/adapters/SQL.d.ts +0 -2
  351. package/dist/adapters/SQL.d.ts.map +0 -1
  352. package/dist/adapters/ServiceBus.d.ts +0 -58
  353. package/dist/adapters/ServiceBus.d.ts.map +0 -1
  354. package/dist/adapters/ServiceBus.js +0 -99
  355. package/dist/adapters/cosmos-client.d.ts +0 -14
  356. package/dist/adapters/cosmos-client.d.ts.map +0 -1
  357. package/dist/adapters/cosmos-client.js +0 -9
  358. package/dist/adapters/index.d.ts +0 -2
  359. package/dist/adapters/index.d.ts.map +0 -1
  360. package/dist/adapters/index.js +0 -2
  361. package/dist/adapters/logger.d.ts +0 -9
  362. package/dist/adapters/logger.d.ts.map +0 -1
  363. package/dist/adapters/logger.js +0 -3
  364. package/dist/adapters/memQueue.d.ts +0 -13
  365. package/dist/adapters/memQueue.d.ts.map +0 -1
  366. package/dist/adapters/memQueue.js +0 -20
  367. package/dist/adapters/mongo-client.d.ts +0 -10
  368. package/dist/adapters/mongo-client.d.ts.map +0 -1
  369. package/dist/adapters/mongo-client.js +0 -13
  370. package/dist/adapters/redis-client.d.ts +0 -39
  371. package/dist/adapters/redis-client.d.ts.map +0 -1
  372. package/dist/adapters/redis-client.js +0 -94
  373. package/dist/api/ContextProvider.d.ts +0 -31
  374. package/dist/api/ContextProvider.d.ts.map +0 -1
  375. package/dist/api/ContextProvider.js +0 -38
  376. package/dist/api/codec.d.ts +0 -5
  377. package/dist/api/codec.d.ts.map +0 -1
  378. package/dist/api/codec.js +0 -5
  379. package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
  380. package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
  381. package/dist/api/internal/RequestContextMiddleware.js +0 -35
  382. package/dist/api/internal/auth.d.ts +0 -15
  383. package/dist/api/internal/auth.d.ts.map +0 -1
  384. package/dist/api/internal/auth.js +0 -47
  385. package/dist/api/internal/events.d.ts +0 -9
  386. package/dist/api/internal/events.d.ts.map +0 -1
  387. package/dist/api/internal/events.js +0 -42
  388. package/dist/api/internal/health.d.ts +0 -3
  389. package/dist/api/internal/health.d.ts.map +0 -1
  390. package/dist/api/internal/health.js +0 -5
  391. package/dist/api/layerUtils.d.ts +0 -24
  392. package/dist/api/layerUtils.d.ts.map +0 -1
  393. package/dist/api/layerUtils.js +0 -16
  394. package/dist/api/middlewares.d.ts +0 -10
  395. package/dist/api/middlewares.d.ts.map +0 -1
  396. package/dist/api/reportError.d.ts +0 -4
  397. package/dist/api/reportError.d.ts.map +0 -1
  398. package/dist/api/reportError.js +0 -27
  399. package/dist/api/routing/middleware/RouterMiddleware.d.ts +0 -15
  400. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
  401. package/dist/api/routing/middleware/middleware.d.ts +0 -9
  402. package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
  403. package/dist/api/routing/middleware/middleware.js +0 -92
  404. package/dist/api/routing/middleware.d.ts +0 -4
  405. package/dist/api/routing/middleware.d.ts.map +0 -1
  406. package/dist/api/routing/schema/jwt.d.ts +0 -4
  407. package/dist/api/routing/schema/jwt.d.ts.map +0 -1
  408. package/dist/api/routing/schema/jwt.js +0 -12
  409. package/dist/api/routing/tsort.d.ts +0 -8
  410. package/dist/api/routing/tsort.d.ts.map +0 -1
  411. package/dist/api/routing/tsort.js +0 -51
  412. package/dist/api/routing/utils.d.ts +0 -19
  413. package/dist/api/routing/utils.d.ts.map +0 -1
  414. package/dist/api/routing/utils.js +0 -44
  415. package/dist/api/routing.d.ts +0 -138
  416. package/dist/api/routing.d.ts.map +0 -1
  417. package/dist/api/routing.js +0 -166
  418. package/dist/api/setupRequest.d.ts +0 -12
  419. package/dist/api/setupRequest.d.ts.map +0 -1
  420. package/dist/api/setupRequest.js +0 -44
  421. package/dist/api/util.d.ts +0 -3
  422. package/dist/api/util.d.ts.map +0 -1
  423. package/dist/api/util.js +0 -14
  424. package/eslint.config.mjs +0 -24
  425. package/src/Emailer/service.ts +0 -52
  426. package/src/Emailer.ts +0 -1
  427. package/src/Model/Repository/ext.ts +0 -283
  428. package/src/Model/Repository/internal/internal.ts +0 -577
  429. package/src/Model/Repository/legacy.ts +0 -27
  430. package/src/Model/Repository/makeRepo.ts +0 -139
  431. package/src/Model/Repository/service.ts +0 -627
  432. package/src/Model/Repository/validation.ts +0 -31
  433. package/src/Model/Repository.ts +0 -5
  434. package/src/Model/dsl.ts +0 -128
  435. package/src/Model/filter/filterApi.ts +0 -60
  436. package/src/Model/filter/types/errors.ts +0 -47
  437. package/src/Model/filter/types/fields.ts +0 -50
  438. package/src/Model/filter/types/path/common.ts +0 -404
  439. package/src/Model/filter/types/path/eager.ts +0 -298
  440. package/src/Model/filter/types/path/index.ts +0 -4
  441. package/src/Model/filter/types/utils.ts +0 -128
  442. package/src/Model/filter/types/validator.ts +0 -46
  443. package/src/Model/filter/types.ts +0 -6
  444. package/src/Model/query/dsl.ts +0 -2110
  445. package/src/Model/query/new-kid-interpreter.ts +0 -210
  446. package/src/Model/query.ts +0 -13
  447. package/src/Model.ts +0 -3
  448. package/src/Operations.ts +0 -235
  449. package/src/OperationsRepo.ts +0 -16
  450. package/src/QueueMaker/service.ts +0 -17
  451. package/src/RequestContext.ts +0 -63
  452. package/src/Store/ContextMapContainer.ts +0 -20
  453. package/src/Store/service.ts +0 -184
  454. package/src/Store.ts +0 -1
  455. package/src/adapters/ServiceBus.ts +0 -209
  456. package/src/adapters/index.ts +0 -0
  457. package/src/adapters/logger.ts +0 -3
  458. package/src/api/internal/auth.ts +0 -68
  459. package/src/api/routing/middleware.ts +0 -6
  460. package/src/api/routing.ts +0 -598
  461. package/src/api/setupRequest.ts +0 -84
  462. /package/src/{adapters/SQL.ts → SQL.ts} +0 -0
  463. /package/src/{api/codec.ts → codec.ts} +0 -0
  464. /package/src/{api/internal → internal}/health.ts +0 -0
  465. /package/src/{api/middlewares.ts → middlewares.ts} +0 -0
  466. /package/src/{api/routing → routing}/tsort.ts +0 -0
  467. /package/src/{api/util.ts → util.ts} +0 -0
@@ -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"))
@@ -1,6 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Effect, type Layer, type NonEmptyReadonlyArray, Option, ServiceMap } from "effect-app"
3
- import { InfraLogger } from "../logger.js"
2
+ import type { NonEmptyReadonlyArray } from "effect-app/Array"
3
+ import * as Context from "effect-app/Context"
4
+ import * as Effect from "effect-app/Effect"
5
+ import type * as Layer from "effect-app/Layer"
6
+ import * as Option from "effect-app/Option"
7
+ import { InfraLogger } from "./logger.js"
4
8
 
5
9
  // TODO: These LayerUtils are flaky, like in dependencies as a readonly array, it breaks when there are two entries
6
10
  // we should look at Service.MakeDeps[E/RIn/ROut] etc.
@@ -27,38 +31,38 @@ export namespace LayerUtils {
27
31
  }
28
32
 
29
33
  export type ContextTagWithDefault<Id, A, LayerE, LayerR> =
30
- & ServiceMap.Service<Id, A>
34
+ & Context.Service<Id, A>
31
35
  & {
32
36
  Default: Layer.Layer<Id, LayerE, LayerR>
33
37
  }
34
38
 
35
39
  export namespace ContextTagWithDefault {
36
- export type Base<A> = ContextTagWithDefault<any, A, any, any>
40
+ export type Base<A> = { readonly Service: A } & { Default: Layer.Layer<any, any, any> }
37
41
  }
38
42
 
39
- export type GetContext<T> = T extends ServiceMap.ServiceMap<infer Y> ? Y : never
43
+ export type GetContext<T> = T extends Context.Context<infer Y> ? Y : never
40
44
 
41
45
  export const mergeContexts = Effect.fnUntraced(
42
46
  function*<
43
47
  T extends readonly {
44
48
  maker: any
45
- handle: Effect.Effect<ServiceMap.ServiceMap<any> | Option.Option<ServiceMap.ServiceMap<any>>>
49
+ handle: Effect.Effect<Context.Context<any> | Option.Option<Context.Context<any>>>
46
50
  }[]
47
51
  >(
48
52
  makers: T
49
53
  ) {
50
- let context = ServiceMap.empty()
54
+ let context = Context.empty()
51
55
  for (const mw of makers) {
52
56
  const ctx = yield* mw.handle.pipe(Effect.provide(context))
53
- const moreContext = ServiceMap.isServiceMap(ctx) ? Option.some(ctx) : ctx
57
+ const moreContext = Context.isContext(ctx) ? Option.some(ctx) : ctx
54
58
  yield* InfraLogger.logDebug(
55
59
  "Built dynamic context for middleware" + (mw.maker.key ?? mw.maker),
56
60
  Option.map(moreContext, (c) => (c as any).toJSON().services)
57
61
  )
58
62
  if (moreContext.value) {
59
- context = ServiceMap.merge(context, moreContext.value)
63
+ context = Context.merge(context, moreContext.value)
60
64
  }
61
65
  }
62
- return context as ServiceMap.ServiceMap<Effect.Success<T[number]["handle"]>>
66
+ return context as Context.Context<Effect.Success<T[number]["handle"]>>
63
67
  }
64
68
  )
@@ -1,6 +1,8 @@
1
- import { Array, Cause, Logger } from "effect-app"
1
+ import * as Array from "effect-app/Array"
2
+ import { spanAttributes } from "effect-app/RequestContext"
3
+ import * as Cause from "effect/Cause"
4
+ import * as Logger from "effect/Logger"
2
5
  import { CurrentLogAnnotations, CurrentLogSpans } from "effect/References"
3
- import { spanAttributes } from "../RequestContext.js"
4
6
  import { getRequestContextFromFiber } from "./shared.js"
5
7
 
6
8
  export const jsonLogger = Logger.make<unknown, void>(
@@ -1,5 +1,5 @@
1
- import { Logger } from "effect-app"
2
- import { spanAttributes } from "../RequestContext.js"
1
+ import { spanAttributes } from "effect-app/RequestContext"
2
+ import * as Logger from "effect/Logger"
3
3
  import { getRequestContextFromFiber } from "./shared.js"
4
4
 
5
5
  export const logfmtLogger = Logger.make<unknown, void>(
@@ -1,13 +1,14 @@
1
- import { type Fiber, Option } from "effect-app"
1
+ import * as Option from "effect-app/Option"
2
+ import { LocaleRef, RequestContext } from "effect-app/RequestContext"
2
3
  import { NonEmptyString255 } from "effect-app/Schema"
3
- import { LocaleRef, RequestContext } from "../RequestContext.js"
4
- import { storeId } from "../Store/Memory.js"
4
+ import { storeId } from "effect-app/Store"
5
+ import type * as Fiber from "effect/Fiber"
5
6
 
6
7
  export function getRequestContextFromFiber(fiber: Fiber.Fiber<unknown, unknown>) {
7
8
  const span = Option.fromNullishOr(fiber.currentSpan)
8
9
  const locale = fiber.getRef(LocaleRef)
9
10
  const namespace = fiber.getRef(storeId)
10
- return new RequestContext({
11
+ return RequestContext.make({
11
12
  span: Option.map(span, (s) => ({ spanId: s.spanId, traceId: s.traceId, sampled: s.sampled })).pipe(
12
13
  Option.getOrElse(() => ({ spanId: "bogus", sampled: true, traceId: "bogus" }))
13
14
  ),
@@ -1,5 +1,6 @@
1
- import { Effect, type Queue, ServiceMap } from "effect-app"
2
- import * as Q from "effect/Queue"
1
+ import * as Context from "effect-app/Context"
2
+ import * as Effect from "effect-app/Effect"
3
+ import * as Queue from "effect/Queue"
3
4
 
4
5
  const make = Effect
5
6
  .gen(function*() {
@@ -9,13 +10,13 @@ const make = Effect
9
10
  getOrCreateQueue: Effect.fnUntraced(function*(k: string) {
10
11
  const q = store.get(k)
11
12
  if (q) return q
12
- const newQ = yield* Q.unbounded<string>()
13
+ const newQ = yield* Queue.unbounded<string>()
13
14
  store.set(k, newQ)
14
15
  return newQ
15
16
  })
16
17
  }
17
18
  })
18
19
 
19
- export class MemQueue extends ServiceMap.Opaque<MemQueue>()("effect-app/MemQueue", { make }) {
20
+ export class MemQueue extends Context.Opaque<MemQueue>()("effect-app/MemQueue", { make }) {
20
21
  static readonly Live = this.toLayer(this.make)
21
22
  }
@@ -1,4 +1,6 @@
1
- import { Effect, Layer, ServiceMap } from "effect-app"
1
+ import * as Context from "effect-app/Context"
2
+ import * as Effect from "effect-app/Effect"
3
+ import * as Layer from "effect-app/Layer"
2
4
  import { MongoClient as MongoClient_ } from "mongodb"
3
5
 
4
6
  // TODO: we should probably share a single client...
@@ -15,7 +17,7 @@ const withClient = (url: string) =>
15
17
 
16
18
  const makeMongoClient = (url: string, dbName?: string) => Effect.map(withClient(url), (x) => ({ db: x.db(dbName) }))
17
19
 
18
- export class MongoClient extends ServiceMap.Service<MongoClient, {
20
+ export class MongoClient extends Context.Service<MongoClient, {
19
21
  readonly db: ReturnType<InstanceType<typeof MongoClient_>["db"]>
20
22
  }>()("@services/MongoClient") {}
21
23
 
package/src/otel.ts ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * OpenTelemetry semantic-convention helpers for span attributes.
3
+ *
4
+ * Aligns repository / queue / cache adapters with stable OTel semconv keys so
5
+ * downstream collectors and dashboards work without per-adapter mappings.
6
+ *
7
+ * - Database: https://opentelemetry.io/docs/specs/semconv/database/
8
+ * - Messaging: https://opentelemetry.io/docs/specs/semconv/messaging/
9
+ * - Cosmos DB: https://opentelemetry.io/docs/specs/semconv/database/cosmosdb/
10
+ */
11
+
12
+ import * as Effect from "effect-app/Effect"
13
+
14
+ export type DbSystem =
15
+ | "postgresql"
16
+ | "sqlite"
17
+ | "cosmosdb"
18
+ | "mongodb"
19
+ | "redis"
20
+ | "other_sql"
21
+ | "memory"
22
+ | "disk"
23
+
24
+ export interface DbSpanOptions {
25
+ /** OTel `db.operation.name` (e.g. `find`, `all`, `filter`, `set`). */
26
+ readonly operation: string
27
+ readonly system: DbSystem
28
+ /** Logical collection / table / container name. */
29
+ readonly collection: string
30
+ /** Tenant / namespace / database name. */
31
+ readonly namespace?: string | undefined
32
+ /** Application-level entity / model name (custom: `app.entity`). */
33
+ readonly entity?: string | undefined
34
+ /** Sanitized / parameterized query text. Never include bound values. */
35
+ readonly query?: string | undefined
36
+ /** Optional fragments merged into final attributes (e.g. id, partition). */
37
+ readonly extra?: Record<string, unknown> | undefined
38
+ }
39
+
40
+ const dbAttributes = (a: DbSpanOptions): Record<string, unknown> => ({
41
+ "db.system.name": a.system,
42
+ "db.operation.name": a.operation,
43
+ "db.collection.name": a.collection,
44
+ ...(a.namespace !== undefined && { "db.namespace": a.namespace }),
45
+ ...(a.query !== undefined && { "db.query.text": a.query }),
46
+ ...(a.entity !== undefined && { "app.entity": a.entity }),
47
+ ...a.extra
48
+ })
49
+
50
+ /**
51
+ * Wrap an effect with an OTel-semconv database span.
52
+ *
53
+ * Span name follows the low-cardinality convention: `<operation> <collection>`.
54
+ */
55
+ export const withDbSpan = (a: DbSpanOptions) =>
56
+ Effect.withSpan(
57
+ `${a.operation} ${a.collection}`,
58
+ { attributes: dbAttributes(a), kind: "client" as const },
59
+ { captureStackTrace: false }
60
+ )
61
+
62
+ /**
63
+ * Annotate the current span with OTel-semconv database attributes.
64
+ *
65
+ * Use when the caller already owns the span (e.g. a repository) and the
66
+ * adapter should only contribute db.* semconv attrs without opening a child.
67
+ * Annotates before running so attrs persist even on failure.
68
+ * No-op if there is no current span.
69
+ */
70
+ export const annotateDb = (a: DbSpanOptions) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
71
+ Effect.flatMap(Effect.annotateCurrentSpan(dbAttributes(a)), () => self)
72
+
73
+ /** Annotate the current span with response metrics from a DB call. */
74
+ export const annotateDbResponse = (m: {
75
+ readonly returnedRows?: number | undefined
76
+ readonly responseBytes?: number | undefined
77
+ }) =>
78
+ Effect.annotateCurrentSpan({
79
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
80
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
81
+ })
82
+
83
+ /** Cosmos-specific response annotations. */
84
+ export const annotateCosmosResponse = (m: {
85
+ readonly requestCharge?: number | undefined
86
+ readonly returnedRows?: number | undefined
87
+ readonly responseBytes?: number | undefined
88
+ readonly statusCode?: number | undefined
89
+ }) =>
90
+ Effect.annotateCurrentSpan({
91
+ ...(m.requestCharge !== undefined && { "azure.cosmosdb.operation.request_charge": m.requestCharge }),
92
+ ...(m.statusCode !== undefined && { "db.response.status_code": String(m.statusCode) }),
93
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
94
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
95
+ })
96
+
97
+ export type MessagingSystem =
98
+ | "servicebus"
99
+ | "rabbitmq"
100
+ | "kafka"
101
+ | "memory"
102
+ | "sql"
103
+
104
+ export type MessagingOperation =
105
+ | "publish"
106
+ | "create"
107
+ | "receive"
108
+ | "process"
109
+ | "settle"
110
+
111
+ export interface MessagingSpanOptions {
112
+ readonly operation: MessagingOperation
113
+ readonly system: MessagingSystem
114
+ /** Queue / topic name. */
115
+ readonly destination: string
116
+ readonly messageId?: string | undefined
117
+ readonly conversationId?: string | undefined
118
+ readonly bodySize?: number | undefined
119
+ readonly extra?: Record<string, unknown> | undefined
120
+ }
121
+
122
+ const messagingAttributes = (a: MessagingSpanOptions): Record<string, unknown> => ({
123
+ "messaging.system": a.system,
124
+ "messaging.operation.name": a.operation,
125
+ "messaging.destination.name": a.destination,
126
+ ...(a.messageId !== undefined && { "messaging.message.id": a.messageId }),
127
+ ...(a.conversationId !== undefined && { "messaging.message.conversation_id": a.conversationId }),
128
+ ...(a.bodySize !== undefined && { "messaging.message.body.size": a.bodySize }),
129
+ ...a.extra
130
+ })
131
+
132
+ /** Wrap an effect with an OTel-semconv messaging span. */
133
+ export const withMessagingSpan = (
134
+ a: MessagingSpanOptions,
135
+ kind: "producer" | "consumer"
136
+ ) =>
137
+ Effect.withSpan(
138
+ `${a.operation} ${a.destination}`,
139
+ { kind, attributes: messagingAttributes(a) },
140
+ { captureStackTrace: false }
141
+ )
142
+
143
+ /** Build messaging span options without wrapping (for Effect.fn / setupRequestContextWithCustomSpan). */
144
+ export const messagingSpanArgs = (
145
+ a: MessagingSpanOptions,
146
+ kind: "producer" | "consumer"
147
+ ) =>
148
+ ({
149
+ name: `${a.operation} ${a.destination}`,
150
+ kind,
151
+ attributes: messagingAttributes(a)
152
+ }) as const