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
@@ -0,0 +1,133 @@
1
+ import * as Cause from "effect/Cause"
2
+ import * as Fiber from "effect/Fiber"
3
+ import * as Context from "./Context.ts"
4
+ import * as Effect from "./Effect.ts"
5
+ import * as Layer from "./Layer.ts"
6
+ import type * as Option from "./Option.ts"
7
+ import * as S from "./Schema.ts"
8
+ import { CurrentToastId, Toast, type ToastId } from "./toast.ts"
9
+ import { wrapEffect } from "./utils.ts"
10
+
11
+ export interface ToastOptions<A, E, Args extends ReadonlyArray<unknown>, WaiR, SucR, ErrR> {
12
+ stableToastId?: undefined | string | ((...args: Args) => string | undefined)
13
+ timeout?: number
14
+ showSpanInfo?: false
15
+ groupId?: string
16
+ onWaiting:
17
+ | string
18
+ | ((...args: Args) => string | null)
19
+ | null
20
+ | ((
21
+ ...args: Args
22
+ ) => Effect.Effect<string | null, never, WaiR>)
23
+ onSuccess:
24
+ | string
25
+ | ((a: A, ...args: Args) => string | null)
26
+ | null
27
+ | ((
28
+ a: A,
29
+ ...args: Args
30
+ ) => Effect.Effect<string | null, never, SucR>)
31
+ onFailure:
32
+ | string
33
+ | ((
34
+ error: Option.Option<E>,
35
+ ...args: Args
36
+ ) => string | { level: "warn" | "error"; message: string })
37
+ | ((
38
+ error: Option.Option<E>,
39
+ ...args: Args
40
+ ) => Effect.Effect<string | { level: "warn" | "error"; message: string }, never, ErrR>)
41
+ }
42
+
43
+ // @effect-diagnostics-next-line missingEffectServiceDependency:off
44
+ export class WithToast extends Context.Service<WithToast>()("WithToast", {
45
+ make: Effect.gen(function*() {
46
+ const toast = yield* Toast
47
+ return <A, E, Args extends readonly unknown[], R, WaiR = never, SucR = never, ErrR = never>(
48
+ options: ToastOptions<A, E, Args, WaiR, SucR, ErrR>
49
+ ) =>
50
+ Effect.fnUntraced(function*(self: Effect.Effect<A, E, R>, ...args: Args) {
51
+ const baseTimeout = options.timeout ?? 3_000
52
+
53
+ const stableToastId = typeof options.stableToastId === "function"
54
+ ? options.stableToastId(...args)
55
+ : options.stableToastId
56
+
57
+ const requestId: string = yield* Effect.currentSpan.pipe(
58
+ Effect.map((span) => span.traceId),
59
+ Effect.orElseSucceed(() => S.StringId.make())
60
+ )
61
+ const groupId = options.groupId
62
+ const meta = { ...(groupId !== undefined ? { groupId } : {}), requestId }
63
+
64
+ const t = yield* wrapEffect(options.onWaiting)(...args)
65
+ const toastId: ToastId | undefined = t === null
66
+ ? stableToastId
67
+ : stableToastId ?? `wait-${Math.random().toString(36).slice(2)}`
68
+
69
+ const waitingFiber = t === null ? undefined : yield* Effect.forkChild(
70
+ Effect.sleep("1 seconds").pipe(
71
+ Effect.andThen(toast.info(t, { id: toastId!, timeout: Infinity, ...meta }))
72
+ )
73
+ )
74
+ const interruptWaiting = waitingFiber ? Fiber.interrupt(waitingFiber) : Effect.void
75
+
76
+ return yield* self.pipe(
77
+ Effect.tap(Effect.fnUntraced(function*(a) {
78
+ yield* interruptWaiting
79
+ const t = yield* wrapEffect(options.onSuccess)(a, ...args)
80
+ if (t === null) {
81
+ return
82
+ }
83
+ yield* toast.success(
84
+ t,
85
+ toastId !== undefined
86
+ ? { id: toastId, timeout: baseTimeout, ...meta }
87
+ : { timeout: baseTimeout, ...meta }
88
+ )
89
+ })),
90
+ Effect.tapCause(Effect.fnUntraced(function*(cause) {
91
+ yield* interruptWaiting
92
+ yield* Effect.logDebug(
93
+ "WithToast - caught error cause: " + Cause.squash(cause),
94
+ Cause.hasInterruptsOnly(cause),
95
+ cause
96
+ )
97
+
98
+ if (Cause.hasInterruptsOnly(cause)) {
99
+ if (toastId) yield* toast.dismiss(toastId)
100
+ return
101
+ }
102
+
103
+ const spanInfo = options.showSpanInfo !== false
104
+ ? yield* Effect.currentSpan.pipe(
105
+ Effect.map((span) => `\nTrace: ${span.traceId}\nSpan: ${span.spanId}`),
106
+ Effect.orElseSucceed(() => "")
107
+ )
108
+ : ""
109
+
110
+ const t = yield* wrapEffect(options.onFailure)(Cause.findErrorOption(cause), ...args)
111
+ const opts = { timeout: baseTimeout * 2, ...meta }
112
+
113
+ if (typeof t === "object") {
114
+ const message = t.message + spanInfo
115
+ return t.level === "warn"
116
+ ? yield* toast.warning(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
117
+ : yield* toast.error(message, toastId !== undefined ? { ...opts, id: toastId } : opts)
118
+ }
119
+ yield* toast.error(t + spanInfo, toastId !== undefined ? { ...opts, id: toastId } : opts)
120
+ }, Effect.uninterruptible)),
121
+ toastId !== undefined ? Effect.provideService(CurrentToastId, CurrentToastId.of({ toastId })) : (_) => _
122
+ )
123
+ })
124
+ })
125
+ }) {
126
+ static readonly DefaultWithoutDependencies = Layer.effect(this, this.make)
127
+ static readonly Default = this.DefaultWithoutDependencies
128
+
129
+ static readonly handle = <A, E, Args extends Array<unknown>, R, WaiR = never, SucR = never, ErrR = never>(
130
+ options: ToastOptions<A, E, Args, WaiR, SucR, ErrR>
131
+ ): (self: Effect.Effect<A, E, R>, ...args: Args) => Effect.Effect<A, E, R | WaiR | SucR | ErrR | WithToast> =>
132
+ (self, ...args) => this.use((_) => _<A, E, Args, R, WaiR, SucR, ErrR>(options)(self, ...args))
133
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moreStrings.test.d.ts","sourceRoot":"","sources":["../moreStrings.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.test.d.ts","sourceRoot":"","sources":["../rpc.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACrF,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AAE7C,qBAAa,iBAAkB,SAAQ,sBAIrC;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIL,qBAAa,KAAM,SAAQ,UAQzB;CAAG"}
1
+ {"version":3,"file":"rpc.test.d.ts","sourceRoot":"","sources":["../rpc.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACrF,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;;;;;;;;;;;;;;;;;;;;;;;;AAE7C,qBAAa,iBAAkB,SAAQ,sBAIrC;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAI0B,KAAK;;;;AAKpC,qBAAa,KAAM,SAAQ,UAQzB;CAAG"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcMiddlewareContext.test.d.ts","sourceRoot":"","sources":["../rpcMiddlewareContext.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretURL.test.d.ts","sourceRoot":"","sources":["../secretURL.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"special.test.d.ts","sourceRoot":"","sources":["../special.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import * as S from "effect-app/Schema"
2
+ import * as fc from "fast-check"
3
+ import { urlAlphabet } from "nanoid"
4
+ import { test } from "vitest"
5
+
6
+ const nanoidAlphabet = new Set(urlAlphabet)
7
+
8
+ const isNanoId = (value: string) => value.length === 21 && Array.from(value).every((char) => nanoidAlphabet.has(char))
9
+
10
+ test("StringId arbitrary generates nanoid-shaped values", () => {
11
+ fc.assert(
12
+ fc.property(S.toArbitrary(S.StringId), (value) => {
13
+ expect(isNanoId(value)).toBe(true)
14
+ expect(S.is(S.StringId)(value)).toBe(true)
15
+ })
16
+ )
17
+ })
package/test/rpc.test.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type * as Effect from "effect/Effect"
2
+ import type * as Option from "effect/Option"
3
+ import { expect, test } from "vitest"
1
4
  import { makeRpcClient, NotLoggedInError, UnauthorizedError } from "../src/client.js"
2
5
  import { S } from "../src/index.js"
3
6
  import { RpcContextMap } from "../src/rpc.js"
@@ -8,16 +11,52 @@ export class RequestContextMap extends RpcContextMap.makeMap({
8
11
  test: RpcContextMap.make()(S.Never)
9
12
  }) {}
10
13
 
11
- const { TaggedRequest } = makeRpcClient(RequestContextMap)
14
+ const stubMiddleware = {
15
+ requestContextMap: RequestContextMap.config,
16
+ requestContext: undefined as never
17
+ }
18
+ const { TaggedRequestFor } = makeRpcClient(stubMiddleware)
19
+ const TaggedRequest = TaggedRequestFor("Test").Query
12
20
 
13
21
  export class Stats extends TaggedRequest<Stats>()("Stats", {}, {
14
22
  allowedRoles: ["manager"],
15
23
  success: {
16
- usersActive24Hours: S.Number,
17
- usersActiveLastWeek: S.Number,
18
- newUsersLast24Hours: S.Number,
19
- newUsersLastWeek: S.Number
24
+ usersActive24Hours: S.Finite,
25
+ usersActiveLastWeek: S.Finite,
26
+ newUsersLast24Hours: S.Finite,
27
+ newUsersLastWeek: S.Finite
20
28
  }
21
29
  }) {}
22
30
 
23
- declare const _stats: typeof Stats.success.Type
31
+ declare const _stats: typeof Stats.Type
32
+ declare const _statsSuccess: typeof Stats.success.Type
33
+ declare const _statsError: typeof Stats.error.Type
34
+ declare const _statsRequestType: typeof Stats.type
35
+
36
+ test("Void decodes and encodes as void", () => {
37
+ const statsFromMake = Stats.make({})
38
+ const statsFromMakeOption = Stats.makeOption({})
39
+ const statsFromMakeEffect = Stats.makeEffect({})
40
+
41
+ expect(S.decodeUnknownSync(S.Void)(undefined)).toBe(undefined)
42
+ expect(S.is(S.Void)(undefined)).toBe(true)
43
+ expect(S.decodeUnknownSync(S.Void)("test")).toBe(undefined)
44
+ expect(S.is(S.Void)("test")).toBe(true)
45
+ expect(S.encodeUnknownSync(S.Void)("test")).toBe(undefined)
46
+ expect(S.encodeUnknownSync(S.toCodecJson(S.Void))("test")).toBe(null)
47
+ expectTypeOf<typeof _stats>().toEqualTypeOf<Stats>()
48
+ expectTypeOf<typeof _statsSuccess>().toEqualTypeOf<{
49
+ readonly usersActive24Hours: number
50
+ readonly usersActiveLastWeek: number
51
+ readonly newUsersLast24Hours: number
52
+ readonly newUsersLastWeek: number
53
+ }>()
54
+ // Resource error carries only `config.error` (and optional `generalErrors`); rcm-derived
55
+ // middleware errors no longer leak into `resource.error` — they reach the wire via the
56
+ // middleware tag attached to the rpc group (`rpc.middlewares[*].error` failure-union).
57
+ expectTypeOf<typeof _statsError>().toEqualTypeOf<never>()
58
+ expectTypeOf<typeof _statsRequestType>().toEqualTypeOf<"query">()
59
+ expectTypeOf(statsFromMake).toEqualTypeOf<Stats>()
60
+ expectTypeOf(statsFromMakeOption).toEqualTypeOf<Option.Option<Stats>>()
61
+ expectTypeOf(statsFromMakeEffect).toEqualTypeOf<Effect.Effect<Stats, S.SchemaError>>()
62
+ })
@@ -0,0 +1,63 @@
1
+ import { expectTypeOf, test } from "vitest"
2
+ import { makeRpcClient, NotLoggedInError, UnauthorizedError } from "../src/client.js"
3
+ import { RpcContextMap } from "../src/rpc.js"
4
+
5
+ // A stand-in for an app service (e.g. `UserProfile`) that the `allowAnonymous`
6
+ // inverted middleware provides into the handler context whenever auth is
7
+ // required (i.e. `allowAnonymous` is not `true`).
8
+ interface UserProfile {
9
+ readonly _tag: "UserProfile"
10
+ }
11
+
12
+ // Mirrors a real app request-context map: one inverted key providing a service
13
+ // by default (unless opted out), and one custom (role) key.
14
+ class RequestContextMap extends RpcContextMap.makeMap({
15
+ allowAnonymous: RpcContextMap.makeInverted<UserProfile>()(NotLoggedInError),
16
+ allowRoles: RpcContextMap.makeCustom()(UnauthorizedError, Array<string>())
17
+ }) {}
18
+
19
+ type Map = typeof RequestContextMap.config
20
+
21
+ // The context a handler receives for a given rpc config — exactly the
22
+ // `GetEffectContext<_RC, rpc.config>` the router computes for the handler
23
+ // (see `RpcMiddleware.ts`). Testing it against config literals pins down the
24
+ // middleware semantics directly.
25
+ type CtxFor<Config> = RpcContextMap.GetEffectContext<Map, Config>
26
+
27
+ test("`GetEffectContext`: the inverted `UserProfile` provision is gated by `allowAnonymous`, not `allowRoles`", () => {
28
+ // Empty config = nothing opted out → auth required → `UserProfile` provided.
29
+ expectTypeOf<CtxFor<{}>>().toEqualTypeOf<UserProfile>()
30
+
31
+ // `allowRoles` does not gate `UserProfile` — still provided.
32
+ expectTypeOf<CtxFor<{ allowRoles: ["user"] }>>().toEqualTypeOf<UserProfile>()
33
+
34
+ // Negative case: opting into anonymous removes the `UserProfile` provision.
35
+ expectTypeOf<CtxFor<{ allowAnonymous: true }>>().toBeNever()
36
+
37
+ // Anonymous wins over roles for the inverted provision.
38
+ expectTypeOf<CtxFor<{ allowAnonymous: true; allowRoles: ["user"] }>>().toBeNever()
39
+
40
+ // Regression documentation: a config that collapses to `Record<string, never>`
41
+ // (what the no-config command overload used to produce) WRONGLY drops
42
+ // `UserProfile` — `keyof Record<string, never>` is `string`, so `allowAnonymous`
43
+ // satisfies `key extends keyof T`, and `T["allowAnonymous"]` (`never`) `extends
44
+ // true`, taking the anonymous branch. This is exactly why the overload must
45
+ // yield `{}` (see the command-builder test below).
46
+ expectTypeOf<CtxFor<Record<string, never>>>().toBeNever()
47
+ })
48
+
49
+ // End-to-end guard for the actual fix: a command defined with NO config object
50
+ // must still provide `UserProfile` (auth required by default). This exercises the
51
+ // no-config `Command` overload, which now yields an empty `{}` config instead of
52
+ // `Record<string, never>`.
53
+ const { TaggedRequestFor } = makeRpcClient({
54
+ requestContextMap: RequestContextMap.config,
55
+ requestContext: undefined as never
56
+ })
57
+ const Command = TaggedRequestFor("Test").Command
58
+
59
+ class NoConfigCmd extends Command<NoConfigCmd>()("NoConfigCmd", {}) {}
60
+
61
+ test("a no-config command still provides the auth-required `UserProfile` service", () => {
62
+ expectTypeOf<RpcContextMap.GetEffectContext<Map, typeof NoConfigCmd.config>>().toEqualTypeOf<UserProfile>()
63
+ })