effect-app 3.16.0 → 4.0.0-beta.0

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 (174) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/Array.js +1 -1
  3. package/dist/Chunk.d.ts +2 -4
  4. package/dist/Chunk.d.ts.map +1 -1
  5. package/dist/Chunk.js +2 -2
  6. package/dist/Config/SecretURL.d.ts +2 -12
  7. package/dist/Config/SecretURL.d.ts.map +1 -1
  8. package/dist/Config/SecretURL.js +2 -4
  9. package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
  10. package/dist/Config/internal/configSecretURL.js +3 -4
  11. package/dist/Effect.d.ts +12 -10
  12. package/dist/Effect.d.ts.map +1 -1
  13. package/dist/Effect.js +6 -15
  14. package/dist/Layer.d.ts +15 -9
  15. package/dist/Layer.d.ts.map +1 -1
  16. package/dist/Layer.js +2 -2
  17. package/dist/Operations.d.ts +37 -47
  18. package/dist/Operations.d.ts.map +1 -1
  19. package/dist/Option.js +3 -3
  20. package/dist/Pure.d.ts +17 -6
  21. package/dist/Pure.d.ts.map +1 -1
  22. package/dist/Pure.js +35 -17
  23. package/dist/Schema/Class.d.ts +13 -16
  24. package/dist/Schema/Class.d.ts.map +1 -1
  25. package/dist/Schema/Class.js +5 -27
  26. package/dist/Schema/brand.d.ts +7 -10
  27. package/dist/Schema/brand.d.ts.map +1 -1
  28. package/dist/Schema/brand.js +3 -2
  29. package/dist/Schema/email.d.ts +1 -1
  30. package/dist/Schema/email.d.ts.map +1 -1
  31. package/dist/Schema/email.js +2 -2
  32. package/dist/Schema/ext.d.ts +42 -45
  33. package/dist/Schema/ext.d.ts.map +1 -1
  34. package/dist/Schema/ext.js +49 -63
  35. package/dist/Schema/moreStrings.d.ts +17 -17
  36. package/dist/Schema/moreStrings.d.ts.map +1 -1
  37. package/dist/Schema/moreStrings.js +10 -10
  38. package/dist/Schema/numbers.d.ts +14 -14
  39. package/dist/Schema/numbers.js +5 -5
  40. package/dist/Schema/phoneNumber.d.ts +1 -1
  41. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  42. package/dist/Schema/phoneNumber.js +2 -2
  43. package/dist/Schema/schema.d.ts +2 -3
  44. package/dist/Schema/schema.d.ts.map +1 -1
  45. package/dist/Schema/schema.js +3 -4
  46. package/dist/Schema/strings.d.ts +4 -4
  47. package/dist/Schema/strings.d.ts.map +1 -1
  48. package/dist/Schema/strings.js +4 -4
  49. package/dist/Schema.d.ts +27 -25
  50. package/dist/Schema.d.ts.map +1 -1
  51. package/dist/Schema.js +22 -21
  52. package/dist/ServiceMap.d.ts +44 -0
  53. package/dist/ServiceMap.d.ts.map +1 -0
  54. package/dist/ServiceMap.js +91 -0
  55. package/dist/Set.d.ts +4 -4
  56. package/dist/Set.d.ts.map +1 -1
  57. package/dist/Set.js +14 -14
  58. package/dist/Struct.d.ts +4 -4
  59. package/dist/Struct.d.ts.map +1 -1
  60. package/dist/_ext/Array.d.ts.map +1 -1
  61. package/dist/_ext/Array.js +4 -4
  62. package/dist/_ext/misc.d.ts +2 -2
  63. package/dist/_ext/misc.js +4 -4
  64. package/dist/_ext/ord.ext.js +2 -2
  65. package/dist/builtin.d.ts +0 -8
  66. package/dist/builtin.d.ts.map +1 -1
  67. package/dist/builtin.js +3 -1
  68. package/dist/client/apiClientFactory.d.ts +14 -16
  69. package/dist/client/apiClientFactory.d.ts.map +1 -1
  70. package/dist/client/apiClientFactory.js +38 -23
  71. package/dist/client/clientFor.d.ts +7 -4
  72. package/dist/client/clientFor.d.ts.map +1 -1
  73. package/dist/client/errors.d.ts +36 -48
  74. package/dist/client/errors.d.ts.map +1 -1
  75. package/dist/client/errors.js +19 -9
  76. package/dist/client/makeClient.d.ts +34 -50
  77. package/dist/client/makeClient.d.ts.map +1 -1
  78. package/dist/client/makeClient.js +28 -18
  79. package/dist/http/Request.d.ts +3 -3
  80. package/dist/http/Request.d.ts.map +1 -1
  81. package/dist/http/Request.js +5 -8
  82. package/dist/http/internal/lib.d.ts +12 -13
  83. package/dist/http/internal/lib.d.ts.map +1 -1
  84. package/dist/http/internal/lib.js +14 -14
  85. package/dist/ids.d.ts +9 -9
  86. package/dist/ids.d.ts.map +1 -1
  87. package/dist/ids.js +1 -1
  88. package/dist/index.d.ts +7 -1
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +8 -2
  91. package/dist/logger.d.ts +1 -1
  92. package/dist/middleware.d.ts +2 -2
  93. package/dist/middleware.d.ts.map +1 -1
  94. package/dist/middleware.js +3 -3
  95. package/dist/rpc/MiddlewareMaker.d.ts +17 -16
  96. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  97. package/dist/rpc/MiddlewareMaker.js +27 -18
  98. package/dist/rpc/RpcContextMap.d.ts +4 -4
  99. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  100. package/dist/rpc/RpcContextMap.js +4 -4
  101. package/dist/rpc/RpcMiddleware.d.ts +24 -40
  102. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  103. package/dist/rpc/RpcMiddleware.js +3 -10
  104. package/dist/utils/effectify.js +2 -2
  105. package/dist/utils/gen.d.ts +4 -5
  106. package/dist/utils/gen.d.ts.map +1 -1
  107. package/dist/utils/logLevel.d.ts +1 -1
  108. package/dist/utils/logLevel.d.ts.map +1 -1
  109. package/dist/utils/logLevel.js +6 -7
  110. package/dist/utils/logger.d.ts +4 -3
  111. package/dist/utils/logger.d.ts.map +1 -1
  112. package/dist/utils/logger.js +10 -9
  113. package/dist/utils.d.ts +4 -5
  114. package/dist/utils.d.ts.map +1 -1
  115. package/dist/utils.js +10 -9
  116. package/package.json +12 -21
  117. package/src/Array.ts +1 -1
  118. package/src/Chunk.ts +2 -2
  119. package/src/Config/SecretURL.ts +3 -18
  120. package/src/Config/internal/configSecretURL.ts +2 -3
  121. package/src/Effect.ts +17 -37
  122. package/src/Layer.ts +16 -11
  123. package/src/Option.ts +2 -2
  124. package/src/Pure.ts +60 -26
  125. package/src/Schema/Class.ts +17 -73
  126. package/src/Schema/brand.ts +11 -12
  127. package/src/Schema/email.ts +2 -2
  128. package/src/Schema/ext.ts +114 -167
  129. package/src/Schema/moreStrings.ts +20 -23
  130. package/src/Schema/numbers.ts +4 -4
  131. package/src/Schema/phoneNumber.ts +2 -2
  132. package/src/Schema/schema.ts +2 -3
  133. package/src/Schema/strings.ts +3 -3
  134. package/src/Schema.ts +49 -47
  135. package/src/ServiceMap.ts +187 -0
  136. package/src/Set.ts +19 -19
  137. package/src/Struct.ts +4 -4
  138. package/src/_ext/Array.ts +4 -5
  139. package/src/_ext/misc.ts +4 -4
  140. package/src/_ext/ord.ext.ts +2 -2
  141. package/src/builtin.ts +2 -8
  142. package/src/client/apiClientFactory.ts +74 -59
  143. package/src/client/clientFor.ts +10 -7
  144. package/src/client/errors.ts +28 -22
  145. package/src/client/makeClient.ts +75 -100
  146. package/src/http/Request.ts +5 -8
  147. package/src/http/internal/lib.ts +13 -13
  148. package/src/ids.ts +1 -1
  149. package/src/index.ts +10 -1
  150. package/src/middleware.ts +2 -2
  151. package/src/rpc/MiddlewareMaker.ts +76 -47
  152. package/src/rpc/RpcContextMap.ts +7 -7
  153. package/src/rpc/RpcMiddleware.ts +28 -54
  154. package/src/utils/effectify.ts +1 -1
  155. package/src/utils/gen.ts +8 -6
  156. package/src/utils/logLevel.ts +6 -6
  157. package/src/utils/logger.ts +15 -20
  158. package/src/utils.ts +12 -12
  159. package/test/dist/rpc.test.d.ts.map +1 -1
  160. package/test/schema.test.ts +8 -8
  161. package/test/utils.test.ts +2 -2
  162. package/tsconfig.json +1 -27
  163. package/dist/Context.d.ts +0 -67
  164. package/dist/Context.d.ts.map +0 -1
  165. package/dist/Context.js +0 -207
  166. package/dist/Tag.d.ts +0 -6
  167. package/dist/Tag.d.ts.map +0 -1
  168. package/dist/Tag.js +0 -9
  169. package/dist/Unify.d.ts +0 -27
  170. package/dist/Unify.d.ts.map +0 -1
  171. package/dist/Unify.js +0 -15
  172. package/src/Context.ts +0 -351
  173. package/src/Tag.ts +0 -11
  174. package/src/Unify.ts +0 -40
package/src/Schema/ext.ts CHANGED
@@ -1,24 +1,38 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
3
- import { Effect, ParseResult, pipe, type SchemaAST } from "effect"
4
- import type { Tag } from "effect/Context"
5
- import type { Schema } from "effect/Schema"
3
+ import { Effect, Option, pipe, Schema, type SchemaAST, SchemaGetter, SchemaIssue, SchemaParser, SchemaTransformation, type ServiceMap } from "effect"
6
4
  import * as S from "effect/Schema"
7
5
  import { type NonEmptyReadonlyArray } from "../Array.js"
8
- import * as Context from "../Context.js"
9
6
  import { extendM, typedKeysOf } from "../utils.js"
10
7
  import { type AST } from "./schema.js"
11
8
 
12
- export const withDefaultConstructor: <A, I, R>(
9
+ // TODO: v4 migration — withConstructorDefault signature changed, propertySignature removed
10
+ // Constraint relaxed from `Self extends S.Top & S.WithoutConstructorDefault` to `Self extends S.Top`
11
+ // because `.pipe()` widens the schema type to `Top` which doesn't satisfy `WithoutConstructorDefault`.
12
+ // The narrowing assertions below are safe — we're asserting "this schema hasn't had a default applied yet".
13
+ export const withDefaultConstructor = <A>(
13
14
  makeDefault: () => NoInfer<A>
14
- ) => (self: Schema<A, I, R>) => S.PropertySignature<":", A, never, ":", I, true, R> = (makeDefault) => (self) =>
15
- S.propertySignature(self).pipe(S.withConstructorDefault(makeDefault))
15
+ ) =>
16
+ <Self extends S.Top>(self: Self): S.withConstructorDefault<Self & S.WithoutConstructorDefault> => {
17
+ type Narrowed = Self & S.WithoutConstructorDefault
18
+ return S.withConstructorDefault<Narrowed>(
19
+ () => Option.some(makeDefault() as Narrowed["~type.make.in"])
20
+ )(self as Narrowed)
21
+ }
22
+
23
+ // TODO: v4 migration - Date is no longer by default encoded to string.
24
+ const DateFromString = Schema.Date.pipe(
25
+ Schema.encodeTo(Schema.String, {
26
+ decode: SchemaGetter.Date(),
27
+ encode: SchemaGetter.transform((_) => _.toISOString())
28
+ })
29
+ )
16
30
 
17
31
  /**
18
- * Like the default Schema `Date` but with `withDefault` => now
32
+ * Like the default Schema `Date` but from String with `withDefault` => now
19
33
  */
20
- export const Date = Object.assign(S.Date, {
21
- withDefault: S.Date.pipe(withDefaultConstructor(() => new global.Date()))
34
+ export const Date = Object.assign(DateFromString, {
35
+ withDefault: DateFromString.pipe(withDefaultConstructor(() => new global.Date()))
22
36
  })
23
37
 
24
38
  /**
@@ -38,11 +52,11 @@ export const Number = Object.assign(S.Number, { withDefault: S.Number.pipe(withD
38
52
  */
39
53
  export const Literal = <Literals extends NonEmptyReadonlyArray<AST.LiteralValue>>(...literals: Literals) =>
40
54
  pipe(
41
- S.Literal(...literals),
55
+ S.Literals(literals),
42
56
  (s) =>
43
57
  Object.assign(s, {
44
58
  changeDefault: <A extends Literals[number]>(a: A) => {
45
- return Object.assign(S.Literal(...literals), {
59
+ return Object.assign(S.Literals(literals), {
46
60
  Default: a,
47
61
  withDefault: s.pipe(withDefaultConstructor(() => a))
48
62
  }) // todo: copy annotations from original?
@@ -55,7 +69,7 @@ export const Literal = <Literals extends NonEmptyReadonlyArray<AST.LiteralValue>
55
69
  /**
56
70
  * Like the default Schema `Array` but with `withDefault` => []
57
71
  */
58
- export function Array<Value extends Schema.Any>(value: Value) {
72
+ export function Array<Value extends S.Top>(value: Value) {
59
73
  return pipe(
60
74
  S.Array(value),
61
75
  (s) => Object.assign(s, { withDefault: s.pipe(withDefaultConstructor(() => [])) })
@@ -65,9 +79,9 @@ export function Array<Value extends Schema.Any>(value: Value) {
65
79
  /**
66
80
  * Like the default Schema `Map` but with `withDefault` => []
67
81
  */
68
- function Map_<Key extends Schema.Any, Value extends Schema.Any>(input: { key: Key; value: Value }) {
82
+ function Map_<Key extends S.Top, Value extends S.Top>(input: { key: Key; value: Value }) {
69
83
  return pipe(
70
- S.Map(input),
84
+ S.ReadonlyMap(input.key, input.value),
71
85
  (s) => Object.assign(s, { withDefault: s.pipe(withDefaultConstructor(() => new global.Map())) })
72
86
  )
73
87
  }
@@ -77,7 +91,7 @@ export { Map_ as Map }
77
91
  /**
78
92
  * Like the default Schema `ReadonlySet` but with `withDefault` => new Set()
79
93
  */
80
- export const ReadonlySet = <Value extends Schema.Any>(value: Value) =>
94
+ export const ReadonlySet = <Value extends S.Top>(value: Value) =>
81
95
  pipe(
82
96
  S.ReadonlySet(value),
83
97
  (s) => Object.assign(s, { withDefault: s.pipe(withDefaultConstructor(() => new Set<S.Schema.Type<Value>>())) })
@@ -86,52 +100,50 @@ export const ReadonlySet = <Value extends Schema.Any>(value: Value) =>
86
100
  /**
87
101
  * Like the default Schema `ReadonlyMap` but with `withDefault` => new Map()
88
102
  */
89
- export const ReadonlyMap = <K extends Schema.Any, V extends Schema.Any>(pair: {
103
+ export const ReadonlyMap = <K extends S.Top, V extends S.Top>(pair: {
90
104
  readonly key: K
91
105
  readonly value: V
92
106
  }) =>
93
107
  pipe(
94
- S.ReadonlyMap(pair),
108
+ S.ReadonlyMap(pair.key, pair.value),
95
109
  (s) => Object.assign(s, { withDefault: s.pipe(withDefaultConstructor(() => new Map())) })
96
110
  )
97
111
 
98
112
  /**
99
113
  * Like the default Schema `NullOr` but with `withDefault` => null
100
114
  */
101
- export const NullOr = <S extends Schema.Any>(self: S) =>
115
+ export const NullOr = <S extends S.Top>(self: S) =>
102
116
  pipe(
103
117
  S.NullOr(self),
104
118
  (s) => Object.assign(s, { withDefault: s.pipe(withDefaultConstructor(() => null)) })
105
119
  )
106
120
 
107
- export const defaultDate = <I, R>(s: Schema<Date, I, R>) => s.pipe(withDefaultConstructor(() => new global.Date()))
121
+ export const defaultDate = (s: S.Top) => s.pipe(withDefaultConstructor(() => new global.Date()))
108
122
 
109
- export const defaultBool = <I, R>(s: Schema<boolean, I, R>) => s.pipe(withDefaultConstructor(() => false))
123
+ export const defaultBool = (s: S.Top) => s.pipe(withDefaultConstructor(() => false))
110
124
 
111
- export const defaultNullable = <A, I, R>(
112
- s: Schema<A | null, I, R>
125
+ export const defaultNullable = (
126
+ s: S.Top
113
127
  ) => s.pipe(withDefaultConstructor(() => null))
114
128
 
115
- export const defaultArray = <A, I, R>(s: Schema<ReadonlyArray<A>, I, R>) => s.pipe(withDefaultConstructor(() => []))
129
+ export const defaultArray = (s: S.Top) => s.pipe(withDefaultConstructor(() => []))
116
130
 
117
- export const defaultMap = <A, A2, I, R>(s: Schema<ReadonlyMap<A, A2>, I, R>) =>
118
- s.pipe(withDefaultConstructor(() => new Map()))
131
+ export const defaultMap = (s: S.Top) => s.pipe(withDefaultConstructor(() => new Map()))
119
132
 
120
- export const defaultSet = <A, I, R>(s: Schema<ReadonlySet<A>, I, R>) =>
121
- s.pipe(withDefaultConstructor(() => new Set<A>()))
133
+ export const defaultSet = (s: S.Top) => s.pipe(withDefaultConstructor(() => new Set()))
122
134
 
123
- export const withDefaultMake = <Self extends S.Schema<any, any, never>>(s: Self) => {
124
- const a = Object.assign(S.decodeSync(s) as WithDefaults<Self>, s)
135
+ export const withDefaultMake = <Self extends S.Top>(s: Self) => {
136
+ const a = Object.assign(S.decodeSync(s as any) as WithDefaults<Self>, s)
125
137
  Object.setPrototypeOf(a, s)
126
138
  return a
127
139
 
128
140
  // return s as Self & WithDefaults<Self>
129
141
  }
130
142
 
131
- export type WithDefaults<Self extends S.Schema<any, any, never>> = (
132
- i: S.Schema.Encoded<Self>,
143
+ export type WithDefaults<Self extends S.Top> = (
144
+ i: Self["Encoded"],
133
145
  options?: SchemaAST.ParseOptions
134
- ) => S.Schema.Type<Self>
146
+ ) => Self["Type"]
135
147
 
136
148
  // type GetKeys<U> = U extends Record<infer K, any> ? K : never
137
149
  // type UnionToIntersection2<U extends object> = {
@@ -148,174 +160,109 @@ export type WithDefaults<Self extends S.Schema<any, any, never>> = (
148
160
  // : never
149
161
 
150
162
  export const inputDate = extendM(
151
- S.Union(S.ValidDateFromSelf, S.Date),
163
+ S.Union([S.DateValid, S.Date]),
152
164
  (s) => ({ withDefault: s.pipe(withDefaultConstructor(() => new globalThis.Date())) })
153
165
  )
154
166
 
155
167
  export interface UnionBrand {}
156
168
 
157
- const makeOpt = (self: S.PropertySignature.Any, exact?: boolean) => {
158
- const ast = self.ast
159
- switch (ast._tag) {
160
- case "PropertySignatureDeclaration": {
161
- return S.makePropertySignature(
162
- new S.PropertySignatureDeclaration(
163
- exact ? ast.type : S.UndefinedOr(S.make(ast.type)).ast,
164
- true,
165
- ast.isReadonly,
166
- ast.annotations,
167
- ast.defaultValue
168
- )
169
- )
170
- }
171
- case "PropertySignatureTransformation": {
172
- return S.makePropertySignature(
173
- new S.PropertySignatureTransformation(
174
- new S.FromPropertySignature(
175
- exact ? ast.from.type : S.UndefinedOr(S.make(ast.from.type)).ast,
176
- true,
177
- ast.from.isReadonly,
178
- ast.from.annotations
179
- ),
180
- new S.ToPropertySignature(
181
- exact ? ast.to.type : S.UndefinedOr(S.make(ast.to.type)).ast,
182
- true,
183
- ast.to.isReadonly,
184
- ast.to.annotations,
185
- ast.to.defaultValue
186
- ),
187
- ast.decode,
188
- ast.encode
189
- )
190
- )
191
- }
192
- }
193
- }
194
-
195
- export function makeOptional<NER extends S.Struct.Fields | S.PropertySignature.Any>(
196
- t: NER // TODO: enforce non empty
169
+ // TODO: v4 migration — makeOpt used internal PropertySignature types that are removed in v4
170
+ // Simplified to use v4's S.optional / S.optionalKey directly
171
+ export function makeOptional<NER extends S.Struct.Fields>(
172
+ t: NER
197
173
  ): {
198
- [K in keyof NER]: S.PropertySignature<
199
- "?:",
200
- Schema.Type<NER[K]> | undefined,
201
- never,
202
- "?:",
203
- Schema.Encoded<NER[K]> | undefined,
204
- NER[K] extends S.PropertySignature<any, any, any, any, any, infer Z, any> ? Z : false,
205
- Schema.Context<NER[K]>
206
- >
174
+ [K in keyof NER]: NER[K] extends S.Top ? ReturnType<typeof S.optional<NER[K] & S.Top>> : any
207
175
  } {
208
176
  return typedKeysOf(t).reduce((prev, cur) => {
209
- if (S.isSchema(t[cur])) {
210
- prev[cur] = S.optional(t[cur] as any)
211
- } else {
212
- prev[cur] = makeOpt(t[cur] as any)
213
- }
177
+ prev[cur] = S.optional(t[cur] as any)
214
178
  return prev
215
179
  }, {} as any)
216
180
  }
217
181
 
218
182
  export function makeExactOptional<NER extends S.Struct.Fields>(
219
- t: NER // TODO: enforce non empty
183
+ t: NER
220
184
  ): {
221
- [K in keyof NER]: S.PropertySignature<
222
- "?:",
223
- Schema.Type<NER[K]>,
224
- never,
225
- "?:",
226
- Schema.Encoded<NER[K]>,
227
- NER[K] extends S.PropertySignature<any, any, any, any, any, infer Z, any> ? Z : false,
228
- Schema.Context<NER[K]>
229
- >
185
+ [K in keyof NER]: NER[K] extends S.Top ? ReturnType<typeof S.optionalKey<NER[K] & S.Top>> : any
230
186
  } {
231
187
  return typedKeysOf(t).reduce((prev, cur) => {
232
- if (S.isSchema(t[cur])) {
233
- prev[cur] = S.optionalWith(t[cur] as any, { exact: true })
234
- } else {
235
- prev[cur] = makeOpt(t[cur] as any)
236
- }
188
+ prev[cur] = S.optionalKey(t[cur] as any)
237
189
  return prev
238
190
  }, {} as any)
239
191
  }
240
192
 
241
193
  /** A version of transform which is only a one way mapping of From->To */
242
- export const transformTo = <To extends Schema.Any, From extends Schema.Any>(
194
+ export const transformTo = <To extends S.Top, From extends S.Top>(
243
195
  from: From,
244
196
  to: To,
245
197
  decode: (
246
- fromA: Schema.Type<From>,
247
- options: SchemaAST.ParseOptions,
248
- ast: SchemaAST.Transformation,
249
- fromI: Schema.Encoded<From>
250
- ) => Schema.Encoded<To>
198
+ fromA: From["Type"],
199
+ options: SchemaAST.ParseOptions
200
+ ) => To["Encoded"]
251
201
  ) =>
252
- S.transformOrFail<To, From, never, never>(
253
- from,
254
- to,
255
- {
256
- decode: (...args) => Effect.sync(() => decode(...args)),
257
- encode: (i, _, ast) =>
258
- ParseResult.fail(
259
- new ParseResult.Forbidden(
260
- ast,
261
- i,
262
- "One way schema transformation, encoding is not allowed"
202
+ from.pipe(
203
+ S.decodeTo(
204
+ to,
205
+ SchemaTransformation.transformOrFail({
206
+ decode: (input: any, options: any) => Effect.sync(() => decode(input, options)),
207
+ encode: (i: any) =>
208
+ Effect.fail(
209
+ new SchemaIssue.Forbidden(
210
+ Option.some(i),
211
+ { message: "One way schema transformation, encoding is not allowed" }
212
+ )
263
213
  )
264
- )
265
- }
214
+ }) as any
215
+ )
266
216
  )
267
217
 
268
218
  /** A version of transformOrFail which is only a one way mapping of From->To */
269
- export const transformToOrFail = <To extends Schema.Any, From extends Schema.Any, RD>(
219
+ export const transformToOrFail = <To extends S.Top, From extends S.Top, RD>(
270
220
  from: From,
271
221
  to: To,
272
222
  decode: (
273
- fromA: Schema.Type<From>,
274
- options: SchemaAST.ParseOptions,
275
- ast: SchemaAST.Transformation
276
- ) => Effect.Effect<Schema.Encoded<To>, ParseResult.ParseIssue, RD>
223
+ fromA: From["Type"],
224
+ options: SchemaAST.ParseOptions
225
+ ) => Effect.Effect<To["Encoded"], SchemaIssue.Issue, RD>
277
226
  ) =>
278
- S.transformOrFail<To, From, RD, never>(from, to, {
279
- decode,
280
- encode: (i, _, ast) =>
281
- ParseResult.fail(
282
- new ParseResult.Forbidden(
283
- ast,
284
- i,
285
- "One way schema transformation, encoding is not allowed"
286
- )
287
- )
288
- })
227
+ from.pipe(
228
+ S.decodeTo(
229
+ to,
230
+ SchemaTransformation.transformOrFail({
231
+ decode: decode as any,
232
+ encode: (i: any) =>
233
+ Effect.fail(
234
+ new SchemaIssue.Forbidden(
235
+ Option.some(i),
236
+ { message: "One way schema transformation, encoding is not allowed" }
237
+ )
238
+ )
239
+ }) as any
240
+ )
241
+ )
289
242
 
290
- export const provide = <Self extends S.Schema.Any, R>(
243
+ // TODO: v4 migration S.declare API changed (no [self] + decode/encode pattern)
244
+ // Need to find v4 equivalent for contextual schema wrapping
245
+ export const provide = <Self extends S.Top, R>(
291
246
  self: Self,
292
- context: Context.Context<R> // TODO: support Layers?
293
- ): S.SchemaClass<S.Schema.Type<Self>, S.Schema.Encoded<Self>, Exclude<S.Schema.Context<Self>, R>> => {
294
- const provide = Effect.provide(context)
247
+ context: ServiceMap.ServiceMap<R>
248
+ ): any => {
249
+ const prov = Effect.provide(context)
295
250
  return S
296
- .declare([self], {
297
- decode: (t) => (n) => provide(ParseResult.decodeUnknown(t)(n)),
298
- encode: (t) => (n) => provide(ParseResult.encodeUnknown(t)(n))
299
- }) as any
251
+ .declare((_u: unknown): _u is unknown => true) // placeholder — needs proper v4 declare
252
+ .pipe(
253
+ S.decodeTo(
254
+ self,
255
+ SchemaTransformation.transformOrFail({
256
+ decode: (n: any) => prov(SchemaParser.decodeUnknownEffect(self)(n)),
257
+ encode: (n: any) => prov(SchemaParser.encodeUnknownEffect(self)(n))
258
+ }) as any
259
+ ) as any
260
+ )
261
+ }
262
+ // TODO: v4 migration — ServiceMap.pick and S.declare pattern removed
263
+ export const contextFromServices = <Self extends S.Top, Tags extends readonly any[]>(
264
+ _self: Self,
265
+ ..._services: Tags
266
+ ): any => {
267
+ throw new Error("contextFromServices: not yet migrated to v4")
300
268
  }
301
- export const contextFromServices = <Self extends S.Schema.Any, Tags extends readonly Tag<any, any>[]>(
302
- self: Self,
303
- ...services: Tags
304
- ): Effect.Effect<
305
- S.SchemaClass<
306
- S.Schema.Type<Self>,
307
- S.Schema.Encoded<Self>,
308
- Exclude<S.Schema.Context<Self>, { [K in keyof Tags]: Tag.Identifier<Tags[K]> }[number]>
309
- >,
310
- never,
311
- { [K in keyof Tags]: Tag.Identifier<Tags[K]> }[number]
312
- > =>
313
- Effect.gen(function*() {
314
- const context = Context.pick(...services)(yield* Effect.context())
315
- const provide = Effect.provide(context)
316
- return S
317
- .declare([self], {
318
- decode: (t) => (n) => provide(ParseResult.decodeUnknown(t)(n)),
319
- encode: (t) => (n) => provide(ParseResult.encodeUnknown(t)(n))
320
- })
321
- }) as any
@@ -1,7 +1,6 @@
1
1
  import { pipe } from "effect"
2
2
  import type { Refinement } from "effect-app/Function"
3
3
  import { extendM } from "effect-app/utils"
4
- import type { LazyArbitrary } from "effect/Arbitrary"
5
4
  import * as S from "effect/Schema"
6
5
  import type { Simplify } from "effect/Types"
7
6
  import { customRandom, nanoid, urlAlphabet } from "nanoid"
@@ -11,7 +10,7 @@ import { withDefaultConstructor, withDefaultMake, type WithDefaults } from "./ex
11
10
  import { type B } from "./schema.js"
12
11
  import type { NonEmptyString255Brand, NonEmptyStringBrand } from "./strings.js"
13
12
 
14
- const nonEmptyString = S.String.pipe(S.nonEmptyString())
13
+ const nonEmptyString = S.NonEmptyString
15
14
 
16
15
  /**
17
16
  * A string that is at least 1 character long and a maximum of 50.
@@ -27,7 +26,7 @@ export type NonEmptyString50 = string & NonEmptyString50Brand
27
26
  * A string that is at least 1 character long and a maximum of 50.
28
27
  */
29
28
  export const NonEmptyString50 = nonEmptyString.pipe(
30
- S.maxLength(50),
29
+ S.check(S.isMaxLength(50)),
31
30
  fromBrand(nominal<NonEmptyString50>(), {
32
31
  identifier: "NonEmptyString50",
33
32
  title: "NonEmptyString50",
@@ -50,7 +49,7 @@ export type NonEmptyString64 = string & NonEmptyString64Brand
50
49
  * A string that is at least 1 character long and a maximum of 64.
51
50
  */
52
51
  export const NonEmptyString64 = nonEmptyString.pipe(
53
- S.maxLength(64),
52
+ S.check(S.isMaxLength(64)),
54
53
  fromBrand(nominal<NonEmptyString64>(), {
55
54
  identifier: "NonEmptyString64",
56
55
  title: "NonEmptyString64",
@@ -74,7 +73,7 @@ export type NonEmptyString80 = string & NonEmptyString80Brand
74
73
  */
75
74
 
76
75
  export const NonEmptyString80 = nonEmptyString.pipe(
77
- S.maxLength(80),
76
+ S.check(S.isMaxLength(80)),
78
77
  fromBrand(nominal<NonEmptyString80>(), {
79
78
  identifier: "NonEmptyString80",
80
79
  title: "NonEmptyString80",
@@ -97,7 +96,7 @@ export type NonEmptyString100 = string & NonEmptyString100Brand
97
96
  * A string that is at least 1 character long and a maximum of 100.
98
97
  */
99
98
  export const NonEmptyString100 = nonEmptyString.pipe(
100
- S.maxLength(100),
99
+ S.check(S.isMaxLength(100)),
101
100
  fromBrand(nominal<NonEmptyString100>(), {
102
101
  identifier: "NonEmptyString100",
103
102
  title: "NonEmptyString100",
@@ -121,8 +120,7 @@ export type Min3String255 = string & Min3String255Brand
121
120
  */
122
121
  export const Min3String255 = pipe(
123
122
  S.String,
124
- S.minLength(3),
125
- S.maxLength(255),
123
+ S.check(S.isMinLength(3), S.isMaxLength(255)),
126
124
  fromBrand(nominal<Min3String255>(), { identifier: "Min3String255", title: "Min3String255", jsonSchema: {} }),
127
125
  withDefaultMake
128
126
  )
@@ -142,10 +140,10 @@ const minLength = 6
142
140
  const maxLength = 50
143
141
  const size = 21
144
142
  const length = 10 * size
145
- const StringIdArb = (): LazyArbitrary<string> => (fc) =>
143
+ const StringIdArb = (): any => (fc: any) =>
146
144
  fc
147
145
  .uint8Array({ minLength: length, maxLength: length })
148
- .map((_) => customRandom(urlAlphabet, size, (size) => _.subarray(0, size))())
146
+ .map((_: any) => customRandom(urlAlphabet, size, (size: number) => _.subarray(0, size))())
149
147
 
150
148
  /**
151
149
  * A string that is at least 6 characters long and a maximum of 50.
@@ -153,8 +151,7 @@ const StringIdArb = (): LazyArbitrary<string> => (fc) =>
153
151
  export const StringId = extendM(
154
152
  pipe(
155
153
  S.String,
156
- S.minLength(minLength),
157
- S.maxLength(maxLength),
154
+ S.check(S.isMinLength(minLength), S.isMaxLength(maxLength)),
158
155
  fromBrand(nominal<StringId>(), {
159
156
  identifier: "StringId",
160
157
  title: "StringId",
@@ -181,19 +178,19 @@ export function prefixedStringId<Brand extends StringId>() {
181
178
  ) => {
182
179
  type FullPrefix = `${Prefix}${Separator}`
183
180
  const pref = `${prefix}${separator ?? "-"}` as FullPrefix
184
- const arb = (): LazyArbitrary<string & Brand> => (fc) =>
181
+ const arb = (): any => (fc: any) =>
185
182
  StringIdArb()(fc).map(
186
- (x) => (pref + x.substring(0, 50 - pref.length)) as Brand
183
+ (x: any) => (pref + x.substring(0, 50 - pref.length)) as Brand
187
184
  )
188
185
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
189
- const s: S.Schema<string & Brand, string> = StringId
186
+ const s: S.Schema<string & Brand> = StringId
190
187
  .pipe(
191
- S.filter((x: StringId): x is string & Brand => x.startsWith(pref), {
188
+ S.refine((x: string): x is string & Brand => x.startsWith(pref), {
192
189
  arbitrary: arb,
193
190
  identifier: name,
194
191
  title: name
195
192
  })
196
- )
193
+ ) as any
197
194
  const schema = s.pipe(withDefaultMake)
198
195
  const make = () => (pref + StringId.make().substring(0, 50 - pref.length)) as Brand
199
196
 
@@ -220,10 +217,10 @@ export const brandedStringId = <
220
217
  Brand extends StringIdBrand
221
218
  >() =>
222
219
  withDefaultMake(
223
- Object.assign(Object.create(StringId), StringId) as S.Schema<string & Brand, string> & {
220
+ Object.assign(Object.create(StringId), StringId) as S.Schema<string & Brand> & {
224
221
  make: () => string & Brand
225
- withDefault: S.PropertySignature<":", string & Brand, never, ":", string, true, never>
226
- } & WithDefaults<S.Schema<string & Brand, string>>
222
+ withDefault: any
223
+ } & WithDefaults<S.Schema<string & Brand>>
227
224
  )
228
225
 
229
226
  export interface PrefixedStringUtils<
@@ -235,7 +232,7 @@ export interface PrefixedStringUtils<
235
232
  readonly unsafeFrom: (str: string) => Brand
236
233
  prefixSafe: <REST extends string>(str: `${Prefix}${Separator}${REST}`) => Brand
237
234
  readonly prefix: Prefix
238
- readonly withDefault: S.PropertySignature<":", Brand, never, ":", string, true, never>
235
+ readonly withDefault: any
239
236
  }
240
237
 
241
238
  export interface UrlBrand extends Simplify<B.Brand<"Url"> & NonEmptyStringBrand> {}
@@ -249,8 +246,8 @@ const isUrl: Refinement<string, Url> = (s: string): s is Url => {
249
246
  export const Url = S
250
247
  .String
251
248
  .pipe(
252
- S.filter(isUrl, {
253
- arbitrary: (): LazyArbitrary<Url> => (fc) => fc.webUrl().map((_) => _ as Url),
249
+ S.refine(isUrl, {
250
+ arbitrary: (): any => (fc: any) => fc.webUrl().map((_: any) => _ as Url),
254
251
  identifier: "Url",
255
252
  title: "Url",
256
253
  jsonSchema: { format: "uri" }
@@ -10,7 +10,7 @@ export interface PositiveIntBrand
10
10
  {}
11
11
  export const PositiveInt = extendM(
12
12
  S.Int.pipe(
13
- S.positive(),
13
+ S.check(S.isGreaterThan(0)),
14
14
  fromBrand(nominal<PositiveInt>(), { identifier: "PositiveInt", title: "PositiveInt", jsonSchema: {} }),
15
15
  withDefaultMake
16
16
  ),
@@ -21,7 +21,7 @@ export type PositiveInt = number & PositiveIntBrand
21
21
  export interface NonNegativeIntBrand extends Simplify<B.Brand<"NonNegativeInt"> & IntBrand & NonNegativeNumberBrand> {}
22
22
  export const NonNegativeInt = extendM(
23
23
  S.Int.pipe(
24
- S.nonNegative(),
24
+ S.check(S.isGreaterThanOrEqualTo(0)),
25
25
  fromBrand(nominal<NonNegativeInt>(), {
26
26
  identifier: "NonNegativeInt",
27
27
  title: "NonNegativeInt",
@@ -43,7 +43,7 @@ export type Int = number & IntBrand
43
43
  export interface PositiveNumberBrand extends Simplify<B.Brand<"PositiveNumber"> & NonNegativeNumberBrand> {}
44
44
  export const PositiveNumber = extendM(
45
45
  S.Number.pipe(
46
- S.positive(),
46
+ S.check(S.isGreaterThan(0)),
47
47
  fromBrand(nominal<PositiveNumber>(), {
48
48
  identifier: "PositiveNumber",
49
49
  title: "PositiveNumber",
@@ -60,7 +60,7 @@ export const NonNegativeNumber = extendM(
60
60
  S
61
61
  .Number
62
62
  .pipe(
63
- S.nonNegative(),
63
+ S.check(S.isGreaterThanOrEqualTo(0)),
64
64
  fromBrand(nominal<NonNegativeNumber>(), {
65
65
  identifier: "NonNegativeNumber",
66
66
  title: "NonNegativeNumber",
@@ -13,11 +13,11 @@ export type PhoneNumber = string & PhoneNumberBrand
13
13
  export const PhoneNumber = S
14
14
  .String
15
15
  .pipe(
16
- S.filter(isValidPhone as Refinement<string, PhoneNumber>, {
16
+ S.refine(isValidPhone as Refinement<string, PhoneNumber>, {
17
17
  identifier: "PhoneNumber",
18
18
  title: "PhoneNumber",
19
19
  description: "a phone number with at least 7 digits",
20
- arbitrary: () => (fc) => Numbers(7, 10)(fc).map((_) => _ as PhoneNumber),
20
+ arbitrary: () => (fc: any) => Numbers(7, 10)(fc).map((_: any) => _ as PhoneNumber),
21
21
  jsonSchema: { format: "phone" }
22
22
  }),
23
23
  withDefaultMake
@@ -1,6 +1,5 @@
1
- import * as A from "effect/Arbitrary"
2
1
  import * as B from "effect/Brand"
3
- import * as P from "effect/ParseResult"
4
2
  import * as AST from "effect/SchemaAST"
3
+ import * as P from "effect/SchemaParser"
5
4
 
6
- export { A, AST, B, P }
5
+ export { AST, B, P }
@@ -22,7 +22,7 @@ export type NonEmptyString64k = string & NonEmptyString64kBrand
22
22
  export const NonEmptyString64k = S
23
23
  .NonEmptyString
24
24
  .pipe(
25
- S.maxLength(64 * 1024),
25
+ S.check(S.isMaxLength(64 * 1024)),
26
26
  fromBrand(nominal<NonEmptyString64k>(), {
27
27
  identifier: "NonEmptyString64k",
28
28
  title: "NonEmptyString64k",
@@ -36,7 +36,7 @@ export type NonEmptyString2k = string & NonEmptyString2kBrand
36
36
  export const NonEmptyString2k = S
37
37
  .NonEmptyString
38
38
  .pipe(
39
- S.maxLength(2 * 1024),
39
+ S.check(S.isMaxLength(2 * 1024)),
40
40
  fromBrand(nominal<NonEmptyString2k>(), {
41
41
  identifier: "NonEmptyString2k",
42
42
  title: "NonEmptyString2k",
@@ -50,7 +50,7 @@ export type NonEmptyString255 = string & NonEmptyString255Brand
50
50
  export const NonEmptyString255 = S
51
51
  .NonEmptyString
52
52
  .pipe(
53
- S.maxLength(255),
53
+ S.check(S.isMaxLength(255)),
54
54
  fromBrand(nominal<NonEmptyString255>(), {
55
55
  identifier: "NonEmptyString255",
56
56
  title: "NonEmptyString255",