effect-app 4.0.0-beta.27 → 4.0.0-beta.272

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 (342) hide show
  1. package/CHANGELOG.md +1275 -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/Effect.d.ts +10 -9
  21. package/dist/Effect.d.ts.map +1 -1
  22. package/dist/Effect.js +5 -8
  23. package/dist/Emailer.d.ts +51 -0
  24. package/dist/Emailer.d.ts.map +1 -0
  25. package/dist/Emailer.js +7 -0
  26. package/dist/Function.d.ts.map +1 -1
  27. package/dist/Layer.d.ts +10 -6
  28. package/dist/Layer.d.ts.map +1 -1
  29. package/dist/Layer.js +3 -2
  30. package/dist/Model/Repository/Registry.d.ts +22 -0
  31. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  32. package/dist/Model/Repository/Registry.js +18 -0
  33. package/dist/Model/Repository/ext.d.ts +60 -0
  34. package/dist/Model/Repository/ext.d.ts.map +1 -0
  35. package/dist/Model/Repository/ext.js +122 -0
  36. package/dist/Model/Repository/internal/internal.d.ts +63 -0
  37. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  38. package/dist/Model/Repository/internal/internal.js +430 -0
  39. package/dist/Model/Repository/legacy.d.ts +21 -0
  40. package/dist/Model/Repository/legacy.d.ts.map +1 -0
  41. package/dist/Model/Repository/legacy.js +2 -0
  42. package/dist/Model/Repository/makeRepo.d.ts +54 -0
  43. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  44. package/dist/Model/Repository/makeRepo.js +27 -0
  45. package/dist/Model/Repository/service.d.ts +121 -0
  46. package/dist/Model/Repository/service.d.ts.map +1 -0
  47. package/dist/Model/Repository/service.js +2 -0
  48. package/dist/Model/Repository/validation.d.ts +58 -0
  49. package/dist/Model/Repository/validation.d.ts.map +1 -0
  50. package/dist/Model/Repository/validation.js +32 -0
  51. package/dist/Model/Repository.d.ts +7 -0
  52. package/dist/Model/Repository.d.ts.map +1 -0
  53. package/dist/Model/Repository.js +7 -0
  54. package/dist/Model/dsl.d.ts +33 -0
  55. package/dist/Model/dsl.d.ts.map +1 -0
  56. package/dist/Model/dsl.js +43 -0
  57. package/dist/Model/filter/filterApi.d.ts +30 -0
  58. package/dist/Model/filter/filterApi.d.ts.map +1 -0
  59. package/dist/Model/filter/filterApi.js +2 -0
  60. package/dist/Model/filter/types/errors.d.ts +29 -0
  61. package/dist/Model/filter/types/errors.d.ts.map +1 -0
  62. package/dist/Model/filter/types/errors.js +2 -0
  63. package/dist/Model/filter/types/fields.d.ts +15 -0
  64. package/dist/Model/filter/types/fields.d.ts.map +1 -0
  65. package/dist/Model/filter/types/fields.js +2 -0
  66. package/dist/Model/filter/types/path/common.d.ts +316 -0
  67. package/dist/Model/filter/types/path/common.d.ts.map +1 -0
  68. package/dist/Model/filter/types/path/common.js +2 -0
  69. package/dist/Model/filter/types/path/eager.d.ts +94 -0
  70. package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
  71. package/dist/Model/filter/types/path/eager.js +36 -0
  72. package/dist/Model/filter/types/path/index.d.ts +4 -0
  73. package/dist/Model/filter/types/path/index.d.ts.map +1 -0
  74. package/dist/Model/filter/types/path/index.js +3 -0
  75. package/dist/Model/filter/types/utils.d.ts +79 -0
  76. package/dist/Model/filter/types/utils.d.ts.map +1 -0
  77. package/dist/Model/filter/types/utils.js +2 -0
  78. package/dist/Model/filter/types/validator.d.ts +30 -0
  79. package/dist/Model/filter/types/validator.d.ts.map +1 -0
  80. package/dist/Model/filter/types/validator.js +2 -0
  81. package/dist/Model/filter/types.d.ts +5 -0
  82. package/dist/Model/filter/types.d.ts.map +1 -0
  83. package/dist/Model/filter/types.js +7 -0
  84. package/dist/Model/query/dsl.d.ts +493 -0
  85. package/dist/Model/query/dsl.d.ts.map +1 -0
  86. package/dist/Model/query/dsl.js +376 -0
  87. package/dist/Model/query/new-kid-interpreter.d.ts +136 -0
  88. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
  89. package/dist/Model/query/new-kid-interpreter.js +336 -0
  90. package/dist/Model/query.d.ts +15 -0
  91. package/dist/Model/query.d.ts.map +1 -0
  92. package/dist/Model/query.js +3 -0
  93. package/dist/Model.d.ts +5 -0
  94. package/dist/Model.d.ts.map +1 -0
  95. package/dist/Model.js +5 -0
  96. package/dist/NonEmptySet.d.ts +3 -1
  97. package/dist/NonEmptySet.d.ts.map +1 -1
  98. package/dist/NonEmptySet.js +2 -2
  99. package/dist/Option.d.ts +1 -0
  100. package/dist/Option.d.ts.map +1 -1
  101. package/dist/Option.js +3 -1
  102. package/dist/Pure.d.ts +7 -5
  103. package/dist/Pure.d.ts.map +1 -1
  104. package/dist/Pure.js +17 -14
  105. package/dist/QueueMaker.d.ts +13 -0
  106. package/dist/QueueMaker.d.ts.map +1 -0
  107. package/dist/QueueMaker.js +4 -0
  108. package/dist/RequestContext.d.ts +154 -0
  109. package/dist/RequestContext.d.ts.map +1 -0
  110. package/dist/RequestContext.js +54 -0
  111. package/dist/Schema/Class.d.ts +160 -19
  112. package/dist/Schema/Class.d.ts.map +1 -1
  113. package/dist/Schema/Class.js +260 -17
  114. package/dist/Schema/FastCheck.d.ts.map +1 -1
  115. package/dist/Schema/SchemaParser.d.ts +5 -0
  116. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  117. package/dist/Schema/SchemaParser.js +6 -0
  118. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  119. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  120. package/dist/Schema/SpecialJsonSchema.js +118 -0
  121. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  122. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  123. package/dist/Schema/SpecialOpenApi.js +123 -0
  124. package/dist/Schema/brand.d.ts +4 -2
  125. package/dist/Schema/brand.d.ts.map +1 -1
  126. package/dist/Schema/brand.js +3 -1
  127. package/dist/Schema/email.d.ts.map +1 -1
  128. package/dist/Schema/email.js +7 -4
  129. package/dist/Schema/ext.d.ts +338 -55
  130. package/dist/Schema/ext.d.ts.map +1 -1
  131. package/dist/Schema/ext.js +358 -53
  132. package/dist/Schema/moreStrings.d.ts +82 -36
  133. package/dist/Schema/moreStrings.d.ts.map +1 -1
  134. package/dist/Schema/moreStrings.js +49 -42
  135. package/dist/Schema/numbers.d.ts +34 -21
  136. package/dist/Schema/numbers.d.ts.map +1 -1
  137. package/dist/Schema/numbers.js +55 -12
  138. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  139. package/dist/Schema/phoneNumber.js +6 -3
  140. package/dist/Schema/strings.d.ts +18 -4
  141. package/dist/Schema/strings.d.ts.map +1 -1
  142. package/dist/Schema/strings.js +1 -5
  143. package/dist/Schema.d.ts +213 -7
  144. package/dist/Schema.d.ts.map +1 -1
  145. package/dist/Schema.js +190 -11
  146. package/dist/Set.d.ts +4 -1
  147. package/dist/Set.d.ts.map +1 -1
  148. package/dist/Set.js +3 -2
  149. package/dist/Store.d.ts +170 -0
  150. package/dist/Store.d.ts.map +1 -0
  151. package/dist/Store.js +121 -0
  152. package/dist/_ext/Array.d.ts +1 -1
  153. package/dist/_ext/Array.d.ts.map +1 -1
  154. package/dist/_ext/Array.js +4 -2
  155. package/dist/_ext/misc.d.ts +4 -1
  156. package/dist/_ext/misc.d.ts.map +1 -1
  157. package/dist/_ext/misc.js +4 -2
  158. package/dist/_ext/ord.ext.d.ts +2 -1
  159. package/dist/_ext/ord.ext.d.ts.map +1 -1
  160. package/dist/_ext/ord.ext.js +2 -2
  161. package/dist/client/InvalidationKeys.d.ts +29 -0
  162. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  163. package/dist/client/InvalidationKeys.js +33 -0
  164. package/dist/client/apiClientFactory.d.ts +19 -31
  165. package/dist/client/apiClientFactory.d.ts.map +1 -1
  166. package/dist/client/apiClientFactory.js +104 -34
  167. package/dist/client/clientFor.d.ts +52 -18
  168. package/dist/client/clientFor.d.ts.map +1 -1
  169. package/dist/client/clientFor.js +9 -1
  170. package/dist/client/errors.d.ts +82 -27
  171. package/dist/client/errors.d.ts.map +1 -1
  172. package/dist/client/errors.js +75 -19
  173. package/dist/client/makeClient.d.ts +494 -32
  174. package/dist/client/makeClient.d.ts.map +1 -1
  175. package/dist/client/makeClient.js +66 -24
  176. package/dist/client.d.ts +1 -0
  177. package/dist/client.d.ts.map +1 -1
  178. package/dist/client.js +2 -1
  179. package/dist/faker.d.ts.map +1 -1
  180. package/dist/http/Request.d.ts +1 -1
  181. package/dist/http/Request.d.ts.map +1 -1
  182. package/dist/http/Request.js +2 -2
  183. package/dist/ids.d.ts +42 -14
  184. package/dist/ids.d.ts.map +1 -1
  185. package/dist/ids.js +30 -5
  186. package/dist/index.d.ts +6 -7
  187. package/dist/index.d.ts.map +1 -1
  188. package/dist/index.js +8 -8
  189. package/dist/middleware.d.ts +13 -7
  190. package/dist/middleware.d.ts.map +1 -1
  191. package/dist/middleware.js +14 -8
  192. package/dist/rpc/Invalidation.d.ts +420 -0
  193. package/dist/rpc/Invalidation.d.ts.map +1 -0
  194. package/dist/rpc/Invalidation.js +168 -0
  195. package/dist/rpc/MiddlewareMaker.d.ts +11 -7
  196. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  197. package/dist/rpc/MiddlewareMaker.js +59 -38
  198. package/dist/rpc/RpcContextMap.d.ts +3 -3
  199. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  200. package/dist/rpc/RpcContextMap.js +4 -4
  201. package/dist/rpc/RpcMiddleware.d.ts +14 -10
  202. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  203. package/dist/rpc/RpcMiddleware.js +1 -1
  204. package/dist/rpc.d.ts +1 -1
  205. package/dist/rpc.d.ts.map +1 -1
  206. package/dist/rpc.js +2 -2
  207. package/dist/runtime.d.ts +19 -0
  208. package/dist/runtime.d.ts.map +1 -0
  209. package/dist/runtime.js +40 -0
  210. package/dist/setupRequest.d.ts +19 -0
  211. package/dist/setupRequest.d.ts.map +1 -0
  212. package/dist/setupRequest.js +69 -0
  213. package/dist/toast.d.ts +51 -0
  214. package/dist/toast.d.ts.map +1 -0
  215. package/dist/toast.js +34 -0
  216. package/dist/transform.d.ts +1 -1
  217. package/dist/transform.d.ts.map +1 -1
  218. package/dist/transform.js +4 -5
  219. package/dist/utils/effectify.d.ts +1 -1
  220. package/dist/utils/effectify.d.ts.map +1 -1
  221. package/dist/utils/effectify.js +2 -2
  222. package/dist/utils/extend.d.ts.map +1 -1
  223. package/dist/utils/gen.d.ts +4 -4
  224. package/dist/utils/gen.d.ts.map +1 -1
  225. package/dist/utils/logLevel.d.ts +2 -2
  226. package/dist/utils/logLevel.d.ts.map +1 -1
  227. package/dist/utils/logger.d.ts +4 -3
  228. package/dist/utils/logger.d.ts.map +1 -1
  229. package/dist/utils/logger.js +4 -4
  230. package/dist/utils.d.ts +34 -39
  231. package/dist/utils.d.ts.map +1 -1
  232. package/dist/utils.js +33 -37
  233. package/dist/validation/validators.d.ts.map +1 -1
  234. package/dist/validation.d.ts.map +1 -1
  235. package/dist/withToast.d.ts +30 -0
  236. package/dist/withToast.d.ts.map +1 -0
  237. package/dist/withToast.js +64 -0
  238. package/package.json +22 -247
  239. package/src/Array.ts +5 -5
  240. package/src/Chunk.ts +3 -3
  241. package/src/Config/SecretURL.ts +6 -3
  242. package/src/Config/internal/configSecretURL.ts +2 -2
  243. package/src/Config.ts +7 -0
  244. package/src/ConfigProvider.ts +5 -0
  245. package/src/{ServiceMap.ts → Context.ts} +56 -63
  246. package/src/Effect.ts +14 -16
  247. package/src/Emailer.ts +51 -0
  248. package/src/Inputify.type.ts +1 -1
  249. package/src/Layer.ts +11 -7
  250. package/src/Model/Repository/Registry.ts +35 -0
  251. package/src/Model/Repository/ext.ts +375 -0
  252. package/src/Model/Repository/internal/internal.ts +741 -0
  253. package/src/Model/Repository/legacy.ts +29 -0
  254. package/src/Model/Repository/makeRepo.ts +145 -0
  255. package/src/Model/Repository/service.ts +676 -0
  256. package/src/Model/Repository/validation.ts +31 -0
  257. package/src/Model/Repository.ts +6 -0
  258. package/src/Model/dsl.ts +129 -0
  259. package/src/Model/filter/filterApi.ts +60 -0
  260. package/src/Model/filter/types/errors.ts +47 -0
  261. package/src/Model/filter/types/fields.ts +50 -0
  262. package/src/Model/filter/types/path/common.ts +404 -0
  263. package/src/Model/filter/types/path/eager.ts +329 -0
  264. package/src/Model/filter/types/path/index.ts +4 -0
  265. package/src/Model/filter/types/utils.ts +128 -0
  266. package/src/Model/filter/types/validator.ts +46 -0
  267. package/src/Model/filter/types.ts +6 -0
  268. package/src/Model/query/dsl.ts +2694 -0
  269. package/src/Model/query/new-kid-interpreter.ts +484 -0
  270. package/src/Model/query.ts +13 -0
  271. package/src/Model.ts +4 -0
  272. package/src/NonEmptySet.ts +6 -4
  273. package/src/Option.ts +2 -0
  274. package/src/Pure.ts +22 -20
  275. package/src/QueueMaker.ts +19 -0
  276. package/src/RequestContext.ts +95 -0
  277. package/src/Schema/Class.ts +593 -59
  278. package/src/Schema/SchemaParser.ts +12 -0
  279. package/src/Schema/SpecialJsonSchema.ts +139 -0
  280. package/src/Schema/SpecialOpenApi.ts +130 -0
  281. package/src/Schema/brand.ts +22 -2
  282. package/src/Schema/email.ts +9 -4
  283. package/src/Schema/ext.ts +446 -91
  284. package/src/Schema/moreStrings.ts +147 -68
  285. package/src/Schema/numbers.ts +97 -28
  286. package/src/Schema/phoneNumber.ts +9 -5
  287. package/src/Schema/strings.ts +23 -14
  288. package/src/Schema.ts +389 -25
  289. package/src/Set.ts +6 -2
  290. package/src/Store.ts +277 -0
  291. package/src/_ext/Array.ts +4 -2
  292. package/src/_ext/misc.ts +4 -1
  293. package/src/_ext/ord.ext.ts +2 -1
  294. package/src/client/InvalidationKeys.ts +50 -0
  295. package/src/client/apiClientFactory.ts +234 -135
  296. package/src/client/clientFor.ts +105 -34
  297. package/src/client/errors.ts +100 -29
  298. package/src/client/makeClient.ts +594 -73
  299. package/src/client.ts +5 -4
  300. package/src/http/Request.ts +3 -3
  301. package/src/http.ts +1 -1
  302. package/src/ids.ts +33 -6
  303. package/src/index.ts +20 -23
  304. package/src/middleware.ts +13 -9
  305. package/src/rpc/Invalidation.ts +261 -0
  306. package/src/rpc/MiddlewareMaker.ts +88 -80
  307. package/src/rpc/README.md +2 -2
  308. package/src/rpc/RpcContextMap.ts +7 -6
  309. package/src/rpc/RpcMiddleware.ts +19 -13
  310. package/src/rpc.ts +4 -4
  311. package/src/runtime.ts +56 -0
  312. package/src/setupRequest.ts +134 -0
  313. package/src/toast.ts +54 -0
  314. package/src/transform.ts +4 -4
  315. package/src/utils/effectify.ts +1 -1
  316. package/src/utils/gen.ts +8 -8
  317. package/src/utils/logLevel.ts +1 -1
  318. package/src/utils/logger.ts +4 -3
  319. package/src/utils.ts +85 -158
  320. package/src/validation.ts +2 -2
  321. package/src/withToast.ts +133 -0
  322. package/test/dist/rpc.test.d.ts.map +1 -1
  323. package/test/dist/secretURL.test.d.ts.map +1 -0
  324. package/test/dist/special.test.d.ts.map +1 -0
  325. package/test/moreStrings.test.ts +1 -1
  326. package/test/rpc.test.ts +46 -6
  327. package/test/schema.test.ts +459 -30
  328. package/test/secretURL.test.ts +160 -0
  329. package/test/special.test.ts +1258 -0
  330. package/test/utils.test.ts +7 -7
  331. package/tsconfig.base.json +6 -5
  332. package/tsconfig.json +3 -1
  333. package/tsconfig.json.bak +2 -2
  334. package/tsconfig.src.json +29 -29
  335. package/tsconfig.test.json +2 -2
  336. package/dist/Operations.d.ts +0 -123
  337. package/dist/Operations.d.ts.map +0 -1
  338. package/dist/Operations.js +0 -29
  339. package/dist/ServiceMap.d.ts.map +0 -1
  340. package/dist/ServiceMap.js +0 -91
  341. package/eslint.config.mjs +0 -26
  342. package/src/Operations.ts +0 -55
@@ -1,6 +1,21 @@
1
- import { type GetContextConfig, type GetEffectError, type RequestContextMapTagAny } from "../rpc/RpcContextMap.js"
2
- import * as S from "../Schema.js"
3
- import { AST } from "../Schema.js"
1
+ import type * as Exit from "effect/Exit"
2
+ import * as SchemaTransformation from "effect/SchemaTransformation"
3
+ import { type GetContextConfig, type RpcContextMap } from "../rpc/RpcContextMap.ts"
4
+ import * as S from "../Schema.ts"
5
+ import { AST } from "../Schema.ts"
6
+ import type { ClientForOptions } from "./clientFor.ts"
7
+
8
+ /**
9
+ * Minimal structural shape for an rpc-client middleware tag.
10
+ * Captures only what `makeRpcClient` and routing/client factory consume from it
11
+ * (no `Default` layer required — that is provided to `makeRouter`).
12
+ */
13
+ export interface ClientMiddleware<RequestContextMap extends Record<string, RpcContextMap.Any>> {
14
+ readonly requestContextMap: RequestContextMap
15
+ readonly requestContext: unknown
16
+ readonly provides?: unknown
17
+ readonly requires?: unknown
18
+ }
4
19
 
5
20
  const merge = (a: any, b: Array<any>) =>
6
21
  a !== undefined && b.length ? S.Union([a, ...b]) : a !== undefined ? a : b.length ? S.Union(b) : S.Never
@@ -8,103 +23,609 @@ const merge = (a: any, b: Array<any>) =>
8
23
  /**
9
24
  * Whatever the input, we will only decode or encode to void
10
25
  */
11
- const ForceVoid: S.Codec<void> = S.Void as any
26
+ export const ForceVoid = S
27
+ .declare((_: unknown): _ is unknown => true)
28
+ .pipe(
29
+ S.decodeTo(S.Any, SchemaTransformation.transform<unknown, unknown>({ decode: () => void 0, encode: () => void 0 }))
30
+ )
12
31
 
13
32
  type SchemaOrFields<T> = T extends S.Top ? T : T extends S.Struct.Fields ? S.Struct<T> : S.Void
14
33
 
15
- type TaggedRequestResult<
34
+ type TaggedRequestSchema<Tag extends string, Payload extends S.Struct.Fields> = S.Struct<
35
+ { readonly _tag: S.tag<Tag> } & Payload
36
+ >
37
+
38
+ type QueryOnlyRequests<Resource> = {
39
+ [K in keyof Resource as Resource[K] extends { readonly type: "query" } ? K : never]: Resource[K]
40
+ }
41
+
42
+ type QueryOnlyResources<Resources> = {
43
+ [K in keyof Resources]: QueryOnlyRequests<Resources[K]>
44
+ }
45
+
46
+ type InputFromPayload<Payload extends S.Struct.Fields> = keyof Payload extends never ? void
47
+ : S.Struct<Payload>["Type"]
48
+
49
+ type OutputFromSuccess<Success extends S.Top> = Success extends typeof ForceVoid ? void : Success["Type"]
50
+
51
+ type InvalidationResources = Record<string, Record<string, unknown>>
52
+
53
+ /**
54
+ * An invalidation instruction returned from `invalidatesQueries`. One of:
55
+ * - a raw query key (`ReadonlyArray<string>`)
56
+ * - an RPC handler object (`{ id, options? }`) — query key derived from `id`
57
+ * - the raw `{ filters, options }` tanstack-query shape
58
+ *
59
+ * `Filters` / `Options` are widened to `Record<string, unknown>` by default so
60
+ * the effect-app core has no dependency on `@tanstack/vue-query`. The vue
61
+ * adapter narrows them via the `InvalidationEntry` alias.
62
+ */
63
+ export type InvalidateQueryInstruction<
64
+ Filters = Record<string, unknown>,
65
+ Options = Record<string, unknown>
66
+ > =
67
+ | ReadonlyArray<string>
68
+ | {
69
+ readonly id: string
70
+ readonly options?: ClientForOptions
71
+ }
72
+ | {
73
+ readonly filters?: Filters
74
+ readonly options?: Options
75
+ }
76
+
77
+ export type InvalidationCallback<Resources, Input = unknown, Success = unknown, Failure = unknown> = (
78
+ queryKey: readonly string[],
79
+ resources: QueryOnlyResources<Resources>,
80
+ ...args: [Input] extends [void] ? [exit: Exit.Exit<Success, Failure>]
81
+ : [input: Input, exit: Exit.Exit<Success, Failure>]
82
+ ) => ReadonlyArray<InvalidateQueryInstruction>
83
+
84
+ export type InvalidationConfig<Resources, Input = unknown, Success = unknown, Failure = unknown> = {
85
+ readonly invalidatesQueries: InvalidationCallback<Resources, Input, Success, Failure>
86
+ readonly invalidationResources?: Resources
87
+ }
88
+
89
+ type InvalidationConfigForCommand<
90
+ Resources,
91
+ Payload extends S.Struct.Fields,
92
+ Success extends S.Top,
93
+ Error extends S.Top
94
+ > = InvalidationConfig<
95
+ Resources,
96
+ InputFromPayload<Payload>,
97
+ OutputFromSuccess<Success>,
98
+ Error["Type"]
99
+ >
100
+
101
+ export const configureInvalidation = <Resources>() =>
102
+ <Input, Success, Failure>(
103
+ invalidatesQueries: InvalidationCallback<Resources, NoInfer<Input>, NoInfer<Success>, NoInfer<Failure>>
104
+ ): InvalidationConfig<Resources, Input, Success, Failure> => ({ invalidatesQueries })
105
+
106
+ export const configureInvalidationCallback = <Resources>() =>
107
+ <Input, Success, Failure>(
108
+ invalidatesQueries: InvalidationCallback<Resources, NoInfer<Input>, NoInfer<Success>, NoInfer<Failure>>
109
+ ): InvalidationCallback<Resources, Input, Success, Failure> => invalidatesQueries
110
+
111
+ export const configureInvalidationResources = <Resources>() =>
112
+ ({}) as Pick<InvalidationConfig<Resources>, "invalidationResources">
113
+
114
+ type TaggedRequestForResult<
115
+ Self,
16
116
  Tag extends string,
17
117
  Payload extends S.Struct.Fields,
18
118
  Success extends S.Top,
19
119
  Error extends S.Top,
20
- Config = Record<string, never>
120
+ Config,
121
+ ModuleName extends string,
122
+ Type extends "command" | "query",
123
+ Stream extends boolean,
124
+ Resources = never,
125
+ Final extends S.Top = never,
126
+ Middleware = unknown
21
127
  > =
22
- & S.TaggedStruct<Tag, Payload>
128
+ & S.Opaque<Self, S.ExtendedSchemaNoEncoded, TaggedRequestSchema<Tag, Payload>, {}>
23
129
  & {
24
- new(...args: any[]): any
130
+ readonly fields: TaggedRequestSchema<Tag, Payload>["fields"]
25
131
  readonly _tag: Tag
26
- readonly fields: { readonly _tag: S.tag<Tag> } & Payload
27
132
  readonly success: Success
28
133
  readonly error: Error
29
134
  readonly config: Config
30
- readonly "~decodingServices": S.Codec.DecodingServices<Success> | S.Codec.DecodingServices<Error>
135
+ readonly id: `${ModuleName}.${Tag}`
136
+ readonly moduleName: ModuleName
137
+ readonly type: Type
138
+ readonly stream: Stream
139
+ readonly middleware?: Middleware
140
+ readonly "~invalidationResources"?: Resources
31
141
  }
142
+ & ([Final] extends [never] ? {} : { readonly final: Final })
32
143
 
33
144
  export const makeRpcClient = <
34
- RequestContextMap extends RequestContextMapTagAny,
145
+ Middleware extends ClientMiddleware<Record<string, RpcContextMap.Any>>,
35
146
  GeneralErrors extends S.Top = never
36
- >(rcs: RequestContextMap, generalErrors?: GeneralErrors) => {
37
- // Long way around ServiceMap/C extends etc to support actual jsdoc from passed in RequestConfig etc... (??)
147
+ >(middleware: Middleware, generalErrors?: GeneralErrors) => {
148
+ // Long way around Context/C extends etc to support actual jsdoc from passed in RequestConfig etc... (??)
38
149
  type ServiceMap = {
39
150
  success: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
40
151
  error: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
152
+ final?: S.Top | S.Struct.Fields // optional final-value schema for stream requests
153
+ stream?: boolean // request metadata — stripped from stored config
41
154
  }
42
155
 
43
- type RequestConfig = GetContextConfig<RequestContextMap["config"]>
156
+ type RequestConfig = GetContextConfig<Middleware["requestContextMap"]>
44
157
 
158
+ // Errors raised by RPC middleware (e.g. `NotLoggedInError` from auth) used to
159
+ // be merged into `resource.error` here so they would surface in the wire
160
+ // failure schema. That merging is gone — the canonical source for middleware
161
+ // errors is now the middleware tag attached to the rpc on both server and
162
+ // client (see `ApiClientFactory.makeFor({ middleware })`). `Rpc.exitSchema`
163
+ // unions in `rpc.middlewares[*].error` automatically.
45
164
  type MergeError<E> = [GeneralErrors] extends [never] ? SchemaOrFields<E> : S.Union<[SchemaOrFields<E>, GeneralErrors]>
46
165
  type ErrorResult<C> = C extends { error: infer E } ? MergeError<E>
47
- : [GeneralErrors] extends [never] ? GetEffectError<RequestContextMap["config"], C>
48
- : MergeError<GetEffectError<RequestContextMap["config"], C>>
49
-
50
- function TaggedRequest<_Self>(): {
51
- <Tag extends string, Payload extends S.Struct.Fields, C extends ServiceMap>(
52
- tag: Tag,
53
- fields: Payload,
54
- config: RequestConfig & C
55
- ): TaggedRequestResult<Tag, Payload, SchemaOrFields<C["success"]>, ErrorResult<C>, Omit<C, "success" | "error">>
56
- <Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "success">>(
57
- tag: Tag,
58
- fields: Payload,
59
- config: RequestConfig & C
60
- ): TaggedRequestResult<Tag, Payload, SchemaOrFields<C["success"]>, ErrorResult<C>, Omit<C, "success" | "error">>
61
- <Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "error">>(
62
- tag: Tag,
63
- fields: Payload,
64
- config: RequestConfig & C
65
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<C>, Omit<C, "success" | "error">>
66
- <Tag extends string, Payload extends S.Struct.Fields, C extends Record<string, any>>(
67
- tag: Tag,
68
- fields: Payload,
69
- config: C & RequestConfig
70
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<C>, Omit<C, "success" | "error">>
71
- <Tag extends string, Payload extends S.Struct.Fields>(
72
- tag: Tag,
73
- fields: Payload
74
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<{}>, Record<string, never>>
75
- } {
76
- // TODO: filter errors based on config + take care of inversion
77
- const errorSchemas = Object.values(rcs.config).map((_) => _.error)
78
- return (<Tag extends string, Fields extends S.Struct.Fields, C extends ServiceMap>(
79
- tag: Tag,
80
- fields: Fields,
81
- config?: C
82
- ) => {
83
- // TODO: S.TaggedRequest removed in v4 — needs rework to use Rpc.make or Request.TaggedClass
84
- // For now, creating a simple tagged struct class with success/failure properties
85
- const failureSchema = merge(
86
- config?.error ? S.isSchema(config.error) ? config.error : S.Struct(config.error) : undefined,
87
- [...errorSchemas, generalErrors].filter(Boolean)
88
- )
89
- const successSchema = config?.success
90
- ? S.isSchema(config.success)
91
- ? AST.isVoid(config.success.ast) ? ForceVoid : config.success
92
- : S.Struct(config.success)
93
- : ForceVoid
94
-
95
- const RequestClass = S.TaggedClass<any>()(tag, fields)
96
- Object.assign(RequestClass, {
97
- _tag: tag,
98
- success: successSchema,
99
- error: failureSchema,
100
- config
101
- })
102
-
103
- return RequestClass
104
- }) as any
166
+ : [GeneralErrors] extends [never] ? typeof S.Never
167
+ : GeneralErrors
168
+
169
+ function makeRequestClass<Tag extends string, Fields extends S.Struct.Fields, C extends Partial<ServiceMap>>(
170
+ tag: Tag,
171
+ fields: Fields,
172
+ config?: C
173
+ ) {
174
+ const failureSchema = merge(
175
+ config?.error ? S.isSchema(config.error) ? config.error : S.Struct(config.error) : undefined,
176
+ [generalErrors].filter(Boolean)
177
+ )
178
+ const successSchema = config?.success
179
+ ? S.isSchema(config.success)
180
+ ? AST.isVoid(config.success.ast) ? ForceVoid : config.success
181
+ : S.Struct(config.success)
182
+ : ForceVoid
183
+
184
+ const finalConfig = (config as any)?.final
185
+ const finalSchema = finalConfig && S.isSchema(finalConfig) ? finalConfig : undefined
186
+
187
+ // Strip stream from the stored config — it's request metadata, not handler config
188
+ const { stream: _stream, ...restConfig } = config ?? ({} as C)
189
+
190
+ const RequestClass = S.Opaque()(S.TaggedStruct(tag, fields))
191
+ Object.assign(RequestClass, {
192
+ _tag: tag,
193
+ success: successSchema,
194
+ error: failureSchema,
195
+ ...(finalSchema !== undefined ? { final: finalSchema } : {}),
196
+ config: restConfig
197
+ })
198
+
199
+ return RequestClass
200
+ }
201
+
202
+ function makeTaggedRequestWithMeta<
203
+ ModuleName extends string,
204
+ Type extends "command" | "query"
205
+ >(
206
+ moduleName: ModuleName,
207
+ type: Type
208
+ ) {
209
+ function TaggedRequestWithMeta<Self, Resources extends InvalidationResources = never>(): {
210
+ // ─── stream: true overloads (must come before non-stream so TypeScript picks them) ───────────
211
+ <
212
+ Tag extends string,
213
+ Payload extends S.Struct.Fields,
214
+ Success extends S.Top | S.Struct.Fields,
215
+ Error extends S.Top | S.Struct.Fields,
216
+ Final extends S.Top | S.Struct.Fields = never,
217
+ C extends RequestConfig & Record<string, any> = RequestConfig & Record<string, any>
218
+ >(
219
+ tag: Tag,
220
+ fields: Payload,
221
+ config:
222
+ & Omit<C, "invalidatesQueries">
223
+ & { stream: true; success: Success; error: Error; final?: Final },
224
+ invalidatesQueries?: InvalidationCallback<
225
+ Resources,
226
+ InputFromPayload<Payload>,
227
+ OutputFromSuccess<SchemaOrFields<Success>>,
228
+ ErrorResult<C & { success: Success; error: Error }>["Type"]
229
+ >
230
+ ): TaggedRequestForResult<
231
+ Self,
232
+ Tag,
233
+ Payload,
234
+ SchemaOrFields<Success>,
235
+ ErrorResult<C & { success: Success; error: Error }>,
236
+ Omit<
237
+ & Omit<C, "invalidatesQueries">
238
+ & {
239
+ success: Success
240
+ error: Error
241
+ }
242
+ & Partial<
243
+ InvalidationConfigForCommand<
244
+ Resources,
245
+ Payload,
246
+ SchemaOrFields<Success>,
247
+ ErrorResult<C & { success: Success; error: Error }>
248
+ >
249
+ >,
250
+ "success" | "error" | "stream"
251
+ >,
252
+ ModuleName,
253
+ Type,
254
+ true,
255
+ Resources,
256
+ [Final] extends [never] ? never : SchemaOrFields<Final>,
257
+ Middleware
258
+ >
259
+ <
260
+ Tag extends string,
261
+ Payload extends S.Struct.Fields,
262
+ Success extends S.Top | S.Struct.Fields,
263
+ Final extends S.Top | S.Struct.Fields = never,
264
+ C extends RequestConfig & Record<string, any> & { error?: never } =
265
+ & RequestConfig
266
+ & Record<string, any>
267
+ & { error?: never }
268
+ >(
269
+ tag: Tag,
270
+ fields: Payload,
271
+ config:
272
+ & Omit<C, "invalidatesQueries">
273
+ & { stream: true; success: Success; final?: Final },
274
+ invalidatesQueries?: InvalidationCallback<
275
+ Resources,
276
+ InputFromPayload<Payload>,
277
+ OutputFromSuccess<SchemaOrFields<Success>>,
278
+ ErrorResult<C & { success: Success }>["Type"]
279
+ >
280
+ ): TaggedRequestForResult<
281
+ Self,
282
+ Tag,
283
+ Payload,
284
+ SchemaOrFields<Success>,
285
+ ErrorResult<C & { success: Success }>,
286
+ Omit<
287
+ & Omit<C, "invalidatesQueries">
288
+ & { success: Success }
289
+ & Partial<
290
+ InvalidationConfigForCommand<
291
+ Resources,
292
+ Payload,
293
+ SchemaOrFields<Success>,
294
+ ErrorResult<C & { success: Success }>
295
+ >
296
+ >,
297
+ "success" | "error" | "stream"
298
+ >,
299
+ ModuleName,
300
+ Type,
301
+ true,
302
+ Resources,
303
+ [Final] extends [never] ? never : SchemaOrFields<Final>,
304
+ Middleware
305
+ >
306
+ // ─── stream: true without `success` overloads ────────────────────────────────────────────────
307
+ <
308
+ Tag extends string,
309
+ Payload extends S.Struct.Fields,
310
+ Error extends S.Top | S.Struct.Fields,
311
+ C extends RequestConfig & Record<string, any> & { success?: never } =
312
+ & RequestConfig
313
+ & Record<string, any>
314
+ & { success?: never }
315
+ >(
316
+ tag: Tag,
317
+ fields: Payload,
318
+ config:
319
+ & Omit<C, "invalidatesQueries">
320
+ & { stream: true; error: Error },
321
+ invalidatesQueries?: InvalidationCallback<
322
+ Resources,
323
+ InputFromPayload<Payload>,
324
+ void,
325
+ ErrorResult<C & { error: Error }>["Type"]
326
+ >
327
+ ): TaggedRequestForResult<
328
+ Self,
329
+ Tag,
330
+ Payload,
331
+ typeof ForceVoid,
332
+ ErrorResult<C & { error: Error }>,
333
+ Omit<
334
+ & Omit<C, "invalidatesQueries">
335
+ & { error: Error }
336
+ & Partial<
337
+ InvalidationConfigForCommand<
338
+ Resources,
339
+ Payload,
340
+ typeof ForceVoid,
341
+ ErrorResult<C & { error: Error }>
342
+ >
343
+ >,
344
+ "success" | "error" | "stream"
345
+ >,
346
+ ModuleName,
347
+ Type,
348
+ true,
349
+ Resources,
350
+ never,
351
+ Middleware
352
+ >
353
+ <
354
+ Tag extends string,
355
+ Payload extends S.Struct.Fields,
356
+ C extends RequestConfig & Record<string, any> & { success?: never; error?: never } =
357
+ & RequestConfig
358
+ & Record<string, any>
359
+ & { success?: never; error?: never }
360
+ >(
361
+ tag: Tag,
362
+ fields: Payload,
363
+ config:
364
+ & Omit<C, "invalidatesQueries">
365
+ & { stream: true },
366
+ invalidatesQueries?: InvalidationCallback<
367
+ Resources,
368
+ InputFromPayload<Payload>,
369
+ void,
370
+ ErrorResult<C>["Type"]
371
+ >
372
+ ): TaggedRequestForResult<
373
+ Self,
374
+ Tag,
375
+ Payload,
376
+ typeof ForceVoid,
377
+ ErrorResult<C>,
378
+ Omit<
379
+ & Omit<C, "invalidatesQueries">
380
+ & Partial<InvalidationConfigForCommand<Resources, Payload, typeof ForceVoid, ErrorResult<C>>>,
381
+ "success" | "error" | "stream"
382
+ >,
383
+ ModuleName,
384
+ Type,
385
+ true,
386
+ Resources,
387
+ never,
388
+ Middleware
389
+ >
390
+ // ─── non-stream overloads ────────────────────────────────────────────────────────────────────
391
+ <
392
+ Tag extends string,
393
+ Payload extends S.Struct.Fields,
394
+ Success extends S.Top | S.Struct.Fields,
395
+ Error extends S.Top | S.Struct.Fields,
396
+ Final extends S.Top | S.Struct.Fields = never,
397
+ C extends RequestConfig & Record<string, any> = RequestConfig & Record<string, any>
398
+ >(
399
+ tag: Tag,
400
+ fields: Payload,
401
+ config:
402
+ & Omit<C, "invalidatesQueries">
403
+ & { success: Success; error: Error; final?: Final },
404
+ invalidatesQueries?: InvalidationCallback<
405
+ Resources,
406
+ InputFromPayload<Payload>,
407
+ OutputFromSuccess<SchemaOrFields<Success>>,
408
+ ErrorResult<C & { success: Success; error: Error }>["Type"]
409
+ >
410
+ ): TaggedRequestForResult<
411
+ Self,
412
+ Tag,
413
+ Payload,
414
+ SchemaOrFields<Success>,
415
+ ErrorResult<C & { success: Success; error: Error }>,
416
+ Omit<
417
+ & Omit<C, "invalidatesQueries">
418
+ & {
419
+ success: Success
420
+ error: Error
421
+ }
422
+ & Partial<
423
+ InvalidationConfigForCommand<
424
+ Resources,
425
+ Payload,
426
+ SchemaOrFields<Success>,
427
+ ErrorResult<C & { success: Success; error: Error }>
428
+ >
429
+ >,
430
+ "success" | "error" | "stream"
431
+ >,
432
+ ModuleName,
433
+ Type,
434
+ false,
435
+ Resources,
436
+ [Final] extends [never] ? never : SchemaOrFields<Final>,
437
+ Middleware
438
+ >
439
+ <
440
+ Tag extends string,
441
+ Payload extends S.Struct.Fields,
442
+ Success extends S.Top | S.Struct.Fields,
443
+ Final extends S.Top | S.Struct.Fields = never,
444
+ C extends RequestConfig & Record<string, any> & { error?: never } =
445
+ & RequestConfig
446
+ & Record<string, any>
447
+ & {
448
+ error?: never
449
+ }
450
+ >(
451
+ tag: Tag,
452
+ fields: Payload,
453
+ config:
454
+ & Omit<C, "invalidatesQueries">
455
+ & { success: Success; final?: Final },
456
+ invalidatesQueries?: InvalidationCallback<
457
+ Resources,
458
+ InputFromPayload<Payload>,
459
+ OutputFromSuccess<SchemaOrFields<Success>>,
460
+ ErrorResult<C & { success: Success }>["Type"]
461
+ >
462
+ ): TaggedRequestForResult<
463
+ Self,
464
+ Tag,
465
+ Payload,
466
+ SchemaOrFields<Success>,
467
+ ErrorResult<C & { success: Success }>,
468
+ Omit<
469
+ & Omit<C, "invalidatesQueries">
470
+ & {
471
+ success: Success
472
+ }
473
+ & Partial<
474
+ InvalidationConfigForCommand<
475
+ Resources,
476
+ Payload,
477
+ SchemaOrFields<Success>,
478
+ ErrorResult<C & { success: Success }>
479
+ >
480
+ >,
481
+ "success" | "error" | "stream"
482
+ >,
483
+ ModuleName,
484
+ Type,
485
+ false,
486
+ Resources,
487
+ [Final] extends [never] ? never : SchemaOrFields<Final>,
488
+ Middleware
489
+ >
490
+ <
491
+ Tag extends string,
492
+ Payload extends S.Struct.Fields,
493
+ Error extends S.Top | S.Struct.Fields,
494
+ C extends RequestConfig & Record<string, any> & { success?: never }
495
+ >(
496
+ tag: Tag,
497
+ fields: Payload,
498
+ config:
499
+ & Omit<C, "invalidatesQueries">
500
+ & { error: Error },
501
+ invalidatesQueries?: InvalidationCallback<
502
+ Resources,
503
+ InputFromPayload<Payload>,
504
+ void,
505
+ ErrorResult<C & { error: Error }>["Type"]
506
+ >
507
+ ): TaggedRequestForResult<
508
+ Self,
509
+ Tag,
510
+ Payload,
511
+ typeof ForceVoid,
512
+ ErrorResult<C & { error: Error }>,
513
+ Omit<
514
+ & Omit<C, "invalidatesQueries">
515
+ & {
516
+ error: Error
517
+ }
518
+ & Partial<
519
+ InvalidationConfigForCommand<
520
+ Resources,
521
+ Payload,
522
+ typeof ForceVoid,
523
+ ErrorResult<C & { error: Error }>
524
+ >
525
+ >,
526
+ "success" | "error" | "stream"
527
+ >,
528
+ ModuleName,
529
+ Type,
530
+ false,
531
+ Resources,
532
+ never,
533
+ Middleware
534
+ >
535
+ <
536
+ Tag extends string,
537
+ Payload extends S.Struct.Fields,
538
+ C extends RequestConfig & Record<string, any> & { success?: never; error?: never }
539
+ >(
540
+ tag: Tag,
541
+ fields: Payload,
542
+ config: Omit<C, "invalidatesQueries">,
543
+ invalidatesQueries?: InvalidationCallback<
544
+ Resources,
545
+ InputFromPayload<Payload>,
546
+ void,
547
+ ErrorResult<C>["Type"]
548
+ >
549
+ ): TaggedRequestForResult<
550
+ Self,
551
+ Tag,
552
+ Payload,
553
+ typeof ForceVoid,
554
+ ErrorResult<C>,
555
+ Omit<
556
+ & Omit<C, "invalidatesQueries">
557
+ & Partial<InvalidationConfigForCommand<Resources, Payload, typeof ForceVoid, ErrorResult<C>>>,
558
+ "success" | "error" | "stream"
559
+ >,
560
+ ModuleName,
561
+ Type,
562
+ false,
563
+ Resources,
564
+ never,
565
+ Middleware
566
+ >
567
+ <Tag extends string, Payload extends S.Struct.Fields>(
568
+ tag: Tag,
569
+ fields: Payload
570
+ ): TaggedRequestForResult<
571
+ Self,
572
+ Tag,
573
+ Payload,
574
+ typeof ForceVoid,
575
+ ErrorResult<{}>,
576
+ Record<string, never>,
577
+ ModuleName,
578
+ Type,
579
+ false,
580
+ never,
581
+ never,
582
+ Middleware
583
+ >
584
+ } {
585
+ return (<Tag extends string, Fields extends S.Struct.Fields, C extends ServiceMap>(
586
+ tag: Tag,
587
+ fields: Fields,
588
+ config?: C,
589
+ invalidatesQueries?: InvalidationCallback<Resources>
590
+ ) => {
591
+ const isStream = (config as any)?.stream === true
592
+ const requestConfig = invalidatesQueries === undefined ? config : { ...config, invalidatesQueries }
593
+ const cls = makeRequestClass(tag, fields, requestConfig)
594
+ Object.assign(cls, {
595
+ id: `${moduleName}.${tag}`,
596
+ moduleName,
597
+ type,
598
+ stream: isStream,
599
+ middleware
600
+ })
601
+ return cls
602
+ }) as any
603
+ }
604
+ return Object.assign(TaggedRequestWithMeta, { moduleName, type } as const)
605
+ }
606
+
607
+ function TaggedRequestFor<ModuleName extends string>(moduleName: ModuleName) {
608
+ const Query = makeTaggedRequestWithMeta(moduleName, "query")
609
+ const Command = makeTaggedRequestWithMeta(moduleName, "command")
610
+
611
+ return {
612
+ moduleName,
613
+ /**
614
+ * Create query request classes for this module.
615
+ * Queries read state and should not mutate server state.
616
+ * Pass `stream: true` in the config to produce a Stream of `success` values (QueryStream behaviour).
617
+ */
618
+ Query,
619
+ /**
620
+ * Create command request classes for this module.
621
+ * Commands mutate state and should avoid returning complex read models.
622
+ * Pass `stream: true` in the config to produce a Stream of `success` values (CommandStream behaviour).
623
+ */
624
+ Command
625
+ } as const
105
626
  }
106
627
 
107
628
  return {
108
- TaggedRequest
629
+ TaggedRequestFor
109
630
  }
110
631
  }