effect-app 4.0.0-beta.15 → 4.0.0-beta.151
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 +595 -0
- package/dist/Array.d.ts +1 -1
- package/dist/Chunk.d.ts +1 -1
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Config/SecretURL.d.ts +1 -1
- package/dist/Config/SecretURL.d.ts.map +1 -1
- package/dist/Config/SecretURL.js +2 -2
- package/dist/Config/internal/configSecretURL.d.ts +1 -1
- package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
- package/dist/Config.d.ts +7 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +6 -0
- package/dist/ConfigProvider.d.ts +39 -0
- package/dist/ConfigProvider.d.ts.map +1 -0
- package/dist/ConfigProvider.js +42 -0
- package/dist/Context.d.ts +40 -0
- package/dist/Context.d.ts.map +1 -0
- package/dist/Context.js +67 -0
- package/dist/Effect.d.ts +9 -10
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +3 -6
- package/dist/Function.d.ts +1 -1
- package/dist/Function.d.ts.map +1 -1
- package/dist/Inputify.type.d.ts +1 -1
- package/dist/Layer.d.ts +6 -5
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +1 -1
- package/dist/NonEmptySet.d.ts +1 -1
- package/dist/NonEmptySet.d.ts.map +1 -1
- package/dist/Operations.d.ts +372 -50
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Operations.js +9 -9
- package/dist/Option.d.ts +1 -1
- package/dist/Option.d.ts.map +1 -1
- package/dist/Pure.d.ts +5 -5
- package/dist/Pure.d.ts.map +1 -1
- package/dist/Pure.js +13 -13
- package/dist/Schema/Class.d.ts +69 -20
- package/dist/Schema/Class.d.ts.map +1 -1
- package/dist/Schema/Class.js +193 -22
- package/dist/Schema/FastCheck.d.ts +1 -1
- package/dist/Schema/FastCheck.d.ts.map +1 -1
- package/dist/Schema/Methods.d.ts +1 -1
- package/dist/Schema/SpecialJsonSchema.d.ts +33 -0
- package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
- package/dist/Schema/SpecialJsonSchema.js +122 -0
- package/dist/Schema/SpecialOpenApi.d.ts +32 -0
- package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
- package/dist/Schema/SpecialOpenApi.js +123 -0
- package/dist/Schema/brand.d.ts +7 -2
- package/dist/Schema/brand.d.ts.map +1 -1
- package/dist/Schema/brand.js +1 -1
- package/dist/Schema/email.d.ts +1 -1
- package/dist/Schema/email.d.ts.map +1 -1
- package/dist/Schema/email.js +7 -4
- package/dist/Schema/ext.d.ts +113 -48
- package/dist/Schema/ext.d.ts.map +1 -1
- package/dist/Schema/ext.js +115 -53
- package/dist/Schema/moreStrings.d.ts +111 -11
- package/dist/Schema/moreStrings.d.ts.map +1 -1
- package/dist/Schema/moreStrings.js +14 -15
- package/dist/Schema/numbers.d.ts +127 -15
- package/dist/Schema/numbers.d.ts.map +1 -1
- package/dist/Schema/numbers.js +10 -12
- package/dist/Schema/phoneNumber.d.ts +1 -1
- package/dist/Schema/phoneNumber.d.ts.map +1 -1
- package/dist/Schema/phoneNumber.js +6 -3
- package/dist/Schema/schema.d.ts +1 -1
- package/dist/Schema/strings.d.ts +37 -5
- package/dist/Schema/strings.d.ts.map +1 -1
- package/dist/Schema/strings.js +1 -5
- package/dist/Schema.d.ts +88 -53
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +125 -63
- package/dist/Set.d.ts +1 -1
- package/dist/Set.d.ts.map +1 -1
- package/dist/TypeTest.d.ts +1 -1
- package/dist/Types.d.ts +1 -1
- package/dist/Widen.type.d.ts +1 -1
- package/dist/_ext/Array.d.ts +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/date.d.ts +1 -1
- package/dist/_ext/misc.d.ts +1 -1
- package/dist/_ext/ord.ext.d.ts +1 -1
- package/dist/_ext/ord.ext.d.ts.map +1 -1
- package/dist/builtin.d.ts +1 -1
- package/dist/builtin.d.ts.map +1 -1
- package/dist/client/apiClientFactory.d.ts +14 -30
- package/dist/client/apiClientFactory.d.ts.map +1 -1
- package/dist/client/apiClientFactory.js +18 -19
- package/dist/client/clientFor.d.ts +7 -6
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/errors.d.ts +44 -19
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +35 -10
- package/dist/client/makeClient.d.ts +77 -29
- package/dist/client/makeClient.d.ts.map +1 -1
- package/dist/client/makeClient.js +49 -23
- package/dist/client.d.ts +1 -1
- package/dist/faker.d.ts +1 -1
- package/dist/faker.d.ts.map +1 -1
- package/dist/http/Request.d.ts +2 -2
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +5 -5
- package/dist/http/internal/lib.d.ts +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/ids.d.ts +3 -3
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +3 -2
- package/dist/index.d.ts +5 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/logger.d.ts +1 -1
- package/dist/middleware.d.ts +8 -8
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +8 -8
- package/dist/rpc/MiddlewareMaker.d.ts +5 -4
- package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
- package/dist/rpc/MiddlewareMaker.js +26 -27
- package/dist/rpc/RpcContextMap.d.ts +3 -3
- package/dist/rpc/RpcContextMap.d.ts.map +1 -1
- package/dist/rpc/RpcContextMap.js +4 -4
- package/dist/rpc/RpcMiddleware.d.ts +5 -4
- package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/rpc/RpcMiddleware.js +1 -1
- package/dist/rpc.d.ts +1 -2
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +1 -2
- package/dist/transform.d.ts +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +3 -3
- package/dist/utils/effectify.d.ts +1 -1
- package/dist/utils/extend.d.ts +1 -1
- package/dist/utils/extend.d.ts.map +1 -1
- package/dist/utils/gen.d.ts +2 -2
- package/dist/utils/gen.d.ts.map +1 -1
- package/dist/utils/logLevel.d.ts +2 -2
- package/dist/utils/logLevel.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +3 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +3 -3
- package/dist/utils.d.ts +30 -10
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -4
- package/dist/validation/validators.d.ts +1 -1
- package/dist/validation/validators.d.ts.map +1 -1
- package/dist/validation.d.ts +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/eslint.config.mjs +1 -1
- package/package.json +35 -19
- package/src/Config/SecretURL.ts +2 -1
- package/src/Config.ts +14 -0
- package/src/ConfigProvider.ts +48 -0
- package/src/{ServiceMap.ts → Context.ts} +52 -59
- package/src/Effect.ts +12 -14
- package/src/Layer.ts +5 -4
- package/src/Operations.ts +9 -9
- package/src/Pure.ts +17 -18
- package/src/Schema/Class.ts +281 -62
- package/src/Schema/SpecialJsonSchema.ts +137 -0
- package/src/Schema/SpecialOpenApi.ts +130 -0
- package/src/Schema/brand.ts +9 -1
- package/src/Schema/email.ts +7 -2
- package/src/Schema/ext.ts +196 -87
- package/src/Schema/moreStrings.ts +22 -20
- package/src/Schema/numbers.ts +14 -16
- package/src/Schema/phoneNumber.ts +5 -1
- package/src/Schema/strings.ts +4 -8
- package/src/Schema.ts +256 -98
- package/src/client/apiClientFactory.ts +107 -113
- package/src/client/clientFor.ts +6 -1
- package/src/client/errors.ts +42 -17
- package/src/client/makeClient.ts +156 -63
- package/src/http/Request.ts +7 -4
- package/src/ids.ts +2 -1
- package/src/index.ts +5 -10
- package/src/middleware.ts +7 -9
- package/src/rpc/MiddlewareMaker.ts +36 -47
- package/src/rpc/RpcContextMap.ts +6 -5
- package/src/rpc/RpcMiddleware.ts +5 -4
- package/src/rpc.ts +0 -1
- package/src/transform.ts +2 -2
- package/src/utils/gen.ts +1 -1
- package/src/utils/logger.ts +2 -2
- package/src/utils.ts +47 -11
- package/test/dist/rpc.test.d.ts.map +1 -1
- package/test/dist/secretURL.test.d.ts.map +1 -0
- package/test/dist/special.test.d.ts.map +1 -0
- package/test/rpc.test.ts +38 -6
- package/test/schema.test.ts +594 -4
- package/test/secretURL.test.ts +157 -0
- package/test/special.test.ts +1005 -0
- package/test/utils.test.ts +6 -6
- package/tsconfig.base.json +0 -1
- package/tsconfig.json +0 -1
- package/dist/ServiceMap.d.ts +0 -44
- package/dist/ServiceMap.d.ts.map +0 -1
- package/dist/ServiceMap.js +0 -91
package/src/Schema/strings.ts
CHANGED
|
@@ -9,9 +9,8 @@ export type NonEmptyString = string & NonEmptyStringBrand
|
|
|
9
9
|
export const NonEmptyString = S
|
|
10
10
|
.NonEmptyString
|
|
11
11
|
.pipe(
|
|
12
|
-
fromBrand(nominal<NonEmptyString>(), {
|
|
12
|
+
fromBrand<NonEmptyString>(nominal<NonEmptyString>(), {
|
|
13
13
|
identifier: "NonEmptyString",
|
|
14
|
-
title: "NonEmptyString",
|
|
15
14
|
jsonSchema: {}
|
|
16
15
|
}),
|
|
17
16
|
withDefaultMake
|
|
@@ -23,9 +22,8 @@ export const NonEmptyString64k = S
|
|
|
23
22
|
.NonEmptyString
|
|
24
23
|
.pipe(
|
|
25
24
|
S.check(S.isMaxLength(64 * 1024)),
|
|
26
|
-
fromBrand(nominal<NonEmptyString64k>(), {
|
|
25
|
+
fromBrand<NonEmptyString64k>(nominal<NonEmptyString64k>(), {
|
|
27
26
|
identifier: "NonEmptyString64k",
|
|
28
|
-
title: "NonEmptyString64k",
|
|
29
27
|
jsonSchema: {}
|
|
30
28
|
}),
|
|
31
29
|
withDefaultMake
|
|
@@ -37,9 +35,8 @@ export const NonEmptyString2k = S
|
|
|
37
35
|
.NonEmptyString
|
|
38
36
|
.pipe(
|
|
39
37
|
S.check(S.isMaxLength(2 * 1024)),
|
|
40
|
-
fromBrand(nominal<NonEmptyString2k>(), {
|
|
38
|
+
fromBrand<NonEmptyString2k>(nominal<NonEmptyString2k>(), {
|
|
41
39
|
identifier: "NonEmptyString2k",
|
|
42
|
-
title: "NonEmptyString2k",
|
|
43
40
|
jsonSchema: {}
|
|
44
41
|
}),
|
|
45
42
|
withDefaultMake
|
|
@@ -51,9 +48,8 @@ export const NonEmptyString255 = S
|
|
|
51
48
|
.NonEmptyString
|
|
52
49
|
.pipe(
|
|
53
50
|
S.check(S.isMaxLength(255)),
|
|
54
|
-
fromBrand(nominal<NonEmptyString255>(), {
|
|
51
|
+
fromBrand<NonEmptyString255>(nominal<NonEmptyString255>(), {
|
|
55
52
|
identifier: "NonEmptyString255",
|
|
56
|
-
title: "NonEmptyString255",
|
|
57
53
|
jsonSchema: {}
|
|
58
54
|
}),
|
|
59
55
|
withDefaultMake
|
package/src/Schema.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SchemaAST, type Tracer } from "effect"
|
|
2
2
|
import * as S from "effect/Schema"
|
|
3
3
|
import type { NonEmptyReadonlyArray } from "./Array.js"
|
|
4
4
|
import { fakerArb } from "./faker.js"
|
|
5
5
|
import { Email as EmailT, type Email as EmailType } from "./Schema/email.js"
|
|
6
|
-
import { withDefaultMake } from "./Schema/ext.js"
|
|
6
|
+
import { concurrencyUnbounded, withDefaultMake } from "./Schema/ext.js"
|
|
7
7
|
import { PhoneNumber as PhoneNumberT, type PhoneNumber as PhoneNumberType } from "./Schema/phoneNumber.js"
|
|
8
|
-
import type
|
|
9
|
-
import { extendM } from "./utils.js"
|
|
8
|
+
import { copy, extendM, type StructuralCopyOrigin } from "./utils.js"
|
|
10
9
|
|
|
11
10
|
export * from "effect/Schema"
|
|
12
|
-
// v4: TaggedError renamed to TaggedErrorClass
|
|
13
|
-
export { TaggedErrorClass as TaggedError } from "effect/Schema"
|
|
14
11
|
|
|
15
12
|
export * from "./Schema/Class.js"
|
|
16
|
-
export { Class, TaggedClass } from "./Schema/Class.js"
|
|
13
|
+
export { Class, ErrorClass, Opaque, TaggedClass, TaggedErrorClass } from "./Schema/Class.js"
|
|
17
14
|
|
|
18
15
|
export { fromBrand, nominal } from "./Schema/brand.js"
|
|
19
|
-
export { Array, Boolean, Date,
|
|
16
|
+
export { Array, Boolean, Date, DateFromString, DateValid, Finite, Literals, NullOr, Number, ReadonlyMap, ReadonlySet } from "./Schema/ext.js"
|
|
20
17
|
export { Int, NonNegativeInt } from "./Schema/numbers.js"
|
|
21
18
|
|
|
22
19
|
export * from "./Schema/email.js"
|
|
@@ -25,6 +22,8 @@ export * from "./Schema/moreStrings.js"
|
|
|
25
22
|
export * from "./Schema/numbers.js"
|
|
26
23
|
export * from "./Schema/phoneNumber.js"
|
|
27
24
|
export * from "./Schema/schema.js"
|
|
25
|
+
export * from "./Schema/SpecialJsonSchema.js"
|
|
26
|
+
export * from "./Schema/SpecialOpenApi.js"
|
|
28
27
|
export * from "./Schema/strings.js"
|
|
29
28
|
export { NonEmptyString } from "./Schema/strings.js"
|
|
30
29
|
|
|
@@ -33,6 +32,128 @@ export * as SchemaParser from "effect/SchemaParser"
|
|
|
33
32
|
|
|
34
33
|
export { Void as Void_ } from "effect/Schema"
|
|
35
34
|
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Struct / NonEmptyArray / Record — with concurrency: "unbounded"
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
type WithSchemaCopy<Self extends S.Top & { readonly Type: object }> = Self & {
|
|
40
|
+
readonly copy: StructuralCopyOrigin<Self["Type"]>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type OptionalMakeInput<Fields extends S.Struct.Fields> = {} extends S.Struct.MakeIn<Fields> ? {
|
|
44
|
+
make(input?: S.Struct.MakeIn<Fields>, options?: S.MakeOptions): S.Struct.Type<Fields>
|
|
45
|
+
}
|
|
46
|
+
: {}
|
|
47
|
+
|
|
48
|
+
export function Struct<const Fields extends S.Struct.Fields>(
|
|
49
|
+
fields: Fields
|
|
50
|
+
): Struct<Fields> & OptionalMakeInput<Fields> {
|
|
51
|
+
const result = S.Struct(fields).annotate(concurrencyUnbounded)
|
|
52
|
+
const allowVoidMake = (schema: any): any => {
|
|
53
|
+
// Normalize omitted input to an empty object so optional/default-only structs can be constructed with make().
|
|
54
|
+
const origMake: any = schema.make
|
|
55
|
+
const origMakeOption: any = schema.makeOption
|
|
56
|
+
const origMakeEffect: any = schema.makeEffect
|
|
57
|
+
schema.make = function(this: any, input: any, options?: any) {
|
|
58
|
+
return origMake.call(this, input === undefined ? {} : input, options)
|
|
59
|
+
}
|
|
60
|
+
schema.makeOption = function(this: any, input: any, options?: any) {
|
|
61
|
+
return origMakeOption.call(this, input === undefined ? {} : input, options)
|
|
62
|
+
}
|
|
63
|
+
schema.makeEffect = function(this: any, input: any, options?: any) {
|
|
64
|
+
return origMakeEffect.call(this, input === undefined ? {} : input, options)
|
|
65
|
+
}
|
|
66
|
+
return schema
|
|
67
|
+
}
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unsafe-assignment
|
|
69
|
+
const origMapFields: any = result.mapFields
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unsafe-assignment
|
|
71
|
+
const origAnnotate: any = result.annotate
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unsafe-assignment
|
|
73
|
+
const origAnnotateKey: any = result.annotateKey
|
|
74
|
+
|
|
75
|
+
const preserveCopyAndMethods = (schema: any): any => {
|
|
76
|
+
schema.copy = copy
|
|
77
|
+
schema.mapFields = function(this: any, f: any, options?: any) {
|
|
78
|
+
return (result as any).mapFields.call(this, f, options)
|
|
79
|
+
}
|
|
80
|
+
schema.annotate = function(this: any, annotations?: any) {
|
|
81
|
+
return (result as any).annotate.call(this, annotations)
|
|
82
|
+
}
|
|
83
|
+
schema.annotateKey = function(this: any, annotations?: any) {
|
|
84
|
+
return (result as any).annotateKey.call(this, annotations)
|
|
85
|
+
}
|
|
86
|
+
return allowVoidMake(schema)
|
|
87
|
+
}
|
|
88
|
+
;(result as any).mapFields = function(this: any, f: any, options?: any) {
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
90
|
+
const mapped = origMapFields.call(this, f, options).annotate(concurrencyUnbounded)
|
|
91
|
+
return preserveCopyAndMethods(mapped)
|
|
92
|
+
}
|
|
93
|
+
;(result as any).annotate = function(this: any, annotations?: any) {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
95
|
+
const annotated = origAnnotate.call(this, annotations)
|
|
96
|
+
return preserveCopyAndMethods(annotated)
|
|
97
|
+
}
|
|
98
|
+
;(result as any).annotateKey = function(this: any, annotations?: any) {
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
100
|
+
const annotated = origAnnotateKey.call(this, annotations)
|
|
101
|
+
return preserveCopyAndMethods(annotated)
|
|
102
|
+
}
|
|
103
|
+
;(result as any).copy = copy
|
|
104
|
+
allowVoidMake(result)
|
|
105
|
+
return result as Struct<Fields> & OptionalMakeInput<Fields>
|
|
106
|
+
}
|
|
107
|
+
export interface Struct<Fields extends S.Struct.Fields> extends WithSchemaCopy<S.Struct<Fields>> {
|
|
108
|
+
annotate(
|
|
109
|
+
annotations: S.Annotations.Bottom<S.Struct.Type<Fields>, S.Struct<Fields>["~type.parameters"]>
|
|
110
|
+
): Struct<Fields>
|
|
111
|
+
annotateKey(annotations: S.Annotations.Key<S.Struct.Type<Fields>>): Struct<Fields>
|
|
112
|
+
mapFields<To extends S.Struct.Fields>(
|
|
113
|
+
f: (fields: Fields) => To,
|
|
114
|
+
options?: {
|
|
115
|
+
readonly unsafePreserveChecks?: boolean | undefined
|
|
116
|
+
}
|
|
117
|
+
): Struct<Readonly<To>>
|
|
118
|
+
}
|
|
119
|
+
export declare namespace Struct {
|
|
120
|
+
export type Fields = S.Struct.Fields
|
|
121
|
+
export type Type<F extends S.Struct.Fields> = S.Struct.Type<F>
|
|
122
|
+
export type Encoded<F extends S.Struct.Fields> = S.Struct.Encoded<F>
|
|
123
|
+
export type DecodingServices<F extends S.Struct.Fields> = S.Struct.DecodingServices<F>
|
|
124
|
+
export type EncodingServices<F extends S.Struct.Fields> = S.Struct.EncodingServices<F>
|
|
125
|
+
export type MakeIn<F extends S.Struct.Fields> = S.Struct.MakeIn<F>
|
|
126
|
+
export type Iso<F extends S.Struct.Fields> = S.Struct.Iso<F>
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function NonEmptyArray<Value extends S.Top>(value: Value): S.NonEmptyArray<Value> {
|
|
130
|
+
return S.NonEmptyArray(value).annotate(concurrencyUnbounded)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function TaggedStruct<const Tag extends SchemaAST.LiteralValue, const Fields extends S.Struct.Fields>(
|
|
134
|
+
value: Tag,
|
|
135
|
+
fields: Fields
|
|
136
|
+
): TaggedStruct<Tag, Fields> {
|
|
137
|
+
return Struct({ _tag: S.tag(value), ...fields }) as any
|
|
138
|
+
}
|
|
139
|
+
export type TaggedStruct<Tag extends SchemaAST.LiteralValue, Fields extends S.Struct.Fields> =
|
|
140
|
+
& WithSchemaCopy<
|
|
141
|
+
S.TaggedStruct<Tag, Fields>
|
|
142
|
+
>
|
|
143
|
+
& OptionalMakeInput<Readonly<{ readonly _tag: S.tag<Tag> } & Fields>>
|
|
144
|
+
|
|
145
|
+
export function Record<Key extends S.Record.Key, Value extends S.Top>(
|
|
146
|
+
key: Key,
|
|
147
|
+
value: Value
|
|
148
|
+
): S.$Record<Key, Value> {
|
|
149
|
+
return S.Record(key, value).annotate(concurrencyUnbounded)
|
|
150
|
+
}
|
|
151
|
+
export declare namespace Record {
|
|
152
|
+
export type Key = S.Record.Key
|
|
153
|
+
export type Type<K extends S.Record.Key, V extends S.Top> = S.Record.Type<K, V>
|
|
154
|
+
export type Encoded<K extends S.Record.Key, V extends S.Top> = S.Record.Encoded<K, V>
|
|
155
|
+
}
|
|
156
|
+
|
|
36
157
|
export const SpanId = Symbol()
|
|
37
158
|
export type SpanId = typeof SpanId
|
|
38
159
|
|
|
@@ -66,104 +187,141 @@ export const PhoneNumber = PhoneNumberT
|
|
|
66
187
|
|
|
67
188
|
export type PhoneNumber = PhoneNumberType
|
|
68
189
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
if (!SchemaAST.isObjects(t)) return acc
|
|
77
|
-
const tag = Array.findFirst(t.propertySignatures, (_: any) => {
|
|
78
|
-
if (_.name === "_tag" && SchemaAST.isLiteral(_.type)) {
|
|
79
|
-
return Option.some(_.type)
|
|
80
|
-
}
|
|
81
|
-
return Option.none()
|
|
82
|
-
})
|
|
83
|
-
const ast = Option.getOrUndefined(tag)
|
|
84
|
-
if (!ast) {
|
|
85
|
-
return acc
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
...acc,
|
|
89
|
-
[String((ast as SchemaAST.Literal).literal)]: (x: { _tag: string }) =>
|
|
90
|
-
x._tag === (ast as SchemaAST.Literal).literal
|
|
91
|
-
}
|
|
92
|
-
}, {} as Is<A>)
|
|
93
|
-
}
|
|
94
|
-
throw new Error("Unsupported")
|
|
190
|
+
// Copied from SchemaAST.collectSentinels (marked @internal in effect).
|
|
191
|
+
// Returns all { key, literal } pairs that can discriminate a union member.
|
|
192
|
+
const getTagFromAST = (schema: S.Top): string => {
|
|
193
|
+
const sentinels = collectSentinelsFromAST(schema.ast)
|
|
194
|
+
const sentinel = sentinels.find((s) => s.key === "_tag")
|
|
195
|
+
if (sentinel !== undefined && typeof sentinel.literal === "string") return sentinel.literal
|
|
196
|
+
throw new Error("No _tag literal found on schema member")
|
|
95
197
|
}
|
|
96
198
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
):
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
199
|
+
function collectSentinelsFromAST(
|
|
200
|
+
ast: SchemaAST.AST
|
|
201
|
+
): Array<{ key: PropertyKey; literal: SchemaAST.LiteralValue | symbol }> {
|
|
202
|
+
switch (ast._tag) {
|
|
203
|
+
case "Declaration": {
|
|
204
|
+
const s = ast.annotations?.["~sentinels"]
|
|
205
|
+
return Array.isArray(s) ? s : []
|
|
206
|
+
}
|
|
207
|
+
case "Objects":
|
|
208
|
+
return ast.propertySignatures.flatMap(
|
|
209
|
+
(ps): Array<{ key: PropertyKey; literal: SchemaAST.LiteralValue | symbol }> => {
|
|
210
|
+
const type = ps.type
|
|
211
|
+
if (!SchemaAST.isOptional(type)) {
|
|
212
|
+
if (SchemaAST.isLiteral(type)) return [{ key: ps.name, literal: type.literal }]
|
|
213
|
+
if (SchemaAST.isUniqueSymbol(type)) return [{ key: ps.name, literal: type.symbol }]
|
|
214
|
+
}
|
|
215
|
+
return []
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
case "Suspend":
|
|
219
|
+
return collectSentinelsFromAST(ast.thunk())
|
|
220
|
+
default:
|
|
221
|
+
return []
|
|
103
222
|
}
|
|
104
|
-
throw new Error("Unsupported")
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export type ExtractUnion<A extends { _tag: string }, Tags extends A["_tag"]> = Extract<A, Record<"_tag", Tags>>
|
|
108
|
-
export type Is<A extends { _tag: string }> = { [K in A as K["_tag"]]: (a: A) => a is K }
|
|
109
|
-
export type ElemType<A> = A extends Array<infer E> ? E : never
|
|
110
|
-
export interface IsAny<A extends { _tag: string }> {
|
|
111
|
-
<Keys extends A["_tag"][]>(...keys: Keys): (a: A) => a is ExtractUnion<A, ElemType<Keys>>
|
|
112
223
|
}
|
|
113
224
|
|
|
114
|
-
export const taggedUnionMap = <
|
|
115
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
|
-
Members extends readonly (S.Top & { fields: { _tag: S.tag<string> } })[]
|
|
117
|
-
>(
|
|
118
|
-
self: Members
|
|
119
|
-
) =>
|
|
120
|
-
self.reduce((acc, key) => {
|
|
121
|
-
// TODO: v4 migration — PropertySignatureDeclaration removed, need v4 AST traversal
|
|
122
|
-
const ast = key.fields._tag.ast as any
|
|
123
|
-
const tag = ((ast.type ?? ast) as SchemaAST.Literal).literal as string // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
124
|
-
acc[tag] = key as any
|
|
125
|
-
return acc
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
|
-
}, {} as any)
|
|
128
|
-
|
|
129
225
|
export const tags = <
|
|
130
|
-
|
|
131
|
-
Members extends NonEmptyReadonlyArray<(S.Top & { fields: { _tag: S.tag<string> } })>
|
|
226
|
+
Members extends NonEmptyReadonlyArray<(S.Top & { readonly Type: { readonly _tag: string } })>
|
|
132
227
|
>(
|
|
133
228
|
self: Members
|
|
134
229
|
) =>
|
|
135
|
-
S.Literals(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
230
|
+
S.Literals(
|
|
231
|
+
self.map(getTagFromAST) as {
|
|
232
|
+
[Index in keyof Members]: Members[Index]["Type"]["_tag"]
|
|
233
|
+
}
|
|
234
|
+
) as S.Literals<
|
|
235
|
+
{
|
|
236
|
+
[Index in keyof Members]: Members[Index]["Type"]["_tag"]
|
|
237
|
+
}
|
|
238
|
+
>
|
|
239
|
+
|
|
240
|
+
type TaggedUnionMembers = NonEmptyReadonlyArray<
|
|
241
|
+
S.Top & { readonly Type: { readonly _tag: string } }
|
|
242
|
+
>
|
|
243
|
+
|
|
244
|
+
type TaggedUnionTags<Members extends TaggedUnionMembers> = S.Literals<
|
|
245
|
+
{
|
|
246
|
+
[Index in keyof Members]: Members[Index]["Type"]["_tag"]
|
|
247
|
+
}
|
|
248
|
+
>
|
|
249
|
+
|
|
250
|
+
type TaggedPropertyKeys<A, Members extends TaggedUnionMembers> = {
|
|
251
|
+
[K in keyof A & string]: A[K] extends Members[number]["Type"] ? K : never
|
|
252
|
+
}[keyof A & string]
|
|
253
|
+
|
|
254
|
+
type PropertyGuardsFor<
|
|
255
|
+
Members extends TaggedUnionMembers,
|
|
256
|
+
K extends string,
|
|
257
|
+
A
|
|
258
|
+
> =
|
|
259
|
+
& {
|
|
260
|
+
readonly [M in Members[number] as `is${M["Type"]["_tag"]}`]: (
|
|
261
|
+
target: A
|
|
262
|
+
) => target is A & { readonly [P in K]: M["Type"] }
|
|
263
|
+
}
|
|
264
|
+
& {
|
|
265
|
+
readonly isAnyOf: <const Tags extends ReadonlyArray<Members[number]["Type"]["_tag"]>>(
|
|
266
|
+
tags: Tags
|
|
267
|
+
) => (
|
|
268
|
+
target: A
|
|
269
|
+
) => target is A & { readonly [P in K]: Extract<Members[number]["Type"], { readonly _tag: Tags[number] }> }
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type PropertyGuards<
|
|
273
|
+
Members extends TaggedUnionMembers,
|
|
274
|
+
K extends string
|
|
275
|
+
> =
|
|
276
|
+
& {
|
|
277
|
+
readonly [M in Members[number] as `is${M["Type"]["_tag"]}`]: <
|
|
278
|
+
T extends { readonly [P in K]: Members[number]["Type"] }
|
|
279
|
+
>(target: T) => target is T & { readonly [P in K]: M["Type"] }
|
|
280
|
+
}
|
|
281
|
+
& {
|
|
282
|
+
readonly isAnyOf: <const Tags extends ReadonlyArray<Members[number]["Type"]["_tag"]>>(
|
|
283
|
+
tags: Tags
|
|
284
|
+
) => <T extends { readonly [P in K]: Members[number]["Type"] }>(
|
|
285
|
+
target: T
|
|
286
|
+
) => target is T & { readonly [P in K]: Extract<Members[number]["Type"], { readonly _tag: Tags[number] }> }
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
type TaggedUnionWithTags<Members extends TaggedUnionMembers> = S.toTaggedUnion<"_tag", Members> & {
|
|
290
|
+
readonly tags: TaggedUnionTags<Members>
|
|
291
|
+
readonly generateGuards: <K extends string>(property: K) => PropertyGuards<Members, K>
|
|
292
|
+
readonly generateGuardsFor: <A>() => <K extends TaggedPropertyKeys<A, Members>>(
|
|
293
|
+
property: K
|
|
294
|
+
) => PropertyGuardsFor<Members, K, A>
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const extendTaggedUnionWithTags = <Members extends TaggedUnionMembers>(
|
|
298
|
+
schema: S.Union<Members>
|
|
299
|
+
): TaggedUnionWithTags<Members> =>
|
|
300
|
+
extendM(schema.pipe(S.toTaggedUnion("_tag")), (tagged) => {
|
|
301
|
+
const makeGuards = (property: string) => {
|
|
302
|
+
const result: any = {}
|
|
303
|
+
const guards: Record<string, (u: unknown) => boolean> = tagged.guards
|
|
304
|
+
for (const tag of Object.keys(guards)) {
|
|
305
|
+
const guard = guards[tag]!
|
|
306
|
+
result[`is${tag}`] = (target: any) => guard(target[property])
|
|
307
|
+
}
|
|
308
|
+
result.isAnyOf = (memberTags: Array<string>) => {
|
|
309
|
+
const check = tagged.isAnyOf(memberTags)
|
|
310
|
+
return (target: any) => check(target[property])
|
|
311
|
+
}
|
|
312
|
+
return result
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
tags: tags(schema.members),
|
|
316
|
+
generateGuards: makeGuards,
|
|
317
|
+
generateGuardsFor: () => makeGuards
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
export const ExtendTaggedUnion = <Members extends TaggedUnionMembers>(
|
|
322
|
+
schema: S.Union<Members>
|
|
323
|
+
): TaggedUnionWithTags<Members> => extendTaggedUnionWithTags(schema)
|
|
154
324
|
|
|
155
325
|
export const TaggedUnion = <
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
>(...a: Members) =>
|
|
159
|
-
pipe(
|
|
160
|
-
S.Union(a),
|
|
161
|
-
(_) =>
|
|
162
|
-
extendM(_, (_) => ({
|
|
163
|
-
is: S.is(_ as any),
|
|
164
|
-
isA: makeIs(_ as any),
|
|
165
|
-
isAnyOf: makeIsAnyOf(_ as any),
|
|
166
|
-
tagMap: taggedUnionMap(a),
|
|
167
|
-
tags: tags(a as any)
|
|
168
|
-
}))
|
|
169
|
-
)
|
|
326
|
+
Members extends TaggedUnionMembers
|
|
327
|
+
>(...a: Members): TaggedUnionWithTags<Members> => extendTaggedUnionWithTags(S.Union(a))
|