effect-app 4.0.0-beta.99 → 4.0.1

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