effect-app 4.0.0-beta.28 → 4.0.0-beta.280

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