@effect-app/infra 4.0.0-beta.31 → 4.0.0-beta.310

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 (473) hide show
  1. package/CHANGELOG.md +2361 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +29 -10
  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 +547 -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 +110 -146
  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 +1 -1
  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 -8
  22. package/dist/MainFiberSet.d.ts.map +1 -1
  23. package/dist/MainFiberSet.js +23 -7
  24. package/dist/QueueMaker/errors.d.ts +4 -2
  25. package/dist/QueueMaker/errors.d.ts.map +1 -1
  26. package/dist/QueueMaker/errors.js +4 -2
  27. package/dist/{adapters/SQL → SQL}/Model.d.ts +31 -42
  28. package/dist/SQL/Model.d.ts.map +1 -0
  29. package/dist/SQL/Model.js +469 -0
  30. package/dist/SQL.d.ts.map +1 -0
  31. package/dist/{adapters/SQL.js → SQL.js} +1 -1
  32. package/dist/Store/Cosmos/query.d.ts +14 -3
  33. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  34. package/dist/Store/Cosmos/query.js +179 -41
  35. package/dist/Store/Cosmos.d.ts +2 -2
  36. package/dist/Store/Cosmos.d.ts.map +1 -1
  37. package/dist/Store/Cosmos.js +385 -254
  38. package/dist/Store/Disk.d.ts +4 -4
  39. package/dist/Store/Disk.d.ts.map +1 -1
  40. package/dist/Store/Disk.js +79 -39
  41. package/dist/Store/Memory.d.ts +5 -9
  42. package/dist/Store/Memory.d.ts.map +1 -1
  43. package/dist/Store/Memory.js +324 -67
  44. package/dist/Store/SQL/Pg.d.ts +4 -0
  45. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  46. package/dist/Store/SQL/Pg.js +253 -0
  47. package/dist/Store/SQL/query.d.ts +49 -0
  48. package/dist/Store/SQL/query.d.ts.map +1 -0
  49. package/dist/Store/SQL/query.js +527 -0
  50. package/dist/Store/SQL.d.ts +21 -0
  51. package/dist/Store/SQL.d.ts.map +1 -0
  52. package/dist/Store/SQL.js +472 -0
  53. package/dist/Store/codeFilter.d.ts +4 -4
  54. package/dist/Store/codeFilter.d.ts.map +1 -1
  55. package/dist/Store/codeFilter.js +6 -4
  56. package/dist/Store/index.d.ts +6 -4
  57. package/dist/Store/index.d.ts.map +1 -1
  58. package/dist/Store/index.js +18 -5
  59. package/dist/Store/utils.d.ts +5 -2
  60. package/dist/Store/utils.d.ts.map +1 -1
  61. package/dist/Store/utils.js +9 -5
  62. package/dist/WorkflowEngineCosmos.d.ts +29 -0
  63. package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
  64. package/dist/WorkflowEngineCosmos.js +542 -0
  65. package/dist/WorkflowEngineSqlite.d.ts +24 -0
  66. package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
  67. package/dist/WorkflowEngineSqlite.js +550 -0
  68. package/dist/arbs.d.ts +1 -1
  69. package/dist/arbs.d.ts.map +1 -1
  70. package/dist/arbs.js +5 -3
  71. package/dist/codec.d.ts.map +1 -0
  72. package/dist/codec.js +5 -0
  73. package/dist/{adapters/cosmos-client.d.ts → cosmos-client.d.ts} +4 -2
  74. package/dist/cosmos-client.d.ts.map +1 -0
  75. package/dist/cosmos-client.js +11 -0
  76. package/dist/errorReporter.d.ts +6 -4
  77. package/dist/errorReporter.d.ts.map +1 -1
  78. package/dist/errorReporter.js +23 -27
  79. package/dist/fileUtil.d.ts +1 -1
  80. package/dist/fileUtil.d.ts.map +1 -1
  81. package/dist/fileUtil.js +2 -2
  82. package/dist/index.d.ts +2 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +3 -2
  85. package/dist/internal/RequestContextMiddleware.d.ts +5 -0
  86. package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
  87. package/dist/internal/RequestContextMiddleware.js +45 -0
  88. package/dist/internal/auth.d.ts +53 -0
  89. package/dist/internal/auth.d.ts.map +1 -0
  90. package/dist/internal/auth.js +180 -0
  91. package/dist/internal/events.d.ts +11 -0
  92. package/dist/internal/events.d.ts.map +1 -0
  93. package/dist/internal/events.js +49 -0
  94. package/dist/internal/health.d.ts.map +1 -0
  95. package/dist/internal/health.js +5 -0
  96. package/dist/{api/layerUtils.d.ts → layerUtils.d.ts} +14 -6
  97. package/dist/layerUtils.d.ts.map +1 -0
  98. package/dist/layerUtils.js +17 -0
  99. package/dist/logger/jsonLogger.d.ts +1 -1
  100. package/dist/logger/jsonLogger.d.ts.map +1 -1
  101. package/dist/logger/jsonLogger.js +5 -3
  102. package/dist/logger/logFmtLogger.d.ts +1 -1
  103. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  104. package/dist/logger/logFmtLogger.js +3 -3
  105. package/dist/logger/shared.d.ts +2 -2
  106. package/dist/logger/shared.d.ts.map +1 -1
  107. package/dist/logger/shared.js +5 -5
  108. package/dist/logger.d.ts.map +1 -1
  109. package/dist/middlewares.d.ts.map +1 -0
  110. package/dist/{api/middlewares.js → middlewares.js} +1 -1
  111. package/dist/{adapters/mongo-client.d.ts → mongo-client.d.ts} +3 -2
  112. package/dist/mongo-client.d.ts.map +1 -0
  113. package/dist/mongo-client.js +15 -0
  114. package/dist/otel.d.ts +75 -0
  115. package/dist/otel.d.ts.map +1 -0
  116. package/dist/otel.js +84 -0
  117. package/dist/rateLimit.d.ts +11 -3
  118. package/dist/rateLimit.d.ts.map +1 -1
  119. package/dist/rateLimit.js +7 -12
  120. package/dist/{adapters/redis-client.d.ts → redis-client.d.ts} +5 -2
  121. package/dist/redis-client.d.ts.map +1 -0
  122. package/dist/redis-client.js +98 -0
  123. package/dist/{api/reportError.d.ts → reportError.d.ts} +1 -1
  124. package/dist/reportError.d.ts.map +1 -0
  125. package/dist/reportError.js +28 -0
  126. package/dist/{api/routing → routing}/middleware/RouterMiddleware.d.ts +4 -3
  127. package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  128. package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
  129. package/dist/routing/middleware/middleware.d.ts +48 -0
  130. package/dist/routing/middleware/middleware.d.ts.map +1 -0
  131. package/dist/routing/middleware/middleware.js +152 -0
  132. package/dist/{api/routing → routing}/middleware.d.ts +0 -1
  133. package/dist/routing/middleware.d.ts.map +1 -0
  134. package/dist/{api/routing → routing}/middleware.js +1 -2
  135. package/dist/routing/schema/jwt.d.ts.map +1 -0
  136. package/dist/routing/schema/jwt.js +13 -0
  137. package/dist/routing/tsort.d.ts.map +1 -0
  138. package/dist/routing/tsort.js +51 -0
  139. package/dist/{api/routing → routing}/utils.d.ts +3 -3
  140. package/dist/routing/utils.d.ts.map +1 -0
  141. package/dist/routing/utils.js +45 -0
  142. package/dist/routing.d.ts +182 -0
  143. package/dist/routing.d.ts.map +1 -0
  144. package/dist/routing.js +256 -0
  145. package/dist/test.d.ts +2 -2
  146. package/dist/test.d.ts.map +1 -1
  147. package/dist/test.js +2 -2
  148. package/dist/util.d.ts.map +1 -0
  149. package/dist/util.js +14 -0
  150. package/docs/cluster-storage.md +26 -0
  151. package/docs/workflow-engine.md +262 -0
  152. package/examples/query.ts +47 -39
  153. package/package.json +38 -352
  154. package/src/CUPS.ts +53 -14
  155. package/src/ClusterCosmos.ts +1118 -0
  156. package/src/ClusterServiceBus.ts +242 -0
  157. package/src/{api/ContextProvider.ts → ContextProvider.ts} +20 -17
  158. package/src/Emailer/Sendgrid.ts +83 -60
  159. package/src/Emailer/fake.ts +4 -4
  160. package/src/MainFiberSet.ts +32 -13
  161. package/src/QueueMaker/errors.ts +3 -1
  162. package/src/{adapters/SQL → SQL}/Model.ts +42 -41
  163. package/src/SQL.ts +1 -0
  164. package/src/Store/Cosmos/query.ts +218 -54
  165. package/src/Store/Cosmos.ts +529 -365
  166. package/src/Store/Disk.ts +112 -70
  167. package/src/Store/Memory.ts +365 -99
  168. package/src/Store/SQL/Pg.ts +389 -0
  169. package/src/Store/SQL/query.ts +603 -0
  170. package/src/Store/SQL.ts +766 -0
  171. package/src/Store/codeFilter.ts +8 -6
  172. package/src/Store/index.ts +25 -10
  173. package/src/Store/utils.ts +32 -25
  174. package/src/WorkflowEngineCosmos.ts +749 -0
  175. package/src/WorkflowEngineSqlite.ts +813 -0
  176. package/src/arbs.ts +5 -3
  177. package/src/{adapters/cosmos-client.ts → cosmos-client.ts} +5 -3
  178. package/src/errorReporter.ts +68 -78
  179. package/src/fileUtil.ts +1 -1
  180. package/src/index.ts +2 -1
  181. package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
  182. package/src/internal/auth.ts +272 -0
  183. package/src/{api/internal → internal}/events.ts +22 -13
  184. package/src/{api/layerUtils.ts → layerUtils.ts} +14 -10
  185. package/src/logger/jsonLogger.ts +5 -3
  186. package/src/logger/logFmtLogger.ts +3 -3
  187. package/src/logger/shared.ts +5 -4
  188. package/src/middlewares.ts +10 -0
  189. package/src/{adapters/mongo-client.ts → mongo-client.ts} +4 -2
  190. package/src/otel.ts +177 -0
  191. package/src/rateLimit.ts +34 -23
  192. package/src/{adapters/redis-client.ts → redis-client.ts} +7 -3
  193. package/src/{api/reportError.ts → reportError.ts} +3 -2
  194. package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +5 -4
  195. package/src/routing/middleware/middleware.ts +196 -0
  196. package/src/routing/middleware.ts +4 -0
  197. package/src/{api/routing → routing}/schema/jwt.ts +2 -1
  198. package/src/{api/routing → routing}/utils.ts +2 -1
  199. package/src/routing.ts +823 -0
  200. package/src/test.ts +4 -4
  201. package/src/vitest.ts +1 -1
  202. package/test/auth.test.ts +101 -0
  203. package/test/cluster-cosmos.test.ts +612 -0
  204. package/test/cluster-servicebus.test.ts +180 -0
  205. package/test/cluster-sqlite.test.ts +205 -0
  206. package/test/contextProvider.test.ts +15 -12
  207. package/test/controller.test.ts +28 -32
  208. package/test/cosmos-query.test.ts +228 -0
  209. package/test/dist/auth.test.d.ts.map +1 -0
  210. package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
  211. package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
  212. package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
  213. package/test/dist/contextProvider.test.d.ts.map +1 -1
  214. package/test/dist/controller.test.d.ts.map +1 -1
  215. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  216. package/test/dist/fixtures.d.ts +29 -11
  217. package/test/dist/fixtures.d.ts.map +1 -1
  218. package/test/dist/fixtures.js +17 -10
  219. package/test/dist/query.test.d.ts.map +1 -1
  220. package/test/dist/rawQuery.test.d.ts.map +1 -1
  221. package/test/dist/repository-ext.test.d.ts.map +1 -0
  222. package/test/dist/requires.test.d.ts.map +1 -1
  223. package/test/dist/router-generator.test.d.ts.map +1 -0
  224. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  225. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  226. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  227. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  228. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  229. package/test/dist/sql-store.test.d.ts.map +1 -0
  230. package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
  231. package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
  232. package/test/fixtures.ts +16 -9
  233. package/test/layerUtils.test.ts +2 -2
  234. package/test/query.test.ts +1130 -41
  235. package/test/rawQuery.test.ts +340 -22
  236. package/test/repository-ext.test.ts +426 -0
  237. package/test/requires.test.ts +10 -5
  238. package/test/router-generator.test.ts +187 -0
  239. package/test/routing-interruptibility.test.ts +66 -0
  240. package/test/rpc-context-map-streaming.test.ts +262 -0
  241. package/test/rpc-e2e-invalidation.test.ts +418 -0
  242. package/test/rpc-multi-middleware.test.ts +85 -10
  243. package/test/rpc-stream-fullstack.test.ts +304 -0
  244. package/test/sql-store.test.ts +1711 -0
  245. package/test/validateSample.test.ts +26 -14
  246. package/test/workflow-engine-cosmos.test.ts +345 -0
  247. package/test/workflow-engine-sqlite.test.ts +297 -0
  248. package/tsconfig.examples.json +1 -1
  249. package/tsconfig.json +9 -2
  250. package/tsconfig.src.json +35 -35
  251. package/tsconfig.test.json +2 -2
  252. package/dist/Emailer/service.d.ts +0 -55
  253. package/dist/Emailer/service.d.ts.map +0 -1
  254. package/dist/Emailer/service.js +0 -6
  255. package/dist/Emailer.d.ts +0 -2
  256. package/dist/Emailer.d.ts.map +0 -1
  257. package/dist/Emailer.js +0 -2
  258. package/dist/Model/Repository/ext.d.ts +0 -41
  259. package/dist/Model/Repository/ext.d.ts.map +0 -1
  260. package/dist/Model/Repository/ext.js +0 -65
  261. package/dist/Model/Repository/internal/internal.d.ts +0 -59
  262. package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
  263. package/dist/Model/Repository/internal/internal.js +0 -316
  264. package/dist/Model/Repository/legacy.d.ts +0 -19
  265. package/dist/Model/Repository/legacy.d.ts.map +0 -1
  266. package/dist/Model/Repository/legacy.js +0 -2
  267. package/dist/Model/Repository/makeRepo.d.ts +0 -49
  268. package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
  269. package/dist/Model/Repository/makeRepo.js +0 -24
  270. package/dist/Model/Repository/service.d.ts +0 -89
  271. package/dist/Model/Repository/service.d.ts.map +0 -1
  272. package/dist/Model/Repository/service.js +0 -2
  273. package/dist/Model/Repository/validation.d.ts +0 -42
  274. package/dist/Model/Repository/validation.d.ts.map +0 -1
  275. package/dist/Model/Repository/validation.js +0 -32
  276. package/dist/Model/Repository.d.ts +0 -6
  277. package/dist/Model/Repository.d.ts.map +0 -1
  278. package/dist/Model/Repository.js +0 -6
  279. package/dist/Model/dsl.d.ts +0 -32
  280. package/dist/Model/dsl.d.ts.map +0 -1
  281. package/dist/Model/dsl.js +0 -44
  282. package/dist/Model/filter/filterApi.d.ts +0 -30
  283. package/dist/Model/filter/filterApi.d.ts.map +0 -1
  284. package/dist/Model/filter/filterApi.js +0 -2
  285. package/dist/Model/filter/types/errors.d.ts +0 -29
  286. package/dist/Model/filter/types/errors.d.ts.map +0 -1
  287. package/dist/Model/filter/types/errors.js +0 -2
  288. package/dist/Model/filter/types/fields.d.ts +0 -15
  289. package/dist/Model/filter/types/fields.d.ts.map +0 -1
  290. package/dist/Model/filter/types/fields.js +0 -2
  291. package/dist/Model/filter/types/path/common.d.ts +0 -316
  292. package/dist/Model/filter/types/path/common.d.ts.map +0 -1
  293. package/dist/Model/filter/types/path/common.js +0 -2
  294. package/dist/Model/filter/types/path/eager.d.ts +0 -95
  295. package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
  296. package/dist/Model/filter/types/path/eager.js +0 -31
  297. package/dist/Model/filter/types/path/index.d.ts +0 -4
  298. package/dist/Model/filter/types/path/index.d.ts.map +0 -1
  299. package/dist/Model/filter/types/path/index.js +0 -3
  300. package/dist/Model/filter/types/utils.d.ts +0 -79
  301. package/dist/Model/filter/types/utils.d.ts.map +0 -1
  302. package/dist/Model/filter/types/utils.js +0 -2
  303. package/dist/Model/filter/types/validator.d.ts +0 -30
  304. package/dist/Model/filter/types/validator.d.ts.map +0 -1
  305. package/dist/Model/filter/types/validator.js +0 -2
  306. package/dist/Model/filter/types.d.ts +0 -5
  307. package/dist/Model/filter/types.d.ts.map +0 -1
  308. package/dist/Model/filter/types.js +0 -7
  309. package/dist/Model/query/dsl.d.ts +0 -248
  310. package/dist/Model/query/dsl.d.ts.map +0 -1
  311. package/dist/Model/query/dsl.js +0 -104
  312. package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
  313. package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
  314. package/dist/Model/query/new-kid-interpreter.js +0 -165
  315. package/dist/Model/query.d.ts +0 -15
  316. package/dist/Model/query.d.ts.map +0 -1
  317. package/dist/Model/query.js +0 -3
  318. package/dist/Model.d.ts +0 -4
  319. package/dist/Model.d.ts.map +0 -1
  320. package/dist/Model.js +0 -4
  321. package/dist/Operations.d.ts +0 -55
  322. package/dist/Operations.d.ts.map +0 -1
  323. package/dist/Operations.js +0 -102
  324. package/dist/OperationsRepo.d.ts +0 -41
  325. package/dist/OperationsRepo.d.ts.map +0 -1
  326. package/dist/OperationsRepo.js +0 -14
  327. package/dist/QueueMaker/SQLQueue.d.ts +0 -16
  328. package/dist/QueueMaker/SQLQueue.d.ts.map +0 -1
  329. package/dist/QueueMaker/SQLQueue.js +0 -130
  330. package/dist/QueueMaker/memQueue.d.ts +0 -11
  331. package/dist/QueueMaker/memQueue.d.ts.map +0 -1
  332. package/dist/QueueMaker/memQueue.js +0 -76
  333. package/dist/QueueMaker/sbqueue.d.ts +0 -12
  334. package/dist/QueueMaker/sbqueue.d.ts.map +0 -1
  335. package/dist/QueueMaker/sbqueue.js +0 -91
  336. package/dist/QueueMaker/service.d.ts +0 -11
  337. package/dist/QueueMaker/service.d.ts.map +0 -1
  338. package/dist/QueueMaker/service.js +0 -4
  339. package/dist/RequestContext.d.ts +0 -63
  340. package/dist/RequestContext.d.ts.map +0 -1
  341. package/dist/RequestContext.js +0 -49
  342. package/dist/RequestFiberSet.d.ts +0 -36
  343. package/dist/RequestFiberSet.d.ts.map +0 -1
  344. package/dist/RequestFiberSet.js +0 -78
  345. package/dist/Store/ContextMapContainer.d.ts +0 -14
  346. package/dist/Store/ContextMapContainer.d.ts.map +0 -1
  347. package/dist/Store/ContextMapContainer.js +0 -16
  348. package/dist/Store/service.d.ts +0 -108
  349. package/dist/Store/service.d.ts.map +0 -1
  350. package/dist/Store/service.js +0 -71
  351. package/dist/Store.d.ts +0 -2
  352. package/dist/Store.d.ts.map +0 -1
  353. package/dist/Store.js +0 -2
  354. package/dist/adapters/SQL/Model.d.ts.map +0 -1
  355. package/dist/adapters/SQL/Model.js +0 -478
  356. package/dist/adapters/SQL.d.ts.map +0 -1
  357. package/dist/adapters/ServiceBus.d.ts +0 -58
  358. package/dist/adapters/ServiceBus.d.ts.map +0 -1
  359. package/dist/adapters/ServiceBus.js +0 -99
  360. package/dist/adapters/cosmos-client.d.ts.map +0 -1
  361. package/dist/adapters/cosmos-client.js +0 -9
  362. package/dist/adapters/index.d.ts +0 -2
  363. package/dist/adapters/index.d.ts.map +0 -1
  364. package/dist/adapters/index.js +0 -2
  365. package/dist/adapters/logger.d.ts +0 -9
  366. package/dist/adapters/logger.d.ts.map +0 -1
  367. package/dist/adapters/logger.js +0 -3
  368. package/dist/adapters/memQueue.d.ts +0 -13
  369. package/dist/adapters/memQueue.d.ts.map +0 -1
  370. package/dist/adapters/memQueue.js +0 -20
  371. package/dist/adapters/mongo-client.d.ts.map +0 -1
  372. package/dist/adapters/mongo-client.js +0 -13
  373. package/dist/adapters/redis-client.d.ts.map +0 -1
  374. package/dist/adapters/redis-client.js +0 -94
  375. package/dist/api/ContextProvider.d.ts +0 -31
  376. package/dist/api/ContextProvider.d.ts.map +0 -1
  377. package/dist/api/ContextProvider.js +0 -38
  378. package/dist/api/codec.d.ts.map +0 -1
  379. package/dist/api/codec.js +0 -5
  380. package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
  381. package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
  382. package/dist/api/internal/RequestContextMiddleware.js +0 -35
  383. package/dist/api/internal/auth.d.ts +0 -15
  384. package/dist/api/internal/auth.d.ts.map +0 -1
  385. package/dist/api/internal/auth.js +0 -47
  386. package/dist/api/internal/events.d.ts +0 -9
  387. package/dist/api/internal/events.d.ts.map +0 -1
  388. package/dist/api/internal/events.js +0 -42
  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.map +0 -1
  392. package/dist/api/layerUtils.js +0 -16
  393. package/dist/api/middlewares.d.ts.map +0 -1
  394. package/dist/api/reportError.d.ts.map +0 -1
  395. package/dist/api/reportError.js +0 -27
  396. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
  397. package/dist/api/routing/middleware/middleware.d.ts +0 -9
  398. package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
  399. package/dist/api/routing/middleware/middleware.js +0 -92
  400. package/dist/api/routing/middleware.d.ts.map +0 -1
  401. package/dist/api/routing/schema/jwt.d.ts.map +0 -1
  402. package/dist/api/routing/schema/jwt.js +0 -12
  403. package/dist/api/routing/tsort.d.ts.map +0 -1
  404. package/dist/api/routing/tsort.js +0 -51
  405. package/dist/api/routing/utils.d.ts.map +0 -1
  406. package/dist/api/routing/utils.js +0 -44
  407. package/dist/api/routing.d.ts +0 -138
  408. package/dist/api/routing.d.ts.map +0 -1
  409. package/dist/api/routing.js +0 -166
  410. package/dist/api/setupRequest.d.ts +0 -12
  411. package/dist/api/setupRequest.d.ts.map +0 -1
  412. package/dist/api/setupRequest.js +0 -44
  413. package/dist/api/util.d.ts.map +0 -1
  414. package/dist/api/util.js +0 -14
  415. package/eslint.config.mjs +0 -24
  416. package/src/Emailer/service.ts +0 -52
  417. package/src/Emailer.ts +0 -1
  418. package/src/Model/Repository/ext.ts +0 -283
  419. package/src/Model/Repository/internal/internal.ts +0 -577
  420. package/src/Model/Repository/legacy.ts +0 -27
  421. package/src/Model/Repository/makeRepo.ts +0 -139
  422. package/src/Model/Repository/service.ts +0 -627
  423. package/src/Model/Repository/validation.ts +0 -31
  424. package/src/Model/Repository.ts +0 -5
  425. package/src/Model/dsl.ts +0 -128
  426. package/src/Model/filter/filterApi.ts +0 -60
  427. package/src/Model/filter/types/errors.ts +0 -47
  428. package/src/Model/filter/types/fields.ts +0 -50
  429. package/src/Model/filter/types/path/common.ts +0 -404
  430. package/src/Model/filter/types/path/eager.ts +0 -298
  431. package/src/Model/filter/types/path/index.ts +0 -4
  432. package/src/Model/filter/types/utils.ts +0 -128
  433. package/src/Model/filter/types/validator.ts +0 -46
  434. package/src/Model/filter/types.ts +0 -6
  435. package/src/Model/query/dsl.ts +0 -2110
  436. package/src/Model/query/new-kid-interpreter.ts +0 -210
  437. package/src/Model/query.ts +0 -13
  438. package/src/Model.ts +0 -3
  439. package/src/Operations.ts +0 -235
  440. package/src/OperationsRepo.ts +0 -16
  441. package/src/QueueMaker/SQLQueue.ts +0 -189
  442. package/src/QueueMaker/memQueue.ts +0 -130
  443. package/src/QueueMaker/sbqueue.ts +0 -137
  444. package/src/QueueMaker/service.ts +0 -17
  445. package/src/RequestContext.ts +0 -63
  446. package/src/RequestFiberSet.ts +0 -105
  447. package/src/Store/ContextMapContainer.ts +0 -20
  448. package/src/Store/index.test.ts.bak +0 -112
  449. package/src/Store/service.ts +0 -184
  450. package/src/Store.ts +0 -1
  451. package/src/adapters/SQL.ts +0 -1
  452. package/src/adapters/ServiceBus.ts +0 -209
  453. package/src/adapters/index.ts +0 -0
  454. package/src/adapters/logger.ts +0 -3
  455. package/src/adapters/memQueue.ts +0 -21
  456. package/src/api/internal/auth.ts +0 -68
  457. package/src/api/middlewares.ts +0 -10
  458. package/src/api/routing/middleware/middleware.ts +0 -128
  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/tsconfig.json.bak +0 -12
  463. /package/dist/{adapters/SQL.d.ts → SQL.d.ts} +0 -0
  464. /package/dist/{api/codec.d.ts → codec.d.ts} +0 -0
  465. /package/dist/{api/internal → internal}/health.d.ts +0 -0
  466. /package/dist/{api/middlewares.d.ts → middlewares.d.ts} +0 -0
  467. /package/dist/{api/routing → routing}/schema/jwt.d.ts +0 -0
  468. /package/dist/{api/routing → routing}/tsort.d.ts +0 -0
  469. /package/dist/{api/util.d.ts → util.d.ts} +0 -0
  470. /package/src/{api/codec.ts → codec.ts} +0 -0
  471. /package/src/{api/internal → internal}/health.ts +0 -0
  472. /package/src/{api/routing → routing}/tsort.ts +0 -0
  473. /package/src/{api/util.ts → util.ts} +0 -0
@@ -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.ts"
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,7 +1,9 @@
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
- import { getRequestContextFromFiber } from "./shared.js"
6
+ import { getRequestContextFromFiber } from "./shared.ts"
5
7
 
6
8
  export const jsonLogger = Logger.make<unknown, void>(
7
9
  ({ cause, date, fiber, logLevel, message }) => {
@@ -1,6 +1,6 @@
1
- import { Logger } from "effect-app"
2
- import { spanAttributes } from "../RequestContext.js"
3
- import { getRequestContextFromFiber } from "./shared.js"
1
+ import { spanAttributes } from "effect-app/RequestContext"
2
+ import * as Logger from "effect/Logger"
3
+ import { getRequestContextFromFiber } from "./shared.ts"
4
4
 
5
5
  export const logfmtLogger = Logger.make<unknown, void>(
6
6
  (options) => {
@@ -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
  ),
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Mechanism for extendning behaviour of all handlers on the server.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+
7
+ export * from "./internal/auth.ts"
8
+ export * from "./internal/events.ts"
9
+ export * from "./internal/health.ts"
10
+ export * from "./internal/RequestContextMiddleware.ts"
@@ -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,177 @@
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
+ import * as Metric from "effect/Metric"
14
+
15
+ export type DbSystem =
16
+ | "postgresql"
17
+ | "sqlite"
18
+ | "cosmosdb"
19
+ | "mongodb"
20
+ | "redis"
21
+ | "other_sql"
22
+ | "memory"
23
+ | "disk"
24
+
25
+ export interface DbSpanOptions {
26
+ /** OTel `db.operation.name` (e.g. `find`, `all`, `filter`, `set`). */
27
+ readonly operation: string
28
+ readonly system: DbSystem
29
+ /** Logical collection / table / container name. */
30
+ readonly collection: string
31
+ /** Tenant / namespace / database name. */
32
+ readonly namespace?: string | undefined
33
+ /** Application-level entity / model name (custom: `app.entity`). */
34
+ readonly entity?: string | undefined
35
+ /** Sanitized / parameterized query text. Never include bound values. */
36
+ readonly query?: string | undefined
37
+ /** Optional fragments merged into final attributes (e.g. id, partition). */
38
+ readonly extra?: Record<string, unknown> | undefined
39
+ }
40
+
41
+ const dbAttributes = (a: DbSpanOptions): Record<string, unknown> => ({
42
+ "db.system.name": a.system,
43
+ "db.operation.name": a.operation,
44
+ "db.collection.name": a.collection,
45
+ ...(a.namespace !== undefined && { "db.namespace": a.namespace }),
46
+ ...(a.query !== undefined && { "db.query.text": a.query }),
47
+ ...(a.entity !== undefined && { "app.entity": a.entity }),
48
+ ...a.extra
49
+ })
50
+
51
+ const dbOperationDuration = Metric.histogram("db.client.operation.duration", {
52
+ boundaries: [0.1, 0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000, 10_000],
53
+ description: "Caller-observed database operation duration in milliseconds"
54
+ })
55
+
56
+ const timeDbOperation = (a: DbSpanOptions) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
57
+ Effect.clockWith((clock) => {
58
+ const startedAt = clock.currentTimeNanosUnsafe()
59
+ return Effect.onExit(self, () => {
60
+ const durationMs = Number(clock.currentTimeNanosUnsafe() - startedAt) / 1_000_000
61
+ return Effect.all([
62
+ Effect.annotateCurrentSpan({ "db.operation.duration_ms": durationMs }),
63
+ Metric.update(
64
+ Metric.withAttributes(dbOperationDuration, {
65
+ "db.system.name": a.system,
66
+ "db.operation.name": a.operation,
67
+ ...(a.entity !== undefined && { "app.entity": a.entity })
68
+ }),
69
+ durationMs
70
+ )
71
+ ], { discard: true })
72
+ })
73
+ })
74
+
75
+ /**
76
+ * Wrap an effect with an OTel-semconv database span.
77
+ *
78
+ * Span name follows the low-cardinality convention: `<operation> <collection>`.
79
+ */
80
+ export const withDbSpan = (a: DbSpanOptions) =>
81
+ Effect.withSpan(
82
+ `${a.operation} ${a.collection}`,
83
+ { attributes: dbAttributes(a), kind: "client" as const },
84
+ { captureStackTrace: false }
85
+ )
86
+
87
+ /**
88
+ * Annotate the current span with OTel-semconv database attributes.
89
+ *
90
+ * Use when the caller already owns the span (e.g. a repository) and the
91
+ * adapter should only contribute db.* semconv attrs without opening a child.
92
+ * Annotates before running so attrs persist even on failure.
93
+ * No-op if there is no current span.
94
+ */
95
+ export const annotateDb = (a: DbSpanOptions) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
96
+ Effect.flatMap(Effect.annotateCurrentSpan(dbAttributes(a)), () => self.pipe(timeDbOperation(a)))
97
+
98
+ /** Annotate the current span with response metrics from a DB call. */
99
+ export const annotateDbResponse = (m: {
100
+ readonly returnedRows?: number | undefined
101
+ readonly responseBytes?: number | undefined
102
+ }) =>
103
+ Effect.annotateCurrentSpan({
104
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
105
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
106
+ })
107
+
108
+ /** Cosmos-specific response annotations. */
109
+ export const annotateCosmosResponse = (m: {
110
+ readonly requestCharge?: number | undefined
111
+ readonly returnedRows?: number | undefined
112
+ readonly responseBytes?: number | undefined
113
+ readonly statusCode?: number | undefined
114
+ }) =>
115
+ Effect.annotateCurrentSpan({
116
+ ...(m.requestCharge !== undefined && { "azure.cosmosdb.operation.request_charge": m.requestCharge }),
117
+ ...(m.statusCode !== undefined && { "db.response.status_code": String(m.statusCode) }),
118
+ ...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
119
+ ...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
120
+ })
121
+
122
+ export type MessagingSystem =
123
+ | "servicebus"
124
+ | "rabbitmq"
125
+ | "kafka"
126
+ | "memory"
127
+ | "sql"
128
+
129
+ export type MessagingOperation =
130
+ | "publish"
131
+ | "create"
132
+ | "receive"
133
+ | "process"
134
+ | "settle"
135
+
136
+ export interface MessagingSpanOptions {
137
+ readonly operation: MessagingOperation
138
+ readonly system: MessagingSystem
139
+ /** Queue / topic name. */
140
+ readonly destination: string
141
+ readonly messageId?: string | undefined
142
+ readonly conversationId?: string | undefined
143
+ readonly bodySize?: number | undefined
144
+ readonly extra?: Record<string, unknown> | undefined
145
+ }
146
+
147
+ const messagingAttributes = (a: MessagingSpanOptions): Record<string, unknown> => ({
148
+ "messaging.system": a.system,
149
+ "messaging.operation.name": a.operation,
150
+ "messaging.destination.name": a.destination,
151
+ ...(a.messageId !== undefined && { "messaging.message.id": a.messageId }),
152
+ ...(a.conversationId !== undefined && { "messaging.message.conversation_id": a.conversationId }),
153
+ ...(a.bodySize !== undefined && { "messaging.message.body.size": a.bodySize }),
154
+ ...a.extra
155
+ })
156
+
157
+ /** Wrap an effect with an OTel-semconv messaging span. */
158
+ export const withMessagingSpan = (
159
+ a: MessagingSpanOptions,
160
+ kind: "producer" | "consumer"
161
+ ) =>
162
+ Effect.withSpan(
163
+ `${a.operation} ${a.destination}`,
164
+ { kind, attributes: messagingAttributes(a) },
165
+ { captureStackTrace: false }
166
+ )
167
+
168
+ /** Build messaging span options without wrapping (for Effect.fn / setupRequestContextWithCustomSpan). */
169
+ export const messagingSpanArgs = (
170
+ a: MessagingSpanOptions,
171
+ kind: "producer" | "consumer"
172
+ ) =>
173
+ ({
174
+ name: `${a.operation} ${a.destination}`,
175
+ kind,
176
+ attributes: messagingAttributes(a)
177
+ }) as const
package/src/rateLimit.ts CHANGED
@@ -20,8 +20,13 @@
20
20
  // }
21
21
  // }
22
22
 
23
- import { Array, type Duration, Effect, type NonEmptyArray } from "effect-app"
23
+ import * as Array from "effect-app/Array"
24
+ import type { NonEmptyArray } from "effect-app/Array"
25
+ import * as Effect from "effect-app/Effect"
26
+ import { dual } from "effect-app/Function"
27
+ import type * as Duration from "effect/Duration"
24
28
  import type { Semaphore } from "effect/Semaphore"
29
+ import type { Concurrency } from "effect/Types"
25
30
 
26
31
  /**
27
32
  * Executes the specified effect, acquiring the specified number of permits
@@ -45,36 +50,42 @@ export function SEM_withPermitsDuration(permits: number, duration: Duration.Dura
45
50
  }
46
51
  }
47
52
 
48
- export function batchPar<R, E, A, R2, E2, A2, T>(
49
- n: number,
50
- forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
51
- forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>
52
- ) {
53
- return (items: Iterable<T>) =>
54
- Effect.forEach(
55
- Array.chunksOf(items, n),
56
- (_, i) =>
57
- Effect
58
- .forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: "inherit" })
59
- .pipe(Effect.flatMap((_) => forEachBatch(_, i))),
60
- { concurrency: "inherit" }
61
- )
53
+ export interface BatchOptions {
54
+ readonly concurrency?: Concurrency | undefined
62
55
  }
63
56
 
64
- export function batch<R, E, A, R2, E2, A2, T>(
65
- n: number,
66
- forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
67
- forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>
68
- ) {
69
- return (items: Iterable<T>) =>
57
+ export const batch: {
58
+ <T, A, E, R, A2, E2, R2>(
59
+ n: number,
60
+ forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
61
+ forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
62
+ options?: BatchOptions
63
+ ): (items: Iterable<T>) => Effect.Effect<Array<A2>, E | E2, R | R2>
64
+ <T, A, E, R, A2, E2, R2>(
65
+ items: Iterable<T>,
66
+ n: number,
67
+ forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
68
+ forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
69
+ options?: BatchOptions
70
+ ): Effect.Effect<Array<A2>, E | E2, R | R2>
71
+ } = dual(
72
+ (args) => typeof args[0] !== "number",
73
+ <T, A, E, R, A2, E2, R2>(
74
+ items: Iterable<T>,
75
+ n: number,
76
+ forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
77
+ forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
78
+ options?: BatchOptions
79
+ ) =>
70
80
  Effect.forEach(
71
81
  Array.chunksOf(items, n),
72
82
  (_, i) =>
73
83
  Effect
74
84
  .forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: "inherit" })
75
- .pipe(Effect.flatMap((_) => forEachBatch(_, i)))
85
+ .pipe(Effect.flatMap((_) => forEachBatch(_, i))),
86
+ { concurrency: options?.concurrency }
76
87
  )
77
- }
88
+ )
78
89
 
79
90
  // export function rateLimit(
80
91
  // n: number,
@@ -1,10 +1,14 @@
1
- import { Data, Effect, Layer, Option, 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"
4
+ import * as Option from "effect-app/Option"
5
+ import * as Data from "effect/Data"
2
6
  import type { RedisClient as Client } from "redis"
3
7
  import Redlock from "redlock"
4
8
 
5
9
  export class ConnectionException extends Data.TaggedError("ConnectionException")<{ cause: Error; message: string }> {
6
10
  constructor(cause: Error) {
7
- super({ message: "A connection error ocurred", cause })
11
+ super({ message: "A connection error occurred", cause })
8
12
  }
9
13
  }
10
14
 
@@ -90,7 +94,7 @@ export const makeRedisClient = (makeClient: () => Client) =>
90
94
  .pipe(Effect.uninterruptible, Effect.orDie)
91
95
  )
92
96
 
93
- export class RedisClient extends ServiceMap.Service<RedisClient, {
97
+ export class RedisClient extends Context.Service<RedisClient, {
94
98
  readonly client: Client
95
99
  readonly lock: Redlock
96
100
  readonly get: (key: string) => Effect.Effect<Option.Option<string>, ConnectionException>
@@ -1,5 +1,6 @@
1
- import { Cause, Effect } from "effect-app"
2
- import { logError, reportError } from "../errorReporter.js"
1
+ import * as Effect from "effect-app/Effect"
2
+ import * as Cause from "effect/Cause"
3
+ import { logError, reportError } from "./errorReporter.ts"
3
4
 
4
5
  // const onExitReportError = (name: string, unknownOnly?: boolean) => {
5
6
  // const report = reportError(name)
@@ -1,13 +1,14 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
- import { type Layer, type ServiceMap } from "effect-app"
4
+ import type * as Context from "effect-app/Context"
5
+ import type * as Layer from "effect-app/Layer"
5
6
  import { type GetContextConfig, type RpcContextMap } from "effect-app/rpc/RpcContextMap"
6
7
  import { type RpcMiddlewareV4 } from "effect-app/rpc/RpcMiddleware"
7
8
  // module:
8
9
  //
9
10
 
10
- // v4: middleware tags are ServiceMap.Service (not Effect) — they carry the RpcMiddlewareV4 as their service Shape
11
+ // v4: middleware tags are Context.Service (not Effect) — they carry the RpcMiddlewareV4 as their service Shape
11
12
  export type RouterMiddleware<
12
13
  Self,
13
14
  RequestContextMap extends Record<string, RpcContextMap.Any>, // what services will the middlware provide dynamically to the next, or raise errors.
@@ -18,9 +19,9 @@ export type RouterMiddleware<
18
19
  _ContextProviderR, // what the context provider requires
19
20
  RequestContextId
20
21
  > =
21
- & ServiceMap.Service<Self, RpcMiddlewareV4<ContextProviderA, ContextProviderE, never>>
22
+ & Context.Service<Self, RpcMiddlewareV4<ContextProviderA, ContextProviderE, never>>
22
23
  & {
23
24
  readonly Default: Layer.Layer<Self, MakeMiddlewareE, MakeMiddlewareR>
24
- readonly requestContext: ServiceMap.Service<RequestContextId, GetContextConfig<RequestContextMap>>
25
+ readonly requestContext: Context.Service<RequestContextId, GetContextConfig<RequestContextMap>>
25
26
  readonly requestContextMap: RequestContextMap
26
27
  }
@@ -0,0 +1,196 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { ConfigureInterruptibilityMiddleware, DevMode, DevModeMiddleware, LoggerMiddleware, RequestCacheMiddleware } from "effect-app/middleware"
3
+ import { RpcContextMap, type RpcMiddleware } from "effect-app/rpc"
4
+ import { pretty } from "effect-app/utils"
5
+ import * as Array from "effect/Array"
6
+ import * as Cause from "effect/Cause"
7
+ import * as Config from "effect/Config"
8
+ import * as Context from "effect/Context"
9
+ import * as Effect from "effect/Effect"
10
+ import * as Layer from "effect/Layer"
11
+ import * as Schema from "effect/Schema"
12
+ import { type Rpc } from "effect/unstable/rpc"
13
+ import { logError, reportError } from "../../errorReporter.ts"
14
+ import { InfraLogger } from "../../logger.ts"
15
+ import { WithNsTransaction } from "../../Store/SQL.ts"
16
+
17
+ const logRequestError = logError("Request")
18
+ const reportRequestError = reportError("Request")
19
+
20
+ // Summarize an rpc payload for the `rpc.request.payload` span attribute.
21
+ // Scalars are kept (long strings snipped), nested objects are recursed into up
22
+ // to `PAYLOAD_MAX_DEPTH` so useful inputs (carrier, packageType, dimensions, ids,
23
+ // …) are captured. Arrays are sampled to the first `PAYLOAD_ARRAY_HEAD` elements
24
+ // (with a `…N more` marker when longer) so pack/pick item arrays — one entry per
25
+ // article, quantity folded into `amount` — are diagnosable without dumping the
26
+ // whole tail on every (high-frequency) SaveItems.
27
+ const PAYLOAD_MAX_DEPTH = 4
28
+ const PAYLOAD_ARRAY_HEAD = 20
29
+ const REDACTED_KEYS = new Set(["password", "secret", "token"])
30
+
31
+ const summarizePayloadValue = (key: string, value: unknown, depth: number): unknown => {
32
+ if (REDACTED_KEYS.has(key)) return "<redacted>"
33
+ if (typeof value === "string") return value.length > 256 ? value.substring(0, 253) + "..." : value
34
+ if (typeof value === "number" || typeof value === "boolean") return value
35
+ if (value === null || value === undefined) return `${value}`
36
+ if (Array.isArray(value)) {
37
+ if (depth >= PAYLOAD_MAX_DEPTH) return `Array[${value.length}]`
38
+ const head = value.slice(0, PAYLOAD_ARRAY_HEAD).map((v) => summarizePayloadValue(key, v, depth + 1))
39
+ return value.length > PAYLOAD_ARRAY_HEAD ? [...head, `…${value.length - PAYLOAD_ARRAY_HEAD} more`] : head
40
+ }
41
+ if (typeof value === "object") {
42
+ return depth >= PAYLOAD_MAX_DEPTH
43
+ ? `Object[${Object.keys(value).length}]`
44
+ : Object.entries(value).reduce((prev, [k, v]) => {
45
+ prev[k] = summarizePayloadValue(k, v, depth + 1)
46
+ return prev
47
+ }, {} as Record<string, unknown>)
48
+ }
49
+ return typeof value
50
+ }
51
+
52
+ const summarizePayload = (payload: unknown): unknown =>
53
+ typeof payload === "object" && payload !== null
54
+ ? Object.entries(payload).reduce((prev, [key, value]) => {
55
+ prev[key] = summarizePayloadValue(key, value, 1)
56
+ return prev
57
+ }, {} as Record<string, unknown>)
58
+ : payload
59
+
60
+ // TODO: do we need this as middleware or just as layer?
61
+ export const DevModeLive = Layer.effect(
62
+ DevMode,
63
+ Effect.gen(function*() {
64
+ const env = yield* Config.string("env").pipe(Config.withDefault("local-dev"))
65
+ return env !== "prod"
66
+ })
67
+ )
68
+
69
+ export const RequestCacheMiddlewareLive = Layer.succeed(
70
+ RequestCacheMiddleware,
71
+ (effect) => effect
72
+ )
73
+
74
+ const isOptimisticConcurrencyException = (input: unknown) =>
75
+ typeof input === "object" && input !== null && "_tag" in input && input._tag === "OptimisticConcurrencyException"
76
+
77
+ export const RequestType = Context.Reference<"command" | "query">(
78
+ "@effect-app/infra/routing/RequestType",
79
+ { defaultValue: () => "query" }
80
+ )
81
+
82
+ export const ConfigureInterruptibilityMiddlewareLive = Layer.effect(
83
+ ConfigureInterruptibilityMiddleware,
84
+ Effect.gen(function*() {
85
+ return (effect, { rpc }) => {
86
+ const requestType = Context.get(rpc.annotations, RequestType)
87
+ const isCommand = requestType === "command"
88
+
89
+ effect = isCommand
90
+ ? Effect.retry(effect, { times: 1, while: isOptimisticConcurrencyException })
91
+ : Effect.interruptible(effect)
92
+
93
+ return effect
94
+ }
95
+ })
96
+ )
97
+
98
+ export const LoggerMiddlewareLive = Layer
99
+ .effect(
100
+ LoggerMiddleware,
101
+ Effect.gen(function*() {
102
+ const devMode = yield* DevMode
103
+ return (effect, { headers, payload, rpc }) =>
104
+ Effect
105
+ .annotateCurrentSpan({
106
+ "rpc.method": rpc._tag,
107
+ "rpc.request.payload": summarizePayload(payload)
108
+ })
109
+ .pipe(
110
+ Effect.andThen(effect),
111
+ // TODO: support SchemaError if the error channel of the request allows it.. but who would want that?
112
+ Effect.catch((_) => Schema.isSchemaError(_) ? Effect.die(_) : Effect.fail(_)),
113
+ Effect.tapCause((cause) => Cause.hasFails(cause) ? logRequestError(cause) : Effect.void),
114
+ Effect.tapCauseIf(Cause.hasDies, (cause) =>
115
+ Effect
116
+ .all([
117
+ reportRequestError(cause, {
118
+ action: rpc._tag
119
+ }),
120
+ InfraLogger
121
+ .logError("Finished request", cause)
122
+ .pipe(Effect.annotateLogs({
123
+ action: rpc._tag,
124
+ req: pretty(payload),
125
+ headers: pretty(headers)
126
+ // resHeaders: pretty(
127
+ // Object
128
+ // .entries(headers)
129
+ // .reduce((prev, [key, value]) => {
130
+ // prev[key] = value && typeof value === "string" ? snipString(value) : value
131
+ // return prev
132
+ // }, {} as Record<string, any>)
133
+ // )
134
+ }))
135
+ ])),
136
+ devMode ? (_) => _ : Effect.catchDefect(() => Effect.die("Internal Server Error"))
137
+ )
138
+ })
139
+ )
140
+ .pipe(Layer.provide(DevModeLive))
141
+
142
+ export const DevModeMiddlewareLive = Layer
143
+ .effect(
144
+ DevModeMiddleware,
145
+ Effect.gen(function*() {
146
+ const devMode = yield* DevMode
147
+ return (effect) => Effect.provideService(effect, DevMode, devMode)
148
+ })
149
+ )
150
+ .pipe(Layer.provide(DevModeLive))
151
+
152
+ export const DefaultGenericMiddlewaresLive = Layer.mergeAll(
153
+ RequestCacheMiddlewareLive,
154
+ ConfigureInterruptibilityMiddlewareLive,
155
+ LoggerMiddlewareLive,
156
+ DevModeMiddlewareLive
157
+ )
158
+
159
+ /**
160
+ * Config entry for `RequestContextMap` that controls per-RPC transaction wrapping.
161
+ * Defaults to `false` (no transaction). Set `requiresTransaction: true` on a route to enable.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * class RequestContextMap extends RpcContextMap.makeMap({
166
+ * requiresTransaction: requiresTransactionConfig,
167
+ * // ...
168
+ * }) {}
169
+ * ```
170
+ */
171
+ export const requiresTransactionConfig = RpcContextMap.makeCustom()(Schema.Never, false)
172
+
173
+ /**
174
+ * Creates the middleware Effect for SQL transaction wrapping.
175
+ * Requires `WithNsTransaction` service.
176
+ * Reads `requiresTransaction` from the RPC config; defaults to `false`.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * const SqlTransactionMiddlewareLive = Layer.effect(
181
+ * SqlTransactionMiddleware,
182
+ * makeSqlTransactionMiddleware(RequestContextMap)
183
+ * )
184
+ * ```
185
+ */
186
+ export const makeSqlTransactionMiddleware = Effect.fnUntraced(function*(
187
+ rcm: { getConfig: (rpc: Rpc.AnyWithProps) => { readonly requiresTransaction?: boolean } }
188
+ ) {
189
+ const withTx = yield* WithNsTransaction
190
+ const mw: RpcMiddleware.RpcMiddlewareV4<never, never, never> = (effect, { rpc }) => {
191
+ const { requiresTransaction } = rcm.getConfig(rpc)
192
+ if (requiresTransaction !== true) return effect
193
+ return withTx(effect)
194
+ }
195
+ return mw
196
+ })
@@ -0,0 +1,4 @@
1
+ // codegen:start {preset: barrel, include: ./middleware/*.ts, nodir: false }
2
+ export * from "./middleware/middleware.ts"
3
+ export * from "./middleware/RouterMiddleware.ts"
4
+ // codegen:end