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.
- package/CHANGELOG.md +6 -0
- package/dist/Array.js +1 -1
- package/dist/Chunk.d.ts +2 -4
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Chunk.js +2 -2
- package/dist/Config/SecretURL.d.ts +2 -12
- package/dist/Config/SecretURL.d.ts.map +1 -1
- package/dist/Config/SecretURL.js +2 -4
- package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
- package/dist/Config/internal/configSecretURL.js +3 -4
- package/dist/Effect.d.ts +12 -10
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +6 -15
- package/dist/Layer.d.ts +15 -9
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +2 -2
- package/dist/Operations.d.ts +37 -47
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Option.js +3 -3
- package/dist/Pure.d.ts +17 -6
- package/dist/Pure.d.ts.map +1 -1
- package/dist/Pure.js +35 -17
- package/dist/Schema/Class.d.ts +13 -16
- package/dist/Schema/Class.d.ts.map +1 -1
- package/dist/Schema/Class.js +5 -27
- package/dist/Schema/brand.d.ts +7 -10
- package/dist/Schema/brand.d.ts.map +1 -1
- package/dist/Schema/brand.js +3 -2
- package/dist/Schema/email.d.ts +1 -1
- package/dist/Schema/email.d.ts.map +1 -1
- package/dist/Schema/email.js +2 -2
- package/dist/Schema/ext.d.ts +42 -45
- package/dist/Schema/ext.d.ts.map +1 -1
- package/dist/Schema/ext.js +49 -63
- package/dist/Schema/moreStrings.d.ts +17 -17
- package/dist/Schema/moreStrings.d.ts.map +1 -1
- package/dist/Schema/moreStrings.js +10 -10
- package/dist/Schema/numbers.d.ts +14 -14
- package/dist/Schema/numbers.js +5 -5
- package/dist/Schema/phoneNumber.d.ts +1 -1
- package/dist/Schema/phoneNumber.d.ts.map +1 -1
- package/dist/Schema/phoneNumber.js +2 -2
- package/dist/Schema/schema.d.ts +2 -3
- package/dist/Schema/schema.d.ts.map +1 -1
- package/dist/Schema/schema.js +3 -4
- package/dist/Schema/strings.d.ts +4 -4
- package/dist/Schema/strings.d.ts.map +1 -1
- package/dist/Schema/strings.js +4 -4
- package/dist/Schema.d.ts +27 -25
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +22 -21
- package/dist/ServiceMap.d.ts +44 -0
- package/dist/ServiceMap.d.ts.map +1 -0
- package/dist/ServiceMap.js +91 -0
- package/dist/Set.d.ts +4 -4
- package/dist/Set.d.ts.map +1 -1
- package/dist/Set.js +14 -14
- package/dist/Struct.d.ts +4 -4
- package/dist/Struct.d.ts.map +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/Array.js +4 -4
- package/dist/_ext/misc.d.ts +2 -2
- package/dist/_ext/misc.js +4 -4
- package/dist/_ext/ord.ext.js +2 -2
- package/dist/builtin.d.ts +0 -8
- package/dist/builtin.d.ts.map +1 -1
- package/dist/builtin.js +3 -1
- package/dist/client/apiClientFactory.d.ts +14 -16
- package/dist/client/apiClientFactory.d.ts.map +1 -1
- package/dist/client/apiClientFactory.js +38 -23
- package/dist/client/clientFor.d.ts +7 -4
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/errors.d.ts +36 -48
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +19 -9
- package/dist/client/makeClient.d.ts +34 -50
- package/dist/client/makeClient.d.ts.map +1 -1
- package/dist/client/makeClient.js +28 -18
- package/dist/http/Request.d.ts +3 -3
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +5 -8
- package/dist/http/internal/lib.d.ts +12 -13
- package/dist/http/internal/lib.d.ts.map +1 -1
- package/dist/http/internal/lib.js +14 -14
- package/dist/ids.d.ts +9 -9
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/logger.d.ts +1 -1
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +3 -3
- package/dist/rpc/MiddlewareMaker.d.ts +17 -16
- package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
- package/dist/rpc/MiddlewareMaker.js +27 -18
- package/dist/rpc/RpcContextMap.d.ts +4 -4
- package/dist/rpc/RpcContextMap.d.ts.map +1 -1
- package/dist/rpc/RpcContextMap.js +4 -4
- package/dist/rpc/RpcMiddleware.d.ts +24 -40
- package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/rpc/RpcMiddleware.js +3 -10
- package/dist/utils/effectify.js +2 -2
- package/dist/utils/gen.d.ts +4 -5
- package/dist/utils/gen.d.ts.map +1 -1
- package/dist/utils/logLevel.d.ts +1 -1
- package/dist/utils/logLevel.d.ts.map +1 -1
- package/dist/utils/logLevel.js +6 -7
- package/dist/utils/logger.d.ts +4 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +10 -9
- package/dist/utils.d.ts +4 -5
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -9
- package/package.json +12 -21
- package/src/Array.ts +1 -1
- package/src/Chunk.ts +2 -2
- package/src/Config/SecretURL.ts +3 -18
- package/src/Config/internal/configSecretURL.ts +2 -3
- package/src/Effect.ts +17 -37
- package/src/Layer.ts +16 -11
- package/src/Option.ts +2 -2
- package/src/Pure.ts +60 -26
- package/src/Schema/Class.ts +17 -73
- package/src/Schema/brand.ts +11 -12
- package/src/Schema/email.ts +2 -2
- package/src/Schema/ext.ts +114 -167
- package/src/Schema/moreStrings.ts +20 -23
- package/src/Schema/numbers.ts +4 -4
- package/src/Schema/phoneNumber.ts +2 -2
- package/src/Schema/schema.ts +2 -3
- package/src/Schema/strings.ts +3 -3
- package/src/Schema.ts +49 -47
- package/src/ServiceMap.ts +187 -0
- package/src/Set.ts +19 -19
- package/src/Struct.ts +4 -4
- package/src/_ext/Array.ts +4 -5
- package/src/_ext/misc.ts +4 -4
- package/src/_ext/ord.ext.ts +2 -2
- package/src/builtin.ts +2 -8
- package/src/client/apiClientFactory.ts +74 -59
- package/src/client/clientFor.ts +10 -7
- package/src/client/errors.ts +28 -22
- package/src/client/makeClient.ts +75 -100
- package/src/http/Request.ts +5 -8
- package/src/http/internal/lib.ts +13 -13
- package/src/ids.ts +1 -1
- package/src/index.ts +10 -1
- package/src/middleware.ts +2 -2
- package/src/rpc/MiddlewareMaker.ts +76 -47
- package/src/rpc/RpcContextMap.ts +7 -7
- package/src/rpc/RpcMiddleware.ts +28 -54
- package/src/utils/effectify.ts +1 -1
- package/src/utils/gen.ts +8 -6
- package/src/utils/logLevel.ts +6 -6
- package/src/utils/logger.ts +15 -20
- package/src/utils.ts +12 -12
- package/test/dist/rpc.test.d.ts.map +1 -1
- package/test/schema.test.ts +8 -8
- package/test/utils.test.ts +2 -2
- package/tsconfig.json +1 -27
- package/dist/Context.d.ts +0 -67
- package/dist/Context.d.ts.map +0 -1
- package/dist/Context.js +0 -207
- package/dist/Tag.d.ts +0 -6
- package/dist/Tag.d.ts.map +0 -1
- package/dist/Tag.js +0 -9
- package/dist/Unify.d.ts +0 -27
- package/dist/Unify.d.ts.map +0 -1
- package/dist/Unify.js +0 -15
- package/src/Context.ts +0 -351
- package/src/Tag.ts +0 -11
- 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,
|
|
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
|
-
|
|
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
|
-
) =>
|
|
15
|
-
|
|
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(
|
|
21
|
-
withDefault:
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
82
|
+
function Map_<Key extends S.Top, Value extends S.Top>(input: { key: Key; value: Value }) {
|
|
69
83
|
return pipe(
|
|
70
|
-
S.
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
121
|
+
export const defaultDate = (s: S.Top) => s.pipe(withDefaultConstructor(() => new global.Date()))
|
|
108
122
|
|
|
109
|
-
export const defaultBool =
|
|
123
|
+
export const defaultBool = (s: S.Top) => s.pipe(withDefaultConstructor(() => false))
|
|
110
124
|
|
|
111
|
-
export const defaultNullable =
|
|
112
|
-
s:
|
|
125
|
+
export const defaultNullable = (
|
|
126
|
+
s: S.Top
|
|
113
127
|
) => s.pipe(withDefaultConstructor(() => null))
|
|
114
128
|
|
|
115
|
-
export const defaultArray =
|
|
129
|
+
export const defaultArray = (s: S.Top) => s.pipe(withDefaultConstructor(() => []))
|
|
116
130
|
|
|
117
|
-
export const defaultMap =
|
|
118
|
-
s.pipe(withDefaultConstructor(() => new Map()))
|
|
131
|
+
export const defaultMap = (s: S.Top) => s.pipe(withDefaultConstructor(() => new Map()))
|
|
119
132
|
|
|
120
|
-
export const defaultSet =
|
|
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.
|
|
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.
|
|
132
|
-
i:
|
|
143
|
+
export type WithDefaults<Self extends S.Top> = (
|
|
144
|
+
i: Self["Encoded"],
|
|
133
145
|
options?: SchemaAST.ParseOptions
|
|
134
|
-
) =>
|
|
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.
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
183
|
+
t: NER
|
|
220
184
|
): {
|
|
221
|
-
[K in keyof NER]: S.
|
|
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
|
-
|
|
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
|
|
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:
|
|
247
|
-
options: SchemaAST.ParseOptions
|
|
248
|
-
|
|
249
|
-
fromI: Schema.Encoded<From>
|
|
250
|
-
) => Schema.Encoded<To>
|
|
198
|
+
fromA: From["Type"],
|
|
199
|
+
options: SchemaAST.ParseOptions
|
|
200
|
+
) => To["Encoded"]
|
|
251
201
|
) =>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
|
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:
|
|
274
|
-
options: SchemaAST.ParseOptions
|
|
275
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
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:
|
|
293
|
-
):
|
|
294
|
-
const
|
|
247
|
+
context: ServiceMap.ServiceMap<R>
|
|
248
|
+
): any => {
|
|
249
|
+
const prov = Effect.provide(context)
|
|
295
250
|
return S
|
|
296
|
-
.declare(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 = ():
|
|
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.
|
|
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 = ():
|
|
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
|
|
186
|
+
const s: S.Schema<string & Brand> = StringId
|
|
190
187
|
.pipe(
|
|
191
|
-
S.
|
|
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
|
|
220
|
+
Object.assign(Object.create(StringId), StringId) as S.Schema<string & Brand> & {
|
|
224
221
|
make: () => string & Brand
|
|
225
|
-
withDefault:
|
|
226
|
-
} & WithDefaults<S.Schema<string & Brand
|
|
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:
|
|
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.
|
|
253
|
-
arbitrary: ():
|
|
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" }
|
package/src/Schema/numbers.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface PositiveIntBrand
|
|
|
10
10
|
{}
|
|
11
11
|
export const PositiveInt = extendM(
|
|
12
12
|
S.Int.pipe(
|
|
13
|
-
S.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
package/src/Schema/schema.ts
CHANGED
package/src/Schema/strings.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type NonEmptyString64k = string & NonEmptyString64kBrand
|
|
|
22
22
|
export const NonEmptyString64k = S
|
|
23
23
|
.NonEmptyString
|
|
24
24
|
.pipe(
|
|
25
|
-
S.
|
|
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.
|
|
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.
|
|
53
|
+
S.check(S.isMaxLength(255)),
|
|
54
54
|
fromBrand(nominal<NonEmptyString255>(), {
|
|
55
55
|
identifier: "NonEmptyString255",
|
|
56
56
|
title: "NonEmptyString255",
|