effect-app 4.0.0-beta.23 → 4.0.0-beta.230

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 (241) hide show
  1. package/CHANGELOG.md +1004 -0
  2. package/dist/Array.d.ts +3 -2
  3. package/dist/Array.d.ts.map +1 -1
  4. package/dist/Array.js +4 -4
  5. package/dist/Chunk.d.ts +1 -1
  6. package/dist/Chunk.d.ts.map +1 -1
  7. package/dist/Config/SecretURL.d.ts +4 -2
  8. package/dist/Config/SecretURL.d.ts.map +1 -1
  9. package/dist/Config/SecretURL.js +3 -6
  10. package/dist/Config/internal/configSecretURL.d.ts +1 -1
  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 +7 -0
  14. package/dist/Config.d.ts.map +1 -0
  15. package/dist/Config.js +6 -0
  16. package/dist/ConfigProvider.d.ts +39 -0
  17. package/dist/ConfigProvider.d.ts.map +1 -0
  18. package/dist/ConfigProvider.js +42 -0
  19. package/dist/Context.d.ts +43 -0
  20. package/dist/Context.d.ts.map +1 -0
  21. package/dist/Context.js +67 -0
  22. package/dist/Effect.d.ts +11 -10
  23. package/dist/Effect.d.ts.map +1 -1
  24. package/dist/Effect.js +6 -7
  25. package/dist/Function.d.ts +1 -1
  26. package/dist/Function.d.ts.map +1 -1
  27. package/dist/Inputify.type.d.ts +1 -1
  28. package/dist/Layer.d.ts +11 -6
  29. package/dist/Layer.d.ts.map +1 -1
  30. package/dist/Layer.js +3 -2
  31. package/dist/NonEmptySet.d.ts +4 -2
  32. package/dist/NonEmptySet.d.ts.map +1 -1
  33. package/dist/NonEmptySet.js +2 -2
  34. package/dist/Option.d.ts +2 -1
  35. package/dist/Option.d.ts.map +1 -1
  36. package/dist/Option.js +3 -1
  37. package/dist/Pure.d.ts +8 -6
  38. package/dist/Pure.d.ts.map +1 -1
  39. package/dist/Pure.js +17 -14
  40. package/dist/Schema/Class.d.ts +66 -20
  41. package/dist/Schema/Class.d.ts.map +1 -1
  42. package/dist/Schema/Class.js +192 -23
  43. package/dist/Schema/FastCheck.d.ts +1 -1
  44. package/dist/Schema/FastCheck.d.ts.map +1 -1
  45. package/dist/Schema/Methods.d.ts +1 -1
  46. package/dist/Schema/SchemaParser.d.ts +5 -0
  47. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  48. package/dist/Schema/SchemaParser.js +6 -0
  49. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  50. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  51. package/dist/Schema/SpecialJsonSchema.js +118 -0
  52. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  53. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  54. package/dist/Schema/SpecialOpenApi.js +123 -0
  55. package/dist/Schema/brand.d.ts +5 -3
  56. package/dist/Schema/brand.d.ts.map +1 -1
  57. package/dist/Schema/brand.js +3 -1
  58. package/dist/Schema/email.d.ts +1 -1
  59. package/dist/Schema/email.d.ts.map +1 -1
  60. package/dist/Schema/email.js +7 -4
  61. package/dist/Schema/ext.d.ts +339 -56
  62. package/dist/Schema/ext.d.ts.map +1 -1
  63. package/dist/Schema/ext.js +351 -53
  64. package/dist/Schema/moreStrings.d.ts +108 -26
  65. package/dist/Schema/moreStrings.d.ts.map +1 -1
  66. package/dist/Schema/moreStrings.js +45 -16
  67. package/dist/Schema/numbers.d.ts +55 -15
  68. package/dist/Schema/numbers.d.ts.map +1 -1
  69. package/dist/Schema/numbers.js +60 -12
  70. package/dist/Schema/phoneNumber.d.ts +1 -1
  71. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  72. package/dist/Schema/phoneNumber.js +6 -3
  73. package/dist/Schema/schema.d.ts +1 -1
  74. package/dist/Schema/strings.d.ts +5 -5
  75. package/dist/Schema/strings.d.ts.map +1 -1
  76. package/dist/Schema/strings.js +1 -5
  77. package/dist/Schema.d.ts +214 -8
  78. package/dist/Schema.d.ts.map +1 -1
  79. package/dist/Schema.js +219 -21
  80. package/dist/Set.d.ts +5 -2
  81. package/dist/Set.d.ts.map +1 -1
  82. package/dist/Set.js +3 -2
  83. package/dist/TypeTest.d.ts +1 -1
  84. package/dist/Types.d.ts +1 -1
  85. package/dist/Widen.type.d.ts +1 -1
  86. package/dist/_ext/Array.d.ts +2 -2
  87. package/dist/_ext/Array.d.ts.map +1 -1
  88. package/dist/_ext/Array.js +4 -2
  89. package/dist/_ext/date.d.ts +1 -1
  90. package/dist/_ext/misc.d.ts +5 -2
  91. package/dist/_ext/misc.d.ts.map +1 -1
  92. package/dist/_ext/misc.js +4 -2
  93. package/dist/_ext/ord.ext.d.ts +3 -2
  94. package/dist/_ext/ord.ext.d.ts.map +1 -1
  95. package/dist/_ext/ord.ext.js +2 -2
  96. package/dist/builtin.d.ts +1 -1
  97. package/dist/builtin.d.ts.map +1 -1
  98. package/dist/client/InvalidationKeys.d.ts +29 -0
  99. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  100. package/dist/client/InvalidationKeys.js +33 -0
  101. package/dist/client/apiClientFactory.d.ts +20 -32
  102. package/dist/client/apiClientFactory.d.ts.map +1 -1
  103. package/dist/client/apiClientFactory.js +96 -33
  104. package/dist/client/clientFor.d.ts +51 -17
  105. package/dist/client/clientFor.d.ts.map +1 -1
  106. package/dist/client/clientFor.js +9 -1
  107. package/dist/client/errors.d.ts +49 -25
  108. package/dist/client/errors.d.ts.map +1 -1
  109. package/dist/client/errors.js +43 -17
  110. package/dist/client/makeClient.d.ts +481 -33
  111. package/dist/client/makeClient.d.ts.map +1 -1
  112. package/dist/client/makeClient.js +66 -24
  113. package/dist/client.d.ts +2 -1
  114. package/dist/client.d.ts.map +1 -1
  115. package/dist/client.js +2 -1
  116. package/dist/faker.d.ts +1 -1
  117. package/dist/faker.d.ts.map +1 -1
  118. package/dist/http/Request.d.ts +2 -2
  119. package/dist/http/Request.d.ts.map +1 -1
  120. package/dist/http/Request.js +2 -2
  121. package/dist/http/internal/lib.d.ts +1 -1
  122. package/dist/http.d.ts +1 -1
  123. package/dist/ids.d.ts +40 -12
  124. package/dist/ids.d.ts.map +1 -1
  125. package/dist/ids.js +25 -3
  126. package/dist/index.d.ts +5 -8
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +6 -8
  129. package/dist/logger.d.ts +1 -1
  130. package/dist/middleware.d.ts +14 -8
  131. package/dist/middleware.d.ts.map +1 -1
  132. package/dist/middleware.js +14 -8
  133. package/dist/rpc/Invalidation.d.ts +402 -0
  134. package/dist/rpc/Invalidation.d.ts.map +1 -0
  135. package/dist/rpc/Invalidation.js +150 -0
  136. package/dist/rpc/MiddlewareMaker.d.ts +11 -7
  137. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  138. package/dist/rpc/MiddlewareMaker.js +59 -38
  139. package/dist/rpc/RpcContextMap.d.ts +4 -4
  140. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  141. package/dist/rpc/RpcContextMap.js +4 -4
  142. package/dist/rpc/RpcMiddleware.d.ts +14 -10
  143. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  144. package/dist/rpc/RpcMiddleware.js +1 -1
  145. package/dist/rpc.d.ts +2 -2
  146. package/dist/rpc.d.ts.map +1 -1
  147. package/dist/rpc.js +2 -2
  148. package/dist/transform.d.ts +2 -2
  149. package/dist/transform.d.ts.map +1 -1
  150. package/dist/transform.js +4 -5
  151. package/dist/utils/effectify.d.ts +2 -2
  152. package/dist/utils/effectify.d.ts.map +1 -1
  153. package/dist/utils/effectify.js +2 -2
  154. package/dist/utils/extend.d.ts +1 -1
  155. package/dist/utils/extend.d.ts.map +1 -1
  156. package/dist/utils/gen.d.ts +2 -2
  157. package/dist/utils/gen.d.ts.map +1 -1
  158. package/dist/utils/logLevel.d.ts +3 -3
  159. package/dist/utils/logLevel.d.ts.map +1 -1
  160. package/dist/utils/logger.d.ts +5 -4
  161. package/dist/utils/logger.d.ts.map +1 -1
  162. package/dist/utils/logger.js +4 -4
  163. package/dist/utils.d.ts +35 -40
  164. package/dist/utils.d.ts.map +1 -1
  165. package/dist/utils.js +19 -27
  166. package/dist/validation/validators.d.ts +1 -1
  167. package/dist/validation/validators.d.ts.map +1 -1
  168. package/dist/validation.d.ts +1 -1
  169. package/dist/validation.d.ts.map +1 -1
  170. package/package.json +46 -24
  171. package/src/Array.ts +3 -3
  172. package/src/Config/SecretURL.ts +5 -2
  173. package/src/Config/internal/configSecretURL.ts +1 -1
  174. package/src/Config.ts +14 -0
  175. package/src/ConfigProvider.ts +48 -0
  176. package/src/{ServiceMap.ts → Context.ts} +56 -60
  177. package/src/Effect.ts +14 -14
  178. package/src/Layer.ts +10 -5
  179. package/src/NonEmptySet.ts +3 -1
  180. package/src/Option.ts +2 -0
  181. package/src/Pure.ts +21 -19
  182. package/src/Schema/Class.ts +274 -64
  183. package/src/Schema/SchemaParser.ts +12 -0
  184. package/src/Schema/SpecialJsonSchema.ts +139 -0
  185. package/src/Schema/SpecialOpenApi.ts +130 -0
  186. package/src/Schema/brand.ts +22 -2
  187. package/src/Schema/email.ts +7 -2
  188. package/src/Schema/ext.ts +432 -88
  189. package/src/Schema/moreStrings.ts +93 -37
  190. package/src/Schema/numbers.ts +64 -16
  191. package/src/Schema/phoneNumber.ts +5 -1
  192. package/src/Schema/strings.ts +4 -8
  193. package/src/Schema.ts +404 -18
  194. package/src/Set.ts +5 -1
  195. package/src/_ext/Array.ts +3 -1
  196. package/src/_ext/misc.ts +4 -1
  197. package/src/_ext/ord.ext.ts +2 -1
  198. package/src/client/InvalidationKeys.ts +50 -0
  199. package/src/client/apiClientFactory.ts +224 -130
  200. package/src/client/clientFor.ts +95 -29
  201. package/src/client/errors.ts +52 -26
  202. package/src/client/makeClient.ts +572 -71
  203. package/src/client.ts +1 -0
  204. package/src/http/Request.ts +1 -1
  205. package/src/ids.ts +25 -3
  206. package/src/index.ts +5 -10
  207. package/src/middleware.ts +13 -9
  208. package/src/rpc/Invalidation.ts +226 -0
  209. package/src/rpc/MiddlewareMaker.ts +82 -74
  210. package/src/rpc/README.md +2 -2
  211. package/src/rpc/RpcContextMap.ts +6 -5
  212. package/src/rpc/RpcMiddleware.ts +14 -11
  213. package/src/rpc.ts +1 -1
  214. package/src/transform.ts +3 -3
  215. package/src/utils/effectify.ts +1 -1
  216. package/src/utils/gen.ts +1 -1
  217. package/src/utils/logLevel.ts +1 -1
  218. package/src/utils/logger.ts +4 -3
  219. package/src/utils.ts +57 -134
  220. package/test/dist/rpc.test.d.ts.map +1 -1
  221. package/test/dist/secretURL.test.d.ts.map +1 -0
  222. package/test/dist/special.test.d.ts.map +1 -0
  223. package/test/moreStrings.test.ts +1 -1
  224. package/test/rpc.test.ts +46 -6
  225. package/test/schema.test.ts +585 -10
  226. package/test/secretURL.test.ts +160 -0
  227. package/test/special.test.ts +1026 -0
  228. package/test/utils.test.ts +7 -7
  229. package/tsconfig.base.json +3 -4
  230. package/tsconfig.json +0 -1
  231. package/tsconfig.json.bak +2 -2
  232. package/tsconfig.src.json +29 -29
  233. package/tsconfig.test.json +2 -2
  234. package/dist/Operations.d.ts +0 -123
  235. package/dist/Operations.d.ts.map +0 -1
  236. package/dist/Operations.js +0 -29
  237. package/dist/ServiceMap.d.ts +0 -44
  238. package/dist/ServiceMap.d.ts.map +0 -1
  239. package/dist/ServiceMap.js +0 -91
  240. package/eslint.config.mjs +0 -26
  241. package/src/Operations.ts +0 -55
package/src/Effect.ts CHANGED
@@ -2,11 +2,13 @@
2
2
  /* eslint-disable prefer-destructuring */
3
3
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
4
 
5
- import { Effect, Option, Ref, type ServiceMap } from "effect"
6
5
  import * as Def from "effect/Deferred"
7
- import * as Fiber from "effect/Fiber"
6
+ import * as Effect from "effect/Effect"
7
+ import * as Option from "effect/Option"
8
+ import * as Ref from "effect/Ref"
8
9
  import type { Scope } from "effect/Scope"
9
10
  import type { Semaphore } from "effect/Semaphore"
11
+ import type * as Context from "./Context.js"
10
12
  import { curry } from "./Function.js"
11
13
  import { typedKeysOf } from "./utils.js"
12
14
 
@@ -111,15 +113,11 @@ export function modifyWithPermitWithEffect<A>(ref: Ref.Ref<A>, semaphore: Semaph
111
113
  )
112
114
  }
113
115
 
114
- export function joinAll<E, A>(fibers: Iterable<Fiber.Fiber<A, E>>): Effect.Effect<readonly A[], E> {
115
- return Fiber.joinAll(fibers) as any
116
- }
117
-
118
116
  type ServiceA<T> = T extends Effect.Effect<infer S, any, any> ? S
119
- : T extends ServiceMap.Service<any, infer S> ? S
117
+ : T extends Context.Service<any, infer S> ? S
120
118
  : never
121
119
  type ServiceR<T> = T extends Effect.Effect<any, any, infer R> ? R
122
- : T extends ServiceMap.Service<infer I, any> ? I
120
+ : T extends Context.Service<infer I, any> ? I
123
121
  : never
124
122
  type ServiceE<T> = T extends Effect.Effect<any, infer E, any> ? E : never
125
123
  // type Values<T> = T extends { [s: string]: infer S } ? ServiceA<S> : never
@@ -140,28 +138,30 @@ type ValuesE<T> = T extends { [s: string]: infer S } ? ServiceE<S> : never
140
138
  * const b = a({ str: "" }) // valid, but shouldn't be!
141
139
  * ```
142
140
  */
141
+ // eslint-disable-next-line import/namespace
143
142
  export interface EffectUnunified<R, E, A> extends Effect.Effect<R, E, A> {}
144
143
 
145
144
  export type LowerFirst<S extends PropertyKey> = S extends `${infer First}${infer Rest}` ? `${Lowercase<First>}${Rest}`
146
145
  : S
147
- export type LowerServices<T extends Record<string, ServiceMap.Service<any, any> | Effect.Effect<any, any, any>>> = {
146
+ export type LowerServices<T extends Record<string, Context.Service<any, any> | Effect.Effect<any, any, any>>> = {
148
147
  [key in keyof T as LowerFirst<key>]: ServiceA<T[key]>
149
148
  }
150
149
 
151
- export function allLower<T extends Record<string, ServiceMap.Service<any, any> | Effect.Effect<any, any, any>>>(
150
+ export function allLower<T extends Record<string, Context.Service<any, any> | Effect.Effect<any, any, any>>>(
152
151
  services: T
153
152
  ) {
154
153
  return Effect.all(
155
154
  typedKeysOf(services).reduce((prev, cur) => {
156
- const svc = services[cur]
157
- prev[((cur as string)[0]!.toLowerCase() + (cur as string).slice(1)) as unknown as LowerFirst<typeof cur>] = svc // "_id" in svc && svc._id === TagTypeId ? svc : svc
155
+ const svc = services[cur]!
156
+ prev[((cur as string)[0]!.toLowerCase() + (cur as string).slice(1)) as unknown as LowerFirst<typeof cur>] =
157
+ "asEffect" in svc ? svc.asEffect() : svc
158
158
  return prev
159
159
  }, {} as any),
160
160
  { concurrency: "inherit" }
161
161
  ) as any as Effect.Effect<LowerServices<T>, ValuesE<T>, ValuesR<T>>
162
162
  }
163
163
 
164
- export function allLowerWith<T extends Record<string, ServiceMap.Service<any, any> | Effect.Effect<any, any, any>>, A>(
164
+ export function allLowerWith<T extends Record<string, Context.Service<any, any> | Effect.Effect<any, any, any>>, A>(
165
165
  services: T,
166
166
  fn: (services: LowerServices<T>) => A
167
167
  ) {
@@ -169,7 +169,7 @@ export function allLowerWith<T extends Record<string, ServiceMap.Service<any, an
169
169
  }
170
170
 
171
171
  export function allLowerWithEffect<
172
- T extends Record<string, ServiceMap.Service<any, any> | Effect.Effect<any, any, any>>,
172
+ T extends Record<string, Context.Service<any, any> | Effect.Effect<any, any, any>>,
173
173
  R,
174
174
  E,
175
175
  A
package/src/Layer.ts CHANGED
@@ -1,6 +1,11 @@
1
- import { type Array, Effect, Layer, type Scope, type ServiceMap, type Types } from "effect"
1
+ import type * as Array from "effect/Array"
2
+ import * as Effect from "effect/Effect"
2
3
  import { type Yieldable } from "effect/Effect"
3
4
  import { dual } from "effect/Function"
5
+ import * as Layer from "effect/Layer"
6
+ import type * as Scope from "effect/Scope"
7
+ import type * as Types from "effect/Types"
8
+ import type * as Context from "./Context.js"
4
9
  import { type EffectGenUtils } from "./utils/gen.js"
5
10
 
6
11
  export * from "effect/Layer"
@@ -11,13 +16,13 @@ type MakeEff<S, E, R> = {
11
16
  readonly make: Effect.Effect<S, E, R>
12
17
  }
13
18
  type MakeGen<S, E = never, R = never> = {
14
- readonly make: () => Generator<Yieldable<any, any, E, R>, S, any>
19
+ readonly make: () => Generator<Yieldable<any, any, E, R>, S>
15
20
  }
16
21
  type MakeGenNo<S> = {
17
22
  readonly make: () => Generator<unknown, S>
18
23
  }
19
24
  type MakeErr<Opts> = Opts extends { make: () => any } ? EffectGenUtils.Error<Opts["make"]> : never
20
- type MakeContext<Opts> = Opts extends { make: () => any } ? EffectGenUtils.ServiceMap<Opts["make"]> : never
25
+ type MakeContext<Opts> = Opts extends { make: () => any } ? EffectGenUtils.Context<Opts["make"]> : never
21
26
 
22
27
  type DependenciesOpt = { dependencies?: Array.NonEmptyReadonlyArray<Layer.Any> }
23
28
  type Dependencies = { dependencies: Array.NonEmptyReadonlyArray<Layer.Any> }
@@ -41,12 +46,12 @@ type PackedOrUnpackedLayer<I, Opts> = Opts extends Dependencies ? PackedLayers<I
41
46
 
42
47
  export const make: {
43
48
  <I, S>(
44
- tag: ServiceMap.Service<I, S>
49
+ tag: Context.Service<I, S>
45
50
  ): <Opts extends Make<Types.NoInfer<S>, any, any>>(
46
51
  options: Opts
47
52
  ) => PackedOrUnpackedLayer<I, Opts>
48
53
  <I, S, Opts extends Make<Types.NoInfer<S>, any, any>>(
49
- tag: ServiceMap.Service<I, S>,
54
+ tag: Context.Service<I, S>,
50
55
  options: Opts
51
56
  ): PackedOrUnpackedLayer<I, Opts>
52
57
  } = dual(2, (tag, options) => {
@@ -1,5 +1,7 @@
1
- import { type Equivalence, Option, type Order } from "effect"
2
1
  import type { NonEmptyReadonlyArray } from "effect/Array"
2
+ import type * as Equivalence from "effect/Equivalence"
3
+ import * as Option from "effect/Option"
4
+ import type * as Order from "effect/Order"
3
5
  import { flow, pipe } from "./Function.js"
4
6
  import { filter_, filterMap, filterMap_, fromArray as fromArrayOriginal, insert as insertOriginal, insert_ as insert_Original, map, map_, reduce, reduce_, remove, remove_, type Set, toArray as toArrayOriginal } from "./Set.js"
5
7
 
package/src/Option.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-return */
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
5
+ // eslint-disable-next-line import/no-unassigned-import
6
+ import "./builtin.js"
5
7
  import { getOrUndefined as value, type Some } from "effect/Option"
6
8
  import * as Option from "effect/Option"
7
9
 
package/src/Pure.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Chunk, Effect, Layer, Result } from "effect"
2
+ import * as Chunk from "effect/Chunk"
3
+ import * as Effect from "effect/Effect"
4
+ import * as Layer from "effect/Layer"
5
+ import * as Result from "effect/Result"
6
+ import * as Context from "./Context.js"
3
7
  import { tuple } from "./Function.js"
4
- import * as ServiceMap from "./ServiceMap.js"
5
8
 
6
9
  const S1 = Symbol()
7
10
  const S2 = Symbol()
@@ -86,9 +89,9 @@ export function GMU<W, S, S2, GA, MR, ME>(modify: (i: GA) => Pure<W, S, S2, MR,
86
89
  ) => GMU_(get, modify, update)
87
90
  }
88
91
 
89
- const tagg = ServiceMap.Service<{ env: PureEnv<never, unknown, never> }>("PureEnv")
92
+ const tagg = Context.Service<{ env: PureEnv<never, unknown, never> }>("PureEnv")
90
93
  function castTag<W, S, S2>() {
91
- return tagg as any as ServiceMap.Service<PureEnvEnv<W, S, S2>, PureEnvEnv<W, S, S2>>
94
+ return tagg as any as Context.Service<PureEnvEnv<W, S, S2>, PureEnvEnv<W, S, S2>>
92
95
  }
93
96
 
94
97
  export const ServiceTag = Symbol()
@@ -100,9 +103,9 @@ export abstract class PhantomTypeParameter<Identifier extends keyof any, Instant
100
103
  }
101
104
  }
102
105
 
103
- export type ServiceShape<T extends ServiceMap.ServiceClass.Shape<any, any>> = Omit<
106
+ export type ServiceShape<T extends Context.ServiceClass.Shape<any, any>> = Omit<
104
107
  T,
105
- keyof ServiceMap.ServiceClass.Shape<any, any>
108
+ keyof Context.ServiceClass.Shape<any, any>
106
109
  >
107
110
 
108
111
  export abstract class ServiceTagged<ServiceKey> extends PhantomTypeParameter<string, ServiceKey> {}
@@ -117,11 +120,11 @@ export interface PureEnvEnv<W, S, S2> extends ServiceTagged<typeof PureEnvEnv> {
117
120
  }
118
121
 
119
122
  export function get<S>(): Pure<never, S, S, never, never, S> {
120
- return (castTag<never, S, S>() as any).use((_: any) => _.env.state)
123
+ return (castTag<never, S, S>()).useSync((_) => _.env.state)
121
124
  }
122
125
 
123
126
  export function set<S>(s: S): Pure<never, S, S, never, never, void> {
124
- return (castTag<never, S, S>() as any).use((_: any) => {
127
+ return (castTag<never, S, S>()).useSync((_) => {
125
128
  _.env.state = s
126
129
  })
127
130
  }
@@ -129,13 +132,13 @@ export function set<S>(s: S): Pure<never, S, S, never, never, void> {
129
132
  export type PureLogT<W> = Pure<W, unknown, never, never, never, void>
130
133
 
131
134
  export function log<W>(w: W): PureLogT<W> {
132
- return (castTag<W, unknown, never>() as any).use((_: any) => {
135
+ return (castTag<W, unknown, never>()).useSync((_) => {
133
136
  _.env.log = Chunk.append(_.env.log, w)
134
137
  })
135
138
  }
136
139
 
137
140
  export function logMany<W>(w: Iterable<W>): PureLogT<W> {
138
- return (castTag<W, unknown, never>() as any).use((_: any) => {
141
+ return (castTag<W, unknown, never>()).useSync((_) => {
139
142
  _.env.log = Chunk.appendAll(_.env.log, Chunk.fromIterable(w))
140
143
  })
141
144
  }
@@ -150,17 +153,16 @@ export function runAll<R, E, A, W3, S1, S3, S4 extends S1>(
150
153
  > {
151
154
  const a = Effect
152
155
  .flatMap(self, (x) =>
153
- (castTag<W3, S1, S3>() as any)
154
- .use(
155
- ({ env: _ }: any) => Effect.sync(() => ({ log: _.log, state: _.state }))
156
+ (castTag<W3, S1, S3>())
157
+ .useSync(
158
+ ({ env: _ }) => ({ log: _.log, state: _.state })
156
159
  )
157
160
  .pipe(
158
- Effect.flatMap((_: any) => Effect.succeed(_)),
159
161
  Effect.map(
160
- ({ log, state }: any) => tuple(log, Result.succeed(tuple(state, x)))
162
+ ({ log, state }) => tuple(log, Result.succeed(tuple(state, x)))
161
163
  )
162
164
  ))
163
- .pipe(Effect.catch((err: any) => (tagg as any).use((env: any) => tuple(env.env.log, Result.fail(err)))))
165
+ .pipe(Effect.catch((err: any) => tagg.useSync((env) => tuple(env.env.log, Result.fail(err)))))
164
166
  return Effect.provide(a, Layer.succeed(tagg, { env: makePureEnv<W3, S3, S4>(s) as any }) as any) as any
165
167
  }
166
168
 
@@ -198,11 +200,11 @@ export function runA<R, E, A, W3, S1, S3, S4 extends S1>(
198
200
  export function modify<S2, A, S3>(
199
201
  mod: (s: S2) => readonly [S3, A]
200
202
  ): Effect.Effect<A, never, { env: PureEnv<never, S2, S3> }> {
201
- return (castTag<never, S3, S2>() as any).use((_: any) => {
203
+ return (castTag<never, S3, S2>()).useSync((_) => {
202
204
  const [s, a] = mod(_.env.state)
203
205
  _.env.state = s as any
204
206
  return a
205
- })
207
+ }) as any
206
208
  }
207
209
 
208
210
  export function modifyM<W, R, E, A, S2, S3>(
@@ -210,7 +212,7 @@ export function modifyM<W, R, E, A, S2, S3>(
210
212
  ): Effect.Effect<A, E, FixEnv<R, W, S2, S3>> {
211
213
  // return serviceWithEffect(_ => Ref.modifyM_(_.state, mod))
212
214
  return Effect.flatMap(
213
- (castTag<W, S3, S2>() as any).use((_: any) => _),
215
+ (castTag<W, S3, S2>()).useSync((_) => _),
214
216
  (_: any) =>
215
217
  Effect.map(mod(_.env.state), ([s, a]: any) => {
216
218
  _.env.state = s
@@ -1,101 +1,311 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { pipe, Struct as Struct2 } from "effect"
3
- import type { Struct } from "effect/Schema"
2
+ import type * as Cause from "effect/Cause"
3
+ import * as Effect from "effect/Effect"
4
+ import * as Option from "effect/Option"
4
5
  import * as S from "effect/Schema"
6
+ import * as SchemaAST from "effect/SchemaAST"
7
+ import * as SchemaIssue from "effect/SchemaIssue"
8
+ import { copyOrigin } from "../utils.js"
9
+ import { concurrencyUnbounded } from "./ext.js"
10
+ import * as SchemaParser from "./SchemaParser.js"
5
11
 
6
12
  type ClassAnnotations<Self> = S.Annotations.Declaration<Self, readonly [any]>
7
13
 
8
- export interface EnhancedClass<Self, SchemaS extends S.Top & { readonly fields: Struct.Fields }, Inherited>
9
- extends S.Class<Self, SchemaS, Inherited>, /* Reason for enhancement */ PropsExtensions<SchemaS["fields"]>
14
+ export interface EnhancedClass<Self, SchemaS extends S.Top & { readonly fields: S.Struct.Fields }, Inherited>
15
+ extends S.Class<Self, SchemaS, Inherited>
10
16
  {
17
+ /**
18
+ * See `copyOrigin` docs in `utils.ts` for return-type design details.
19
+ */
20
+ readonly copy: ReturnType<typeof copyOrigin<new(_: any) => Self>>
11
21
  }
12
22
  type MissingSelfGeneric<Usage extends string, Params extends string = ""> =
13
23
  `Missing \`Self\` generic - use \`class Self extends ${Usage}<Self>()(${Params}{ ... })\``
14
24
 
15
- export interface PropsExtensions<Fields> {
16
- // include: <NewProps extends S.Struct.Fields>(
17
- // fnc: (fields: Fields) => NewProps
18
- // ) => NewProps
19
- pick: <P extends keyof Fields>(...keys: readonly P[]) => Pick<Fields, P>
20
- omit: <P extends keyof Fields>(...keys: readonly P[]) => Omit<Fields, P>
21
- }
22
-
23
- type HasFields<Fields extends Struct.Fields> = {
25
+ type HasFields<Fields extends S.Struct.Fields> = {
24
26
  readonly fields: Fields
25
27
  } | {
26
28
  readonly from: HasFields<Fields>
27
29
  }
28
30
 
29
- export const Class: <Self = never>(identifier: string) => <Fields extends S.Struct.Fields>(
31
+ type ClassOptions = {
32
+ readonly strict?: boolean
33
+ }
34
+
35
+ export declare const ExtendedSchemaNoEncoded: unique symbol
36
+
37
+ export type ExtendedSchemaNoEncoded = typeof ExtendedSchemaNoEncoded
38
+
39
+ type WithEncoded<SchemaS extends S.Top, Encoded> = Omit<SchemaS, "Encoded"> & { readonly Encoded: Encoded }
40
+
41
+ type ExtendedSchema<SchemaS extends S.Top, Encoded> = [Encoded] extends [ExtendedSchemaNoEncoded] ? SchemaS
42
+ : WithEncoded<SchemaS, Encoded>
43
+
44
+ export type Class<Self, S extends S.Top & { readonly fields: S.Struct.Fields }, Inherited> = EnhancedClass<
45
+ Self,
46
+ S,
47
+ Inherited
48
+ >
49
+
50
+ /**
51
+ * Build a modified Declaration that accepts struct-matching values during
52
+ * encoding, given the original Declaration and the class's fields.
53
+ */
54
+ function makeRelaxedDeclaration(
55
+ ast: SchemaAST.Declaration,
56
+ fields: S.Struct.Fields,
57
+ cls: any
58
+ ): SchemaAST.Declaration {
59
+ const parseOptions = ast.annotations?.["parseOptions"] as SchemaAST.ParseOptions | undefined
60
+ const structSchema = S.Struct(fields)
61
+ const annotatedStruct = parseOptions ? S.toType(structSchema).annotate({ parseOptions }) : S.toType(structSchema)
62
+ const decodeStruct = SchemaParser.decodeUnknownEffect(annotatedStruct)
63
+
64
+ return new SchemaAST.Declaration(
65
+ ast.typeParameters,
66
+ () => (input: unknown, self: SchemaAST.Declaration, options: SchemaAST.ParseOptions) => {
67
+ if (input instanceof cls) {
68
+ return Effect.succeed(input)
69
+ }
70
+ if (input !== null && typeof input === "object") {
71
+ return decodeStruct(input, options)
72
+ }
73
+ return Effect.fail(new SchemaIssue.InvalidType(self, Option.some(input)))
74
+ },
75
+ ast.annotations,
76
+ ast.checks,
77
+ ast.encoding,
78
+ ast.context
79
+ )
80
+ }
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Class — like Schema.Class but with relaxed encoding
84
+ // ---------------------------------------------------------------------------
85
+
86
+ /**
87
+ * Like `Schema.Class`, but the resulting class accepts plain objects matching
88
+ * the struct schema during encoding — not only `instanceof` or type-id
89
+ * checks.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import * as Schema from "effect/Schema"
94
+ * import { Class } from "./Class.js"
95
+ *
96
+ * class A extends Class<A>("A")({ a: Schema.String }) {}
97
+ *
98
+ * // Construction works as normal:
99
+ * new A({ a: "hello" })
100
+ *
101
+ * // Encoding accepts plain objects:
102
+ * Schema.encodeUnknownSync(A)({ a: "hello" }) // { a: "hello" }
103
+ * ```
104
+ */
105
+ export const Class: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand = {}>(
106
+ identifier: string
107
+ ) => <Fields extends S.Struct.Fields>(
30
108
  fieldsOr: Fields | HasFields<Fields>,
31
- annotations?: ClassAnnotations<Self>
109
+ annotations?: ClassAnnotations<Self>,
110
+ options?: ClassOptions
32
111
  ) => [Self] extends [never] ? MissingSelfGeneric<"Class">
33
112
  : EnhancedClass<
34
113
  Self,
35
- S.Struct<Fields>,
36
- {}
37
- > = (identifier) => (fields, annotations) => {
38
- const cls = S.Class as any
39
- return class extends cls(identifier)(fields, annotations) {
40
- constructor(a: any, b = true) {
41
- super(a, b)
114
+ ExtendedSchema<S.Struct<Fields>, Encoded>,
115
+ Brand
116
+ > = (identifier) => (fields, annotations, options) => {
117
+ const relaxed = options?.strict === false
118
+ // Build the original Schema.Class
119
+ const Base = (S.Class as any)(identifier)(fields, { ...concurrencyUnbounded, ...annotations })
120
+ // Get the original ast getter from the base class
121
+ const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
122
+
123
+ // Cache per-class to avoid recomputing
124
+ const astCache = new WeakMap<any, SchemaAST.Declaration>()
125
+ const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
126
+
127
+ return class extends Base {
128
+ static get copy() {
129
+ let cached = copyCache.get(this)
130
+ if (cached === undefined) {
131
+ cached = copyOrigin(this)
132
+ copyCache.set(this, cached)
133
+ }
134
+ return cached
135
+ }
136
+ static get ast(): SchemaAST.Declaration {
137
+ let cached = astCache.get(this)
138
+ if (cached !== undefined) return cached
139
+ // Call the original getter with `this` bound to the actual user class,
140
+ // so getClassSchema(this) creates a schema that uses `new this(...)`.
141
+ const originalAst = originalAstDescriptor.get!.call(this) as SchemaAST.Declaration
142
+ cached = relaxed ? makeRelaxedDeclaration(originalAst, Base.fields, this) : originalAst
143
+ astCache.set(this, cached)
144
+ return cached
145
+ }
146
+ static mapFields(f: any, options?: any) {
147
+ return Base.mapFields(f, options).annotate(concurrencyUnbounded)
42
148
  }
43
- // static readonly include = include(fields)
44
- static readonly pick = (...selection: any[]) => pipe(this["fields"], Struct2.pick(selection))
45
- static readonly omit = (...selection: any[]) => pipe(this["fields"], Struct2.omit(selection))
46
149
  } as any
47
150
  }
48
151
 
49
- export const TaggedClass: <Self = never>(identifier?: string) => <Tag extends string, Fields extends S.Struct.Fields>(
152
+ // ---------------------------------------------------------------------------
153
+ // TaggedClass — like Schema.TaggedClass but with relaxed encoding
154
+ // ---------------------------------------------------------------------------
155
+
156
+ /**
157
+ * Like `Schema.TaggedClass`, but the resulting class accepts plain objects
158
+ * matching the struct schema during encoding.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * import * as Schema from "effect/Schema"
163
+ * import { TaggedClass } from "./Class.js"
164
+ *
165
+ * class Circle extends TaggedClass<Circle>()("Circle", {
166
+ * radius: Schema.Number
167
+ * }) {}
168
+ *
169
+ * Schema.encodeUnknownSync(Circle)({ _tag: "Circle", radius: 5 })
170
+ * ```
171
+ */
172
+ export const TaggedClass: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand = {}>(
173
+ identifier?: string
174
+ ) => <Tag extends string, Fields extends S.Struct.Fields>(
50
175
  tag: Tag,
51
176
  fieldsOr: Fields | HasFields<Fields>,
52
- annotations?: ClassAnnotations<Self>
53
- ) => [Self] extends [never] ? MissingSelfGeneric<"Class">
177
+ annotations?: ClassAnnotations<Self>,
178
+ options?: ClassOptions
179
+ ) => [Self] extends [never] ? MissingSelfGeneric<"TaggedClass">
54
180
  : EnhancedClass<
55
181
  Self,
56
- S.Struct<{ readonly _tag: S.tag<Tag> } & Fields>,
57
- {}
58
- > = (identifier) => (tag, fields, annotations) => {
59
- const cls = S.TaggedClass as any
60
- return class extends cls(identifier)(tag, fields, annotations) {
61
- constructor(a: any, b = true) {
62
- super(a, b)
182
+ ExtendedSchema<S.Struct<{ readonly _tag: S.tag<Tag> } & Fields>, Encoded>,
183
+ Brand
184
+ > = (identifier) => (tag, fields, annotations, options) => {
185
+ const relaxed = options?.strict === false
186
+ const Base = (S.TaggedClass as any)(identifier)(tag, fields, { ...concurrencyUnbounded, ...annotations })
187
+ const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
188
+ const astCache = new WeakMap<any, SchemaAST.Declaration>()
189
+ const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
190
+
191
+ return class extends Base {
192
+ static get copy() {
193
+ let cached = copyCache.get(this)
194
+ if (cached === undefined) {
195
+ cached = copyOrigin(this)
196
+ copyCache.set(this, cached)
197
+ }
198
+ return cached
199
+ }
200
+ static get ast(): SchemaAST.Declaration {
201
+ let cached = astCache.get(this)
202
+ if (cached !== undefined) return cached
203
+ const originalAst = originalAstDescriptor.get!.call(this) as SchemaAST.Declaration
204
+ cached = relaxed ? makeRelaxedDeclaration(originalAst, Base.fields, this) : originalAst
205
+ astCache.set(this, cached)
206
+ return cached
207
+ }
208
+ static mapFields(f: any, options?: any) {
209
+ return Base.mapFields(f, options).annotate(concurrencyUnbounded)
63
210
  }
64
- // static readonly include = include(fields)
65
- static readonly pick = (...selection: any[]) => pipe(this["fields"], Struct2.pick(selection))
66
- static readonly omit = (...selection: any[]) => pipe(this["fields"], Struct2.omit(selection))
67
211
  } as any
68
212
  }
69
213
 
70
- export const ExtendedClass: <Self, _SelfFrom>(identifier: string) => <Fields extends S.Struct.Fields>(
214
+ // ---------------------------------------------------------------------------
215
+ // ErrorClass — like Schema.ErrorClass but with relaxed encoding
216
+ // ---------------------------------------------------------------------------
217
+
218
+ export const ErrorClass: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand = {}>(
219
+ identifier: string
220
+ ) => <Fields extends S.Struct.Fields>(
71
221
  fieldsOr: Fields | HasFields<Fields>,
72
- annotations?: ClassAnnotations<Self>
73
- ) => EnhancedClass<
74
- Self,
75
- S.Struct<Fields>,
76
- {}
77
- > = Class as any
78
-
79
- export interface EnhancedTaggedClass<Self, Tag extends string, Fields extends Struct.Fields, SelfFrom>
80
- extends
81
- EnhancedClass<
82
- Self,
83
- S.Struct<Fields> & { readonly Encoded: SelfFrom },
84
- {}
85
- >
86
- {
87
- readonly _tag: Tag
88
- }
222
+ annotations?: ClassAnnotations<Self>,
223
+ options?: ClassOptions
224
+ ) => [Self] extends [never] ? MissingSelfGeneric<"ErrorClass">
225
+ : EnhancedClass<
226
+ Self,
227
+ ExtendedSchema<S.Struct<Fields>, Encoded>,
228
+ Cause.YieldableError & Brand
229
+ > = (identifier) => (fields, annotations, options) => {
230
+ const relaxed = options?.strict === false
231
+ const Base = (S.ErrorClass as any)(identifier)(fields, { ...concurrencyUnbounded, ...annotations })
232
+ const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
233
+ const astCache = new WeakMap<any, SchemaAST.Declaration>()
234
+ const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
235
+
236
+ return class extends Base {
237
+ static get copy() {
238
+ let cached = copyCache.get(this)
239
+ if (cached === undefined) {
240
+ cached = copyOrigin(this)
241
+ copyCache.set(this, cached)
242
+ }
243
+ return cached
244
+ }
245
+ static get ast(): SchemaAST.Declaration {
246
+ let cached = astCache.get(this)
247
+ if (cached !== undefined) return cached
248
+ const originalAst = originalAstDescriptor.get!.call(this) as SchemaAST.Declaration
249
+ cached = relaxed ? makeRelaxedDeclaration(originalAst, Base.fields, this) : originalAst
250
+ astCache.set(this, cached)
251
+ return cached
252
+ }
253
+ static mapFields(f: any, options?: any) {
254
+ return Base.mapFields(f, options).annotate(concurrencyUnbounded)
255
+ }
256
+ } as any
257
+ }
89
258
 
90
- export const ExtendedTaggedClass: <Self, SelfFrom>(
259
+ // ---------------------------------------------------------------------------
260
+ // TaggedErrorClass — like Schema.TaggedErrorClass but with relaxed encoding
261
+ // ---------------------------------------------------------------------------
262
+
263
+ export const TaggedErrorClass: <Self = never, Encoded = ExtendedSchemaNoEncoded, Brand = {}>(
91
264
  identifier?: string
92
265
  ) => <Tag extends string, Fields extends S.Struct.Fields>(
93
266
  tag: Tag,
94
267
  fieldsOr: Fields | HasFields<Fields>,
95
- annotations?: ClassAnnotations<Self>
96
- ) => EnhancedTaggedClass<
97
- Self,
98
- Tag,
99
- { readonly _tag: S.tag<Tag> } & Fields,
100
- SelfFrom
101
- > = TaggedClass as any
268
+ annotations?: ClassAnnotations<Self>,
269
+ options?: ClassOptions
270
+ ) => [Self] extends [never] ? MissingSelfGeneric<"TaggedErrorClass">
271
+ : EnhancedClass<
272
+ Self,
273
+ ExtendedSchema<S.Struct<{ readonly _tag: S.tag<Tag> } & Fields>, Encoded>,
274
+ Cause.YieldableError & Brand
275
+ > = (identifier) => (tag, fields, annotations, options) => {
276
+ const relaxed = options?.strict === false
277
+ const Base = (S.TaggedErrorClass as any)(identifier)(tag, fields, { ...concurrencyUnbounded, ...annotations })
278
+ const originalAstDescriptor = Object.getOwnPropertyDescriptor(Base, "ast")!
279
+ const astCache = new WeakMap<any, SchemaAST.Declaration>()
280
+ const copyCache = new WeakMap<any, ReturnType<typeof copyOrigin>>()
281
+
282
+ return class extends Base {
283
+ static get copy() {
284
+ let cached = copyCache.get(this)
285
+ if (cached === undefined) {
286
+ cached = copyOrigin(this)
287
+ copyCache.set(this, cached)
288
+ }
289
+ return cached
290
+ }
291
+ static get ast(): SchemaAST.Declaration {
292
+ let cached = astCache.get(this)
293
+ if (cached !== undefined) return cached
294
+ const originalAst = originalAstDescriptor.get!.call(this) as SchemaAST.Declaration
295
+ cached = relaxed ? makeRelaxedDeclaration(originalAst, Base.fields, this) : originalAst
296
+ astCache.set(this, cached)
297
+ return cached
298
+ }
299
+ static mapFields(f: any, options?: any) {
300
+ return Base.mapFields(f, options).annotate(concurrencyUnbounded)
301
+ }
302
+ } as any
303
+ }
304
+
305
+ export interface Opaque<Self, Encoded, SchemaS extends S.Top, Brand>
306
+ extends S.Opaque<Self, ExtendedSchema<SchemaS, Encoded>, Brand>
307
+ {}
308
+
309
+ export const Opaque: <Self, Encoded = ExtendedSchemaNoEncoded, Brand = {}>() => <S extends S.Top>(
310
+ schema: S
311
+ ) => Opaque<Self, Encoded, S, Brand> & Omit<S, keyof S.Top> = S.Opaque as any
@@ -0,0 +1,12 @@
1
+ import * as SchemaParser from "effect/SchemaParser"
2
+ import { withDefaultParseOptions } from "./ext.js"
3
+
4
+ export * from "effect/SchemaParser"
5
+
6
+ export const decodeEffectConcurrently: typeof SchemaParser.decodeEffect = withDefaultParseOptions(
7
+ SchemaParser.decodeEffect
8
+ )
9
+
10
+ export const decodeUnknownEffectConcurrently: typeof SchemaParser.decodeUnknownEffect = withDefaultParseOptions(
11
+ SchemaParser.decodeUnknownEffect
12
+ )