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

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