effect-app 4.0.0-beta.33 → 4.0.0-beta.331

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 (369) hide show
  1. package/CHANGELOG.md +1628 -0
  2. package/dist/Array.d.ts +2 -1
  3. package/dist/Array.d.ts.map +1 -1
  4. package/dist/Array.js +4 -4
  5. package/dist/Chunk.d.ts.map +1 -1
  6. package/dist/Config/SecretURL.d.ts +3 -1
  7. package/dist/Config/SecretURL.d.ts.map +1 -1
  8. package/dist/Config/SecretURL.js +3 -6
  9. package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
  10. package/dist/Config/internal/configSecretURL.js +2 -2
  11. package/dist/Config.d.ts +2 -0
  12. package/dist/Config.d.ts.map +1 -0
  13. package/dist/Config.js +8 -0
  14. package/dist/ConfigProvider.d.ts +2 -0
  15. package/dist/ConfigProvider.d.ts.map +1 -0
  16. package/dist/ConfigProvider.js +6 -0
  17. package/dist/{ServiceMap.d.ts → Context.d.ts} +18 -20
  18. package/dist/Context.d.ts.map +1 -0
  19. package/dist/Context.js +67 -0
  20. package/dist/DataDependencies.d.ts +136 -0
  21. package/dist/DataDependencies.d.ts.map +1 -0
  22. package/dist/DataDependencies.js +112 -0
  23. package/dist/Effect.d.ts +10 -9
  24. package/dist/Effect.d.ts.map +1 -1
  25. package/dist/Effect.js +6 -9
  26. package/dist/Emailer.d.ts +51 -0
  27. package/dist/Emailer.d.ts.map +1 -0
  28. package/dist/Emailer.js +7 -0
  29. package/dist/Function.d.ts.map +1 -1
  30. package/dist/Layer.d.ts +10 -6
  31. package/dist/Layer.d.ts.map +1 -1
  32. package/dist/Layer.js +3 -2
  33. package/dist/Model/Repository/Registry.d.ts +22 -0
  34. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  35. package/dist/Model/Repository/Registry.js +18 -0
  36. package/dist/Model/Repository/dependency.d.ts +6 -0
  37. package/dist/Model/Repository/dependency.d.ts.map +1 -0
  38. package/dist/Model/Repository/dependency.js +29 -0
  39. package/dist/Model/Repository/ext.d.ts +60 -0
  40. package/dist/Model/Repository/ext.d.ts.map +1 -0
  41. package/dist/Model/Repository/ext.js +124 -0
  42. package/dist/Model/Repository/internal/internal.d.ts +68 -0
  43. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  44. package/dist/Model/Repository/internal/internal.js +611 -0
  45. package/dist/Model/Repository/legacy.d.ts +21 -0
  46. package/dist/Model/Repository/legacy.d.ts.map +1 -0
  47. package/dist/Model/Repository/legacy.js +2 -0
  48. package/dist/Model/Repository/makeRepo.d.ts +71 -0
  49. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  50. package/dist/Model/Repository/makeRepo.js +30 -0
  51. package/dist/Model/Repository/service.d.ts +121 -0
  52. package/dist/Model/Repository/service.d.ts.map +1 -0
  53. package/dist/Model/Repository/service.js +2 -0
  54. package/dist/Model/Repository/validation.d.ts +72 -0
  55. package/dist/Model/Repository/validation.d.ts.map +1 -0
  56. package/dist/Model/Repository/validation.js +39 -0
  57. package/dist/Model/Repository.d.ts +8 -0
  58. package/dist/Model/Repository.d.ts.map +1 -0
  59. package/dist/Model/Repository.js +8 -0
  60. package/dist/Model/dsl.d.ts +33 -0
  61. package/dist/Model/dsl.d.ts.map +1 -0
  62. package/dist/Model/dsl.js +43 -0
  63. package/dist/Model/filter/filterApi.d.ts +30 -0
  64. package/dist/Model/filter/filterApi.d.ts.map +1 -0
  65. package/dist/Model/filter/filterApi.js +2 -0
  66. package/dist/Model/filter/types/errors.d.ts +29 -0
  67. package/dist/Model/filter/types/errors.d.ts.map +1 -0
  68. package/dist/Model/filter/types/errors.js +2 -0
  69. package/dist/Model/filter/types/fields.d.ts +15 -0
  70. package/dist/Model/filter/types/fields.d.ts.map +1 -0
  71. package/dist/Model/filter/types/fields.js +2 -0
  72. package/dist/Model/filter/types/path/common.d.ts +316 -0
  73. package/dist/Model/filter/types/path/common.d.ts.map +1 -0
  74. package/dist/Model/filter/types/path/common.js +2 -0
  75. package/dist/Model/filter/types/path/eager.d.ts +94 -0
  76. package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
  77. package/dist/Model/filter/types/path/eager.js +36 -0
  78. package/dist/Model/filter/types/path/index.d.ts +4 -0
  79. package/dist/Model/filter/types/path/index.d.ts.map +1 -0
  80. package/dist/Model/filter/types/path/index.js +3 -0
  81. package/dist/Model/filter/types/utils.d.ts +79 -0
  82. package/dist/Model/filter/types/utils.d.ts.map +1 -0
  83. package/dist/Model/filter/types/utils.js +2 -0
  84. package/dist/Model/filter/types/validator.d.ts +30 -0
  85. package/dist/Model/filter/types/validator.d.ts.map +1 -0
  86. package/dist/Model/filter/types/validator.js +2 -0
  87. package/dist/Model/filter/types.d.ts +5 -0
  88. package/dist/Model/filter/types.d.ts.map +1 -0
  89. package/dist/Model/filter/types.js +7 -0
  90. package/dist/Model/query/dsl.d.ts +630 -0
  91. package/dist/Model/query/dsl.d.ts.map +1 -0
  92. package/dist/Model/query/dsl.js +376 -0
  93. package/dist/Model/query/new-kid-interpreter.d.ts +132 -0
  94. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
  95. package/dist/Model/query/new-kid-interpreter.js +370 -0
  96. package/dist/Model/query.d.ts +15 -0
  97. package/dist/Model/query.d.ts.map +1 -0
  98. package/dist/Model/query.js +3 -0
  99. package/dist/Model.d.ts +6 -0
  100. package/dist/Model.d.ts.map +1 -0
  101. package/dist/Model.js +6 -0
  102. package/dist/NonEmptySet.d.ts +3 -1
  103. package/dist/NonEmptySet.d.ts.map +1 -1
  104. package/dist/NonEmptySet.js +2 -2
  105. package/dist/Option.d.ts +1 -0
  106. package/dist/Option.d.ts.map +1 -1
  107. package/dist/Option.js +3 -1
  108. package/dist/Pure.d.ts +7 -5
  109. package/dist/Pure.d.ts.map +1 -1
  110. package/dist/Pure.js +7 -4
  111. package/dist/QueueMaker.d.ts +11 -0
  112. package/dist/QueueMaker.d.ts.map +1 -0
  113. package/dist/QueueMaker.js +11 -0
  114. package/dist/RequestContext.d.ts +87 -0
  115. package/dist/RequestContext.d.ts.map +1 -0
  116. package/dist/RequestContext.js +45 -0
  117. package/dist/RequestScopedDependencies.d.ts +21 -0
  118. package/dist/RequestScopedDependencies.d.ts.map +1 -0
  119. package/dist/RequestScopedDependencies.js +16 -0
  120. package/dist/Schema/Class.d.ts +200 -20
  121. package/dist/Schema/Class.d.ts.map +1 -1
  122. package/dist/Schema/Class.js +268 -17
  123. package/dist/Schema/FastCheck.d.ts.map +1 -1
  124. package/dist/Schema/SchemaParser.d.ts +5 -0
  125. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  126. package/dist/Schema/SchemaParser.js +6 -0
  127. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  128. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  129. package/dist/Schema/SpecialJsonSchema.js +117 -0
  130. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  131. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  132. package/dist/Schema/SpecialOpenApi.js +123 -0
  133. package/dist/Schema/brand.d.ts +5 -5
  134. package/dist/Schema/brand.d.ts.map +1 -1
  135. package/dist/Schema/brand.js +3 -1
  136. package/dist/Schema/email.d.ts.map +1 -1
  137. package/dist/Schema/email.js +12 -6
  138. package/dist/Schema/ext.d.ts +335 -61
  139. package/dist/Schema/ext.d.ts.map +1 -1
  140. package/dist/Schema/ext.js +388 -63
  141. package/dist/Schema/moreStrings.d.ts +82 -36
  142. package/dist/Schema/moreStrings.d.ts.map +1 -1
  143. package/dist/Schema/moreStrings.js +90 -53
  144. package/dist/Schema/numbers.d.ts +33 -21
  145. package/dist/Schema/numbers.d.ts.map +1 -1
  146. package/dist/Schema/numbers.js +65 -12
  147. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  148. package/dist/Schema/phoneNumber.js +11 -7
  149. package/dist/Schema/schema.d.ts +1 -1
  150. package/dist/Schema/schema.d.ts.map +1 -1
  151. package/dist/Schema/schema.js +2 -2
  152. package/dist/Schema/strings.d.ts +18 -4
  153. package/dist/Schema/strings.d.ts.map +1 -1
  154. package/dist/Schema/strings.js +1 -5
  155. package/dist/Schema.d.ts +225 -7
  156. package/dist/Schema.d.ts.map +1 -1
  157. package/dist/Schema.js +193 -26
  158. package/dist/SchemaAST.d.ts +2 -0
  159. package/dist/SchemaAST.d.ts.map +1 -0
  160. package/dist/SchemaAST.js +2 -0
  161. package/dist/Set.d.ts +4 -1
  162. package/dist/Set.d.ts.map +1 -1
  163. package/dist/Set.js +3 -2
  164. package/dist/Store.d.ts +215 -0
  165. package/dist/Store.d.ts.map +1 -0
  166. package/dist/Store.js +113 -0
  167. package/dist/_ext/Array.d.ts +1 -1
  168. package/dist/_ext/Array.d.ts.map +1 -1
  169. package/dist/_ext/Array.js +4 -2
  170. package/dist/_ext/misc.d.ts +4 -1
  171. package/dist/_ext/misc.d.ts.map +1 -1
  172. package/dist/_ext/misc.js +4 -2
  173. package/dist/_ext/ord.ext.d.ts +2 -1
  174. package/dist/_ext/ord.ext.d.ts.map +1 -1
  175. package/dist/_ext/ord.ext.js +2 -2
  176. package/dist/builtin.d.ts +2 -14
  177. package/dist/builtin.d.ts.map +1 -1
  178. package/dist/builtin.js +1 -1
  179. package/dist/client/InvalidationKeys.d.ts +30 -0
  180. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  181. package/dist/client/InvalidationKeys.js +37 -0
  182. package/dist/client/apiClientFactory.d.ts +19 -31
  183. package/dist/client/apiClientFactory.d.ts.map +1 -1
  184. package/dist/client/apiClientFactory.js +157 -39
  185. package/dist/client/clientFor.d.ts +54 -18
  186. package/dist/client/clientFor.d.ts.map +1 -1
  187. package/dist/client/clientFor.js +9 -1
  188. package/dist/client/errors.d.ts +82 -27
  189. package/dist/client/errors.d.ts.map +1 -1
  190. package/dist/client/errors.js +75 -19
  191. package/dist/client/makeClient.d.ts +490 -34
  192. package/dist/client/makeClient.d.ts.map +1 -1
  193. package/dist/client/makeClient.js +62 -30
  194. package/dist/client.d.ts +2 -0
  195. package/dist/client.d.ts.map +1 -1
  196. package/dist/client.js +3 -1
  197. package/dist/faker.d.ts.map +1 -1
  198. package/dist/http/Request.d.ts +1 -1
  199. package/dist/http/Request.d.ts.map +1 -1
  200. package/dist/http/Request.js +2 -2
  201. package/dist/ids.d.ts +32 -14
  202. package/dist/ids.d.ts.map +1 -1
  203. package/dist/ids.js +38 -6
  204. package/dist/index.d.ts +6 -7
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +8 -8
  207. package/dist/middleware.d.ts +13 -7
  208. package/dist/middleware.d.ts.map +1 -1
  209. package/dist/middleware.js +14 -8
  210. package/dist/rpc/Invalidation.d.ts +1124 -0
  211. package/dist/rpc/Invalidation.d.ts.map +1 -0
  212. package/dist/rpc/Invalidation.js +178 -0
  213. package/dist/rpc/MiddlewareMaker.d.ts +11 -7
  214. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  215. package/dist/rpc/MiddlewareMaker.js +59 -38
  216. package/dist/rpc/RpcContextMap.d.ts +3 -3
  217. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  218. package/dist/rpc/RpcContextMap.js +4 -4
  219. package/dist/rpc/RpcMiddleware.d.ts +14 -10
  220. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  221. package/dist/rpc/RpcMiddleware.js +1 -1
  222. package/dist/rpc.d.ts +1 -1
  223. package/dist/rpc.d.ts.map +1 -1
  224. package/dist/rpc.js +2 -2
  225. package/dist/runtime.d.ts +19 -0
  226. package/dist/runtime.d.ts.map +1 -0
  227. package/dist/runtime.js +40 -0
  228. package/dist/setupRequest.d.ts +20 -0
  229. package/dist/setupRequest.d.ts.map +1 -0
  230. package/dist/setupRequest.js +72 -0
  231. package/dist/toast.d.ts +51 -0
  232. package/dist/toast.d.ts.map +1 -0
  233. package/dist/toast.js +34 -0
  234. package/dist/transform.d.ts +1 -1
  235. package/dist/transform.d.ts.map +1 -1
  236. package/dist/transform.js +4 -5
  237. package/dist/utils/effectify.d.ts +1 -1
  238. package/dist/utils/effectify.d.ts.map +1 -1
  239. package/dist/utils/effectify.js +2 -2
  240. package/dist/utils/extend.d.ts.map +1 -1
  241. package/dist/utils/gen.d.ts +4 -4
  242. package/dist/utils/gen.d.ts.map +1 -1
  243. package/dist/utils/logLevel.d.ts +2 -2
  244. package/dist/utils/logLevel.d.ts.map +1 -1
  245. package/dist/utils/logger.d.ts +4 -3
  246. package/dist/utils/logger.d.ts.map +1 -1
  247. package/dist/utils/logger.js +4 -4
  248. package/dist/utils.d.ts +34 -39
  249. package/dist/utils.d.ts.map +1 -1
  250. package/dist/utils.js +33 -37
  251. package/dist/validation/validators.d.ts.map +1 -1
  252. package/dist/validation.d.ts.map +1 -1
  253. package/dist/withToast.d.ts +30 -0
  254. package/dist/withToast.d.ts.map +1 -0
  255. package/dist/withToast.js +64 -0
  256. package/package.json +27 -251
  257. package/src/Array.ts +5 -5
  258. package/src/Chunk.ts +3 -3
  259. package/src/Config/SecretURL.ts +6 -3
  260. package/src/Config/internal/configSecretURL.ts +2 -2
  261. package/src/Config.ts +7 -0
  262. package/src/ConfigProvider.ts +5 -0
  263. package/src/{ServiceMap.ts → Context.ts} +56 -63
  264. package/src/DataDependencies.ts +171 -0
  265. package/src/Effect.ts +15 -17
  266. package/src/Emailer.ts +51 -0
  267. package/src/Inputify.type.ts +1 -1
  268. package/src/Layer.ts +11 -7
  269. package/src/Model/Repository/Registry.ts +35 -0
  270. package/src/Model/Repository/dependency.ts +32 -0
  271. package/src/Model/Repository/ext.ts +374 -0
  272. package/src/Model/Repository/internal/internal.ts +988 -0
  273. package/src/Model/Repository/legacy.ts +29 -0
  274. package/src/Model/Repository/makeRepo.ts +168 -0
  275. package/src/Model/Repository/service.ts +676 -0
  276. package/src/Model/Repository/validation.ts +38 -0
  277. package/src/Model/Repository.ts +7 -0
  278. package/src/Model/dsl.ts +129 -0
  279. package/src/Model/filter/filterApi.ts +78 -0
  280. package/src/Model/filter/types/errors.ts +47 -0
  281. package/src/Model/filter/types/fields.ts +50 -0
  282. package/src/Model/filter/types/path/common.ts +404 -0
  283. package/src/Model/filter/types/path/eager.ts +329 -0
  284. package/src/Model/filter/types/path/index.ts +4 -0
  285. package/src/Model/filter/types/utils.ts +128 -0
  286. package/src/Model/filter/types/validator.ts +46 -0
  287. package/src/Model/filter/types.ts +6 -0
  288. package/src/Model/query/dsl.ts +3092 -0
  289. package/src/Model/query/new-kid-interpreter.ts +532 -0
  290. package/src/Model/query.ts +13 -0
  291. package/src/Model.ts +5 -0
  292. package/src/NonEmptySet.ts +6 -4
  293. package/src/Option.ts +2 -0
  294. package/src/Pure.ts +10 -7
  295. package/src/QueueMaker.ts +11 -0
  296. package/src/RequestContext.ts +48 -0
  297. package/src/RequestScopedDependencies.ts +45 -0
  298. package/src/Schema/Class.ts +648 -60
  299. package/src/Schema/SchemaParser.ts +12 -0
  300. package/src/Schema/SpecialJsonSchema.ts +137 -0
  301. package/src/Schema/SpecialOpenApi.ts +130 -0
  302. package/src/Schema/brand.ts +24 -9
  303. package/src/Schema/email.ts +14 -7
  304. package/src/Schema/ext.ts +508 -102
  305. package/src/Schema/moreStrings.ts +217 -86
  306. package/src/Schema/numbers.ts +107 -28
  307. package/src/Schema/phoneNumber.ts +13 -9
  308. package/src/Schema/schema.ts +1 -1
  309. package/src/Schema/strings.ts +23 -14
  310. package/src/Schema.ts +403 -46
  311. package/src/SchemaAST.ts +1 -0
  312. package/src/Set.ts +6 -2
  313. package/src/Store.ts +325 -0
  314. package/src/_ext/Array.ts +4 -2
  315. package/src/_ext/misc.ts +4 -1
  316. package/src/_ext/ord.ext.ts +2 -1
  317. package/src/builtin-json.d.ts +24 -0
  318. package/src/builtin.ts +16 -21
  319. package/src/client/InvalidationKeys.ts +55 -0
  320. package/src/client/apiClientFactory.ts +301 -141
  321. package/src/client/clientFor.ts +107 -34
  322. package/src/client/errors.ts +100 -29
  323. package/src/client/makeClient.ts +594 -80
  324. package/src/client.ts +6 -4
  325. package/src/http/Request.ts +3 -3
  326. package/src/http.ts +1 -1
  327. package/src/ids.ts +45 -7
  328. package/src/index.ts +20 -23
  329. package/src/middleware.ts +13 -9
  330. package/src/rpc/Invalidation.ts +278 -0
  331. package/src/rpc/MiddlewareMaker.ts +88 -80
  332. package/src/rpc/README.md +2 -2
  333. package/src/rpc/RpcContextMap.ts +7 -6
  334. package/src/rpc/RpcMiddleware.ts +19 -13
  335. package/src/rpc.ts +4 -4
  336. package/src/runtime.ts +57 -0
  337. package/src/setupRequest.ts +138 -0
  338. package/src/toast.ts +54 -0
  339. package/src/transform.ts +4 -4
  340. package/src/utils/effectify.ts +1 -1
  341. package/src/utils/gen.ts +8 -8
  342. package/src/utils/logLevel.ts +1 -1
  343. package/src/utils/logger.ts +4 -3
  344. package/src/utils.ts +85 -158
  345. package/src/validation.ts +2 -2
  346. package/src/withToast.ts +133 -0
  347. package/test/dist/rpc.test.d.ts.map +1 -1
  348. package/test/dist/rpcMiddlewareContext.test.d.ts.map +1 -0
  349. package/test/dist/secretURL.test.d.ts.map +1 -0
  350. package/test/dist/special.test.d.ts.map +1 -0
  351. package/test/moreStrings.test.ts +55 -10
  352. package/test/rpc.test.ts +38 -10
  353. package/test/rpcMiddlewareContext.test.ts +63 -0
  354. package/test/schema.test.ts +505 -26
  355. package/test/secretURL.test.ts +160 -0
  356. package/test/special.test.ts +1261 -0
  357. package/test/utils.test.ts +7 -7
  358. package/tsconfig.base.json +6 -5
  359. package/tsconfig.json +9 -2
  360. package/tsconfig.src.json +29 -29
  361. package/tsconfig.test.json +2 -2
  362. package/dist/Operations.d.ts +0 -123
  363. package/dist/Operations.d.ts.map +0 -1
  364. package/dist/Operations.js +0 -29
  365. package/dist/ServiceMap.d.ts.map +0 -1
  366. package/dist/ServiceMap.js +0 -91
  367. package/eslint.config.mjs +0 -26
  368. package/src/Operations.ts +0 -55
  369. package/tsconfig.json.bak +0 -12
@@ -0,0 +1,374 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
3
+ import * as Exit from "effect/Exit"
4
+ import * as Request from "effect/Request"
5
+ import * as RequestResolver from "effect/RequestResolver"
6
+ import * as Array from "../../Array.ts"
7
+ import type { NonEmptyArray } from "../../Array.ts"
8
+ import { type DatabaseError, type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../../client/errors.ts"
9
+ import * as Effect from "../../Effect.ts"
10
+ import * as Option from "../../Option.ts"
11
+ import { type FixEnv, type PureEnv, runTerm } from "../../Pure.ts"
12
+ import { AnyPureDSL } from "../dsl.ts"
13
+ import type { FieldValues } from "../filter/types.ts"
14
+ import type { Query, QueryEnd, QueryWhere } from "../query.ts"
15
+ import * as Q from "../query.ts"
16
+ import type { Repository } from "./service.ts"
17
+
18
+ interface BatchOptions {
19
+ readonly batch?: true | number
20
+ }
21
+
22
+ const asReadonlyArray = <T>(itemOrItems: T | ReadonlyArray<T>): ReadonlyArray<T> =>
23
+ globalThis.Array.isArray(itemOrItems)
24
+ ? itemOrItems as ReadonlyArray<T>
25
+ : [itemOrItems as T]
26
+
27
+ const getBatchSize = (batch?: true | number) =>
28
+ batch === true
29
+ ? 100
30
+ : typeof batch === "number" && Number.isFinite(batch) && batch > 0
31
+ ? Math.floor(batch)
32
+ : undefined
33
+
34
+ export const extendRepo = <
35
+ T,
36
+ Encoded extends FieldValues,
37
+ Evt,
38
+ ItemType extends string,
39
+ IdKey extends keyof T & keyof Encoded,
40
+ RSchema,
41
+ RPublish,
42
+ RProvided = never
43
+ >(
44
+ repo: Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided>
45
+ ) => {
46
+ const get = (id: T[IdKey]) =>
47
+ repo.find(id).pipe(
48
+ Effect.flatMap(Option.match({
49
+ onNone: () => Effect.fail(new NotFoundError<ItemType>({ type: repo.itemType, id })),
50
+ onSome: Effect.succeed
51
+ }))
52
+ )
53
+ function saveManyWithPure_<
54
+ R,
55
+ A,
56
+ E,
57
+ S1 extends T,
58
+ S2 extends T
59
+ >(
60
+ items: Iterable<S1>,
61
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
62
+ ) {
63
+ return saveAllWithEffectInt(
64
+ runTerm(pure, [...items])
65
+ )
66
+ }
67
+
68
+ function saveWithPure_<
69
+ R,
70
+ A,
71
+ E,
72
+ S1 extends T,
73
+ S2 extends T
74
+ >(
75
+ item: S1,
76
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, S1, S2>>
77
+ ) {
78
+ return saveAllWithEffectInt(
79
+ runTerm(pure, item)
80
+ .pipe(Effect
81
+ .map(([item, events, a]) => [[item], events, a]))
82
+ )
83
+ }
84
+
85
+ function saveAllWithEffectInt<
86
+ P extends T,
87
+ R,
88
+ E,
89
+ A
90
+ >(
91
+ gen: Effect.Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
92
+ ): Effect.Effect<
93
+ A,
94
+ E | InvalidStateError | OptimisticConcurrencyException | DatabaseError,
95
+ R | RSchema | RPublish
96
+ > {
97
+ return Effect.flatMap(gen, ([items, events, a]) => repo.saveAndPublish(items, events).pipe(Effect.map(() => a)))
98
+ }
99
+
100
+ function saveManyWithPureBatched_<
101
+ R,
102
+ A,
103
+ E,
104
+ S1 extends T,
105
+ S2 extends T
106
+ >(
107
+ items: Iterable<S1>,
108
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>,
109
+ batchSize = 100
110
+ ) {
111
+ return Effect.forEach(
112
+ Array.chunksOf(items, batchSize),
113
+ (batch) =>
114
+ saveAllWithEffectInt(
115
+ runTerm(pure, batch)
116
+ )
117
+ )
118
+ }
119
+
120
+ type PureStoreError = InvalidStateError | OptimisticConcurrencyException | DatabaseError
121
+
122
+ const queryAndSavePure: {
123
+ <A, E2, R2, T2 extends T>(
124
+ q: (
125
+ q: Query<Encoded>
126
+ ) => QueryEnd<Encoded, "one">,
127
+ pure: Effect.Effect<A, E2, FixEnv<R2, Evt, T, T2>>
128
+ ): Effect.Effect<
129
+ A,
130
+ PureStoreError | NotFoundError<ItemType> | E2,
131
+ | RSchema
132
+ | RPublish
133
+ | Exclude<R2, {
134
+ env: PureEnv<Evt, T, T2>
135
+ }>
136
+ >
137
+ <A, E2, R2, T2 extends T>(
138
+ q: (
139
+ q: Query<Encoded>
140
+ ) =>
141
+ | Query<Encoded>
142
+ | QueryWhere<Encoded>
143
+ | QueryEnd<Encoded>,
144
+ pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
145
+ ): Effect.Effect<
146
+ A,
147
+ PureStoreError | E2,
148
+ | RSchema
149
+ | RPublish
150
+ | Exclude<R2, {
151
+ env: PureEnv<Evt, readonly T[], readonly T2[]>
152
+ }>
153
+ >
154
+ <A, E2, R2, T2 extends T>(
155
+ q: (
156
+ q: Query<Encoded>
157
+ ) =>
158
+ | Query<Encoded>
159
+ | QueryWhere<Encoded>
160
+ | QueryEnd<Encoded>,
161
+ pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>,
162
+ batch: "batched" | number
163
+ ): Effect.Effect<
164
+ A[],
165
+ PureStoreError | E2,
166
+ | RSchema
167
+ | RPublish
168
+ | Exclude<R2, {
169
+ env: PureEnv<Evt, readonly T[], readonly T2[]>
170
+ }>
171
+ >
172
+ } = ((q: any, pure: any, batch?: "batched" | number) =>
173
+ // Overload dispatch: query returns T | T[]; pure helpers are generic on item shape.
174
+ // Runtime path is query → pure term → saveAndPublish (which raises DatabaseError).
175
+ repo.query(q).pipe(
176
+ Effect.andThen((_) =>
177
+ Array.isArray(_)
178
+ ? batch === undefined
179
+ ? saveManyWithPure_(_ as T[], pure)
180
+ : saveManyWithPureBatched_(_ as T[], pure, batch === "batched" ? 100 : batch)
181
+ : saveWithPure_(_ as T, pure)
182
+ )
183
+ )) as typeof queryAndSavePure
184
+
185
+ const saveManyWithPure: {
186
+ <R, A, E, S1 extends T, S2 extends T>(
187
+ items: Iterable<S1>,
188
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
189
+ ): Effect.Effect<
190
+ A,
191
+ PureStoreError | E,
192
+ | RSchema
193
+ | RPublish
194
+ | Exclude<R, {
195
+ env: PureEnv<Evt, readonly S1[], readonly S2[]>
196
+ }>
197
+ >
198
+ <R, A, E, S1 extends T, S2 extends T>(
199
+ items: Iterable<S1>,
200
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>,
201
+ batch: "batched" | number
202
+ ): Effect.Effect<
203
+ A[],
204
+ PureStoreError | E,
205
+ | RSchema
206
+ | RPublish
207
+ | Exclude<R, {
208
+ env: PureEnv<Evt, readonly S1[], readonly S2[]>
209
+ }>
210
+ >
211
+ } = ((items: Iterable<T>, pure: any, batch?: "batched" | number) =>
212
+ batch
213
+ ? Effect.forEach(
214
+ Array.chunksOf([...items], batch === "batched" ? 100 : batch),
215
+ (batchItems) =>
216
+ saveAllWithEffectInt(
217
+ runTerm(pure, batchItems as any)
218
+ )
219
+ )
220
+ : saveAllWithEffectInt(
221
+ runTerm(pure, [...items] as any)
222
+ )) as typeof saveManyWithPure
223
+
224
+ const byIdAndSaveWithPure: {
225
+ <R, A, E, S2 extends T>(
226
+ id: T[IdKey],
227
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, T, S2>>
228
+ ): Effect.Effect<
229
+ A,
230
+ PureStoreError | NotFoundError<ItemType> | E,
231
+ | RSchema
232
+ | RPublish
233
+ | Exclude<R, {
234
+ env: PureEnv<Evt, T, S2>
235
+ }>
236
+ >
237
+ } = (id, pure) => get(id).pipe(Effect.flatMap((item) => saveWithPure_(item, pure)))
238
+
239
+ // query can raise DatabaseError; NotFound is completed per-entry. Dual package
240
+ // round-trips may still surface other store errors via failCause — keep channel honest.
241
+ type Req =
242
+ & Request.Request<T, NotFoundError<ItemType> | DatabaseError>
243
+ & { _tag: `Get${ItemType}`; id: T[IdKey] }
244
+ const _request = Request.tagged<Req>(`Get${repo.itemType}`)
245
+
246
+ const requestResolver = RequestResolver
247
+ .make((
248
+ entries: NonEmptyArray<Request.Entry<Req>>,
249
+ _key: unknown
250
+ ) =>
251
+ (repo.query(Q.where(repo.idKey as any, "in" as any, entries.map((_) => _.request.id)) as any) as Effect.Effect<
252
+ readonly T[],
253
+ DatabaseError
254
+ >)
255
+ .pipe(
256
+ Effect.andThen((items) =>
257
+ Effect.forEach(entries, (entry) =>
258
+ Request.complete(
259
+ Array
260
+ .findFirst(items, (_) => _[repo.idKey] === entry.request.id)
261
+ .pipe(Option.match({
262
+ onNone: () => Exit.fail(new NotFoundError({ type: repo.itemType, id: entry.request.id })),
263
+ onSome: Exit.succeed
264
+ }))
265
+ )(entry), { discard: true })
266
+ ),
267
+ Effect
268
+ .catchCause((cause) =>
269
+ Effect.forEach(entries, (entry) => Request.complete(Exit.failCause(cause))(entry), { discard: true })
270
+ )
271
+ )
272
+ )
273
+ .pipe(
274
+ RequestResolver.batchN(20)
275
+ )
276
+
277
+ const exts = {
278
+ request: (id: T[IdKey]) => Effect.request(_request({ id }), requestResolver),
279
+ get,
280
+ log: (evt: Evt) => AnyPureDSL.log(evt),
281
+ /**
282
+ * Enables chunked writes for large batches via `options.batch`.
283
+ * Note: batching breaks transactional properties because chunks are saved independently.
284
+ */
285
+ save: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
286
+ const items = asReadonlyArray(itemOrItems)
287
+ if (!Array.isReadonlyArrayNonEmpty(items)) {
288
+ return Effect.void
289
+ }
290
+ const batchSize = getBatchSize(options?.batch)
291
+ if (batchSize === undefined) {
292
+ return repo.saveAndPublish(items)
293
+ }
294
+ return Effect.forEach(
295
+ Array.chunksOf(items, batchSize),
296
+ (batch) => repo.saveAndPublish(batch),
297
+ { discard: true }
298
+ )
299
+ },
300
+ saveWithEvents: (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => repo.saveAndPublish(items, events),
301
+ /**
302
+ * Enables chunked deletes for large batches via `options.batch`.
303
+ * Note: batching breaks transactional properties because chunks are removed independently.
304
+ */
305
+ remove: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
306
+ const items = asReadonlyArray(itemOrItems)
307
+ if (!Array.isReadonlyArrayNonEmpty(items)) {
308
+ return Effect.void as Effect.Effect<void, DatabaseError, RSchema | RPublish>
309
+ }
310
+ const batchSize = getBatchSize(options?.batch)
311
+ if (batchSize === undefined) {
312
+ return repo.removeAndPublish(items)
313
+ }
314
+ return Effect.forEach(
315
+ Array.chunksOf(items, batchSize),
316
+ (batch) => repo.removeAndPublish(batch),
317
+ { discard: true }
318
+ )
319
+ },
320
+ /**
321
+ * Enables chunked deletes for large batches via `options.batch`.
322
+ * Note: batching breaks transactional properties because chunks are removed independently.
323
+ */
324
+ removeById: (idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>, options?: BatchOptions) => {
325
+ const ids = asReadonlyArray(idOrIds)
326
+ if (!Array.isReadonlyArrayNonEmpty(ids)) {
327
+ return Effect.void as Effect.Effect<void, DatabaseError, RSchema>
328
+ }
329
+ const batchSize = getBatchSize(options?.batch)
330
+ if (batchSize === undefined) {
331
+ return repo.removeById(ids)
332
+ }
333
+ return Effect.forEach(
334
+ Array.chunksOf(ids, batchSize),
335
+ (batch) => repo.removeById(batch),
336
+ { discard: true }
337
+ )
338
+ },
339
+ queryAndSavePure,
340
+ saveManyWithPure,
341
+ byIdAndSaveWithPure,
342
+ saveWithPure: <
343
+ R,
344
+ A,
345
+ E,
346
+ S1 extends T,
347
+ S2 extends T
348
+ >(
349
+ item: S1,
350
+ pure: Effect.Effect<A, E, FixEnv<R, Evt, S1, S2>>
351
+ ) =>
352
+ saveAllWithEffectInt(
353
+ runTerm(pure, item)
354
+ .pipe(Effect.map(([item, events, a]) => [[item], events, a]))
355
+ )
356
+ }
357
+
358
+ return {
359
+ ...repo,
360
+ ...exts
361
+ } as Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided> & typeof exts
362
+ }
363
+
364
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
365
+ export interface ExtendedRepository<
366
+ T,
367
+ Encoded extends FieldValues,
368
+ Evt,
369
+ ItemType extends string,
370
+ IdKey extends keyof T & keyof Encoded,
371
+ RSchema,
372
+ RPublish,
373
+ RProvided = never
374
+ > extends ReturnType<typeof extendRepo<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided>> {}