effect-app 4.0.0-beta.32 → 4.0.0-beta.321

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 +1570 -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 +579 -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 +63 -0
  49. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  50. package/dist/Model/Repository/makeRepo.js +27 -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 +58 -0
  55. package/dist/Model/Repository/validation.d.ts.map +1 -0
  56. package/dist/Model/Repository/validation.js +32 -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 +7 -6
  138. package/dist/Schema/ext.d.ts +337 -56
  139. package/dist/Schema/ext.d.ts.map +1 -1
  140. package/dist/Schema/ext.js +381 -58
  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 +47 -51
  144. package/dist/Schema/numbers.d.ts +34 -21
  145. package/dist/Schema/numbers.d.ts.map +1 -1
  146. package/dist/Schema/numbers.js +55 -12
  147. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  148. package/dist/Schema/phoneNumber.js +6 -6
  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 +170 -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 +42 -14
  202. package/dist/ids.d.ts.map +1 -1
  203. package/dist/ids.js +30 -5
  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 +950 -0
  273. package/src/Model/Repository/legacy.ts +29 -0
  274. package/src/Model/Repository/makeRepo.ts +156 -0
  275. package/src/Model/Repository/service.ts +676 -0
  276. package/src/Model/Repository/validation.ts +31 -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 +9 -7
  304. package/src/Schema/ext.ts +502 -98
  305. package/src/Schema/moreStrings.ts +145 -83
  306. package/src/Schema/numbers.ts +97 -28
  307. package/src/Schema/phoneNumber.ts +8 -8
  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 +280 -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 +33 -6
  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 +7 -9
  352. package/test/rpc.test.ts +42 -14
  353. package/test/rpcMiddlewareContext.test.ts +63 -0
  354. package/test/schema.test.ts +514 -35
  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
package/src/Store.ts ADDED
@@ -0,0 +1,280 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type * as Redacted from "effect/Redacted"
3
+ import * as Semaphore from "effect/Semaphore"
4
+ import type { NonEmptyReadonlyArray } from "./Array.ts"
5
+ import type { DatabaseError, OptimisticConcurrencyException } from "./client/errors.ts"
6
+ import * as Context from "./Context.ts"
7
+ import * as Effect from "./Effect.ts"
8
+ import type { FilterResult } from "./Model/filter/filterApi.ts"
9
+ import type { FieldValues } from "./Model/filter/types.ts"
10
+ import type { FieldPath } from "./Model/filter/types/path/index.ts"
11
+ import type { AggregateIrExpression, ComputedProjectionIrExpression, RawQuery } from "./Model/query.ts"
12
+ import type * as Option from "./Option.ts"
13
+ import * as RequestScopedDependencies from "./RequestScopedDependencies.ts"
14
+ import { NonEmptyString255, type Top as SchemaTop } from "./Schema.ts"
15
+
16
+ /**
17
+ * Adapter-neutral unique-key definition for stores that support unique indexes,
18
+ * such as the Cosmos adapter. This shape is intentionally kept structurally
19
+ * compatible with adapter-specific `UniqueKey` types. Each path identifies a
20
+ * field participating in the unique key, and adapters forward these paths
21
+ * directly to the underlying storage engine.
22
+ */
23
+ export interface UniqueKey {
24
+ readonly paths: string[]
25
+ }
26
+
27
+ export interface StoreConfig<E> {
28
+ partitionValue: (e?: E) => string
29
+ /**
30
+ * Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database.
31
+ * Memory/Disk use separate store instances per namespace. CosmosDB uses namespace-prefixed partition keys. SQL uses a `_namespace` column.
32
+ */
33
+ allowNamespace?: (namespace: string) => boolean
34
+ /**
35
+ * just in time migrations, supported by the database driver, supporting queries, for simple default values
36
+ */
37
+ defaultValues?: Partial<E>
38
+
39
+ /**
40
+ * How many items can be processed in one batch at a time.
41
+ * Defaults to 100 for CosmosDB.
42
+ */
43
+ maxBulkSize?: number
44
+
45
+ /**
46
+ * Unique indexes, mainly for CosmosDB
47
+ */
48
+ uniqueKeys?: UniqueKey[]
49
+ /**
50
+ * Domain schema whose Encoded shape is stored. JSON adapters use
51
+ * `Schema.toCodecJson(Schema.toEncoded(schema))` for documents, query
52
+ * values, and defaults. Date/Map/Set (and app types such as DateOnly)
53
+ * stay native on Encoded and lower only on this JSON boundary.
54
+ */
55
+ schema?: SchemaTop
56
+ }
57
+
58
+ export type SupportedValues = string | boolean | number | null
59
+ export type SupportedValues2 = string | boolean | number
60
+
61
+ // default is eq
62
+ export type Where =
63
+ | { key: string; t?: "eq" | "not-eq"; value: SupportedValues }
64
+ | { key: string; t: "gt" | "lt" | "gte" | "lte"; value: SupportedValues2 }
65
+ | {
66
+ key: string
67
+ t: "contains" | "starts-with" | "ends-with" | "not-contains" | "not-starts-with" | "not-ends-with"
68
+ value: string
69
+ }
70
+ | { key: string; t: "includes" | "not-includes"; value: string }
71
+ | {
72
+ key: string
73
+ t: "in" | "not-in"
74
+ value: readonly (SupportedValues)[]
75
+ }
76
+
77
+ export type Filter = readonly FilterResult[]
78
+
79
+ export interface O<TFieldValues extends FieldValues> {
80
+ key: FieldPath<TFieldValues>
81
+ direction: "ASC" | "DESC"
82
+ }
83
+
84
+ export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded = never> {
85
+ t: Encoded
86
+ filter?: Filter | undefined
87
+ select?:
88
+ | NonEmptyReadonlyArray<
89
+ U | { key: string; subKeys: readonly string[] } | {
90
+ key: string
91
+ computed: ComputedProjectionIrExpression
92
+ } | {
93
+ key: string
94
+ path: string
95
+ } | {
96
+ key: string
97
+ aggregate: AggregateIrExpression
98
+ }
99
+ >
100
+ | undefined
101
+ order?: NonEmptyReadonlyArray<O<NoInfer<Encoded>>>
102
+ limit?: number | undefined
103
+ skip?: number | undefined
104
+ }
105
+
106
+ export type FilterFunc<Encoded extends FieldValues> = <U extends keyof Encoded = never>(
107
+ args: FilterArgs<Encoded, U>
108
+ ) => Effect.Effect<(U extends undefined ? Encoded : Pick<Encoded, U>)[], DatabaseError>
109
+
110
+ export interface Store<
111
+ IdKey extends keyof Encoded,
112
+ Encoded extends FieldValues,
113
+ PM extends PersistenceModelType<Encoded> = PersistenceModelType<Encoded>
114
+ > {
115
+ all: Effect.Effect<PM[], DatabaseError>
116
+ filter: FilterFunc<Encoded>
117
+ find: (id: Encoded[IdKey]) => Effect.Effect<Option.Option<PM>, DatabaseError>
118
+ set: (e: PM) => Effect.Effect<PM, OptimisticConcurrencyException | DatabaseError>
119
+ batchSet: (
120
+ items: NonEmptyReadonlyArray<PM>
121
+ ) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException | DatabaseError>
122
+ bulkSet: (
123
+ items: NonEmptyReadonlyArray<PM>
124
+ ) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException | DatabaseError>
125
+ batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void, DatabaseError>
126
+ queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[], DatabaseError>
127
+ /**
128
+ * Explicitly seed a namespace. Primary is seeded eagerly on initialization.
129
+ * Non-primary namespaces must be seeded explicitly before use.
130
+ */
131
+ seedNamespace: (namespace: string) => Effect.Effect<void, DatabaseError>
132
+ }
133
+
134
+ export class StoreMaker extends Context.Opaque<StoreMaker, {
135
+ make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
136
+ name: string,
137
+ idKey: IdKey,
138
+ seed?: Effect.Effect<Iterable<Encoded>, E, R>,
139
+ config?: StoreConfig<Encoded>
140
+ ) => Effect.Effect<Store<IdKey, Encoded>, E, R>
141
+ }>()("effect-app/StoreMaker") {
142
+ }
143
+
144
+ export const makeContextMap = () => {
145
+ const etags = new Map<string, string>()
146
+ const getEtag = (id: string) => etags.get(id)
147
+ const setEtag = (id: string, eTag: string | undefined) => {
148
+ if (eTag === undefined) {
149
+ etags.delete(id)
150
+ } else {
151
+ etags.set(id, eTag)
152
+ }
153
+ }
154
+
155
+ // const parsedCache = new Map<
156
+ // Parser<any, any, any>,
157
+ // Map<unknown, These.These<unknown, unknown>>
158
+ // >()
159
+
160
+ // const parserCache = new Map<
161
+ // Parser<any, any, any>,
162
+ // (i: any) => These.These<any, any>
163
+ // >()
164
+
165
+ // const setAndReturn = <I, E, A>(
166
+ // p: Parser<I, E, A>,
167
+ // np: (i: I) => These.These<E, A>
168
+ // ) => {
169
+ // parserCache.set(p, np)
170
+ // return np
171
+ // }
172
+
173
+ // const parserEnv: ParserEnv = {
174
+ // // TODO: lax: true would turn off refinement checks, may help on large payloads
175
+ // // but of course removes confirming of validation rules (which may be okay for a database owned by the app, as we write safely)
176
+ // lax: false,
177
+ // cache: {
178
+ // getOrSetParser: (p) => parserCache.get(p) ?? setAndReturn(p, (i) => parserEnv.cache!.getOrSet(i, p)),
179
+ // getOrSetParsers: (parsers) => {
180
+ // return Object.entries(parsers).reduce((prev, [k, v]) => {
181
+ // prev[k] = parserEnv.cache!.getOrSetParser(v)
182
+ // return prev
183
+ // }, {} as any)
184
+ // },
185
+ // getOrSet: (i, parse): any => {
186
+ // const c = parsedCache.get(parse)
187
+ // if (c) {
188
+ // const f = c.get(i)
189
+ // if (f) {
190
+ // // console.log("$$$ cache hit", i)
191
+ // return f
192
+ // } else {
193
+ // const nf = parse(i, parserEnv)
194
+ // c.set(i, nf)
195
+ // return nf
196
+ // }
197
+ // } else {
198
+ // const nf = parse(i, parserEnv)
199
+ // parsedCache.set(parse, new Map([[i, nf]]))
200
+ // return nf
201
+ // }
202
+ // }
203
+ // }
204
+ // }
205
+
206
+ const store = new Map<symbol, unknown>()
207
+ const sem = Semaphore.makeUnsafe(1)
208
+
209
+ return {
210
+ createdAt: new Date(),
211
+ get: getEtag,
212
+ set: setEtag,
213
+ getOrCreateStore: <T>(key: symbol, make: () => T): T => {
214
+ let value = store.get(key) as T | undefined
215
+ if (value === undefined) {
216
+ value = make()
217
+ store.set(key, value)
218
+ }
219
+ return value
220
+ },
221
+ getOrCreateStoreEffect: <T, E, R>(key: symbol, make: Effect.Effect<T, E, R>): Effect.Effect<T, E, R> =>
222
+ sem.withPermits(1)(Effect.uninterruptible(Effect.gen(function*() {
223
+ const value = store.get(key) as T | undefined
224
+ if (value !== undefined) return value
225
+ const v = yield* make
226
+ store.set(key, v)
227
+ return v
228
+ }))),
229
+ clear: () => {
230
+ etags.clear()
231
+ store.clear()
232
+ }
233
+ }
234
+ }
235
+
236
+ const makeMap = Effect.acquireRelease(
237
+ Effect.sync(() => makeContextMap()),
238
+ (m) => Effect.sync(() => m.clear())
239
+ )
240
+
241
+ export class ContextMap extends Context.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
242
+ }
243
+
244
+ export const ContextMapContainer = RequestScopedDependencies.make(
245
+ "ContextMapContainer",
246
+ ContextMap.make.pipe(Effect.map(ContextMap.of))
247
+ )
248
+
249
+ export type ContextMapNotStartedError = RequestScopedDependencies.RequestScopedDependencyNotStartedError
250
+
251
+ export const getContextMap = ContextMapContainer.current
252
+
253
+ /**
254
+ * Runs `make` at most once per ContextMap (i.e. per request) and caches the
255
+ * resulting value in the ContextMap under a fresh symbol. Subsequent calls of
256
+ * the returned Effect within the same ContextMap return the cached value.
257
+ *
258
+ * Uses the ContextMap's shared semaphore for safe single initialization.
259
+ */
260
+ export const cachedPerRequest = <A, E, R>(
261
+ make: Effect.Effect<A, E, R>
262
+ ): Effect.Effect<A, E | ContextMapNotStartedError, R> => {
263
+ const cacheKey = Symbol()
264
+ return getContextMap.pipe(
265
+ Effect.flatMap((ctxMap) => ctxMap.getOrCreateStoreEffect(cacheKey, make))
266
+ )
267
+ }
268
+
269
+ const defaultNs: NonEmptyString255 = NonEmptyString255("primary")
270
+ export class storeId extends Context.Reference("StoreId", { defaultValue: (): NonEmptyString255 => defaultNs }) {}
271
+
272
+ export type PersistenceModelType<Encoded extends object> = Encoded & {
273
+ _etag?: string | undefined
274
+ }
275
+
276
+ export interface StorageConfig {
277
+ url: Redacted.Redacted
278
+ prefix: string
279
+ dbName: string
280
+ }
package/src/_ext/Array.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { Chunk, Effect, Equal } from "effect-app"
2
- import { NotFoundError } from "../client/errors.js"
1
+ import * as Chunk from "effect-app/Chunk"
2
+ import * as Effect from "effect-app/Effect"
3
+ import * as Equal from "effect/Equal"
4
+ import { NotFoundError } from "../client/errors.ts"
3
5
 
4
6
  function getFirstBy<A, Type extends string>(
5
7
  a: Iterable<A>,
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,24 @@
1
+ // JSON / Body return-type overrides (`any` -> `unknown`), isolated from
2
+ // `builtin.ts` so consumers that source-link this package (e.g. an embedded
3
+ // Effect-source setup) can toggle them off. As a `declare global`, the override
4
+ // is program-wide: in linked mode it leaks into source-linked Effect and breaks
5
+ // Effect's own `JSON.parse(...)` / `response.json()` call sites (TS2322
6
+ // `unknown` vs `Json`). `builtin.ts` triple-slash-references this file, so
7
+ // normal builds keep the override.
8
+ declare global {
9
+ interface JSON {
10
+ /**
11
+ * Converts a JavaScript Object Notation (JSON) string into an object.
12
+ * @param text A valid JSON string.
13
+ * @param reviver A function that transforms the results. This function is called for each member of the object.
14
+ * If a member contains nested objects, the nested objects are transformed before the parent object is.
15
+ */
16
+ parse(text: string, reviver?: (this: any, key: string, value: any) => any): unknown
17
+ }
18
+
19
+ interface Body {
20
+ json(): Promise<unknown>
21
+ }
22
+ }
23
+
24
+ export {}
package/src/builtin.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // oxlint-disable-next-line typescript/triple-slash-reference
2
+ /// <reference path="./builtin-json.d.ts" />
1
3
  import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect/Array"
2
4
 
3
5
  declare global {
@@ -17,34 +19,27 @@ declare global {
17
19
  split(separator: string | RegExp, limit?: number): [string, ...string[]]
18
20
  }
19
21
 
20
- interface JSON {
21
- /**
22
- * Converts a JavaScript Object Notation (JSON) string into an object.
23
- * @param text A valid JSON string.
24
- * @param reviver A function that transforms the results. This function is called for each member of the object.
25
- * If a member contains nested objects, the nested objects are transformed before the parent object is.
26
- */
27
- parse(text: string, reviver?: (this: any, key: string, value: any) => any): unknown
28
- }
29
-
30
- interface Body {
31
- json(): Promise<unknown>
32
- }
22
+ // JSON.parse / Body.json overrides live in ./builtin-json.d.ts (referenced
23
+ // above) so a source-linked consumer can disable them in linked mode.
33
24
 
34
25
  interface Array<T> {
35
- map<A, B>(
36
- this: NonEmptyArray<A>,
37
- map: (a: A, index: number) => B
38
- ): NonEmptyArray<B>
26
+ // Conditional return instead of a `this`-typed overload: a `this` overload
27
+ // is selected-then-rejected on union-of-array receivers (TS2684), poisoning
28
+ // foreign code like `(readonly A[] | readonly B[]).map(...)`. A single
29
+ // conditional-return signature refines NonEmpty without a `this` param.
30
+ map<U>(
31
+ callbackfn: (value: T, index: number, array: T[]) => U,
32
+ thisArg?: any
33
+ ): this extends NonEmptyArray<any> ? NonEmptyArray<U> : U[]
39
34
  }
40
35
  interface ReadonlyArray<T> {
41
36
  // Subsequent property declarations must have the same type. Property 'length' must be of type 'number', but here has type 'NonNegativeInt'.
42
37
  // readonly length: NonNegativeInt
43
38
 
44
- map<A, B>(
45
- this: NonEmptyReadonlyArray<A>,
46
- map: (a: A, index: number) => B
47
- ): NonEmptyReadonlyArray<B>
39
+ map<U>(
40
+ callbackfn: (value: T, index: number, array: readonly T[]) => U,
41
+ thisArg?: any
42
+ ): this extends NonEmptyReadonlyArray<any> ? NonEmptyReadonlyArray<U> : U[]
48
43
  }
49
44
  }
50
45
 
@@ -0,0 +1,55 @@
1
+ import * as Equal from "effect/Equal"
2
+ import * as Ref from "effect/Ref"
3
+ import * as Context from "../Context.ts"
4
+ import * as Effect from "../Effect.ts"
5
+ import type { InvalidationKey } from "../rpc/Invalidation.ts"
6
+
7
+ export type { InvalidationKey }
8
+ /** Shape of the per-mutation service that accumulates server-provided invalidation keys. */
9
+ export interface InvalidationKeysService {
10
+ readonly add: (key: InvalidationKey) => Effect.Effect<void>
11
+ readonly get: Effect.Effect<ReadonlyArray<InvalidationKey>>
12
+ }
13
+
14
+ /**
15
+ * Context.Reference that accumulates invalidation keys received from the server via the
16
+ * `x-invalidate` HTTP response header.
17
+ *
18
+ * The default is a no-op: when not explicitly provided (e.g. outside a mutation wrapper)
19
+ * all calls are ignored. The mutation wrapper in `@effect-app/vue` provides a real
20
+ * implementation backed by a `Ref`.
21
+ */
22
+ export const InvalidationKeysFromServer = Context.Reference<InvalidationKeysService>(
23
+ "effect-app/client/InvalidationKeysFromServer",
24
+ {
25
+ defaultValue: () => ({
26
+ add: (_key: InvalidationKey) => Effect.void,
27
+ get: Effect.succeed([] as ReadonlyArray<InvalidationKey>)
28
+ })
29
+ }
30
+ )
31
+ export type InvalidationKeysFromServer = typeof InvalidationKeysFromServer
32
+
33
+ /**
34
+ * Creates a fresh `InvalidationKeysService` implementation backed by a `Ref`.
35
+ *
36
+ * @param ref - The `Ref` that stores the accumulated keys.
37
+ * @param onAdded - V3: Optional Effect run after a distinct key is added. Use to trigger
38
+ * mid-stream query invalidation without waiting for the stream to complete. Repeated keys
39
+ * stay accumulated for the final refresh but do not retrigger the callback.
40
+ */
41
+ export const makeInvalidationKeysService = (
42
+ ref: Ref.Ref<ReadonlyArray<InvalidationKey>>,
43
+ onAdded?: (key: InvalidationKey) => Effect.Effect<void>
44
+ ): InvalidationKeysService => ({
45
+ add: (key) =>
46
+ Ref
47
+ .modify(ref, (keys) => {
48
+ if (keys.some((existing) => Equal.equals(existing, key))) return [false, keys]
49
+ return [true, [...keys, key]]
50
+ })
51
+ .pipe(
52
+ Effect.flatMap((added) => added && onAdded ? onAdded(key) : Effect.void)
53
+ ),
54
+ get: Ref.get(ref)
55
+ })