effect-app 4.0.0-beta.26 → 4.0.0-beta.260

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 (365) hide show
  1. package/CHANGELOG.md +1192 -0
  2. package/dist/Array.d.ts +3 -2
  3. package/dist/Array.d.ts.map +1 -1
  4. package/dist/Array.js +4 -4
  5. package/dist/Chunk.d.ts +1 -1
  6. package/dist/Chunk.d.ts.map +1 -1
  7. package/dist/Config/SecretURL.d.ts +4 -2
  8. package/dist/Config/SecretURL.d.ts.map +1 -1
  9. package/dist/Config/SecretURL.js +3 -6
  10. package/dist/Config/internal/configSecretURL.d.ts +1 -1
  11. package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
  12. package/dist/Config/internal/configSecretURL.js +2 -2
  13. package/dist/Config.d.ts +7 -0
  14. package/dist/Config.d.ts.map +1 -0
  15. package/dist/Config.js +6 -0
  16. package/dist/ConfigProvider.d.ts +39 -0
  17. package/dist/ConfigProvider.d.ts.map +1 -0
  18. package/dist/ConfigProvider.js +42 -0
  19. package/dist/Context.d.ts +42 -0
  20. package/dist/Context.d.ts.map +1 -0
  21. package/dist/Context.js +67 -0
  22. package/dist/Effect.d.ts +13 -12
  23. package/dist/Effect.d.ts.map +1 -1
  24. package/dist/Effect.js +5 -8
  25. package/dist/Emailer.d.ts +51 -0
  26. package/dist/Emailer.d.ts.map +1 -0
  27. package/dist/Emailer.js +7 -0
  28. package/dist/Function.d.ts +1 -1
  29. package/dist/Function.d.ts.map +1 -1
  30. package/dist/Inputify.type.d.ts +1 -1
  31. package/dist/Layer.d.ts +11 -7
  32. package/dist/Layer.d.ts.map +1 -1
  33. package/dist/Layer.js +3 -2
  34. package/dist/Model/Repository/Registry.d.ts +21 -0
  35. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  36. package/dist/Model/Repository/Registry.js +18 -0
  37. package/dist/Model/Repository/ext.d.ts +60 -0
  38. package/dist/Model/Repository/ext.d.ts.map +1 -0
  39. package/dist/Model/Repository/ext.js +122 -0
  40. package/dist/Model/Repository/internal/internal.d.ts +63 -0
  41. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  42. package/dist/Model/Repository/internal/internal.js +430 -0
  43. package/dist/Model/Repository/legacy.d.ts +21 -0
  44. package/dist/Model/Repository/legacy.d.ts.map +1 -0
  45. package/dist/Model/Repository/legacy.js +2 -0
  46. package/dist/Model/Repository/makeRepo.d.ts +54 -0
  47. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  48. package/dist/Model/Repository/makeRepo.js +27 -0
  49. package/dist/Model/Repository/service.d.ts +121 -0
  50. package/dist/Model/Repository/service.d.ts.map +1 -0
  51. package/dist/Model/Repository/service.js +2 -0
  52. package/dist/Model/Repository/validation.d.ts +58 -0
  53. package/dist/Model/Repository/validation.d.ts.map +1 -0
  54. package/dist/Model/Repository/validation.js +32 -0
  55. package/dist/Model/Repository.d.ts +7 -0
  56. package/dist/Model/Repository.d.ts.map +1 -0
  57. package/dist/Model/Repository.js +7 -0
  58. package/dist/Model/dsl.d.ts +33 -0
  59. package/dist/Model/dsl.d.ts.map +1 -0
  60. package/dist/Model/dsl.js +43 -0
  61. package/dist/Model/filter/filterApi.d.ts +30 -0
  62. package/dist/Model/filter/filterApi.d.ts.map +1 -0
  63. package/dist/Model/filter/filterApi.js +2 -0
  64. package/dist/Model/filter/types/errors.d.ts +29 -0
  65. package/dist/Model/filter/types/errors.d.ts.map +1 -0
  66. package/dist/Model/filter/types/errors.js +2 -0
  67. package/dist/Model/filter/types/fields.d.ts +15 -0
  68. package/dist/Model/filter/types/fields.d.ts.map +1 -0
  69. package/dist/Model/filter/types/fields.js +2 -0
  70. package/dist/Model/filter/types/path/common.d.ts +316 -0
  71. package/dist/Model/filter/types/path/common.d.ts.map +1 -0
  72. package/dist/Model/filter/types/path/common.js +2 -0
  73. package/dist/Model/filter/types/path/eager.d.ts +95 -0
  74. package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
  75. package/dist/Model/filter/types/path/eager.js +31 -0
  76. package/dist/Model/filter/types/path/index.d.ts +4 -0
  77. package/dist/Model/filter/types/path/index.d.ts.map +1 -0
  78. package/dist/Model/filter/types/path/index.js +3 -0
  79. package/dist/Model/filter/types/utils.d.ts +79 -0
  80. package/dist/Model/filter/types/utils.d.ts.map +1 -0
  81. package/dist/Model/filter/types/utils.js +2 -0
  82. package/dist/Model/filter/types/validator.d.ts +30 -0
  83. package/dist/Model/filter/types/validator.d.ts.map +1 -0
  84. package/dist/Model/filter/types/validator.js +2 -0
  85. package/dist/Model/filter/types.d.ts +5 -0
  86. package/dist/Model/filter/types.d.ts.map +1 -0
  87. package/dist/Model/filter/types.js +7 -0
  88. package/dist/Model/query/dsl.d.ts +493 -0
  89. package/dist/Model/query/dsl.d.ts.map +1 -0
  90. package/dist/Model/query/dsl.js +376 -0
  91. package/dist/Model/query/new-kid-interpreter.d.ts +136 -0
  92. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
  93. package/dist/Model/query/new-kid-interpreter.js +336 -0
  94. package/dist/Model/query.d.ts +15 -0
  95. package/dist/Model/query.d.ts.map +1 -0
  96. package/dist/Model/query.js +3 -0
  97. package/dist/Model.d.ts +5 -0
  98. package/dist/Model.d.ts.map +1 -0
  99. package/dist/Model.js +5 -0
  100. package/dist/NonEmptySet.d.ts +4 -2
  101. package/dist/NonEmptySet.d.ts.map +1 -1
  102. package/dist/NonEmptySet.js +2 -2
  103. package/dist/Option.d.ts +2 -1
  104. package/dist/Option.d.ts.map +1 -1
  105. package/dist/Option.js +3 -1
  106. package/dist/Pure.d.ts +8 -6
  107. package/dist/Pure.d.ts.map +1 -1
  108. package/dist/Pure.js +17 -14
  109. package/dist/QueueMaker.d.ts +13 -0
  110. package/dist/QueueMaker.d.ts.map +1 -0
  111. package/dist/QueueMaker.js +4 -0
  112. package/dist/RequestContext.d.ts +91 -0
  113. package/dist/RequestContext.d.ts.map +1 -0
  114. package/dist/RequestContext.js +49 -0
  115. package/dist/Schema/Class.d.ts +66 -20
  116. package/dist/Schema/Class.d.ts.map +1 -1
  117. package/dist/Schema/Class.js +192 -27
  118. package/dist/Schema/FastCheck.d.ts +1 -1
  119. package/dist/Schema/FastCheck.d.ts.map +1 -1
  120. package/dist/Schema/Methods.d.ts +1 -1
  121. package/dist/Schema/SchemaParser.d.ts +5 -0
  122. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  123. package/dist/Schema/SchemaParser.js +6 -0
  124. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  125. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  126. package/dist/Schema/SpecialJsonSchema.js +118 -0
  127. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  128. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  129. package/dist/Schema/SpecialOpenApi.js +123 -0
  130. package/dist/Schema/brand.d.ts +5 -3
  131. package/dist/Schema/brand.d.ts.map +1 -1
  132. package/dist/Schema/brand.js +3 -1
  133. package/dist/Schema/email.d.ts +1 -1
  134. package/dist/Schema/email.d.ts.map +1 -1
  135. package/dist/Schema/email.js +7 -4
  136. package/dist/Schema/ext.d.ts +339 -56
  137. package/dist/Schema/ext.d.ts.map +1 -1
  138. package/dist/Schema/ext.js +358 -53
  139. package/dist/Schema/moreStrings.d.ts +83 -37
  140. package/dist/Schema/moreStrings.d.ts.map +1 -1
  141. package/dist/Schema/moreStrings.js +49 -42
  142. package/dist/Schema/numbers.d.ts +35 -22
  143. package/dist/Schema/numbers.d.ts.map +1 -1
  144. package/dist/Schema/numbers.js +55 -12
  145. package/dist/Schema/phoneNumber.d.ts +1 -1
  146. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  147. package/dist/Schema/phoneNumber.js +6 -3
  148. package/dist/Schema/schema.d.ts +1 -1
  149. package/dist/Schema/strings.d.ts +19 -5
  150. package/dist/Schema/strings.d.ts.map +1 -1
  151. package/dist/Schema/strings.js +1 -5
  152. package/dist/Schema.d.ts +214 -8
  153. package/dist/Schema.d.ts.map +1 -1
  154. package/dist/Schema.js +190 -11
  155. package/dist/Set.d.ts +5 -2
  156. package/dist/Set.d.ts.map +1 -1
  157. package/dist/Set.js +3 -2
  158. package/dist/Store.d.ts +170 -0
  159. package/dist/Store.d.ts.map +1 -0
  160. package/dist/Store.js +121 -0
  161. package/dist/TypeTest.d.ts +1 -1
  162. package/dist/Types.d.ts +1 -1
  163. package/dist/Widen.type.d.ts +1 -1
  164. package/dist/_ext/Array.d.ts +2 -2
  165. package/dist/_ext/Array.d.ts.map +1 -1
  166. package/dist/_ext/Array.js +4 -2
  167. package/dist/_ext/date.d.ts +1 -1
  168. package/dist/_ext/misc.d.ts +5 -2
  169. package/dist/_ext/misc.d.ts.map +1 -1
  170. package/dist/_ext/misc.js +4 -2
  171. package/dist/_ext/ord.ext.d.ts +3 -2
  172. package/dist/_ext/ord.ext.d.ts.map +1 -1
  173. package/dist/_ext/ord.ext.js +2 -2
  174. package/dist/builtin.d.ts +1 -1
  175. package/dist/builtin.d.ts.map +1 -1
  176. package/dist/client/InvalidationKeys.d.ts +29 -0
  177. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  178. package/dist/client/InvalidationKeys.js +33 -0
  179. package/dist/client/apiClientFactory.d.ts +20 -32
  180. package/dist/client/apiClientFactory.d.ts.map +1 -1
  181. package/dist/client/apiClientFactory.js +104 -34
  182. package/dist/client/clientFor.d.ts +53 -19
  183. package/dist/client/clientFor.d.ts.map +1 -1
  184. package/dist/client/clientFor.js +9 -1
  185. package/dist/client/errors.d.ts +49 -25
  186. package/dist/client/errors.d.ts.map +1 -1
  187. package/dist/client/errors.js +43 -17
  188. package/dist/client/makeClient.d.ts +495 -33
  189. package/dist/client/makeClient.d.ts.map +1 -1
  190. package/dist/client/makeClient.js +66 -24
  191. package/dist/client.d.ts +6 -5
  192. package/dist/client.d.ts.map +1 -1
  193. package/dist/client.js +2 -1
  194. package/dist/faker.d.ts +1 -1
  195. package/dist/faker.d.ts.map +1 -1
  196. package/dist/http/Request.d.ts +2 -2
  197. package/dist/http/Request.d.ts.map +1 -1
  198. package/dist/http/Request.js +2 -2
  199. package/dist/http/internal/lib.d.ts +1 -1
  200. package/dist/http.d.ts +1 -1
  201. package/dist/ids.d.ts +43 -15
  202. package/dist/ids.d.ts.map +1 -1
  203. package/dist/ids.js +30 -5
  204. package/dist/index.d.ts +7 -8
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +8 -8
  207. package/dist/logger.d.ts +1 -1
  208. package/dist/middleware.d.ts +14 -8
  209. package/dist/middleware.d.ts.map +1 -1
  210. package/dist/middleware.js +14 -8
  211. package/dist/rpc/Invalidation.d.ts +420 -0
  212. package/dist/rpc/Invalidation.d.ts.map +1 -0
  213. package/dist/rpc/Invalidation.js +168 -0
  214. package/dist/rpc/MiddlewareMaker.d.ts +12 -8
  215. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  216. package/dist/rpc/MiddlewareMaker.js +59 -38
  217. package/dist/rpc/RpcContextMap.d.ts +4 -4
  218. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  219. package/dist/rpc/RpcContextMap.js +4 -4
  220. package/dist/rpc/RpcMiddleware.d.ts +15 -11
  221. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  222. package/dist/rpc/RpcMiddleware.js +1 -1
  223. package/dist/rpc.d.ts +2 -2
  224. package/dist/rpc.d.ts.map +1 -1
  225. package/dist/rpc.js +2 -2
  226. package/dist/runtime.d.ts +19 -0
  227. package/dist/runtime.d.ts.map +1 -0
  228. package/dist/runtime.js +40 -0
  229. package/dist/setupRequest.d.ts +19 -0
  230. package/dist/setupRequest.d.ts.map +1 -0
  231. package/dist/setupRequest.js +69 -0
  232. package/dist/toast.d.ts +51 -0
  233. package/dist/toast.d.ts.map +1 -0
  234. package/dist/toast.js +34 -0
  235. package/dist/transform.d.ts +2 -2
  236. package/dist/transform.d.ts.map +1 -1
  237. package/dist/transform.js +4 -5
  238. package/dist/utils/effectify.d.ts +2 -2
  239. package/dist/utils/effectify.d.ts.map +1 -1
  240. package/dist/utils/effectify.js +2 -2
  241. package/dist/utils/extend.d.ts +1 -1
  242. package/dist/utils/extend.d.ts.map +1 -1
  243. package/dist/utils/gen.d.ts +5 -5
  244. package/dist/utils/gen.d.ts.map +1 -1
  245. package/dist/utils/logLevel.d.ts +3 -3
  246. package/dist/utils/logLevel.d.ts.map +1 -1
  247. package/dist/utils/logger.d.ts +5 -4
  248. package/dist/utils/logger.d.ts.map +1 -1
  249. package/dist/utils/logger.js +4 -4
  250. package/dist/utils.d.ts +40 -45
  251. package/dist/utils.d.ts.map +1 -1
  252. package/dist/utils.js +19 -27
  253. package/dist/validation/validators.d.ts +1 -1
  254. package/dist/validation/validators.d.ts.map +1 -1
  255. package/dist/validation.d.ts +1 -1
  256. package/dist/validation.d.ts.map +1 -1
  257. package/dist/withToast.d.ts +30 -0
  258. package/dist/withToast.d.ts.map +1 -0
  259. package/dist/withToast.js +64 -0
  260. package/package.json +20 -245
  261. package/src/Array.ts +3 -3
  262. package/src/Config/SecretURL.ts +5 -2
  263. package/src/Config/internal/configSecretURL.ts +1 -1
  264. package/src/Config.ts +14 -0
  265. package/src/ConfigProvider.ts +48 -0
  266. package/src/{ServiceMap.ts → Context.ts} +56 -63
  267. package/src/Effect.ts +12 -14
  268. package/src/Emailer.ts +51 -0
  269. package/src/Layer.ts +10 -6
  270. package/src/Model/Repository/Registry.ts +34 -0
  271. package/src/Model/Repository/ext.ts +375 -0
  272. package/src/Model/Repository/internal/internal.ts +741 -0
  273. package/src/Model/Repository/legacy.ts +29 -0
  274. package/src/Model/Repository/makeRepo.ts +145 -0
  275. package/src/Model/Repository/service.ts +666 -0
  276. package/src/Model/Repository/validation.ts +31 -0
  277. package/src/Model/Repository.ts +6 -0
  278. package/src/Model/dsl.ts +129 -0
  279. package/src/Model/filter/filterApi.ts +60 -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 +297 -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 +2694 -0
  289. package/src/Model/query/new-kid-interpreter.ts +484 -0
  290. package/src/Model/query.ts +13 -0
  291. package/src/Model.ts +4 -0
  292. package/src/NonEmptySet.ts +3 -1
  293. package/src/Option.ts +2 -0
  294. package/src/Pure.ts +21 -19
  295. package/src/QueueMaker.ts +19 -0
  296. package/src/RequestContext.ts +62 -0
  297. package/src/Schema/Class.ts +274 -68
  298. package/src/Schema/SchemaParser.ts +12 -0
  299. package/src/Schema/SpecialJsonSchema.ts +139 -0
  300. package/src/Schema/SpecialOpenApi.ts +130 -0
  301. package/src/Schema/brand.ts +22 -2
  302. package/src/Schema/email.ts +7 -2
  303. package/src/Schema/ext.ts +443 -88
  304. package/src/Schema/moreStrings.ts +146 -67
  305. package/src/Schema/numbers.ts +96 -27
  306. package/src/Schema/phoneNumber.ts +5 -1
  307. package/src/Schema/strings.ts +22 -13
  308. package/src/Schema.ts +374 -10
  309. package/src/Set.ts +5 -1
  310. package/src/Store.ts +277 -0
  311. package/src/_ext/Array.ts +3 -1
  312. package/src/_ext/misc.ts +4 -1
  313. package/src/_ext/ord.ext.ts +2 -1
  314. package/src/client/InvalidationKeys.ts +50 -0
  315. package/src/client/apiClientFactory.ts +230 -131
  316. package/src/client/clientFor.ts +102 -31
  317. package/src/client/errors.ts +52 -26
  318. package/src/client/makeClient.ts +592 -71
  319. package/src/client.ts +5 -4
  320. package/src/http/Request.ts +1 -1
  321. package/src/ids.ts +32 -5
  322. package/src/index.ts +7 -10
  323. package/src/middleware.ts +13 -9
  324. package/src/rpc/Invalidation.ts +261 -0
  325. package/src/rpc/MiddlewareMaker.ts +83 -75
  326. package/src/rpc/README.md +2 -2
  327. package/src/rpc/RpcContextMap.ts +6 -5
  328. package/src/rpc/RpcMiddleware.ts +18 -12
  329. package/src/rpc.ts +1 -1
  330. package/src/runtime.ts +56 -0
  331. package/src/setupRequest.ts +134 -0
  332. package/src/toast.ts +54 -0
  333. package/src/transform.ts +3 -3
  334. package/src/utils/effectify.ts +1 -1
  335. package/src/utils/gen.ts +8 -8
  336. package/src/utils/logLevel.ts +1 -1
  337. package/src/utils/logger.ts +4 -3
  338. package/src/utils.ts +62 -139
  339. package/src/withToast.ts +133 -0
  340. package/test/dist/rpc-dynamic-middleware.test.d.ts.map +1 -0
  341. package/test/dist/rpc.test.d.ts.map +1 -1
  342. package/test/dist/secretURL.test.d.ts.map +1 -0
  343. package/test/dist/special.test.d.ts.map +1 -0
  344. package/test/dist/stream-error.types.d.ts +2 -0
  345. package/test/dist/stream-error.types.d.ts.map +1 -0
  346. package/test/dist/stream-error.types.js +27 -0
  347. package/test/moreStrings.test.ts +1 -1
  348. package/test/rpc.test.ts +46 -6
  349. package/test/schema.test.ts +459 -30
  350. package/test/secretURL.test.ts +160 -0
  351. package/test/special.test.ts +1026 -0
  352. package/test/utils.test.ts +7 -7
  353. package/tsconfig.base.json +6 -5
  354. package/tsconfig.json +2 -1
  355. package/tsconfig.json.bak +2 -2
  356. package/tsconfig.src.json +29 -29
  357. package/tsconfig.test.json +2 -2
  358. package/dist/Operations.d.ts +0 -123
  359. package/dist/Operations.d.ts.map +0 -1
  360. package/dist/Operations.js +0 -29
  361. package/dist/ServiceMap.d.ts +0 -44
  362. package/dist/ServiceMap.d.ts.map +0 -1
  363. package/dist/ServiceMap.js +0 -91
  364. package/eslint.config.mjs +0 -26
  365. package/src/Operations.ts +0 -55
package/src/Store.ts ADDED
@@ -0,0 +1,277 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as Data from "effect/Data"
3
+ import type * as Redacted from "effect/Redacted"
4
+ import * as Semaphore from "effect/Semaphore"
5
+ import type { NonEmptyReadonlyArray } from "./Array.js"
6
+ import type { OptimisticConcurrencyException } from "./client/errors.js"
7
+ import * as Context from "./Context.js"
8
+ import * as Effect from "./Effect.js"
9
+ import * as Layer from "./Layer.js"
10
+ import type { FilterResult } from "./Model/filter/filterApi.js"
11
+ import type { FieldValues } from "./Model/filter/types.js"
12
+ import type { FieldPath } from "./Model/filter/types/path/index.js"
13
+ import type { AggregateIrExpression, ComputedProjectionIrExpression, RawQuery } from "./Model/query.js"
14
+ import type * as Option from "./Option.js"
15
+ import { NonEmptyString255 } from "./Schema.js"
16
+
17
+ /**
18
+ * Adapter-neutral unique-key definition for stores that support unique indexes,
19
+ * such as the Cosmos adapter. This shape is intentionally kept structurally
20
+ * compatible with adapter-specific `UniqueKey` types. Each path identifies a
21
+ * field participating in the unique key, and adapters forward these paths
22
+ * directly to the underlying storage engine.
23
+ */
24
+ export interface UniqueKey {
25
+ readonly paths: string[]
26
+ }
27
+
28
+ export interface StoreConfig<E> {
29
+ partitionValue: (e?: E) => string
30
+ /**
31
+ * Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database.
32
+ * Memory/Disk use separate store instances per namespace. CosmosDB uses namespace-prefixed partition keys. SQL uses a `_namespace` column.
33
+ */
34
+ allowNamespace?: (namespace: string) => boolean
35
+ /**
36
+ * just in time migrations, supported by the database driver, supporting queries, for simple default values
37
+ */
38
+ defaultValues?: Partial<E>
39
+
40
+ /**
41
+ * How many items can be processed in one batch at a time.
42
+ * Defaults to 100 for CosmosDB.
43
+ */
44
+ maxBulkSize?: number
45
+
46
+ /**
47
+ * Unique indexes, mainly for CosmosDB
48
+ */
49
+ uniqueKeys?: UniqueKey[]
50
+ }
51
+
52
+ export type SupportedValues = string | boolean | number | null
53
+ export type SupportedValues2 = string | boolean | number
54
+
55
+ // default is eq
56
+ export type Where =
57
+ | { key: string; t?: "eq" | "not-eq"; value: SupportedValues }
58
+ | { key: string; t: "gt" | "lt" | "gte" | "lte"; value: SupportedValues2 }
59
+ | {
60
+ key: string
61
+ t: "contains" | "starts-with" | "ends-with" | "not-contains" | "not-starts-with" | "not-ends-with"
62
+ value: string
63
+ }
64
+ | { key: string; t: "includes" | "not-includes"; value: string }
65
+ | {
66
+ key: string
67
+ t: "in" | "not-in"
68
+ value: readonly (SupportedValues)[]
69
+ }
70
+
71
+ export type Filter = readonly FilterResult[]
72
+
73
+ export interface O<TFieldValues extends FieldValues> {
74
+ key: FieldPath<TFieldValues>
75
+ direction: "ASC" | "DESC"
76
+ }
77
+
78
+ export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded = never> {
79
+ t: Encoded
80
+ filter?: Filter | undefined
81
+ select?:
82
+ | NonEmptyReadonlyArray<
83
+ U | { key: string; subKeys: readonly string[] } | {
84
+ key: string
85
+ computed: ComputedProjectionIrExpression
86
+ } | {
87
+ key: string
88
+ path: string
89
+ } | {
90
+ key: string
91
+ aggregate: AggregateIrExpression
92
+ }
93
+ >
94
+ | undefined
95
+ order?: NonEmptyReadonlyArray<O<NoInfer<Encoded>>>
96
+ limit?: number | undefined
97
+ skip?: number | undefined
98
+ }
99
+
100
+ export type FilterFunc<Encoded extends FieldValues> = <U extends keyof Encoded = never>(
101
+ args: FilterArgs<Encoded, U>
102
+ ) => Effect.Effect<(U extends undefined ? Encoded : Pick<Encoded, U>)[]>
103
+
104
+ export interface Store<
105
+ IdKey extends keyof Encoded,
106
+ Encoded extends FieldValues,
107
+ PM extends PersistenceModelType<Encoded> = PersistenceModelType<Encoded>
108
+ > {
109
+ all: Effect.Effect<PM[]>
110
+ filter: FilterFunc<Encoded>
111
+ find: (id: Encoded[IdKey]) => Effect.Effect<Option.Option<PM>>
112
+ set: (e: PM) => Effect.Effect<PM, OptimisticConcurrencyException>
113
+ batchSet: (
114
+ items: NonEmptyReadonlyArray<PM>
115
+ ) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
116
+ bulkSet: (
117
+ items: NonEmptyReadonlyArray<PM>
118
+ ) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
119
+ batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void>
120
+ queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[]>
121
+ /**
122
+ * Explicitly seed a namespace. Primary is seeded eagerly on initialization.
123
+ * Non-primary namespaces must be seeded explicitly before use.
124
+ */
125
+ seedNamespace: (namespace: string) => Effect.Effect<void>
126
+ }
127
+
128
+ export class StoreMaker extends Context.Opaque<StoreMaker, {
129
+ make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
130
+ name: string,
131
+ idKey: IdKey,
132
+ seed?: Effect.Effect<Iterable<Encoded>, E, R>,
133
+ config?: StoreConfig<Encoded>
134
+ ) => Effect.Effect<Store<IdKey, Encoded>, E, R>
135
+ }>()("effect-app/StoreMaker") {
136
+ }
137
+
138
+ export const makeContextMap = () => {
139
+ const etags = new Map<string, string>()
140
+ const getEtag = (id: string) => etags.get(id)
141
+ const setEtag = (id: string, eTag: string | undefined) => {
142
+ if (eTag === undefined) {
143
+ etags.delete(id)
144
+ } else {
145
+ etags.set(id, eTag)
146
+ }
147
+ }
148
+
149
+ // const parsedCache = new Map<
150
+ // Parser<any, any, any>,
151
+ // Map<unknown, These.These<unknown, unknown>>
152
+ // >()
153
+
154
+ // const parserCache = new Map<
155
+ // Parser<any, any, any>,
156
+ // (i: any) => These.These<any, any>
157
+ // >()
158
+
159
+ // const setAndReturn = <I, E, A>(
160
+ // p: Parser<I, E, A>,
161
+ // np: (i: I) => These.These<E, A>
162
+ // ) => {
163
+ // parserCache.set(p, np)
164
+ // return np
165
+ // }
166
+
167
+ // const parserEnv: ParserEnv = {
168
+ // // TODO: lax: true would turn off refinement checks, may help on large payloads
169
+ // // but of course removes confirming of validation rules (which may be okay for a database owned by the app, as we write safely)
170
+ // lax: false,
171
+ // cache: {
172
+ // getOrSetParser: (p) => parserCache.get(p) ?? setAndReturn(p, (i) => parserEnv.cache!.getOrSet(i, p)),
173
+ // getOrSetParsers: (parsers) => {
174
+ // return Object.entries(parsers).reduce((prev, [k, v]) => {
175
+ // prev[k] = parserEnv.cache!.getOrSetParser(v)
176
+ // return prev
177
+ // }, {} as any)
178
+ // },
179
+ // getOrSet: (i, parse): any => {
180
+ // const c = parsedCache.get(parse)
181
+ // if (c) {
182
+ // const f = c.get(i)
183
+ // if (f) {
184
+ // // console.log("$$$ cache hit", i)
185
+ // return f
186
+ // } else {
187
+ // const nf = parse(i, parserEnv)
188
+ // c.set(i, nf)
189
+ // return nf
190
+ // }
191
+ // } else {
192
+ // const nf = parse(i, parserEnv)
193
+ // parsedCache.set(parse, new Map([[i, nf]]))
194
+ // return nf
195
+ // }
196
+ // }
197
+ // }
198
+ // }
199
+
200
+ const store = new Map<symbol, unknown>()
201
+ const sem = Semaphore.makeUnsafe(1)
202
+
203
+ return {
204
+ createdAt: new Date(),
205
+ get: getEtag,
206
+ set: setEtag,
207
+ getOrCreateStore: <T>(key: symbol, make: () => T): T => {
208
+ let value = store.get(key) as T | undefined
209
+ if (value === undefined) {
210
+ value = make()
211
+ store.set(key, value)
212
+ }
213
+ return value
214
+ },
215
+ getOrCreateStoreEffect: <T, E, R>(key: symbol, make: Effect.Effect<T, E, R>): Effect.Effect<T, E, R> =>
216
+ sem.withPermits(1)(Effect.uninterruptible(Effect.gen(function*() {
217
+ const value = store.get(key) as T | undefined
218
+ if (value !== undefined) return value
219
+ const v = yield* make
220
+ store.set(key, v)
221
+ return v
222
+ }))),
223
+ clear: () => {
224
+ etags.clear()
225
+ store.clear()
226
+ }
227
+ }
228
+ }
229
+
230
+ const makeMap = Effect.acquireRelease(
231
+ Effect.sync(() => makeContextMap()),
232
+ (m) => Effect.sync(() => m.clear())
233
+ )
234
+
235
+ export class ContextMap extends Context.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
236
+ }
237
+
238
+ export class ContextMapContainer extends Context.Reference("ContextMapContainer", {
239
+ defaultValue: (): ContextMap | "root" => "root"
240
+ }) {
241
+ static readonly layer = Layer.effect(this, ContextMap.make.pipe(Effect.map(ContextMap.of)))
242
+ }
243
+
244
+ export class ContextMapNotStartedError extends Data.TaggedError("ContextMapNotStartedError") {}
245
+
246
+ export const getContextMap = ContextMapContainer.pipe(
247
+ Effect.filterOrFail((_) => _ !== "root", () => new ContextMapNotStartedError())
248
+ )
249
+
250
+ /**
251
+ * Runs `make` at most once per ContextMap (i.e. per request) and caches the
252
+ * resulting value in the ContextMap under a fresh symbol. Subsequent calls of
253
+ * the returned Effect within the same ContextMap return the cached value.
254
+ *
255
+ * Uses the ContextMap's shared semaphore for safe single initialization.
256
+ */
257
+ export const cachedPerRequest = <A, E, R>(
258
+ make: Effect.Effect<A, E, R>
259
+ ): Effect.Effect<A, E | ContextMapNotStartedError, R> => {
260
+ const cacheKey = Symbol()
261
+ return getContextMap.pipe(
262
+ Effect.flatMap((ctxMap) => ctxMap.getOrCreateStoreEffect(cacheKey, make))
263
+ )
264
+ }
265
+
266
+ const defaultNs: NonEmptyString255 = NonEmptyString255("primary")
267
+ export class storeId extends Context.Reference("StoreId", { defaultValue: (): NonEmptyString255 => defaultNs }) {}
268
+
269
+ export type PersistenceModelType<Encoded extends object> = Encoded & {
270
+ _etag?: string | undefined
271
+ }
272
+
273
+ export interface StorageConfig {
274
+ url: Redacted.Redacted
275
+ prefix: string
276
+ dbName: string
277
+ }
package/src/_ext/Array.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { Chunk, Effect, Equal } from "effect-app"
1
+ import * as Chunk from "effect-app/Chunk"
2
+ import * as Effect from "effect-app/Effect"
3
+ import * as Equal from "effect/Equal"
2
4
  import { NotFoundError } from "../client/errors.js"
3
5
 
4
6
  function getFirstBy<A, Type extends string>(
package/src/_ext/misc.ts CHANGED
@@ -1,5 +1,8 @@
1
- import { Effect, Option, Result, type Scope } from "effect"
2
1
  import type { LazyArg } from "effect-app/Function"
2
+ import * as Effect from "effect/Effect"
3
+ import * as Option from "effect/Option"
4
+ import * as Result from "effect/Result"
5
+ import type * as Scope from "effect/Scope"
3
6
 
4
7
  export type _R<T extends Effect.Effect<any, any, any>> = [T] extends [
5
8
  Effect.Effect<any, any, infer R>
@@ -1,4 +1,5 @@
1
- import { Chunk, type Equivalence } from "effect"
1
+ import * as Chunk from "effect/Chunk"
2
+ import type * as Equivalence from "effect/Equivalence"
2
3
 
3
4
  export function toArray<A>(
4
5
  gen: Generator<A, void, unknown>
@@ -0,0 +1,50 @@
1
+ import * as Ref from "effect/Ref"
2
+ import * as Context from "../Context.js"
3
+ import * as Effect from "../Effect.js"
4
+ import type { InvalidationKey } from "../rpc/Invalidation.js"
5
+
6
+ export type { InvalidationKey }
7
+ /** Shape of the per-mutation service that accumulates server-provided invalidation keys. */
8
+ export interface InvalidationKeysService {
9
+ readonly add: (key: InvalidationKey) => Effect.Effect<void>
10
+ readonly get: Effect.Effect<ReadonlyArray<InvalidationKey>>
11
+ }
12
+
13
+ /**
14
+ * Context.Reference that accumulates invalidation keys received from the server via the
15
+ * `x-invalidate` HTTP response header.
16
+ *
17
+ * The default is a no-op: when not explicitly provided (e.g. outside a mutation wrapper)
18
+ * all calls are ignored. The mutation wrapper in `@effect-app/vue` provides a real
19
+ * implementation backed by a `Ref`.
20
+ */
21
+ export const InvalidationKeysFromServer = Context.Reference<InvalidationKeysService>(
22
+ "effect-app/client/InvalidationKeysFromServer",
23
+ {
24
+ defaultValue: () => ({
25
+ add: (_key: InvalidationKey) => Effect.void,
26
+ get: Effect.succeed([] as ReadonlyArray<InvalidationKey>)
27
+ })
28
+ }
29
+ )
30
+ export type InvalidationKeysFromServer = typeof InvalidationKeysFromServer
31
+
32
+ /**
33
+ * Creates a fresh `InvalidationKeysService` implementation backed by a `Ref`.
34
+ *
35
+ * @param ref - The `Ref` that stores the accumulated keys.
36
+ * @param onAdded - V3: Optional Effect run after a key is added. Use to trigger mid-stream
37
+ * query invalidation without waiting for the stream to complete.
38
+ */
39
+ export const makeInvalidationKeysService = (
40
+ ref: Ref.Ref<ReadonlyArray<InvalidationKey>>,
41
+ onAdded?: (key: InvalidationKey) => Effect.Effect<void>
42
+ ): InvalidationKeysService => ({
43
+ // When onAdded is set, fire it immediately without accumulating in the ref —
44
+ // the key is handled on arrival and must not be re-processed at stream end.
45
+ add: (key) =>
46
+ onAdded
47
+ ? onAdded(key)
48
+ : Ref.update(ref, (keys) => [...keys, key]),
49
+ get: Ref.get(ref)
50
+ })