@effect-app/infra 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/.eslintrc.cjs +11 -0
  2. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-314902b6271c341511f7398a50469024 +0 -0
  3. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-3f072cc7afa09b6adaead0527ab9df83 +0 -0
  4. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-74c3c295c110fc861b6a4c673afc3e24 +0 -0
  5. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-bf6dae8cb9ea9740ceb39aefaf12716c +0 -0
  6. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-cf9d1486029526079a5f68f2041dea02 +0 -0
  7. package/.jest-cache/haste-map-4ca41cc04e60c616a19cbb483cbf487b-e2f1f4b6d87214e3c49442fed31f310c-b4710ed9fb3d0757c4bf23045c585670 +0 -0
  8. package/.jest-cache/haste-map-4ca41cc04e60c616a19cbb483cbf487b-e2f1f4b6d87214e3c49442fed31f310c-ee17e5395bb1b7b36a4e2e22a6ae1449 +0 -0
  9. package/.jest-cache/haste-map-7dc16d7fae8c072843ed1c69eae73100-a8a4225b317477b49bca31f54559afb3-c16136699bb7f463be85273162b447c3 +0 -0
  10. package/.jest-cache/haste-map-9aa1e395a82e108eb49698982c574272-e2f1f4b6d87214e3c49442fed31f310c-f7435f46fc41ac5a13d06a49cae9a650 +0 -0
  11. package/.jest-cache/haste-map-9d206b45d610536c9ec65eec263c6964-a8a4225b317477b49bca31f54559afb3-3510506a330b44f1ae629033aac8fbb3 +0 -0
  12. package/.jest-cache/haste-map-a00ab30d0d656f9d3990958a54b9ccfd-87603b0fc921b26b622a5859b4c92bed-17b550b450b18840c25861aa6e835f0c +0 -0
  13. package/.jest-cache/haste-map-a00ab30d0d656f9d3990958a54b9ccfd-87603b0fc921b26b622a5859b4c92bed-4dc31290b1efc98335eb4c89167d75c3 +0 -0
  14. package/.jest-cache/haste-map-ab843cb0ffbadfd0deea4adb182c7ecd-87603b0fc921b26b622a5859b4c92bed-997106edf4bbc31567a378146180e45e +0 -0
  15. package/.jest-cache/haste-map-ab843cb0ffbadfd0deea4adb182c7ecd-87603b0fc921b26b622a5859b4c92bed-f0cd25414f9ed16c446940ca3aa23c1b +0 -0
  16. package/.jest-cache/haste-map-cf17f2edf0e949eebfdfca561816457c-e7a7ff05756c055cb63be97ba8537525-2cac07d09e6384e2d37c49714edad0ba +0 -0
  17. package/.jest-cache/haste-map-cf17f2edf0e949eebfdfca561816457c-e7a7ff05756c055cb63be97ba8537525-d7967c2976c5feac7161c964f0aa442f +0 -0
  18. package/.jest-cache/haste-map-fb1a173276d25bbff02f815600059283-938122bdc1c8836874b6585d7acb2e99-f705929cca05ce95ceaa6d520b560ce8 +0 -0
  19. package/.prettierignore +6 -0
  20. package/_cjs/_global.cjs +6 -0
  21. package/_cjs/_global.cjs.map +1 -0
  22. package/_cjs/_global.ext.cjs +6 -0
  23. package/_cjs/_global.ext.cjs.map +1 -0
  24. package/_cjs/_global.schema.cjs +5 -0
  25. package/_cjs/_global.schema.cjs.map +1 -0
  26. package/_cjs/errors.cjs +82 -0
  27. package/_cjs/errors.cjs.map +1 -0
  28. package/_cjs/ext.cjs +4 -0
  29. package/_cjs/ext.cjs.map +1 -0
  30. package/_cjs/index.cjs +6 -0
  31. package/_cjs/index.cjs.map +1 -0
  32. package/_cjs/lib/RequestContext.cjs +70 -0
  33. package/_cjs/lib/RequestContext.cjs.map +1 -0
  34. package/_cjs/lib/api/authorization.jwt.cjs +44 -0
  35. package/_cjs/lib/api/authorization.jwt.cjs.map +1 -0
  36. package/_cjs/lib/api/defaultErrorHandler.cjs +45 -0
  37. package/_cjs/lib/api/defaultErrorHandler.cjs.map +1 -0
  38. package/_cjs/lib/api/reportError.cjs +64 -0
  39. package/_cjs/lib/api/reportError.cjs.map +1 -0
  40. package/_cjs/lib/api/routing.cjs +262 -0
  41. package/_cjs/lib/api/routing.cjs.map +1 -0
  42. package/_cjs/lib/api/setupRequest.cjs +35 -0
  43. package/_cjs/lib/api/setupRequest.cjs.map +1 -0
  44. package/_cjs/lib/api/util.cjs +17 -0
  45. package/_cjs/lib/api/util.cjs.map +1 -0
  46. package/_cjs/lib/api/writeDocs.cjs +31 -0
  47. package/_cjs/lib/api/writeDocs.cjs.map +1 -0
  48. package/_cjs/lib/errorReporter.cjs +72 -0
  49. package/_cjs/lib/errorReporter.cjs.map +1 -0
  50. package/_cjs/lib/ext/Array.cjs +30 -0
  51. package/_cjs/lib/ext/Array.cjs.map +1 -0
  52. package/_cjs/lib/fileUtil.cjs +36 -0
  53. package/_cjs/lib/fileUtil.cjs.map +1 -0
  54. package/_cjs/lib/filter/types/errors.cjs +6 -0
  55. package/_cjs/lib/filter/types/errors.cjs.map +1 -0
  56. package/_cjs/lib/filter/types/fields.cjs +6 -0
  57. package/_cjs/lib/filter/types/fields.cjs.map +1 -0
  58. package/_cjs/lib/filter/types/index.cjs +61 -0
  59. package/_cjs/lib/filter/types/index.cjs.map +1 -0
  60. package/_cjs/lib/filter/types/path/common.cjs +6 -0
  61. package/_cjs/lib/filter/types/path/common.cjs.map +1 -0
  62. package/_cjs/lib/filter/types/path/eager.cjs +6 -0
  63. package/_cjs/lib/filter/types/path/eager.cjs.map +1 -0
  64. package/_cjs/lib/filter/types/path/index.cjs +8 -0
  65. package/_cjs/lib/filter/types/path/index.cjs.map +1 -0
  66. package/_cjs/lib/filter/types/utils.cjs +6 -0
  67. package/_cjs/lib/filter/types/utils.cjs.map +1 -0
  68. package/_cjs/lib/filter/types/validator.cjs +6 -0
  69. package/_cjs/lib/filter/types/validator.cjs.map +1 -0
  70. package/_cjs/lib/filter.cjs +238 -0
  71. package/_cjs/lib/filter.cjs.map +1 -0
  72. package/_cjs/lib/instrument.cjs +20 -0
  73. package/_cjs/lib/instrument.cjs.map +1 -0
  74. package/_cjs/lib/rateLimit.cjs +88 -0
  75. package/_cjs/lib/rateLimit.cjs.map +1 -0
  76. package/_cjs/services/CUPS/service.cjs +15 -0
  77. package/_cjs/services/CUPS/service.cjs.map +1 -0
  78. package/_cjs/services/CUPS.cjs +113 -0
  79. package/_cjs/services/CUPS.cjs.map +1 -0
  80. package/_cjs/services/Cache.cjs +39 -0
  81. package/_cjs/services/Cache.cjs.map +1 -0
  82. package/_cjs/services/Emailer/Sendgrid.cjs +112 -0
  83. package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -0
  84. package/_cjs/services/Emailer/fake.cjs +24 -0
  85. package/_cjs/services/Emailer/fake.cjs.map +1 -0
  86. package/_cjs/services/Emailer/service.cjs +12 -0
  87. package/_cjs/services/Emailer/service.cjs.map +1 -0
  88. package/_cjs/services/Emailer.cjs +17 -0
  89. package/_cjs/services/Emailer.cjs.map +1 -0
  90. package/_cjs/services/Repository.cjs +247 -0
  91. package/_cjs/services/Repository.cjs.map +1 -0
  92. package/_cjs/services/ServiceBus.cjs +69 -0
  93. package/_cjs/services/ServiceBus.cjs.map +1 -0
  94. package/_cjs/services/Store/Cosmos.cjs +324 -0
  95. package/_cjs/services/Store/Cosmos.cjs.map +1 -0
  96. package/_cjs/services/Store/Cosmos.test.cjs +59 -0
  97. package/_cjs/services/Store/Cosmos.test.cjs.map +1 -0
  98. package/_cjs/services/Store/Disk.cjs +62 -0
  99. package/_cjs/services/Store/Disk.cjs.map +1 -0
  100. package/_cjs/services/Store/Memory.cjs +70 -0
  101. package/_cjs/services/Store/Memory.cjs.map +1 -0
  102. package/_cjs/services/Store/Redis.cjs +72 -0
  103. package/_cjs/services/Store/Redis.cjs.map +1 -0
  104. package/_cjs/services/Store/codeFilter.test.cjs +61 -0
  105. package/_cjs/services/Store/codeFilter.test.cjs.map +1 -0
  106. package/_cjs/services/Store/index.cjs +72 -0
  107. package/_cjs/services/Store/index.cjs.map +1 -0
  108. package/_cjs/services/Store/service.cjs +72 -0
  109. package/_cjs/services/Store/service.cjs.map +1 -0
  110. package/_cjs/services/Store/utils.cjs +78 -0
  111. package/_cjs/services/Store/utils.cjs.map +1 -0
  112. package/_cjs/services/Store.cjs +17 -0
  113. package/_cjs/services/Store.cjs.map +1 -0
  114. package/_cjs/services/memQueue.cjs +32 -0
  115. package/_cjs/services/memQueue.cjs.map +1 -0
  116. package/_cjs/test.arbs.cjs +32 -0
  117. package/_cjs/test.arbs.cjs.map +1 -0
  118. package/_cjs/vendor/Cache/Cache/_internal/AtomicBoolean.cjs +14 -0
  119. package/_cjs/vendor/Cache/Cache/_internal/AtomicBoolean.cjs.map +1 -0
  120. package/_cjs/vendor/Cache/Cache/_internal/AtomicNumber.cjs +29 -0
  121. package/_cjs/vendor/Cache/Cache/_internal/AtomicNumber.cjs.map +1 -0
  122. package/_cjs/vendor/Cache/Cache/_internal/AtomicReference.cjs +32 -0
  123. package/_cjs/vendor/Cache/Cache/_internal/AtomicReference.cjs.map +1 -0
  124. package/_cjs/vendor/Cache/Cache/_internal/CacheInternal.cjs +266 -0
  125. package/_cjs/vendor/Cache/Cache/_internal/CacheInternal.cjs.map +1 -0
  126. package/_cjs/vendor/Cache/Cache/_internal/CacheState.cjs +31 -0
  127. package/_cjs/vendor/Cache/Cache/_internal/CacheState.cjs.map +1 -0
  128. package/_cjs/vendor/Cache/Cache/_internal/KeySet.cjs +67 -0
  129. package/_cjs/vendor/Cache/Cache/_internal/KeySet.cjs.map +1 -0
  130. package/_cjs/vendor/Cache/Cache/_internal/MapKey.cjs +44 -0
  131. package/_cjs/vendor/Cache/Cache/_internal/MapKey.cjs.map +1 -0
  132. package/_cjs/vendor/Cache/Cache/_internal/MapValue.cjs +33 -0
  133. package/_cjs/vendor/Cache/Cache/_internal/MapValue.cjs.map +1 -0
  134. package/_cjs/vendor/Cache/Cache/definition.cjs +13 -0
  135. package/_cjs/vendor/Cache/Cache/definition.cjs.map +1 -0
  136. package/_cjs/vendor/Cache/Cache/operations/make.cjs +20 -0
  137. package/_cjs/vendor/Cache/Cache/operations/make.cjs.map +1 -0
  138. package/_cjs/vendor/Cache/Cache/operations/makeWith.cjs +23 -0
  139. package/_cjs/vendor/Cache/Cache/operations/makeWith.cjs.map +1 -0
  140. package/_cjs/vendor/Cache/Cache/operations.cjs +28 -0
  141. package/_cjs/vendor/Cache/Cache/operations.cjs.map +1 -0
  142. package/_cjs/vendor/Cache/Cache.cjs +28 -0
  143. package/_cjs/vendor/Cache/Cache.cjs.map +1 -0
  144. package/_cjs/vendor/Cache/CacheStats/definition.cjs +13 -0
  145. package/_cjs/vendor/Cache/CacheStats/definition.cjs.map +1 -0
  146. package/_cjs/vendor/Cache/CacheStats.cjs +17 -0
  147. package/_cjs/vendor/Cache/CacheStats.cjs.map +1 -0
  148. package/_cjs/vendor/Cache/EntryStats/definition.cjs +11 -0
  149. package/_cjs/vendor/Cache/EntryStats/definition.cjs.map +1 -0
  150. package/_cjs/vendor/Cache/EntryStats.cjs +17 -0
  151. package/_cjs/vendor/Cache/EntryStats.cjs.map +1 -0
  152. package/_cjs/vendor/Cache/Lookup/definition.cjs +6 -0
  153. package/_cjs/vendor/Cache/Lookup/definition.cjs.map +1 -0
  154. package/_cjs/vendor/Cache/Lookup.cjs +17 -0
  155. package/_cjs/vendor/Cache/Lookup.cjs.map +1 -0
  156. package/_cjs/vendor/Cache/index.cjs +17 -0
  157. package/_cjs/vendor/Cache/index.cjs.map +1 -0
  158. package/_src/_global.ext.ts +34 -0
  159. package/_src/_global.schema.ts +10 -0
  160. package/_src/_global.ts +14 -0
  161. package/_src/errors.ts +50 -0
  162. package/_src/ext.ts +1 -0
  163. package/_src/index.ts +0 -0
  164. package/_src/lib/RequestContext.ts +132 -0
  165. package/_src/lib/api/authorization.jwt.ts +52 -0
  166. package/_src/lib/api/defaultErrorHandler.ts +92 -0
  167. package/_src/lib/api/reportError.ts +50 -0
  168. package/_src/lib/api/routing.ts +623 -0
  169. package/_src/lib/api/setupRequest.ts +22 -0
  170. package/_src/lib/api/util.ts +14 -0
  171. package/_src/lib/api/writeDocs.ts +26 -0
  172. package/_src/lib/errorReporter.ts +63 -0
  173. package/_src/lib/ext/Array.ts +32 -0
  174. package/_src/lib/fileUtil.ts +56 -0
  175. package/_src/lib/filter/types/errors.ts +47 -0
  176. package/_src/lib/filter/types/fields.ts +50 -0
  177. package/_src/lib/filter/types/index.ts +5 -0
  178. package/_src/lib/filter/types/path/common.ts +404 -0
  179. package/_src/lib/filter/types/path/eager.ts +146 -0
  180. package/_src/lib/filter/types/path/index.ts +14 -0
  181. package/_src/lib/filter/types/utils.ts +106 -0
  182. package/_src/lib/filter/types/validator.ts +46 -0
  183. package/_src/lib/filter.ts +323 -0
  184. package/_src/lib/instrument.ts +9 -0
  185. package/_src/lib/rateLimit.ts +126 -0
  186. package/_src/services/CUPS/service.ts +16 -0
  187. package/_src/services/CUPS.ts +105 -0
  188. package/_src/services/Cache.ts +45 -0
  189. package/_src/services/Emailer/Sendgrid.ts +123 -0
  190. package/_src/services/Emailer/fake.ts +14 -0
  191. package/_src/services/Emailer/service.ts +33 -0
  192. package/_src/services/Emailer.ts +1 -0
  193. package/_src/services/Repository.ts +513 -0
  194. package/_src/services/ServiceBus.ts +111 -0
  195. package/_src/services/Store/Cosmos.test.ts +91 -0
  196. package/_src/services/Store/Cosmos.ts +545 -0
  197. package/_src/services/Store/Disk.ts +81 -0
  198. package/_src/services/Store/Memory.ts +77 -0
  199. package/_src/services/Store/Redis.ts +92 -0
  200. package/_src/services/Store/codeFilter.test.ts +74 -0
  201. package/_src/services/Store/index.test.ts.bak +112 -0
  202. package/_src/services/Store/index.ts +62 -0
  203. package/_src/services/Store/service.ts +174 -0
  204. package/_src/services/Store/utils.ts +126 -0
  205. package/_src/services/Store.ts +1 -0
  206. package/_src/services/memQueue.ts +30 -0
  207. package/_src/test.arbs.ts +27 -0
  208. package/_src/vendor/Cache/Cache/_internal/AtomicBoolean.ts +7 -0
  209. package/_src/vendor/Cache/Cache/_internal/AtomicNumber.ts +28 -0
  210. package/_src/vendor/Cache/Cache/_internal/AtomicReference.ts +30 -0
  211. package/_src/vendor/Cache/Cache/_internal/CacheInternal.ts +293 -0
  212. package/_src/vendor/Cache/Cache/_internal/CacheState.ts +56 -0
  213. package/_src/vendor/Cache/Cache/_internal/KeySet.ts +58 -0
  214. package/_src/vendor/Cache/Cache/_internal/MapKey.ts +43 -0
  215. package/_src/vendor/Cache/Cache/_internal/MapValue.ts +39 -0
  216. package/_src/vendor/Cache/Cache/definition.ts +112 -0
  217. package/_src/vendor/Cache/Cache/operations/make.ts +17 -0
  218. package/_src/vendor/Cache/Cache/operations/makeWith.ts +32 -0
  219. package/_src/vendor/Cache/Cache/operations.ts +4 -0
  220. package/_src/vendor/Cache/Cache.ts +4 -0
  221. package/_src/vendor/Cache/CacheStats/definition.ts +23 -0
  222. package/_src/vendor/Cache/CacheStats.ts +3 -0
  223. package/_src/vendor/Cache/EntryStats/definition.ts +19 -0
  224. package/_src/vendor/Cache/EntryStats.ts +3 -0
  225. package/_src/vendor/Cache/Lookup/definition.ts +15 -0
  226. package/_src/vendor/Cache/Lookup.ts +3 -0
  227. package/_src/vendor/Cache/global.ts.bak +23 -0
  228. package/_src/vendor/Cache/index.ts +4 -0
  229. package/dist/_global.d.ts +10 -0
  230. package/dist/_global.d.ts.map +1 -0
  231. package/dist/_global.ext.d.ts +34 -0
  232. package/dist/_global.ext.d.ts.map +1 -0
  233. package/dist/_global.ext.js +2 -0
  234. package/dist/_global.js +12 -0
  235. package/dist/_global.schema.d.ts +6 -0
  236. package/dist/_global.schema.d.ts.map +1 -0
  237. package/dist/_global.schema.js +9 -0
  238. package/dist/errors.d.ts +41 -0
  239. package/dist/errors.d.ts.map +1 -0
  240. package/dist/errors.js +51 -0
  241. package/dist/ext.d.ts +2 -0
  242. package/dist/ext.d.ts.map +1 -0
  243. package/dist/ext.js +2 -0
  244. package/dist/index.d.ts +2 -0
  245. package/dist/index.d.ts.map +1 -0
  246. package/dist/index.js +2 -0
  247. package/dist/lib/RequestContext.d.ts +122 -0
  248. package/dist/lib/RequestContext.d.ts.map +1 -0
  249. package/dist/lib/RequestContext.js +52 -0
  250. package/dist/lib/api/authorization.jwt.d.ts +7 -0
  251. package/dist/lib/api/authorization.jwt.d.ts.map +1 -0
  252. package/dist/lib/api/authorization.jwt.js +32 -0
  253. package/dist/lib/api/defaultErrorHandler.d.ts +8 -0
  254. package/dist/lib/api/defaultErrorHandler.d.ts.map +1 -0
  255. package/dist/lib/api/defaultErrorHandler.js +37 -0
  256. package/dist/lib/api/reportError.d.ts +32 -0
  257. package/dist/lib/api/reportError.d.ts.map +1 -0
  258. package/dist/lib/api/reportError.js +44 -0
  259. package/dist/lib/api/routing.d.ts +100 -0
  260. package/dist/lib/api/routing.d.ts.map +1 -0
  261. package/dist/lib/api/routing.js +248 -0
  262. package/dist/lib/api/setupRequest.d.ts +13 -0
  263. package/dist/lib/api/setupRequest.d.ts.map +1 -0
  264. package/dist/lib/api/setupRequest.js +25 -0
  265. package/dist/lib/api/util.d.ts +3 -0
  266. package/dist/lib/api/util.d.ts.map +1 -0
  267. package/dist/lib/api/util.js +14 -0
  268. package/dist/lib/api/writeDocs.d.ts +3 -0
  269. package/dist/lib/api/writeDocs.d.ts.map +1 -0
  270. package/dist/lib/api/writeDocs.js +23 -0
  271. package/dist/lib/errorReporter.d.ts +8 -0
  272. package/dist/lib/errorReporter.d.ts.map +1 -0
  273. package/dist/lib/errorReporter.js +45 -0
  274. package/dist/lib/ext/Array.d.ts +19 -0
  275. package/dist/lib/ext/Array.d.ts.map +1 -0
  276. package/dist/lib/ext/Array.js +21 -0
  277. package/dist/lib/fileUtil.d.ts +22 -0
  278. package/dist/lib/fileUtil.d.ts.map +1 -0
  279. package/dist/lib/fileUtil.js +23 -0
  280. package/dist/lib/filter/types/errors.d.ts +30 -0
  281. package/dist/lib/filter/types/errors.d.ts.map +1 -0
  282. package/dist/lib/filter/types/errors.js +2 -0
  283. package/dist/lib/filter/types/fields.d.ts +29 -0
  284. package/dist/lib/filter/types/fields.d.ts.map +1 -0
  285. package/dist/lib/filter/types/fields.js +2 -0
  286. package/dist/lib/filter/types/index.d.ts +6 -0
  287. package/dist/lib/filter/types/index.d.ts.map +1 -0
  288. package/dist/lib/filter/types/index.js +6 -0
  289. package/dist/lib/filter/types/path/common.d.ts +316 -0
  290. package/dist/lib/filter/types/path/common.d.ts.map +1 -0
  291. package/dist/lib/filter/types/path/common.js +2 -0
  292. package/dist/lib/filter/types/path/eager.d.ts +95 -0
  293. package/dist/lib/filter/types/path/eager.d.ts.map +1 -0
  294. package/dist/lib/filter/types/path/eager.js +2 -0
  295. package/dist/lib/filter/types/path/index.d.ts +4 -0
  296. package/dist/lib/filter/types/path/index.d.ts.map +1 -0
  297. package/dist/lib/filter/types/path/index.js +4 -0
  298. package/dist/lib/filter/types/utils.d.ts +68 -0
  299. package/dist/lib/filter/types/utils.d.ts.map +1 -0
  300. package/dist/lib/filter/types/utils.js +2 -0
  301. package/dist/lib/filter/types/validator.d.ts +30 -0
  302. package/dist/lib/filter/types/validator.d.ts.map +1 -0
  303. package/dist/lib/filter/types/validator.js +2 -0
  304. package/dist/lib/filter.d.ts +133 -0
  305. package/dist/lib/filter.d.ts.map +1 -0
  306. package/dist/lib/filter.js +171 -0
  307. package/dist/lib/instrument.d.ts +7 -0
  308. package/dist/lib/instrument.d.ts.map +1 -0
  309. package/dist/lib/instrument.js +12 -0
  310. package/dist/lib/rateLimit.d.ts +43 -0
  311. package/dist/lib/rateLimit.d.ts.map +1 -0
  312. package/dist/lib/rateLimit.js +76 -0
  313. package/dist/services/CUPS/service.d.ts +19 -0
  314. package/dist/services/CUPS/service.d.ts.map +1 -0
  315. package/dist/services/CUPS/service.js +5 -0
  316. package/dist/services/CUPS.d.ts +10 -0
  317. package/dist/services/CUPS.d.ts.map +1 -0
  318. package/dist/services/CUPS.js +89 -0
  319. package/dist/services/Cache.d.ts +28 -0
  320. package/dist/services/Cache.d.ts.map +1 -0
  321. package/dist/services/Cache.js +28 -0
  322. package/dist/services/Emailer/Sendgrid.d.ts +180 -0
  323. package/dist/services/Emailer/Sendgrid.d.ts.map +1 -0
  324. package/dist/services/Emailer/Sendgrid.js +102 -0
  325. package/dist/services/Emailer/fake.d.ts +7 -0
  326. package/dist/services/Emailer/fake.d.ts.map +1 -0
  327. package/dist/services/Emailer/fake.js +15 -0
  328. package/dist/services/Emailer/service.d.ts +41 -0
  329. package/dist/services/Emailer/service.d.ts.map +1 -0
  330. package/dist/services/Emailer/service.js +3 -0
  331. package/dist/services/Emailer.d.ts +2 -0
  332. package/dist/services/Emailer.d.ts.map +1 -0
  333. package/dist/services/Emailer.js +2 -0
  334. package/dist/services/Repository.d.ts +300 -0
  335. package/dist/services/Repository.d.ts.map +1 -0
  336. package/dist/services/Repository.js +193 -0
  337. package/dist/services/ServiceBus.d.ts +26 -0
  338. package/dist/services/ServiceBus.d.ts.map +1 -0
  339. package/dist/services/ServiceBus.js +53 -0
  340. package/dist/services/Store/Cosmos.d.ts +56 -0
  341. package/dist/services/Store/Cosmos.d.ts.map +1 -0
  342. package/dist/services/Store/Cosmos.js +321 -0
  343. package/dist/services/Store/Cosmos.test.d.ts.map +1 -0
  344. package/dist/services/Store/Disk.d.ts +14 -0
  345. package/dist/services/Store/Disk.d.ts.map +1 -0
  346. package/dist/services/Store/Disk.js +52 -0
  347. package/dist/services/Store/Memory.d.ts +17 -0
  348. package/dist/services/Store/Memory.d.ts.map +1 -0
  349. package/dist/services/Store/Memory.js +60 -0
  350. package/dist/services/Store/Redis.d.ts +12 -0
  351. package/dist/services/Store/Redis.d.ts.map +1 -0
  352. package/dist/services/Store/Redis.js +59 -0
  353. package/dist/services/Store/codeFilter.test.d.ts.map +1 -0
  354. package/dist/services/Store/index.d.ts +10 -0
  355. package/dist/services/Store/index.d.ts.map +1 -0
  356. package/dist/services/Store/index.js +52 -0
  357. package/dist/services/Store/service.d.ts +113 -0
  358. package/dist/services/Store/service.d.ts.map +1 -0
  359. package/dist/services/Store/service.js +63 -0
  360. package/dist/services/Store/utils.d.ts +14 -0
  361. package/dist/services/Store/utils.d.ts.map +1 -0
  362. package/dist/services/Store/utils.js +103 -0
  363. package/dist/services/Store.d.ts +2 -0
  364. package/dist/services/Store.d.ts.map +1 -0
  365. package/dist/services/Store.js +2 -0
  366. package/dist/services/memQueue.d.ts +18 -0
  367. package/dist/services/memQueue.d.ts.map +1 -0
  368. package/dist/services/memQueue.js +24 -0
  369. package/dist/test.arbs.d.ts +13 -0
  370. package/dist/test.arbs.d.ts.map +1 -0
  371. package/dist/test.arbs.js +22 -0
  372. package/dist/vendor/Cache/Cache/_internal/AtomicBoolean.d.ts +5 -0
  373. package/dist/vendor/Cache/Cache/_internal/AtomicBoolean.d.ts.map +1 -0
  374. package/dist/vendor/Cache/Cache/_internal/AtomicBoolean.js +7 -0
  375. package/dist/vendor/Cache/Cache/_internal/AtomicNumber.d.ts +8 -0
  376. package/dist/vendor/Cache/Cache/_internal/AtomicNumber.d.ts.map +1 -0
  377. package/dist/vendor/Cache/Cache/_internal/AtomicNumber.js +22 -0
  378. package/dist/vendor/Cache/Cache/_internal/AtomicReference.d.ts +10 -0
  379. package/dist/vendor/Cache/Cache/_internal/AtomicReference.d.ts.map +1 -0
  380. package/dist/vendor/Cache/Cache/_internal/AtomicReference.js +25 -0
  381. package/dist/vendor/Cache/Cache/_internal/CacheInternal.d.ts +51 -0
  382. package/dist/vendor/Cache/Cache/_internal/CacheInternal.d.ts.map +1 -0
  383. package/dist/vendor/Cache/Cache/_internal/CacheInternal.js +253 -0
  384. package/dist/vendor/Cache/Cache/_internal/CacheState.d.ts +33 -0
  385. package/dist/vendor/Cache/Cache/_internal/CacheState.d.ts.map +1 -0
  386. package/dist/vendor/Cache/Cache/_internal/CacheState.js +21 -0
  387. package/dist/vendor/Cache/Cache/_internal/KeySet.d.ts +20 -0
  388. package/dist/vendor/Cache/Cache/_internal/KeySet.d.ts.map +1 -0
  389. package/dist/vendor/Cache/Cache/_internal/KeySet.js +61 -0
  390. package/dist/vendor/Cache/Cache/_internal/MapKey.d.ts +24 -0
  391. package/dist/vendor/Cache/Cache/_internal/MapKey.d.ts.map +1 -0
  392. package/dist/vendor/Cache/Cache/_internal/MapKey.js +37 -0
  393. package/dist/vendor/Cache/Cache/_internal/MapValue.d.ts +32 -0
  394. package/dist/vendor/Cache/Cache/_internal/MapValue.d.ts.map +1 -0
  395. package/dist/vendor/Cache/Cache/_internal/MapValue.js +24 -0
  396. package/dist/vendor/Cache/Cache/definition.d.ts +100 -0
  397. package/dist/vendor/Cache/Cache/definition.d.ts.map +1 -0
  398. package/dist/vendor/Cache/Cache/definition.js +5 -0
  399. package/dist/vendor/Cache/Cache/operations/make.d.ts +12 -0
  400. package/dist/vendor/Cache/Cache/operations/make.d.ts.map +1 -0
  401. package/dist/vendor/Cache/Cache/operations/make.js +12 -0
  402. package/dist/vendor/Cache/Cache/operations/makeWith.d.ts +14 -0
  403. package/dist/vendor/Cache/Cache/operations/makeWith.d.ts.map +1 -0
  404. package/dist/vendor/Cache/Cache/operations/makeWith.js +15 -0
  405. package/dist/vendor/Cache/Cache/operations.d.ts +3 -0
  406. package/dist/vendor/Cache/Cache/operations.d.ts.map +1 -0
  407. package/dist/vendor/Cache/Cache/operations.js +4 -0
  408. package/dist/vendor/Cache/Cache.d.ts +3 -0
  409. package/dist/vendor/Cache/Cache.d.ts.map +1 -0
  410. package/dist/vendor/Cache/Cache.js +4 -0
  411. package/dist/vendor/Cache/CacheStats/definition.d.ts +19 -0
  412. package/dist/vendor/Cache/CacheStats/definition.d.ts.map +1 -0
  413. package/dist/vendor/Cache/CacheStats/definition.js +6 -0
  414. package/dist/vendor/Cache/CacheStats.d.ts +2 -0
  415. package/dist/vendor/Cache/CacheStats.d.ts.map +1 -0
  416. package/dist/vendor/Cache/CacheStats.js +3 -0
  417. package/dist/vendor/Cache/EntryStats/definition.d.ts +17 -0
  418. package/dist/vendor/Cache/EntryStats/definition.d.ts.map +1 -0
  419. package/dist/vendor/Cache/EntryStats/definition.js +4 -0
  420. package/dist/vendor/Cache/EntryStats.d.ts +2 -0
  421. package/dist/vendor/Cache/EntryStats.d.ts.map +1 -0
  422. package/dist/vendor/Cache/EntryStats.js +3 -0
  423. package/dist/vendor/Cache/Lookup/definition.d.ts +17 -0
  424. package/dist/vendor/Cache/Lookup/definition.d.ts.map +1 -0
  425. package/dist/vendor/Cache/Lookup/definition.js +2 -0
  426. package/dist/vendor/Cache/Lookup.d.ts +2 -0
  427. package/dist/vendor/Cache/Lookup.d.ts.map +1 -0
  428. package/dist/vendor/Cache/Lookup.js +3 -0
  429. package/dist/vendor/Cache/index.d.ts +5 -0
  430. package/dist/vendor/Cache/index.d.ts.map +1 -0
  431. package/dist/vendor/Cache/index.js +5 -0
  432. package/package.json +756 -0
  433. package/tsconfig.json +107 -0
  434. package/tsconfig.json.bak +47 -0
  435. package/tsplus.config.json +6 -0
  436. package/types/modules.d.ts +1 -0
  437. package/vitest.config.ts +5 -0
  438. package/wallaby.cjs +1 -0
@@ -0,0 +1,545 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import * as CosmosClient from "@effect-app/infra-adapters/cosmos-client"
4
+
5
+ import { OptimisticConcurrencyException } from "../../errors.js"
6
+
7
+ import { omit } from "@effect-app/prelude/utils"
8
+
9
+ import type {
10
+ Filter,
11
+ FilterJoinSelect,
12
+ JoinFindFilter,
13
+ LegacyFilter,
14
+ PersistenceModelType,
15
+ StorageConfig,
16
+ Store,
17
+ StoreConfig,
18
+ StoreWhereFilter,
19
+ SupportedValues
20
+ } from "./service.js"
21
+ import { StoreMaker } from "./service.js"
22
+
23
+ // TODO: Retry operation when running into RU limit.
24
+ export function makeCosmosStore({ prefix }: StorageConfig) {
25
+ return Effect.gen(function*($) {
26
+ const { db } = yield* $(CosmosClient.CosmosClient.access)
27
+ return {
28
+ make: <Id extends string, PM extends PersistenceModelType<Id>, Id2 extends Id>(
29
+ name: string,
30
+ existing?: Effect<never, never, ROMap<Id2, PM>>,
31
+ config?: StoreConfig<PM>
32
+ ) =>
33
+ Effect.gen(function*($) {
34
+ const containerId = `${prefix}${name}`
35
+ yield* $(
36
+ Effect.promise(() =>
37
+ db.containers.createIfNotExists({
38
+ id: containerId,
39
+ uniqueKeyPolicy: config?.uniqueKeys
40
+ ? { uniqueKeys: config.uniqueKeys }
41
+ : undefined
42
+ })
43
+ )
44
+ )
45
+ const container = db.container(containerId)
46
+ const bulk = container.items.bulk.bind(container.items)
47
+ const execBatch = container.items.batch.bind(container.items)
48
+ const importedMarkerId = containerId
49
+
50
+ const bulkSet = (items: NonEmptyReadonlyArray<PM>) =>
51
+ Effect.gen(function*($) {
52
+ // TODO: disable batching if need atomicity
53
+ // we delay and batch to keep low amount of RUs
54
+ const b = [...items].map(
55
+ x =>
56
+ [
57
+ x,
58
+ Opt.fromNullable(x._etag).match(
59
+ () => ({
60
+ operationType: "Create" as const,
61
+ resourceBody: {
62
+ ...omit(x, "_etag"),
63
+ _partitionKey: config?.partitionValue(x)
64
+ } as any,
65
+ partitionKey: config?.partitionValue(x)
66
+ }),
67
+ eTag => ({
68
+ operationType: "Replace" as const,
69
+ id: x.id,
70
+ resourceBody: {
71
+ ...omit(x, "_etag"),
72
+ _partitionKey: config?.partitionValue(x)
73
+ } as any,
74
+ ifMatch: eTag,
75
+ partitionKey: config?.partitionValue(x)
76
+ })
77
+ )
78
+ ] as const
79
+ )
80
+ const batches = b.chunk(config?.maxBulkSize ?? 10).toReadonlyArray()
81
+
82
+ const batchResult = yield* $(
83
+ batches.map((x, i) => [i, x] as const)
84
+ .forEachEffect(
85
+ ([i, batch]) =>
86
+ Effect.promise(() => bulk(batch.map(([, op]) => op)))
87
+ .delay(DUR.makeMillis(i === 0 ? 0 : 1100))
88
+ .flatMap(responses =>
89
+ Effect.gen(function*($) {
90
+ const r = responses.find(x => x.statusCode === 412)
91
+ if (r) {
92
+ return yield* $(
93
+ Effect.fail(
94
+ new OptimisticConcurrencyException(
95
+ name,
96
+ JSON.stringify(r.resourceBody?.["id"])
97
+ )
98
+ )
99
+ )
100
+ }
101
+ const r2 = responses.find(
102
+ x => x.statusCode > 299 || x.statusCode < 200
103
+ )
104
+ if (r2) {
105
+ return yield* $(
106
+ Effect.die(
107
+ new CosmosDbOperationError(
108
+ "not able to update record: " + r2.statusCode
109
+ )
110
+ )
111
+ )
112
+ }
113
+ return batch.map(([e], i) => ({
114
+ ...e,
115
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
116
+ _etag: responses[i]!.eTag
117
+ }))
118
+ })
119
+ )
120
+ )
121
+ )
122
+ return batchResult.toReadonlyArray().flat() as unknown as NonEmptyReadonlyArray<PM>
123
+ }).instrument("cosmos.bulkSet")
124
+ .logAnnotate("cosmos.db", containerId)
125
+
126
+ const batchSet = (items: NonEmptyReadonlyArray<PM>) => {
127
+ return Do($ => {
128
+ const batch = [...items].map(
129
+ x =>
130
+ [
131
+ x,
132
+ Opt.fromNullable(x._etag).match(
133
+ () => ({
134
+ operationType: "Create" as const,
135
+ resourceBody: {
136
+ ...omit(x, "_etag"),
137
+ _partitionKey: config?.partitionValue(x)
138
+ } as any
139
+ }),
140
+ eTag => ({
141
+ operationType: "Replace" as const,
142
+ id: x.id,
143
+ resourceBody: {
144
+ ...omit(x, "_etag"),
145
+ _partitionKey: config?.partitionValue(x)
146
+ } as any,
147
+ ifMatch: eTag
148
+ })
149
+ )
150
+ ] as const
151
+ )
152
+
153
+ const ex = batch.map(([, c]) => c)
154
+
155
+ return $(
156
+ Effect.promise(() => execBatch(ex, ex[0]?.resourceBody._partitionKey))
157
+ .flatMap(x =>
158
+ Effect.gen(function*($) {
159
+ const result = x.result ?? []
160
+ const firstFailed = result.find(
161
+ (x: any) => x.statusCode > 299 || x.statusCode < 200
162
+ )
163
+ if (firstFailed) {
164
+ const code = firstFailed.statusCode ?? 0
165
+ if (code === 412) {
166
+ return yield* $(
167
+ Effect.fail(new OptimisticConcurrencyException(name, "batch"))
168
+ )
169
+ }
170
+
171
+ return yield* $(
172
+ Effect.die(
173
+ new CosmosDbOperationError("not able to update record: " + code)
174
+ )
175
+ )
176
+ }
177
+
178
+ return batch.map(([e], i) => ({
179
+ ...e,
180
+ _etag: result[i]?.eTag
181
+ })) as unknown as NonEmptyReadonlyArray<PM>
182
+ })
183
+ )
184
+ )
185
+ }).instrument("cosmos.batchSet")
186
+ .logAnnotate("cosmos.db", containerId)
187
+ }
188
+
189
+ const s: Store<PM, Id> = {
190
+ all: Effect(() => ({
191
+ query: `SELECT * FROM ${name} f WHERE f.id != @id`,
192
+ parameters: [{ name: "@id", value: importedMarkerId }]
193
+ }))
194
+ .tap(q => logQuery(q))
195
+ .flatMap(q =>
196
+ Effect.promise(() =>
197
+ container.items
198
+ .query<PM>(q)
199
+ .fetchAll()
200
+ .then(({ resources }) => resources.toChunk)
201
+ )
202
+ ).instrument("cosmos.all")
203
+ .logAnnotate("cosmos.db", containerId),
204
+ filterJoinSelect: <T extends object>(
205
+ filter: FilterJoinSelect,
206
+ cursor?: { skip?: number; limit?: number }
207
+ ) =>
208
+ filter.keys
209
+ .forEachEffect(k =>
210
+ Effect(() => buildFilterJoinSelectCosmosQuery(filter, k, name, cursor?.skip, cursor?.limit))
211
+ .tap(q => logQuery(q))
212
+ .flatMap(q =>
213
+ Effect.promise(() =>
214
+ container.items
215
+ .query<T>(q)
216
+ .fetchAll()
217
+ .then(({ resources }) => resources.toChunk)
218
+ )
219
+ )
220
+ )
221
+ .map(a => {
222
+ const v = a
223
+ .flatMap(_ => _)
224
+ .map(x =>
225
+ spread(
226
+ x,
227
+ ({ r, ...rest }: any) => ({ ...rest, ...r } as T & { _rootId: string })
228
+ )
229
+ )
230
+ return Chunk.fromIterable(v)
231
+ }).instrument("cosmos.filterJoinSelect")
232
+ .logAnnotate("cosmos.db", containerId),
233
+ /**
234
+ * May return duplicate results for "join_find", when matching more than once.
235
+ */
236
+ filter: (filter: Filter<PM>, cursor?: { skip?: number; limit?: number }) => {
237
+ const skip = cursor?.skip
238
+ const limit = cursor?.limit
239
+ return (filter.type === "join_find"
240
+ ? // This is a problem if one of the multiple joined arrays can be empty!
241
+ // https://stackoverflow.com/questions/60320780/azure-cosmosdb-sql-join-not-returning-results-when-the-child-contains-empty-arra
242
+ // so we use multiple queries instead.
243
+ filter.keys
244
+ .forEachEffect(k =>
245
+ Effect(() => buildFindJoinCosmosQuery(filter, k, name, skip, limit))
246
+ .tap(q => logQuery(q))
247
+ .flatMap(q =>
248
+ Effect.promise(() =>
249
+ container.items
250
+ .query<PM>(q)
251
+ .fetchAll()
252
+ .then(({ resources }) => resources.toChunk)
253
+ )
254
+ )
255
+ )
256
+ .map(_ => _.flatMap(_ => _))
257
+ : Effect(() => buildCosmosQuery(filter, name, importedMarkerId, skip, limit))
258
+ .tap(q => logQuery(q))
259
+ .flatMap(q =>
260
+ Effect.promise(() =>
261
+ container.items.query<{ f: PM }>(
262
+ q
263
+ )
264
+ .fetchAll()
265
+ .then(({ resources }) => resources.map(_ => _.f).toChunk)
266
+ )
267
+ )).instrument("cosmos.filter")
268
+ .logAnnotate("cosmos.db", containerId)
269
+ },
270
+ find: id =>
271
+ Effect.promise(() =>
272
+ container
273
+ .item(id, config?.partitionValue({ id } as PM))
274
+ .read<PM>()
275
+ .then(({ resource }) => Opt.fromNullable(resource))
276
+ ).instrument("cosmos.find")
277
+ .logAnnotate("cosmos.db", containerId),
278
+ set: e =>
279
+ Opt.fromNullable(e._etag)
280
+ .match(
281
+ () =>
282
+ Effect.promise(() =>
283
+ container.items.create({
284
+ ...e,
285
+ _partitionKey: config?.partitionValue(e)
286
+ })
287
+ ),
288
+ eTag =>
289
+ Effect.promise(() =>
290
+ container.item(e.id, config?.partitionValue(e)).replace(
291
+ { ...e, _partitionKey: config?.partitionValue(e) },
292
+ {
293
+ accessCondition: {
294
+ type: "IfMatch",
295
+ condition: eTag
296
+ }
297
+ }
298
+ )
299
+ )
300
+ )
301
+ .flatMap(x => {
302
+ if (x.statusCode === 412) {
303
+ return Effect.fail(new OptimisticConcurrencyException(name, e.id))
304
+ }
305
+ if (x.statusCode > 299 || x.statusCode < 200) {
306
+ return Effect.die(
307
+ new CosmosDbOperationError(
308
+ "not able to update record: " + x.statusCode
309
+ )
310
+ )
311
+ }
312
+ return Effect({
313
+ ...e,
314
+ _etag: x.etag
315
+ })
316
+ })
317
+ .instrument("cosmos.set")
318
+ .logAnnotate("cosmos.db", containerId),
319
+ batchSet,
320
+ bulkSet,
321
+ remove: (e: PM) =>
322
+ Effect.promise(() => container.item(e.id, config?.partitionValue(e)).delete())
323
+ .instrument("cosmos.remove")
324
+ .logAnnotate("cosmos.db", containerId)
325
+ }
326
+
327
+ // handle mock data
328
+ const marker = yield* $(
329
+ Effect.promise(() =>
330
+ container
331
+ .item(importedMarkerId, importedMarkerId)
332
+ .read<{ id: string }>()
333
+ .then(({ resource }) => Opt.fromNullable(resource))
334
+ )
335
+ )
336
+
337
+ if (!marker.isSome()) {
338
+ console.log("Creating mock data for " + name)
339
+ if (existing) {
340
+ const m = yield* $(existing)
341
+ yield* $(
342
+ Effect([...m.values()].toNonEmpty)
343
+ .flatMapOpt(a =>
344
+ s
345
+ .bulkSet(a)
346
+ .orDie
347
+ // we delay extra here, so that initial creation between Companies/POs also have an interval between them.
348
+ .delay(DUR.makeMillis(1100))
349
+ )
350
+ )
351
+ }
352
+ // Mark as imported
353
+ yield* $(
354
+ Effect.promise(() =>
355
+ container.items.create({
356
+ _partitionKey: importedMarkerId,
357
+ id: importedMarkerId
358
+ })
359
+ )
360
+ )
361
+ }
362
+ return s
363
+ })
364
+ }
365
+ })
366
+ }
367
+
368
+ function logQuery(q: {
369
+ query: string
370
+ parameters: {
371
+ name: string
372
+ value: SupportedValues | readonly SupportedValues[]
373
+ }[]
374
+ }) {
375
+ return Effect.logDebug("cosmos query")
376
+ .apply(Effect.logAnnotates({
377
+ query: q.query,
378
+ parameters: JSON.stringify(
379
+ q.parameters.reduce((acc, v) => {
380
+ acc[v.name] = v.value
381
+ return acc
382
+ }, {} as Record<string, SupportedValues | readonly SupportedValues[]>),
383
+ undefined,
384
+ 2
385
+ )
386
+ }))
387
+ }
388
+
389
+ /**
390
+ * @deprecated: should build Select into Where query
391
+ */
392
+ export function buildFilterJoinSelectCosmosQuery(
393
+ filter: FilterJoinSelect,
394
+ k: string,
395
+ name: string,
396
+ skip?: number,
397
+ limit?: number
398
+ ) {
399
+ const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
400
+ return {
401
+ query: `
402
+ SELECT r, f.id as _rootId
403
+ FROM ${name} f
404
+ JOIN r IN f.${k}
405
+ WHERE LOWER(r.${filter.valueKey}) = LOWER(@value)
406
+ ${lm}
407
+ `,
408
+ parameters: [{ name: "@value", value: filter.value }]
409
+ }
410
+ }
411
+
412
+ /**
413
+ * @deprecated: is now part of Where query as k.-1.valueKey
414
+ */
415
+ export function buildFindJoinCosmosQuery(
416
+ filter: JoinFindFilter,
417
+ k: string,
418
+ name: string,
419
+ skip?: number,
420
+ limit?: number
421
+ ) {
422
+ const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
423
+ return {
424
+ query: `
425
+ SELECT DISTINCT VALUE f
426
+ FROM ${name} f
427
+ JOIN r IN f.${k}
428
+ WHERE LOWER(r.${filter.valueKey}) = LOWER(@value)
429
+ ${lm}`,
430
+ parameters: [{ name: "@value", value: filter.value }]
431
+ }
432
+ }
433
+
434
+ /**
435
+ * @deprecated: should build into Where query
436
+ */
437
+ export function buildLegacyCosmosQuery<PM>(
438
+ filter: LegacyFilter<PM>,
439
+ name: string,
440
+ importedMarkerId: string,
441
+ skip?: number,
442
+ limit?: number
443
+ ) {
444
+ const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
445
+ return {
446
+ query: `
447
+ SELECT f
448
+ FROM ${name} AS f
449
+ WHERE f.id != @id AND f.${
450
+ String(
451
+ filter.by
452
+ )
453
+ } LIKE @filter
454
+ ${lm}`,
455
+ parameters: [
456
+ { name: "@id", value: importedMarkerId },
457
+ {
458
+ name: "@filter",
459
+ value: filter.type === "endsWith"
460
+ ? `%${filter.value}`
461
+ : filter.type === "contains"
462
+ ? `%${filter.value}%`
463
+ : `${filter.value}%`
464
+ }
465
+ ]
466
+ }
467
+ }
468
+
469
+ export function buildWhereCosmosQuery(
470
+ filter: StoreWhereFilter,
471
+ name: string,
472
+ importedMarkerId: string,
473
+ skip?: number,
474
+ limit?: number
475
+ ) {
476
+ const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
477
+ return {
478
+ query: `
479
+ SELECT f
480
+ FROM ${name} AS f
481
+ ${
482
+ filter.where.filter(_ => _.key.includes(".-1."))
483
+ .map(_ => _.key.split(".-1.")[0])
484
+ .map(_ => `JOIN ${_} IN f.${_}`)
485
+ .uniq(Equal.string)
486
+ .join("\n")
487
+ }
488
+ WHERE f.id != @id AND ${
489
+ filter.where
490
+ .map(_ =>
491
+ _.key.includes(".-1.") ?
492
+ { ..._, f: _.key.split(".-1.")[0], key: _.key.split(".-1.")[1]! } :
493
+ { ..._, f: "f" }
494
+ )
495
+ .map(
496
+ (x, i) =>
497
+ x.t === "in"
498
+ ? `ARRAY_CONTAINS(@v${i}, ${x.f}.${x.key})`
499
+ : x.t === "not-in"
500
+ ? `ARRAY_CONTAINS(@v${i}, ${x.f}.${x.key}, false)`
501
+ : x.t === "not-eq"
502
+ ? x.value === null
503
+ ? `IS_NULL(${x.f}.${x.key}) = false`
504
+ : `${lowerIfNeeded(`${x.f}.${x.key}`, x.value)} <> ${lowerIfNeeded(`@v${i}`, x.value)}`
505
+ : x.value === null
506
+ ? `IS_NULL(${x.f}.${x.key}) = true`
507
+ : `${lowerIfNeeded(`${x.f}.${x.key}`, x.value)} = ${lowerIfNeeded(`@v${i}`, x.value)}`
508
+ )
509
+ .join(filter.mode === "or" ? " OR " : " AND ")
510
+ }
511
+ ${lm}`,
512
+ parameters: [
513
+ { name: "@id", value: importedMarkerId },
514
+ ...filter.where
515
+ .map((x, i) => ({
516
+ name: `@v${i}`,
517
+ value: x.value
518
+ }))
519
+ .mutable
520
+ ]
521
+ }
522
+ }
523
+
524
+ const lowerIfNeeded = (key: unknown, value: unknown) => typeof value === "string" ? `LOWER(${key})` : `${key}`
525
+
526
+ export function buildCosmosQuery<PM>(
527
+ filter: LegacyFilter<PM> | StoreWhereFilter,
528
+ name: string,
529
+ importedMarkerId: string,
530
+ skip?: number,
531
+ limit?: number
532
+ ) {
533
+ return filter.type === "startsWith" ||
534
+ filter.type === "endsWith" ||
535
+ filter.type === "contains"
536
+ ? buildLegacyCosmosQuery(filter, name, importedMarkerId, skip, limit)
537
+ : buildWhereCosmosQuery(filter, name, importedMarkerId, skip, limit)
538
+ }
539
+
540
+ class CosmosDbOperationError {
541
+ constructor(readonly message: string) {}
542
+ }
543
+ export function CosmosStoreLive(config: Config<StorageConfig>) {
544
+ return config.config.flatMap(makeCosmosStore).toLayer(StoreMaker)
545
+ }
@@ -0,0 +1,81 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as fu from "@effect-app/infra-adapters/simpledb/fileutil"
3
+
4
+ import fs from "fs"
5
+
6
+ import { makeMemoryStore } from "./Memory.js"
7
+ import type { PersistenceModelType, StorageConfig, Store, StoreConfig } from "./service.js"
8
+ import { StoreMaker } from "./service.js"
9
+
10
+ /**
11
+ * The Disk-backed store, flushes writes in background, but keeps the data in memory
12
+ * and should therefore be as fast as the Memory Store.
13
+ */
14
+ export function makeDiskStore({ prefix }: StorageConfig) {
15
+ return Effect(() => {
16
+ const dir = "./.data"
17
+ if (!fs.existsSync(dir)) {
18
+ fs.mkdirSync(dir)
19
+ }
20
+ return {
21
+ make: <Id extends string, Id2 extends Id, E extends PersistenceModelType<Id>>(
22
+ name: string,
23
+ existing?: Effect<never, never, ROMap<Id2, E>>,
24
+ _config?: StoreConfig<E>
25
+ ) =>
26
+ Effect.gen(function*($) {
27
+ const file = dir + "/" + prefix + name + ".json"
28
+ const fsStore = {
29
+ get: fu
30
+ .readTextFile(file)
31
+ .map(x => JSON.parse(x) as E[])
32
+ .orDie,
33
+ setRaw: (v: Iterable<E>) => JSON.stringify([...v], undefined, 2)["|>"](json => fu.writeTextFile(file, json))
34
+ }
35
+
36
+ const { make } = makeMemoryStore()
37
+
38
+ const store = yield* $(
39
+ make<Id, Id, E>(
40
+ name,
41
+ !fs.existsSync(file)
42
+ ? existing ?? Effect(ROMap.empty)
43
+ : fsStore.get.map(x => ROMap.make(x.map(x => [x.id, x] as const)))
44
+ )
45
+ )
46
+
47
+ yield* $(store.all.flatMap(fsStore.setRaw))
48
+
49
+ const sem = Semaphore.unsafeMake(1)
50
+ const withPermit = sem.withPermits(1)
51
+ const flushToDisk = store.all.flatMap(fsStore.setRaw).apply(withPermit)
52
+ const s: Store<E, Id> = {
53
+ ...store,
54
+ batchSet: flow(store.batchSet, t =>
55
+ t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)),
56
+ bulkSet: flow(store.bulkSet, t =>
57
+ t.tap(() =>
58
+ flushToDisk.tapErrorCause(err =>
59
+ Effect(console.error(err))
60
+ ).forkDaemon
61
+ )),
62
+ set: flow(store.set, t =>
63
+ t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)),
64
+ remove: flow(store.remove, t =>
65
+ t.tap(() =>
66
+ flushToDisk.tapErrorCause(err =>
67
+ Effect(console.error(err))
68
+ ).forkDaemon
69
+ ))
70
+ }
71
+ return s
72
+ })
73
+ }
74
+ })
75
+ }
76
+
77
+ export function DiskStoreLive(config: Config<StorageConfig>) {
78
+ return config.config
79
+ .flatMap(makeDiskStore)
80
+ .toLayer(StoreMaker)
81
+ }
@@ -0,0 +1,77 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import type { Filter, FilterJoinSelect, PersistenceModelType, Store, StoreConfig } from "./service.js"
4
+ import { StoreMaker } from "./service.js"
5
+ import { codeFilter, codeFilterJoinSelect, makeETag, makeUpdateETag } from "./utils.js"
6
+
7
+ export function memFilter<T extends { id: string }>(filter: Filter<T>, cursor?: { skip?: number; limit?: number }) {
8
+ return ((c: Chunk<T>): Chunk<T> => {
9
+ const skip = cursor?.skip
10
+ const limit = cursor?.limit
11
+ if (!skip && limit === 1) {
12
+ return c.findFirstMap(codeFilter(filter)).map(Chunk.make).getOrElse(() => Chunk.empty())
13
+ }
14
+ let r = c.filterMap(codeFilter(filter))
15
+ if (skip) {
16
+ r = r.drop(skip)
17
+ }
18
+ if (limit !== undefined) {
19
+ r = r.take(limit)
20
+ }
21
+ return r.toChunk
22
+ })
23
+ }
24
+
25
+ export const makeMemoryStore = () => ({
26
+ make: <Id extends string, Id2 extends Id, PM extends PersistenceModelType<Id>>(
27
+ name: string,
28
+ existing?: Effect<never, never, ROMap<Id2, PM>>,
29
+ _config?: StoreConfig<PM>
30
+ ) =>
31
+ Effect.gen(function*($) {
32
+ const updateETag = makeUpdateETag(name)
33
+ const items = yield* $(existing ?? Effect(ROMap.empty))
34
+ const store = yield* $(
35
+ Ref.make<ROMap<Id, PM>>(
36
+ ROMap.make([...items.entries()].map(([id, e]) => [id, makeETag(e)]))
37
+ )
38
+ )
39
+ const sem = Semaphore.unsafeMake(1)
40
+ const withPermit = sem.withPermits(1)
41
+ const values = store.get.map(s => s.values())
42
+ const all = values.map(Chunk.fromIterable)
43
+ const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
44
+ items
45
+ .forEachEffect(i => s.find(i.id).flatMap(current => updateETag(i, current)))
46
+ .tap(items =>
47
+ store.get
48
+ .map(m => {
49
+ const mut = ROMap.toMutable(m)
50
+ items.forEach(e => mut.set(e.id, e))
51
+ return ROMap.fromMutable(mut)
52
+ })
53
+ .flatMap(_ => store.set(_))
54
+ )
55
+ .map(_ => _.toReadonlyArray() as NonEmptyReadonlyArray<PM>)
56
+ .apply(withPermit)
57
+ const s: Store<PM, Id> = {
58
+ all,
59
+ find: id => store.get.map(ROMap.lookup(id)),
60
+ filter: (filter: Filter<PM>, cursor?: { skip?: number; limit?: number }) => all.map(memFilter(filter, cursor)),
61
+ filterJoinSelect: <T extends object>(filter: FilterJoinSelect) =>
62
+ all.map(c => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
63
+ set: e =>
64
+ s
65
+ .find(e.id)
66
+ .flatMap(current => updateETag(e, current))
67
+ .tap(e => store.get.map(ROMap.insert(e.id, e)).flatMap(_ => store.set(_)))
68
+ .apply(withPermit),
69
+ batchSet,
70
+ bulkSet: batchSet,
71
+ remove: (e: PM) => store.get.map(ROMap.remove(e.id)).flatMap(_ => store.set(_)).apply(withPermit)
72
+ }
73
+ return s
74
+ })
75
+ })
76
+
77
+ export const MemoryStoreLive = StoreMaker.makeLayer(makeMemoryStore())