effect-app 4.0.0-beta.3 → 4.0.0-beta.300

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 (371) hide show
  1. package/CHANGELOG.md +1592 -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/Context.d.ts +42 -0
  18. package/dist/Context.d.ts.map +1 -0
  19. package/dist/Context.js +67 -0
  20. package/dist/DataDependencies.d.ts +388 -0
  21. package/dist/DataDependencies.d.ts.map +1 -0
  22. package/dist/DataDependencies.js +64 -0
  23. package/dist/Effect.d.ts +10 -9
  24. package/dist/Effect.d.ts.map +1 -1
  25. package/dist/Effect.js +5 -7
  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/ext.d.ts +60 -0
  37. package/dist/Model/Repository/ext.d.ts.map +1 -0
  38. package/dist/Model/Repository/ext.js +122 -0
  39. package/dist/Model/Repository/internal/internal.d.ts +63 -0
  40. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  41. package/dist/Model/Repository/internal/internal.js +438 -0
  42. package/dist/Model/Repository/legacy.d.ts +21 -0
  43. package/dist/Model/Repository/legacy.d.ts.map +1 -0
  44. package/dist/Model/Repository/legacy.js +2 -0
  45. package/dist/Model/Repository/makeRepo.d.ts +54 -0
  46. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  47. package/dist/Model/Repository/makeRepo.js +27 -0
  48. package/dist/Model/Repository/service.d.ts +121 -0
  49. package/dist/Model/Repository/service.d.ts.map +1 -0
  50. package/dist/Model/Repository/service.js +2 -0
  51. package/dist/Model/Repository/validation.d.ts +58 -0
  52. package/dist/Model/Repository/validation.d.ts.map +1 -0
  53. package/dist/Model/Repository/validation.js +32 -0
  54. package/dist/Model/Repository.d.ts +7 -0
  55. package/dist/Model/Repository.d.ts.map +1 -0
  56. package/dist/Model/Repository.js +7 -0
  57. package/dist/Model/dsl.d.ts +33 -0
  58. package/dist/Model/dsl.d.ts.map +1 -0
  59. package/dist/Model/dsl.js +43 -0
  60. package/dist/Model/filter/filterApi.d.ts +30 -0
  61. package/dist/Model/filter/filterApi.d.ts.map +1 -0
  62. package/dist/Model/filter/filterApi.js +2 -0
  63. package/dist/Model/filter/types/errors.d.ts +29 -0
  64. package/dist/Model/filter/types/errors.d.ts.map +1 -0
  65. package/dist/Model/filter/types/errors.js +2 -0
  66. package/dist/Model/filter/types/fields.d.ts +15 -0
  67. package/dist/Model/filter/types/fields.d.ts.map +1 -0
  68. package/dist/Model/filter/types/fields.js +2 -0
  69. package/dist/Model/filter/types/path/common.d.ts +316 -0
  70. package/dist/Model/filter/types/path/common.d.ts.map +1 -0
  71. package/dist/Model/filter/types/path/common.js +2 -0
  72. package/dist/Model/filter/types/path/eager.d.ts +94 -0
  73. package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
  74. package/dist/Model/filter/types/path/eager.js +36 -0
  75. package/dist/Model/filter/types/path/index.d.ts +4 -0
  76. package/dist/Model/filter/types/path/index.d.ts.map +1 -0
  77. package/dist/Model/filter/types/path/index.js +3 -0
  78. package/dist/Model/filter/types/utils.d.ts +79 -0
  79. package/dist/Model/filter/types/utils.d.ts.map +1 -0
  80. package/dist/Model/filter/types/utils.js +2 -0
  81. package/dist/Model/filter/types/validator.d.ts +30 -0
  82. package/dist/Model/filter/types/validator.d.ts.map +1 -0
  83. package/dist/Model/filter/types/validator.js +2 -0
  84. package/dist/Model/filter/types.d.ts +5 -0
  85. package/dist/Model/filter/types.d.ts.map +1 -0
  86. package/dist/Model/filter/types.js +7 -0
  87. package/dist/Model/query/dsl.d.ts +514 -0
  88. package/dist/Model/query/dsl.d.ts.map +1 -0
  89. package/dist/Model/query/dsl.js +376 -0
  90. package/dist/Model/query/new-kid-interpreter.d.ts +132 -0
  91. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
  92. package/dist/Model/query/new-kid-interpreter.js +361 -0
  93. package/dist/Model/query.d.ts +15 -0
  94. package/dist/Model/query.d.ts.map +1 -0
  95. package/dist/Model/query.js +3 -0
  96. package/dist/Model.d.ts +5 -0
  97. package/dist/Model.d.ts.map +1 -0
  98. package/dist/Model.js +5 -0
  99. package/dist/NonEmptySet.d.ts +3 -1
  100. package/dist/NonEmptySet.d.ts.map +1 -1
  101. package/dist/NonEmptySet.js +2 -2
  102. package/dist/Option.d.ts +1 -0
  103. package/dist/Option.d.ts.map +1 -1
  104. package/dist/Option.js +3 -1
  105. package/dist/Pure.d.ts +7 -5
  106. package/dist/Pure.d.ts.map +1 -1
  107. package/dist/Pure.js +17 -14
  108. package/dist/QueueMaker.d.ts +11 -0
  109. package/dist/QueueMaker.d.ts.map +1 -0
  110. package/dist/QueueMaker.js +11 -0
  111. package/dist/RequestContext.d.ts +87 -0
  112. package/dist/RequestContext.d.ts.map +1 -0
  113. package/dist/RequestContext.js +45 -0
  114. package/dist/RequestScopedDependencies.d.ts +21 -0
  115. package/dist/RequestScopedDependencies.d.ts.map +1 -0
  116. package/dist/RequestScopedDependencies.js +16 -0
  117. package/dist/Schema/Class.d.ts +188 -19
  118. package/dist/Schema/Class.d.ts.map +1 -1
  119. package/dist/Schema/Class.js +259 -22
  120. package/dist/Schema/FastCheck.d.ts.map +1 -1
  121. package/dist/Schema/SchemaParser.d.ts +5 -0
  122. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  123. package/dist/Schema/SchemaParser.js +6 -0
  124. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  125. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  126. package/dist/Schema/SpecialJsonSchema.js +118 -0
  127. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  128. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  129. package/dist/Schema/SpecialOpenApi.js +123 -0
  130. package/dist/Schema/brand.d.ts +11 -6
  131. package/dist/Schema/brand.d.ts.map +1 -1
  132. package/dist/Schema/brand.js +3 -1
  133. package/dist/Schema/email.d.ts.map +1 -1
  134. package/dist/Schema/email.js +9 -5
  135. package/dist/Schema/ext.d.ts +340 -56
  136. package/dist/Schema/ext.d.ts.map +1 -1
  137. package/dist/Schema/ext.js +361 -63
  138. package/dist/Schema/moreStrings.d.ts +82 -36
  139. package/dist/Schema/moreStrings.d.ts.map +1 -1
  140. package/dist/Schema/moreStrings.js +53 -44
  141. package/dist/Schema/numbers.d.ts +34 -21
  142. package/dist/Schema/numbers.d.ts.map +1 -1
  143. package/dist/Schema/numbers.js +55 -12
  144. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  145. package/dist/Schema/phoneNumber.js +8 -4
  146. package/dist/Schema/schema.d.ts +1 -1
  147. package/dist/Schema/schema.d.ts.map +1 -1
  148. package/dist/Schema/schema.js +2 -2
  149. package/dist/Schema/strings.d.ts +18 -4
  150. package/dist/Schema/strings.d.ts.map +1 -1
  151. package/dist/Schema/strings.js +1 -5
  152. package/dist/Schema.d.ts +238 -58
  153. package/dist/Schema.d.ts.map +1 -1
  154. package/dist/Schema.js +227 -69
  155. package/dist/SchemaAST.d.ts +2 -0
  156. package/dist/SchemaAST.d.ts.map +1 -0
  157. package/dist/SchemaAST.js +2 -0
  158. package/dist/Set.d.ts +4 -1
  159. package/dist/Set.d.ts.map +1 -1
  160. package/dist/Set.js +3 -2
  161. package/dist/Store.d.ts +163 -0
  162. package/dist/Store.d.ts.map +1 -0
  163. package/dist/Store.js +113 -0
  164. package/dist/_ext/Array.d.ts +1 -1
  165. package/dist/_ext/Array.d.ts.map +1 -1
  166. package/dist/_ext/Array.js +4 -2
  167. package/dist/_ext/misc.d.ts +4 -1
  168. package/dist/_ext/misc.d.ts.map +1 -1
  169. package/dist/_ext/misc.js +4 -2
  170. package/dist/_ext/ord.ext.d.ts +2 -1
  171. package/dist/_ext/ord.ext.d.ts.map +1 -1
  172. package/dist/_ext/ord.ext.js +2 -2
  173. package/dist/builtin.d.ts +2 -14
  174. package/dist/builtin.d.ts.map +1 -1
  175. package/dist/builtin.js +1 -1
  176. package/dist/client/InvalidationKeys.d.ts +30 -0
  177. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  178. package/dist/client/InvalidationKeys.js +37 -0
  179. package/dist/client/apiClientFactory.d.ts +19 -31
  180. package/dist/client/apiClientFactory.d.ts.map +1 -1
  181. package/dist/client/apiClientFactory.js +160 -41
  182. package/dist/client/clientFor.d.ts +54 -18
  183. package/dist/client/clientFor.d.ts.map +1 -1
  184. package/dist/client/clientFor.js +9 -1
  185. package/dist/client/errors.d.ts +82 -27
  186. package/dist/client/errors.d.ts.map +1 -1
  187. package/dist/client/errors.js +75 -19
  188. package/dist/client/makeClient.d.ts +492 -32
  189. package/dist/client/makeClient.d.ts.map +1 -1
  190. package/dist/client/makeClient.js +62 -38
  191. package/dist/client.d.ts +2 -0
  192. package/dist/client.d.ts.map +1 -1
  193. package/dist/client.js +3 -1
  194. package/dist/faker.d.ts.map +1 -1
  195. package/dist/http/Request.d.ts +1 -1
  196. package/dist/http/Request.d.ts.map +1 -1
  197. package/dist/http/Request.js +5 -5
  198. package/dist/ids.d.ts +42 -14
  199. package/dist/ids.d.ts.map +1 -1
  200. package/dist/ids.js +30 -5
  201. package/dist/index.d.ts +6 -8
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +8 -9
  204. package/dist/middleware.d.ts +13 -7
  205. package/dist/middleware.d.ts.map +1 -1
  206. package/dist/middleware.js +14 -8
  207. package/dist/rpc/Invalidation.d.ts +3140 -0
  208. package/dist/rpc/Invalidation.d.ts.map +1 -0
  209. package/dist/rpc/Invalidation.js +178 -0
  210. package/dist/rpc/MiddlewareMaker.d.ts +11 -7
  211. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  212. package/dist/rpc/MiddlewareMaker.js +59 -38
  213. package/dist/rpc/RpcContextMap.d.ts +3 -3
  214. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  215. package/dist/rpc/RpcContextMap.js +4 -4
  216. package/dist/rpc/RpcMiddleware.d.ts +14 -10
  217. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  218. package/dist/rpc/RpcMiddleware.js +1 -1
  219. package/dist/rpc.d.ts +1 -1
  220. package/dist/rpc.d.ts.map +1 -1
  221. package/dist/rpc.js +2 -2
  222. package/dist/runtime.d.ts +19 -0
  223. package/dist/runtime.d.ts.map +1 -0
  224. package/dist/runtime.js +40 -0
  225. package/dist/setupRequest.d.ts +20 -0
  226. package/dist/setupRequest.d.ts.map +1 -0
  227. package/dist/setupRequest.js +72 -0
  228. package/dist/toast.d.ts +51 -0
  229. package/dist/toast.d.ts.map +1 -0
  230. package/dist/toast.js +34 -0
  231. package/dist/transform.d.ts +1 -1
  232. package/dist/transform.d.ts.map +1 -1
  233. package/dist/transform.js +4 -5
  234. package/dist/utils/effectify.d.ts +1 -1
  235. package/dist/utils/effectify.d.ts.map +1 -1
  236. package/dist/utils/effectify.js +2 -2
  237. package/dist/utils/extend.d.ts.map +1 -1
  238. package/dist/utils/gen.d.ts +4 -4
  239. package/dist/utils/gen.d.ts.map +1 -1
  240. package/dist/utils/logLevel.d.ts +2 -2
  241. package/dist/utils/logLevel.d.ts.map +1 -1
  242. package/dist/utils/logger.d.ts +4 -3
  243. package/dist/utils/logger.d.ts.map +1 -1
  244. package/dist/utils/logger.js +4 -4
  245. package/dist/utils.d.ts +50 -37
  246. package/dist/utils.d.ts.map +1 -1
  247. package/dist/utils.js +51 -36
  248. package/dist/validation/validators.d.ts.map +1 -1
  249. package/dist/validation.d.ts.map +1 -1
  250. package/dist/withToast.d.ts +30 -0
  251. package/dist/withToast.d.ts.map +1 -0
  252. package/dist/withToast.js +64 -0
  253. package/package.json +27 -255
  254. package/src/Array.ts +5 -5
  255. package/src/Chunk.ts +3 -3
  256. package/src/Config/SecretURL.ts +6 -3
  257. package/src/Config/internal/configSecretURL.ts +2 -2
  258. package/src/Config.ts +7 -0
  259. package/src/ConfigProvider.ts +5 -0
  260. package/src/{ServiceMap.ts → Context.ts} +59 -65
  261. package/src/DataDependencies.ts +114 -0
  262. package/src/Effect.ts +15 -16
  263. package/src/Emailer.ts +51 -0
  264. package/src/Inputify.type.ts +1 -1
  265. package/src/Layer.ts +11 -7
  266. package/src/Model/Repository/Registry.ts +35 -0
  267. package/src/Model/Repository/ext.ts +375 -0
  268. package/src/Model/Repository/internal/internal.ts +755 -0
  269. package/src/Model/Repository/legacy.ts +29 -0
  270. package/src/Model/Repository/makeRepo.ts +145 -0
  271. package/src/Model/Repository/service.ts +676 -0
  272. package/src/Model/Repository/validation.ts +31 -0
  273. package/src/Model/Repository.ts +6 -0
  274. package/src/Model/dsl.ts +129 -0
  275. package/src/Model/filter/filterApi.ts +60 -0
  276. package/src/Model/filter/types/errors.ts +47 -0
  277. package/src/Model/filter/types/fields.ts +50 -0
  278. package/src/Model/filter/types/path/common.ts +404 -0
  279. package/src/Model/filter/types/path/eager.ts +329 -0
  280. package/src/Model/filter/types/path/index.ts +4 -0
  281. package/src/Model/filter/types/utils.ts +128 -0
  282. package/src/Model/filter/types/validator.ts +46 -0
  283. package/src/Model/filter/types.ts +6 -0
  284. package/src/Model/query/dsl.ts +2770 -0
  285. package/src/Model/query/new-kid-interpreter.ts +526 -0
  286. package/src/Model/query.ts +13 -0
  287. package/src/Model.ts +4 -0
  288. package/src/NonEmptySet.ts +6 -4
  289. package/src/Option.ts +2 -0
  290. package/src/Pure.ts +22 -20
  291. package/src/QueueMaker.ts +11 -0
  292. package/src/RequestContext.ts +48 -0
  293. package/src/RequestScopedDependencies.ts +45 -0
  294. package/src/Schema/Class.ts +631 -63
  295. package/src/Schema/SchemaParser.ts +12 -0
  296. package/src/Schema/SpecialJsonSchema.ts +139 -0
  297. package/src/Schema/SpecialOpenApi.ts +130 -0
  298. package/src/Schema/brand.ts +34 -8
  299. package/src/Schema/email.ts +12 -5
  300. package/src/Schema/ext.ts +469 -106
  301. package/src/Schema/moreStrings.ts +155 -73
  302. package/src/Schema/numbers.ts +97 -28
  303. package/src/Schema/phoneNumber.ts +12 -6
  304. package/src/Schema/schema.ts +1 -1
  305. package/src/Schema/strings.ts +23 -14
  306. package/src/Schema.ts +468 -121
  307. package/src/SchemaAST.ts +1 -0
  308. package/src/Set.ts +6 -2
  309. package/src/Store.ts +273 -0
  310. package/src/_ext/Array.ts +4 -2
  311. package/src/_ext/misc.ts +4 -1
  312. package/src/_ext/ord.ext.ts +2 -1
  313. package/src/builtin-json.d.ts +24 -0
  314. package/src/builtin.ts +16 -21
  315. package/src/client/InvalidationKeys.ts +55 -0
  316. package/src/client/apiClientFactory.ts +306 -144
  317. package/src/client/clientFor.ts +107 -34
  318. package/src/client/errors.ts +109 -29
  319. package/src/client/makeClient.ts +593 -87
  320. package/src/client.ts +6 -4
  321. package/src/http/Request.ts +9 -6
  322. package/src/http.ts +1 -1
  323. package/src/ids.ts +34 -7
  324. package/src/index.ts +20 -24
  325. package/src/middleware.ts +13 -9
  326. package/src/rpc/Invalidation.ts +278 -0
  327. package/src/rpc/MiddlewareMaker.ts +88 -80
  328. package/src/rpc/README.md +2 -2
  329. package/src/rpc/RpcContextMap.ts +7 -6
  330. package/src/rpc/RpcMiddleware.ts +19 -13
  331. package/src/rpc.ts +4 -4
  332. package/src/runtime.ts +56 -0
  333. package/src/setupRequest.ts +138 -0
  334. package/src/toast.ts +54 -0
  335. package/src/transform.ts +4 -4
  336. package/src/utils/effectify.ts +1 -1
  337. package/src/utils/gen.ts +8 -8
  338. package/src/utils/logLevel.ts +1 -1
  339. package/src/utils/logger.ts +4 -3
  340. package/src/utils.ts +105 -156
  341. package/src/validation.ts +2 -2
  342. package/src/withToast.ts +133 -0
  343. package/test/dist/moreStrings.test.d.ts.map +1 -0
  344. package/test/dist/rpc.test.d.ts.map +1 -1
  345. package/test/dist/rpcMiddlewareContext.test.d.ts.map +1 -0
  346. package/test/dist/secretURL.test.d.ts.map +1 -0
  347. package/test/dist/special.test.d.ts.map +1 -0
  348. package/test/moreStrings.test.ts +17 -0
  349. package/test/rpc.test.ts +45 -6
  350. package/test/rpcMiddlewareContext.test.ts +63 -0
  351. package/test/schema.test.ts +613 -7
  352. package/test/secretURL.test.ts +160 -0
  353. package/test/special.test.ts +1258 -0
  354. package/test/utils.test.ts +7 -7
  355. package/tsconfig.base.json +6 -5
  356. package/tsconfig.json +3 -1
  357. package/tsconfig.src.json +29 -29
  358. package/tsconfig.test.json +2 -2
  359. package/dist/Operations.d.ts +0 -87
  360. package/dist/Operations.d.ts.map +0 -1
  361. package/dist/Operations.js +0 -29
  362. package/dist/ServiceMap.d.ts +0 -44
  363. package/dist/ServiceMap.d.ts.map +0 -1
  364. package/dist/ServiceMap.js +0 -91
  365. package/dist/Struct.d.ts +0 -44
  366. package/dist/Struct.d.ts.map +0 -1
  367. package/dist/Struct.js +0 -29
  368. package/eslint.config.mjs +0 -26
  369. package/src/Operations.ts +0 -55
  370. package/src/Struct.ts +0 -54
  371. package/tsconfig.json.bak +0 -12
@@ -1,19 +1,23 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import * as Config from "effect/Config"
3
- import { flow } from "effect/Function"
2
+ import { constant, flow } from "effect/Function"
4
3
  import * as Layer from "effect/Layer"
5
4
  import * as ManagedRuntime from "effect/ManagedRuntime"
5
+ import * as Option from "effect/Option"
6
6
  import * as Predicate from "effect/Predicate"
7
7
  import * as Schema from "effect/Schema"
8
+ import * as Stream from "effect/Stream"
8
9
  import * as Struct from "effect/Struct"
9
10
  import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/unstable/rpc"
10
- import * as Effect from "../Effect.js"
11
- import { HttpClient, HttpClientRequest } from "../http.js"
12
- import * as Option from "../Option.js"
13
- import type * as S from "../Schema.js"
14
- import * as ServiceMap from "../ServiceMap.js"
15
- import { typedKeysOf, typedValuesOf } from "../utils.js"
16
- import type { Client, ClientForOptions, Requests, RequestsAny } from "./clientFor.js"
11
+ import * as Config from "../Config.ts"
12
+ import * as Context from "../Context.ts"
13
+ import * as DataDependencies from "../DataDependencies.ts"
14
+ import * as Effect from "../Effect.ts"
15
+ import { HttpClient, HttpClientRequest } from "../http.ts"
16
+ import { Invalidation } from "../rpc.ts"
17
+ import type * as S from "../Schema.ts"
18
+ import { typedKeysOf, typedValuesOf } from "../utils.ts"
19
+ import type { Client, ClientForOptions, ExtractModuleName, RequestsAny } from "./clientFor.ts"
20
+ import { InvalidationKeysFromServer } from "./InvalidationKeys.ts"
17
21
 
18
22
  export interface ApiConfig {
19
23
  url: string
@@ -31,16 +35,22 @@ export const DefaultApiConfig = Config.all({
31
35
  })
32
36
 
33
37
  export type Req = S.Top & {
34
- new(...args: any[]): any
38
+ readonly make: (...args: any[]) => any
35
39
  _tag: string
36
40
  fields: S.Struct.Fields
37
41
  success: S.Top
38
42
  error: S.Top
43
+ /** Optional final-value schema for stream requests. When set, the execute effect resolves with the last stream value decoded to this type. */
44
+ final?: S.Top
39
45
  config?: Record<string, any>
40
- readonly "~decodingServices"?: unknown
46
+ readonly id: string
47
+ readonly moduleName: string
48
+ readonly type: "command" | "query"
49
+ readonly stream: boolean
50
+ readonly middleware?: unknown
41
51
  }
42
52
 
43
- class RequestName extends ServiceMap.Reference("RequestName", {
53
+ class RequestName extends Context.Reference("RequestName", {
44
54
  defaultValue: () => ({ requestName: "Unspecified", moduleName: "Error" })
45
55
  }) {}
46
56
 
@@ -50,17 +60,17 @@ export const HttpClientLayer = (config: ApiConfig) =>
50
60
  Effect
51
61
  .gen(function*() {
52
62
  const baseClient = yield* HttpClient.HttpClient
53
- const ctx = yield* RequestName
54
63
  const client = baseClient.pipe(
55
64
  HttpClient.mapRequest(HttpClientRequest.prependUrl(config.url + "/rpc")),
56
65
  HttpClient.mapRequest(
57
66
  HttpClientRequest.setHeaders(config.headers.pipe(Option.getOrElse(() => ({}))))
58
67
  ),
59
- HttpClient.mapRequest((req) =>
60
- flow(
61
- HttpClientRequest.appendUrlParam("action", ctx.requestName),
62
- HttpClientRequest.appendUrl("/" + ctx.moduleName)
63
- )(req)
68
+ HttpClient.mapRequestEffect((req) =>
69
+ Effect.map(RequestName, (ctx) =>
70
+ flow(
71
+ HttpClientRequest.appendUrlParam("action", ctx.requestName),
72
+ HttpClientRequest.appendUrl("/" + ctx.moduleName)
73
+ )(req))
64
74
  )
65
75
  )
66
76
  return client
@@ -76,7 +86,7 @@ export const HttpClientFromConfigLayer = Layer.unwrap(
76
86
 
77
87
  export const RpcSerializationLayer = (config: ApiConfig) =>
78
88
  Layer.mergeAll(
79
- RpcSerialization.layerJson,
89
+ RpcSerialization.layerNdjson,
80
90
  HttpClientLayer(config)
81
91
  )
82
92
 
@@ -84,14 +94,14 @@ type RpcHandlers<M extends RequestsAny> = {
84
94
  [K in keyof M]: Rpc.Rpc<M[K]["_tag"], M[K], M[K]["success"], M[K]["error"]>
85
95
  }
86
96
 
87
- const getFiltered = <M extends Requests>(resource: M) => {
97
+ const getFiltered = <M extends RequestsAny>(resource: M) => {
88
98
  type Filtered = {
89
99
  [K in keyof M as M[K] extends Req ? K : never]: M[K] extends Req ? M[K] : never
90
100
  }
91
101
  // TODO: Record.filter
92
102
  const filtered = typedKeysOf(resource).reduce((acc, cur) => {
93
103
  if (
94
- Predicate.isObject(resource[cur])
104
+ Predicate.isObjectKeyword(resource[cur])
95
105
  && (resource[cur].success)
96
106
  ) {
97
107
  acc[cur as keyof Filtered] = resource[cur] as any
@@ -102,179 +112,331 @@ const getFiltered = <M extends Requests>(resource: M) => {
102
112
  return filtered as unknown as Filtered
103
113
  }
104
114
 
105
- export const getMeta = <M extends Requests>(resource: M) => {
106
- const meta = (resource as any).meta as { moduleName: string }
107
- if (!meta) throw new Error("No meta defined in Resource!")
108
- return meta as M["meta"]
115
+ export const getMeta = <M extends RequestsAny>(
116
+ resource: M
117
+ ): { moduleName: ExtractModuleName<M>; middleware?: unknown } => {
118
+ const first = typedValuesOf(getFiltered(resource))[0]
119
+ if (first && "moduleName" in first) return { moduleName: first.moduleName, middleware: (first as any).middleware }
120
+ throw new Error("No moduleName on requests!")
109
121
  }
110
122
 
111
- export const makeRpcGroupFromRequestsAndModuleName = <M extends Requests, const ModuleName extends string>(
123
+ export const makeRpcGroupFromRequestsAndModuleName = <M extends RequestsAny, const ModuleName extends string>(
112
124
  resource: M,
113
- moduleName: ModuleName
125
+ moduleName: ModuleName,
126
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
+ middleware?: any
114
128
  ) => {
115
129
  const filtered = getFiltered(resource)
116
130
  type newM = typeof filtered
117
- const rpcs = RpcGroup
131
+ const baseRpcs = RpcGroup
118
132
  .make(
119
133
  ...typedValuesOf(filtered).map((_) => {
120
- return Rpc.make((_ as any)._tag, { payload: _ as any, success: (_ as any).success, error: (_ as any).error })
134
+ const r = _ as any
135
+ const isStream = r.stream
136
+ const isCommand = r.type === "command"
137
+ return (isCommand
138
+ ? isStream
139
+ ? Invalidation.makeStreamRpc(r._tag, {
140
+ payload: r,
141
+ success: r.success,
142
+ error: r.error,
143
+ stream: true as const
144
+ })
145
+ : Invalidation.makeCommandRpc(r._tag, { payload: r, success: r.success, error: r.error })
146
+ : Rpc.make(r._tag, {
147
+ payload: r,
148
+ success: isStream ? r.success : Invalidation.QueryResponseWithMetaData(r.success),
149
+ error: r.error,
150
+ stream: isStream
151
+ })) as any
121
152
  })
122
153
  )
123
- .prefix(`${moduleName}.`) as unknown as RpcGroup.RpcGroup<
124
- Rpc.Prefixed<RpcHandlers<newM>[keyof newM], `${ModuleName}.`>
125
- >
154
+ .prefix(`${moduleName}.`)
155
+ // Attach the middleware tag (schema-only on the client — no Live invoked)
156
+ // so its declared `error` joins the rpc failure union via
157
+ // `Rpc.exitSchema`'s `rpc.middlewares[*].error` walk. Required for stream
158
+ // rpcs whose top-level `errorSchema` is forced to `Never` by effect-rpc;
159
+ // without it, middleware-thrown errors fail client decode.
160
+ const rpcs = (middleware ? baseRpcs.middleware(middleware) : baseRpcs) as unknown as RpcGroup.RpcGroup<
161
+ Rpc.Prefixed<RpcHandlers<newM>[keyof newM], `${ModuleName}.`>
162
+ >
126
163
  return rpcs
127
164
  }
128
165
 
129
- export const makeRpcGroup = <
130
- M extends Requests,
131
- const ModuleName extends string
132
- >(
133
- resource: M & { meta: { moduleName: ModuleName } }
134
- ) => makeRpcGroupFromRequestsAndModuleName(resource, resource.meta.moduleName)
135
-
136
- const makeRpcTag = <M extends Requests>(resource: M) => {
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ const makeRpcTag = <M extends RequestsAny>(resource: M, middleware?: any) => {
137
168
  const meta = getMeta(resource)
138
- const rpcs = makeRpcGroupFromRequestsAndModuleName(resource, meta.moduleName)
169
+ const rpcs = makeRpcGroupFromRequestsAndModuleName(resource, meta.moduleName, middleware)
139
170
 
140
171
  // Use Object.assign instead of class extension to avoid TS2509 with complex generic return types.
141
172
  // The first type arg is `any` because this is a dynamically created tag — its identity is the string key.
142
- const TheClient = ServiceMap.Opaque<
173
+ const TheClient = Context.Opaque<
143
174
  any,
144
175
  RpcClient.RpcClient<RpcGroup.Rpcs<typeof rpcs>>
145
176
  >()(`RpcClient.${meta.moduleName}`)
146
177
  // Use Layer.effect directly (not TheClient.toLayer) so TypeScript properly excludes Scope
147
178
  const layer = Layer.effect(
148
179
  TheClient,
149
- Effect.map(
150
- RpcClient.make(rpcs, { spanPrefix: "RpcClient." + meta.moduleName }),
151
- (cl) => (cl as any)[meta.moduleName]
152
- )
180
+ RpcClient.make(rpcs)
153
181
  )
154
182
  return Object.assign(TheClient, { layer })
155
183
  }
156
184
 
157
185
  const makeApiClientFactory = Effect
158
186
  .gen(function*() {
159
- const ctx = yield* Effect.services<RpcSerialization.RpcSerialization | HttpClient.HttpClient>()
160
- const makeClientFor = <M extends Requests>(
187
+ const ctx = yield* Effect.context<RpcSerialization.RpcSerialization | HttpClient.HttpClient>()
188
+ const makeClientFor = Effect.fnUntraced(function*<M extends RequestsAny>(
161
189
  resource: M,
162
190
  requestLevelLayers = Layer.empty,
163
191
  options?: ClientForOptions
164
- ) =>
165
- Effect.gen(function*() {
166
- const TheClient = makeRpcTag(resource)
167
-
168
- const meta = getMeta(resource)
169
-
170
- // TODO: somehow we need a protocol per REQUEST kind of it seems ...
171
- // otherwise it locks up on the client, navigation remains empty...
172
- const clientLayer = TheClient.layer.pipe(
173
- // add ApiClientFactory for nested schemas
174
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
175
- Layer.provide(Layer.succeed(ApiClientFactory, makeClientForCached as any)),
176
- Layer.provide(
177
- RpcClient
178
- .layerProtocolHttp({
179
- url: "" // why not here set meta.moduleName as root?
192
+ ) {
193
+ const meta = getMeta(resource)
194
+
195
+ const TheClient = makeRpcTag(resource, meta.middleware)
196
+
197
+ // TODO: somehow we need a protocol per REQUEST kind of it seems ...
198
+ // otherwise it locks up on the client, navigation remains empty...
199
+ const clientLayer = TheClient.layer.pipe(
200
+ // add ApiClientFactory for nested schemas
201
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
202
+ Layer.provide(Layer.succeed(ApiClientFactory, makeClientForCached as any)),
203
+ Layer.provide(
204
+ RpcClient
205
+ .layerProtocolHttp({ url: "" }) // why not here set meta.moduleName as root?
206
+ .pipe(
207
+ Layer.provideMerge(Layer.succeedContext(ctx))
208
+ )
209
+ )
210
+ )
211
+ const mr = ManagedRuntime.make(clientLayer)
212
+
213
+ const filtered = getFiltered(resource)
214
+
215
+ // Unwrap `CommandResponseWithMetaData` (success) and `CommandFailureWithMetaData`
216
+ // (handler-thrown failure): forward accumulated invalidation keys to
217
+ // `InvalidationKeysFromServer` and yield the raw payload / re-fail with the raw
218
+ // error. Middleware-thrown failures arrive raw on the Cause already (no wrap to
219
+ // strip) — the `else` branch passes them through.
220
+ const forwardDependencies = (
221
+ dependencies: DataDependencies.DataDependencySet | undefined,
222
+ options?: { readonly reads?: boolean }
223
+ ) =>
224
+ dependencies === undefined
225
+ ? Effect.void
226
+ : Effect.gen(function*() {
227
+ const dependencyRecorder = yield* DataDependencies.getDataDependencyRecorder
228
+ if (options?.reads) {
229
+ yield* Effect.forEach(dependencies.reads, dependencyRecorder.read, { discard: true })
230
+ }
231
+ yield* Effect.forEach(dependencies.writes, dependencyRecorder.write, { discard: true })
232
+ })
233
+
234
+ const unwrapCommand = (eff: Effect.Effect<any, any, any>): Effect.Effect<any, any, any> =>
235
+ eff.pipe(
236
+ Effect.flatMap((result: any) =>
237
+ Effect.gen(function*() {
238
+ const keys: ReadonlyArray<Invalidation.InvalidationKey> = result?.metadata?.invalidateQueries ?? []
239
+ const invalidationKeys = yield* InvalidationKeysFromServer
240
+ yield* Effect.forEach(keys, (key) => invalidationKeys.add(key), { discard: true })
241
+ yield* forwardDependencies(result?.metadata?.dataDependencies)
242
+ return result.payload
243
+ })
244
+ ),
245
+ Effect.catch((result: any) =>
246
+ result?._tag === "CommandFailureWithMetaData"
247
+ ? Effect.gen(function*() {
248
+ const keys: ReadonlyArray<Invalidation.InvalidationKey> = result.metadata?.invalidateQueries ?? []
249
+ const invalidationKeys = yield* InvalidationKeysFromServer
250
+ yield* Effect.forEach(keys, (key) => invalidationKeys.add(key), { discard: true })
251
+ yield* forwardDependencies(result.metadata?.dataDependencies)
252
+ return yield* Effect.fail(result.error)
180
253
  })
181
- .pipe(
182
- Layer.provideMerge(Layer.succeedServices(ctx))
183
- )
254
+ : Effect.fail(result)
184
255
  )
185
256
  )
186
- const mr = ManagedRuntime.make(clientLayer)
187
257
 
188
- const filtered = getFiltered(resource)
189
- return {
190
- mr,
191
- client: (typedKeysOf(filtered)
192
- .reduce((prev, cur) => {
193
- const h = filtered[cur]!
258
+ const unwrapQuery = (eff: Effect.Effect<any, any, any>): Effect.Effect<any, any, any> =>
259
+ eff.pipe(
260
+ Effect.flatMap((result: any) =>
261
+ Effect.gen(function*() {
262
+ yield* forwardDependencies(result?.metadata?.dataDependencies, { reads: true })
263
+ return result.payload
264
+ })
265
+ )
266
+ )
194
267
 
195
- const Request = h
268
+ return {
269
+ mr,
270
+ client: typedKeysOf(filtered)
271
+ .reduce((prev, cur) => {
272
+ const h = filtered[cur]!
273
+
274
+ const Request = h
275
+
276
+ const id = `${meta.moduleName}.${cur as string}`
277
+ .replaceAll(".js", "")
278
+
279
+ const requestMeta = {
280
+ Request,
281
+ id,
282
+ options,
283
+ disableQueryInvalidation: (h as { config?: { disableQueryInvalidation?: boolean } })
284
+ .config
285
+ ?.disableQueryInvalidation === true
286
+ }
287
+
288
+ const requestNameLayer = Layer.succeed(RequestName, {
289
+ requestName: cur as string,
290
+ moduleName: meta.moduleName
291
+ })
292
+
293
+ const layers = requestLevelLayers.pipe(Layer.provideMerge(requestNameLayer))
294
+
295
+ const fields = Struct.omit(Request.fields, ["_tag"] as const)
296
+ const requestAttr = `${meta.moduleName}.${h._tag}`
297
+ const isCommand = h.type === "command"
298
+ const isStream = h.stream
299
+
300
+ const buildEffect = (input: any) =>
301
+ mr.contextEffect.pipe(
302
+ Effect.flatMap((svcs) => {
303
+ const rpcEffect = TheClient
304
+ .use((client) => (client as any)[requestAttr]!(Request.make(input)) as Effect.Effect<any, any>)
305
+ .pipe(
306
+ // local: true → isolate to this RPC call. `layers` is pure today
307
+ // (RequestName + caller-supplied requestLevelLayers), but the
308
+ // flag prevents a stateful caller-supplied layer from leaking
309
+ // across RPC calls via the ambient fiber MemoMap.
310
+ Effect.provide(layers, { local: true }),
311
+ Effect.provide(svcs)
312
+ )
313
+ return isCommand ? unwrapCommand(rpcEffect) : isStream ? rpcEffect : unwrapQuery(rpcEffect)
314
+ }),
315
+ // Forwarding the server's dependency metadata needs a recorder in scope. A parent
316
+ // query/command (vue) provides one; a top-level call gets a fresh per-request one.
317
+ DataDependencies.ensureDataDependencyRecorder
318
+ )
196
319
 
197
- const id = `${meta.moduleName}.${cur as string}`
198
- .replaceAll(".js", "")
320
+ const buildStream = (input: any) => {
321
+ const stream = Stream.unwrap(
322
+ mr.contextEffect.pipe(
323
+ Effect.flatMap((svcs) =>
324
+ TheClient
325
+ .useSync((client) => {
326
+ const rpcStream = (client as any)[requestAttr]!(
327
+ Request.make(input)
328
+ ) as Stream.Stream<any, any, any>
329
+ return rpcStream.pipe(
330
+ // Collect server invalidation keys from the "done" chunk, then discard it.
331
+ Stream.tap((item: any) =>
332
+ item._tag === "done" || item._tag === "metadata"
333
+ ? Effect.gen(function*() {
334
+ const metadata = item.metadata as Invalidation.CommandMetaData
335
+ const invalidationKeys = yield* InvalidationKeysFromServer
336
+ yield* Effect.forEach(metadata.invalidateQueries, invalidationKeys.add, {
337
+ discard: true
338
+ })
339
+ const dependencyRecorder = yield* DataDependencies.getDataDependencyRecorder
340
+ yield* Effect.forEach(
341
+ metadata.dataDependencies.reads,
342
+ dependencyRecorder.read,
343
+ { discard: true }
344
+ )
345
+ yield* Effect.forEach(
346
+ metadata.dataDependencies.writes,
347
+ dependencyRecorder.write,
348
+ { discard: true }
349
+ )
350
+ })
351
+ : Effect.void
352
+ ),
353
+ Stream.filter((item: any) => item._tag === "value"),
354
+ Stream.map((item: any) => item.value),
355
+ // V2: unwrap StreamFailureChunk — forward keys from failures too,
356
+ // then re-fail with the original error so callers see the unmodified
357
+ // error type.
358
+ Stream.catch((err: any) =>
359
+ err?._tag === "error" && err?.metadata
360
+ ? Stream.fromEffect(
361
+ Effect.gen(function*() {
362
+ const metadata = err.metadata as Invalidation.CommandMetaData
363
+ const invalidationKeys = yield* InvalidationKeysFromServer
364
+ yield* Effect.forEach(metadata.invalidateQueries, invalidationKeys.add, {
365
+ discard: true
366
+ })
367
+ const dependencyRecorder = yield* DataDependencies.getDataDependencyRecorder
368
+ yield* Effect.forEach(
369
+ metadata.dataDependencies.writes,
370
+ dependencyRecorder.write,
371
+ { discard: true }
372
+ )
373
+ return yield* Effect.fail(err.error)
374
+ })
375
+ )
376
+ : Stream.fail(err)
377
+ ),
378
+ // local: true — see buildEffect above.
379
+ Stream.provide(layers, { local: true }),
380
+ Stream.provide(svcs)
381
+ )
382
+ })
383
+ .pipe(Effect.provide(svcs))
384
+ )
385
+ )
386
+ )
387
+ // Forwarding the server's dependency metadata needs a recorder in scope. A parent
388
+ // query/command (vue) provides one; a top-level stream call gets a fresh per-request one.
389
+ return Stream.unwrap(
390
+ Effect.map(
391
+ DataDependencies.DataDependencyRecorder,
392
+ (current) =>
393
+ current === "root"
394
+ ? Stream.provide(stream, DataDependencies.DataDependencyRecorder.layer)
395
+ : stream
396
+ )
397
+ )
398
+ }
199
399
 
200
- const requestMeta = {
201
- Request,
202
- id,
203
- options
400
+ // @ts-expect-error doc
401
+ prev[cur] = Object.keys(fields).length === 0
402
+ ? {
403
+ handler: isStream ? constant(buildStream({})) : constant(buildEffect({})),
404
+ ...requestMeta
405
+ }
406
+ : {
407
+ handler: isStream
408
+ ? (req: any) => buildStream(req)
409
+ : (req: any) => buildEffect(req),
410
+ ...requestMeta
204
411
  }
205
412
 
206
- const requestNameLayer = Layer.succeed(RequestName, {
207
- requestName: cur as string,
208
- moduleName: meta.moduleName
209
- })
210
-
211
- const layers = requestLevelLayers.pipe(Layer.provideMerge(requestNameLayer))
212
-
213
- const fields = Struct.omit(Request.fields, ["_tag"] as const)
214
- const requestAttr = h._tag
215
- // @ts-expect-error doc
216
- prev[cur] = Object.keys(fields).length === 0
217
- ? {
218
- handler: mr.servicesEffect.pipe(
219
- Effect.flatMap((svcs) =>
220
- TheClient
221
- .use((client) => (client as any)[requestAttr]!(new Request()) as Effect.Effect<any, any, never>)
222
- .pipe(
223
- Effect.provide(layers),
224
- Effect.provide(svcs)
225
- )
226
- )
227
- ),
228
- ...requestMeta
229
- }
230
- : {
231
- handler: (req: any) =>
232
- mr.servicesEffect.pipe(
233
- Effect.flatMap((svcs) =>
234
- TheClient
235
- .use((client) =>
236
- (client as any)[requestAttr]!(new Request(req)) as Effect.Effect<any, any, never>
237
- )
238
- .pipe(
239
- Effect.provide(layers),
240
- Effect.provide(svcs)
241
- )
242
- )
243
- ),
244
-
245
- ...requestMeta
246
- }
247
-
248
- return prev
249
- }, {} as Client<M, M["meta"]["moduleName"]>))
250
- }
251
- })
413
+ return prev
414
+ }, {} as Client<M, ExtractModuleName<M>>)
415
+ }
416
+ })
252
417
 
253
418
  const register: ManagedRuntime.ManagedRuntime<any, any>[] = []
254
419
  yield* Effect.addFinalizer(() => Effect.forEach(register, (mr) => mr.disposeEffect))
255
420
 
256
421
  const cacheL = new Map<any, Map<any, Client<any, any>>>()
257
422
 
258
- function makeClientForCached(requestLevelLayers: Layer.Layer<never, never, never>, options?: ClientForOptions) {
423
+ function makeClientForCached(requestLevelLayers: Layer.Layer<never>, options?: ClientForOptions) {
259
424
  let cache = cacheL.get(requestLevelLayers)
260
425
  if (!cache) {
261
426
  cache = new Map<any, Client<any, any>>()
262
427
  cacheL.set(requestLevelLayers, cache)
263
428
  }
264
429
 
265
- return <M extends Requests>(
266
- models: M
267
- ): Effect.Effect<Client<M, M["meta"]["moduleName"]>> =>
268
- Effect.gen(function*() {
269
- const found = cache.get(models)
270
- if (found) {
271
- return found
272
- }
273
- const m = yield* makeClientFor(models, requestLevelLayers, options)
274
- cache.set(models, m.client)
275
- register.push(m.mr)
276
- return m.client
277
- })
430
+ return Effect.fnUntraced(function*<M extends RequestsAny>(models: M) {
431
+ const found = cache.get(models) as Client<M, ExtractModuleName<M>> | undefined
432
+ if (found) {
433
+ return found
434
+ }
435
+ const m = yield* makeClientFor(models, requestLevelLayers, options)
436
+ cache.set(models, m.client)
437
+ register.push(m.mr)
438
+ return m.client
439
+ })
278
440
  }
279
441
 
280
442
  return makeClientForCached
@@ -284,7 +446,7 @@ const makeApiClientFactory = Effect
284
446
  * Used to create clients for resource modules.
285
447
  */
286
448
  export class ApiClientFactory
287
- extends ServiceMap.Opaque<ApiClientFactory, Effect.Success<typeof makeApiClientFactory>>()("ApiClientFactory")
449
+ extends Context.Opaque<ApiClientFactory, Effect.Success<typeof makeApiClientFactory>>()("ApiClientFactory")
288
450
  {
289
451
  static readonly layer = (config: ApiConfig) =>
290
452
  ApiClientFactory.toLayer(makeApiClientFactory).pipe(Layer.provide(RpcSerializationLayer(config)))
@@ -296,8 +458,8 @@ export class ApiClientFactory
296
458
  )
297
459
 
298
460
  static readonly makeFor =
299
- (requestLevelLayers: Layer.Layer<never, never, never>, options?: ClientForOptions) =>
300
- <M extends Requests>(
461
+ (requestLevelLayers: Layer.Layer<never>, options?: ClientForOptions) =>
462
+ <M extends RequestsAny>(
301
463
  resource: M
302
464
  ) =>
303
465
  ApiClientFactory.use((apiClientFactory) => {