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/client/makeClient.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SchemaTransformation } from "effect"
|
|
1
2
|
import { type GetContextConfig, type GetEffectError, type RequestContextMapTagAny } from "../rpc/RpcContextMap.js"
|
|
2
3
|
import * as S from "../Schema.js"
|
|
3
4
|
import { AST } from "../Schema.js"
|
|
@@ -8,33 +9,46 @@ const merge = (a: any, b: Array<any>) =>
|
|
|
8
9
|
/**
|
|
9
10
|
* Whatever the input, we will only decode or encode to void
|
|
10
11
|
*/
|
|
11
|
-
const ForceVoid
|
|
12
|
+
export const ForceVoid = S
|
|
13
|
+
.declare((_: unknown): _ is unknown => true)
|
|
14
|
+
.pipe(
|
|
15
|
+
S.decodeTo(S.Any, SchemaTransformation.transform<unknown, unknown>({ decode: () => void 0, encode: () => void 0 }))
|
|
16
|
+
)
|
|
12
17
|
|
|
13
18
|
type SchemaOrFields<T> = T extends S.Top ? T : T extends S.Struct.Fields ? S.Struct<T> : S.Void
|
|
14
19
|
|
|
15
|
-
type
|
|
20
|
+
type TaggedRequestSchema<Tag extends string, Payload extends S.Struct.Fields> = S.Struct<
|
|
21
|
+
{ readonly _tag: S.tag<Tag> } & Payload
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
type TaggedRequestForResult<
|
|
25
|
+
Self,
|
|
16
26
|
Tag extends string,
|
|
17
27
|
Payload extends S.Struct.Fields,
|
|
18
28
|
Success extends S.Top,
|
|
19
29
|
Error extends S.Top,
|
|
20
|
-
Config
|
|
30
|
+
Config,
|
|
31
|
+
ModuleName extends string,
|
|
32
|
+
Type extends "command" | "query"
|
|
21
33
|
> =
|
|
22
|
-
& S.
|
|
34
|
+
& S.EnhancedClass<Self, TaggedRequestSchema<Tag, Payload>, {}>
|
|
23
35
|
& {
|
|
24
|
-
new(...args: any[]): any
|
|
25
36
|
readonly _tag: Tag
|
|
26
|
-
readonly fields: { readonly _tag: S.tag<Tag> } & Payload
|
|
27
37
|
readonly success: Success
|
|
28
38
|
readonly error: Error
|
|
29
39
|
readonly config: Config
|
|
30
40
|
readonly "~decodingServices": S.Codec.DecodingServices<Success> | S.Codec.DecodingServices<Error>
|
|
41
|
+
readonly "~encodingServices": S.Codec.EncodingServices<Success> | S.Codec.EncodingServices<Error>
|
|
42
|
+
readonly id: `${ModuleName}.${Tag}`
|
|
43
|
+
readonly moduleName: ModuleName
|
|
44
|
+
readonly type: Type
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
export const makeRpcClient = <
|
|
34
48
|
RequestContextMap extends RequestContextMapTagAny,
|
|
35
49
|
GeneralErrors extends S.Top = never
|
|
36
50
|
>(rcs: RequestContextMap, generalErrors?: GeneralErrors) => {
|
|
37
|
-
// Long way around
|
|
51
|
+
// Long way around Context/C extends etc to support actual jsdoc from passed in RequestConfig etc... (??)
|
|
38
52
|
type ServiceMap = {
|
|
39
53
|
success: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
|
|
40
54
|
error: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
|
|
@@ -47,64 +61,143 @@ export const makeRpcClient = <
|
|
|
47
61
|
: [GeneralErrors] extends [never] ? GetEffectError<RequestContextMap["config"], C>
|
|
48
62
|
: MergeError<GetEffectError<RequestContextMap["config"], C>>
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
config:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
64
|
+
// TODO: filter errors based on config + take care of inversion
|
|
65
|
+
const errorSchemas = Object.values(rcs.config).map((_) => _.error)
|
|
66
|
+
|
|
67
|
+
function makeRequestClass<Tag extends string, Fields extends S.Struct.Fields, C extends ServiceMap>(
|
|
68
|
+
tag: Tag,
|
|
69
|
+
fields: Fields,
|
|
70
|
+
config?: C
|
|
71
|
+
) {
|
|
72
|
+
const failureSchema = merge(
|
|
73
|
+
config?.error ? S.isSchema(config.error) ? config.error : S.Struct(config.error) : undefined,
|
|
74
|
+
[...errorSchemas, generalErrors].filter(Boolean)
|
|
75
|
+
)
|
|
76
|
+
const successSchema = config?.success
|
|
77
|
+
? S.isSchema(config.success)
|
|
78
|
+
? AST.isVoid(config.success.ast) ? ForceVoid : config.success
|
|
79
|
+
: S.Struct(config.success)
|
|
80
|
+
: ForceVoid
|
|
81
|
+
|
|
82
|
+
const RequestClass = S.TaggedClass<any>()(tag, fields)
|
|
83
|
+
Object.assign(RequestClass, {
|
|
84
|
+
_tag: tag,
|
|
85
|
+
success: successSchema,
|
|
86
|
+
error: failureSchema,
|
|
87
|
+
config
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
return RequestClass
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function makeTaggedRequestWithMeta<ModuleName extends string, Type extends "command" | "query">(
|
|
94
|
+
moduleName: ModuleName,
|
|
95
|
+
type: Type
|
|
96
|
+
) {
|
|
97
|
+
function TaggedRequestWithMeta<Self>(): {
|
|
98
|
+
<Tag extends string, Payload extends S.Struct.Fields, C extends ServiceMap>(
|
|
99
|
+
tag: Tag,
|
|
100
|
+
fields: Payload,
|
|
101
|
+
config: RequestConfig & C
|
|
102
|
+
): TaggedRequestForResult<
|
|
103
|
+
Self,
|
|
104
|
+
Tag,
|
|
105
|
+
Payload,
|
|
106
|
+
SchemaOrFields<C["success"]>,
|
|
107
|
+
ErrorResult<C>,
|
|
108
|
+
Omit<C, "success" | "error">,
|
|
109
|
+
ModuleName,
|
|
110
|
+
Type
|
|
111
|
+
>
|
|
112
|
+
<Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "success">>(
|
|
113
|
+
tag: Tag,
|
|
114
|
+
fields: Payload,
|
|
115
|
+
config: RequestConfig & C
|
|
116
|
+
): TaggedRequestForResult<
|
|
117
|
+
Self,
|
|
118
|
+
Tag,
|
|
119
|
+
Payload,
|
|
120
|
+
SchemaOrFields<C["success"]>,
|
|
121
|
+
ErrorResult<C>,
|
|
122
|
+
Omit<C, "success" | "error">,
|
|
123
|
+
ModuleName,
|
|
124
|
+
Type
|
|
125
|
+
>
|
|
126
|
+
<Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "error">>(
|
|
127
|
+
tag: Tag,
|
|
128
|
+
fields: Payload,
|
|
129
|
+
config: RequestConfig & C
|
|
130
|
+
): TaggedRequestForResult<
|
|
131
|
+
Self,
|
|
132
|
+
Tag,
|
|
133
|
+
Payload,
|
|
134
|
+
typeof ForceVoid,
|
|
135
|
+
ErrorResult<C>,
|
|
136
|
+
Omit<C, "success" | "error">,
|
|
137
|
+
ModuleName,
|
|
138
|
+
Type
|
|
139
|
+
>
|
|
140
|
+
<Tag extends string, Payload extends S.Struct.Fields, C extends Record<string, any>>(
|
|
141
|
+
tag: Tag,
|
|
142
|
+
fields: Payload,
|
|
143
|
+
config: C & RequestConfig
|
|
144
|
+
): TaggedRequestForResult<
|
|
145
|
+
Self,
|
|
146
|
+
Tag,
|
|
147
|
+
Payload,
|
|
148
|
+
typeof ForceVoid,
|
|
149
|
+
ErrorResult<C>,
|
|
150
|
+
Omit<C, "success" | "error">,
|
|
151
|
+
ModuleName,
|
|
152
|
+
Type
|
|
153
|
+
>
|
|
154
|
+
<Tag extends string, Payload extends S.Struct.Fields>(
|
|
155
|
+
tag: Tag,
|
|
156
|
+
fields: Payload
|
|
157
|
+
): TaggedRequestForResult<
|
|
158
|
+
Self,
|
|
159
|
+
Tag,
|
|
160
|
+
Payload,
|
|
161
|
+
typeof ForceVoid,
|
|
162
|
+
ErrorResult<{}>,
|
|
163
|
+
Record<string, never>,
|
|
164
|
+
ModuleName,
|
|
165
|
+
Type
|
|
166
|
+
>
|
|
167
|
+
} {
|
|
168
|
+
return (<Tag extends string, Fields extends S.Struct.Fields, C extends ServiceMap>(
|
|
169
|
+
tag: Tag,
|
|
170
|
+
fields: Fields,
|
|
171
|
+
config?: C
|
|
172
|
+
) => {
|
|
173
|
+
const cls = makeRequestClass(tag, fields, config)
|
|
174
|
+
Object.assign(cls, { id: `${moduleName}.${tag}`, moduleName, type })
|
|
175
|
+
return cls
|
|
176
|
+
}) as any
|
|
177
|
+
}
|
|
178
|
+
return Object.assign(TaggedRequestWithMeta, { moduleName, type } as const)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function TaggedRequestFor<ModuleName extends string>(moduleName: ModuleName) {
|
|
182
|
+
const Query = makeTaggedRequestWithMeta(moduleName, "query")
|
|
183
|
+
const Command = makeTaggedRequestWithMeta(moduleName, "command")
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
moduleName,
|
|
187
|
+
/**
|
|
188
|
+
* Create query request classes for this module.
|
|
189
|
+
* Queries read state and should not mutate server state.
|
|
190
|
+
*/
|
|
191
|
+
Query,
|
|
192
|
+
/**
|
|
193
|
+
* Create command request classes for this module.
|
|
194
|
+
* Commands mutate state and should avoid returning complex read models.
|
|
195
|
+
*/
|
|
196
|
+
Command
|
|
197
|
+
} as const
|
|
105
198
|
}
|
|
106
199
|
|
|
107
200
|
return {
|
|
108
|
-
|
|
201
|
+
TaggedRequestFor
|
|
109
202
|
}
|
|
110
203
|
}
|
package/src/http/Request.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Option } from "effect"
|
|
1
2
|
import type { HttpClientResponse } from "effect/unstable/http/HttpClientResponse"
|
|
2
3
|
import * as Effect from "../Effect.js"
|
|
3
4
|
import { HttpClient, HttpClientError, HttpClientRequest, HttpHeaders } from "./internal/lib.js"
|
|
@@ -24,16 +25,18 @@ export const demandJson = (client: HttpClient.HttpClient) =>
|
|
|
24
25
|
.mapRequest(client, (_) => HttpClientRequest.acceptJson(_))
|
|
25
26
|
.pipe(HttpClient.transform((r, request) =>
|
|
26
27
|
Effect.tap(r, (response) =>
|
|
27
|
-
|
|
28
|
-
.
|
|
29
|
-
|
|
28
|
+
Option
|
|
29
|
+
.exists(
|
|
30
|
+
HttpHeaders.get(response.headers, "Content-Type"),
|
|
31
|
+
(_) => _.startsWith("application/json")
|
|
32
|
+
)
|
|
30
33
|
? Effect.void
|
|
31
34
|
: Effect.fail(
|
|
32
35
|
new HttpClientError.DecodeError({
|
|
33
36
|
request,
|
|
34
37
|
response,
|
|
35
38
|
description: "not json response: "
|
|
36
|
-
+ HttpHeaders.get(response.headers, "Content-Type")
|
|
39
|
+
+ Option.getOrElse(HttpHeaders.get(response.headers, "Content-Type"), () => "<missing>")
|
|
37
40
|
})
|
|
38
41
|
))
|
|
39
42
|
))
|
package/src/ids.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Effect } from "effect"
|
|
1
2
|
import { brandedStringId, type Codec, NonEmptyString255, StringId, type StringIdBrand, withDefaultMake } from "effect-app/Schema"
|
|
2
3
|
import type { B } from "effect-app/Schema/schema"
|
|
3
4
|
import type { Simplify } from "effect/Types"
|
|
@@ -17,7 +18,7 @@ export const RequestId = extendM(
|
|
|
17
18
|
const make = StringId.make as () => NonEmptyString255
|
|
18
19
|
return ({
|
|
19
20
|
make,
|
|
20
|
-
withDefault:
|
|
21
|
+
withDefault: S.withConstructorDefault(Effect.sync(make))(s as typeof s & S.WithoutConstructorDefault)
|
|
21
22
|
})
|
|
22
23
|
}
|
|
23
24
|
)
|
package/src/index.ts
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-unassigned-import
|
|
1
2
|
import "./builtin.js"
|
|
2
3
|
|
|
3
|
-
import * as ServiceMap from "./ServiceMap.js"
|
|
4
|
-
|
|
5
4
|
export * as Fnc from "./Function.js"
|
|
6
5
|
export * as Utils from "./utils.js"
|
|
7
6
|
|
|
8
7
|
export * as Array from "./Array.js"
|
|
8
|
+
export * as Config from "./Config.js"
|
|
9
|
+
export * as ConfigProvider from "./ConfigProvider.js"
|
|
10
|
+
export * as Context from "./Context.js"
|
|
9
11
|
export * as Effect from "./Effect.js"
|
|
10
12
|
export * as Layer from "./Layer.js"
|
|
11
13
|
export * as NonEmptySet from "./NonEmptySet.js"
|
|
12
|
-
export * as ServiceMap from "./ServiceMap.js"
|
|
13
14
|
export * as Set from "./Set.js"
|
|
14
15
|
|
|
15
|
-
export {
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated use ServiceMap directly instead
|
|
18
|
-
*/
|
|
19
|
-
ServiceMap as Context
|
|
20
|
-
}
|
|
21
|
-
|
|
22
16
|
export { type NonEmptyArray, type NonEmptyReadonlyArray } from "./Array.js"
|
|
23
17
|
|
|
24
18
|
export * from "effect"
|
|
@@ -26,5 +20,6 @@ export * from "effect"
|
|
|
26
20
|
export type * as Types from "./Types.js"
|
|
27
21
|
|
|
28
22
|
export * as SecretURL from "./Config/SecretURL.js"
|
|
23
|
+
export * as RpcX from "./rpc.js"
|
|
29
24
|
export * as S from "./Schema.js"
|
|
30
25
|
export { copy } from "./utils.js"
|
package/src/middleware.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Context } from "effect-app"
|
|
3
|
+
import { RpcMiddleware } from "./rpc.js"
|
|
4
4
|
|
|
5
|
-
export class DevMode extends
|
|
5
|
+
export class DevMode extends Context.Reference("DevMode", { defaultValue: () => false }) {}
|
|
6
6
|
|
|
7
|
-
export class RequestCacheMiddleware
|
|
8
|
-
extends RpcX.RpcMiddleware.Tag<RequestCacheMiddleware>()("RequestCacheMiddleware")
|
|
9
|
-
{}
|
|
7
|
+
export class RequestCacheMiddleware extends RpcMiddleware.Tag<RequestCacheMiddleware>()("RequestCacheMiddleware") {}
|
|
10
8
|
|
|
11
9
|
export class ConfigureInterruptibilityMiddleware
|
|
12
|
-
extends
|
|
10
|
+
extends RpcMiddleware.Tag<ConfigureInterruptibilityMiddleware>()("ConfigureInterruptibilityMiddleware")
|
|
13
11
|
{}
|
|
14
12
|
|
|
15
|
-
export class LoggerMiddleware extends
|
|
13
|
+
export class LoggerMiddleware extends RpcMiddleware.Tag<LoggerMiddleware>()("LoggerMiddleware") {}
|
|
16
14
|
|
|
17
|
-
export class DevModeMiddleware extends
|
|
15
|
+
export class DevModeMiddleware extends RpcMiddleware.Tag<DevModeMiddleware>()("DevModeMiddleware") {}
|
|
18
16
|
|
|
19
17
|
export const DefaultGenericMiddlewares = [
|
|
20
18
|
RequestCacheMiddleware,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Effect, Layer, type Schema, Schema as S, type Scope
|
|
2
|
+
import { Effect, Layer, type Schema, Schema as S, type Scope } from "effect"
|
|
3
3
|
import { type NonEmptyArray, type NonEmptyReadonlyArray } from "effect/Array"
|
|
4
4
|
import { type Simplify } from "effect/Types"
|
|
5
5
|
import { Rpc, type RpcGroup, type RpcSchema } from "effect/unstable/rpc"
|
|
6
6
|
import { type HandlersFrom } from "effect/unstable/rpc/RpcGroup"
|
|
7
|
-
import
|
|
8
|
-
import { type HttpHeaders } from "../http.js"
|
|
7
|
+
import * as Context from "../Context.js"
|
|
9
8
|
import { PreludeLogger } from "../logger.js"
|
|
10
9
|
import { type TypeTestId } from "../TypeTest.js"
|
|
11
10
|
import { typedValuesOf } from "../utils.js"
|
|
@@ -61,13 +60,13 @@ export interface MiddlewareMaker<
|
|
|
61
60
|
}
|
|
62
61
|
>
|
|
63
62
|
{
|
|
64
|
-
readonly layer: Layer.Layer<Self, never,
|
|
63
|
+
readonly layer: Layer.Layer<Self, never, Context.Service.Identifier<MiddlewareProviders[number]>>
|
|
65
64
|
readonly requestContext: RequestContextTag<RequestContextMap>
|
|
66
65
|
readonly requestContextMap: RequestContextMap
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
export interface RequestContextTag<RequestContextMap extends Record<string, RpcContextMap.Any>>
|
|
70
|
-
extends
|
|
69
|
+
extends Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>
|
|
71
70
|
{}
|
|
72
71
|
|
|
73
72
|
export namespace MiddlewareMaker {
|
|
@@ -258,10 +257,10 @@ export type MiddlewaresBuilder<
|
|
|
258
257
|
: { new(_: never): {} }
|
|
259
258
|
: { new(_: never): {} })
|
|
260
259
|
|
|
261
|
-
const middlewareMaker =
|
|
260
|
+
const middlewareMaker = Effect.fnUntraced(function*<
|
|
262
261
|
MiddlewareProviders extends ReadonlyArray<MiddlewareMaker.Any>
|
|
263
|
-
>(middlewares: MiddlewareProviders)
|
|
264
|
-
RpcMiddlewareV4<
|
|
262
|
+
>(middlewares: MiddlewareProviders) {
|
|
263
|
+
type Middleware = RpcMiddlewareV4<
|
|
265
264
|
MiddlewareMaker.ManyProvided<MiddlewareProviders>,
|
|
266
265
|
MiddlewareMaker.ManyErrors<MiddlewareProviders>,
|
|
267
266
|
Exclude<
|
|
@@ -270,42 +269,32 @@ const middlewareMaker = <
|
|
|
270
269
|
> extends never ? never
|
|
271
270
|
: Exclude<MiddlewareMaker.ManyRequired<MiddlewareProviders>, MiddlewareMaker.ManyProvided<MiddlewareProviders>>
|
|
272
271
|
>
|
|
273
|
-
|
|
272
|
+
type Next = Parameters<Middleware>[0]
|
|
273
|
+
type Options = Parameters<Middleware>[1]
|
|
274
|
+
|
|
274
275
|
// we want to run them in reverse order because latter middlewares will provide context to former ones
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
let handler = next
|
|
294
|
-
|
|
295
|
-
// inspired from Effect/RpcMiddleware
|
|
296
|
-
for (const tag of middlewares) {
|
|
297
|
-
// use the tag to get the middleware from context
|
|
298
|
-
const middleware = ServiceMap.getUnsafe(context, tag)
|
|
299
|
-
|
|
300
|
-
// wrap the current handler, allowing the middleware to run before and after it
|
|
301
|
-
handler = PreludeLogger.logDebug("Applying middleware wrap " + tag.key).pipe(
|
|
302
|
-
Effect.andThen(middleware(handler, options))
|
|
303
|
-
) as any
|
|
304
|
-
}
|
|
305
|
-
return handler
|
|
276
|
+
const reversed = middlewares.toReversed()
|
|
277
|
+
const context = yield* Effect.context()
|
|
278
|
+
|
|
279
|
+
// returns a Effect/RpcMiddlewareV4 with Scope.Scope in requirements
|
|
280
|
+
// v4: wrap middleware takes (effect, options) as two params instead of a single options bag
|
|
281
|
+
return (next: Next, options: Options) => {
|
|
282
|
+
// we start with the actual handler
|
|
283
|
+
let handler = next
|
|
284
|
+
|
|
285
|
+
// inspired from Effect/RpcMiddleware
|
|
286
|
+
for (const tag of reversed) {
|
|
287
|
+
// use the tag to get the middleware from context
|
|
288
|
+
const middleware = Context.getUnsafe(context, tag)
|
|
289
|
+
|
|
290
|
+
// wrap the current handler, allowing the middleware to run before and after it
|
|
291
|
+
handler = PreludeLogger.logDebug("Applying middleware wrap " + tag.key).pipe(
|
|
292
|
+
Effect.andThen(middleware(handler, options))
|
|
293
|
+
) as any
|
|
306
294
|
}
|
|
307
|
-
|
|
308
|
-
}
|
|
295
|
+
return handler
|
|
296
|
+
}
|
|
297
|
+
})
|
|
309
298
|
|
|
310
299
|
const makeMiddlewareBasic = <Self>() =>
|
|
311
300
|
// by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
|
|
@@ -321,7 +310,7 @@ const makeMiddlewareBasic = <Self>() =>
|
|
|
321
310
|
// reverse middlewares and wrap one after the other
|
|
322
311
|
const middleware = middlewareMaker(make)
|
|
323
312
|
|
|
324
|
-
const failures = make.
|
|
313
|
+
const failures = make.flatMap((_) => _.error ? [_.error] : [])
|
|
325
314
|
const provides = make.flatMap((_) => !_.provides ? [] : Array.isArray(_.provides) ? _.provides : [_.provides])
|
|
326
315
|
const requires = make
|
|
327
316
|
.flatMap((_) => !_.requires ? [] : Array.isArray(_.requires) ? _.requires : [_.requires])
|
|
@@ -367,7 +356,7 @@ const makeMiddlewareBasic = <Self>() =>
|
|
|
367
356
|
return Object.assign(MiddlewareMaker, {
|
|
368
357
|
layer,
|
|
369
358
|
// tag to be used to retrieve the RequestContextConfig from Rpc annotations
|
|
370
|
-
requestContext:
|
|
359
|
+
requestContext: Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>(
|
|
371
360
|
"RequestContextConfig"
|
|
372
361
|
),
|
|
373
362
|
requestContextMap: rcm
|
|
@@ -379,8 +368,8 @@ export const Tag = <Self>() =>
|
|
|
379
368
|
const Id extends string,
|
|
380
369
|
RequestContextMap extends RequestContextMapTagAny
|
|
381
370
|
>(id: Id, rcm: RequestContextMap): MiddlewaresBuilder<Self, Id, RequestContextMap["config"]> => {
|
|
382
|
-
|
|
383
|
-
const requestContext =
|
|
371
|
+
const allMiddleware: MiddlewareMaker.Any[] = []
|
|
372
|
+
const requestContext = Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap["config"]>>(
|
|
384
373
|
"RequestContextConfig"
|
|
385
374
|
)
|
|
386
375
|
const it = {
|
|
@@ -437,7 +426,7 @@ export const Tag = <Self>() =>
|
|
|
437
426
|
middleware: (...middlewares: any[]) => {
|
|
438
427
|
for (const mw of middlewares) {
|
|
439
428
|
// recall that we run middlewares in reverse order
|
|
440
|
-
allMiddleware
|
|
429
|
+
allMiddleware.unshift(mw)
|
|
441
430
|
}
|
|
442
431
|
return allMiddleware.filter((m) => !!m.dynamic).length !== Object.keys(rcm.config).length
|
|
443
432
|
// for sure, until all the dynamic middlewares are provided it's non sensical to call makeMiddlewareBasic
|
package/src/rpc/RpcContextMap.ts
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
4
|
|
|
5
|
-
import { type Schema as S
|
|
5
|
+
import { type Schema as S } from "effect"
|
|
6
6
|
import { type AnyWithProps } from "effect/unstable/rpc/Rpc"
|
|
7
|
+
import * as Context from "../Context.js"
|
|
7
8
|
import { type RpcDynamic } from "./RpcMiddleware.js"
|
|
8
9
|
|
|
9
10
|
type Values<T extends Record<any, any>> = T[keyof T]
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
* Middleware is inactivate by default, the Key is optional in route context, and the service is optionally provided as Effect
|
|
13
|
+
* Middleware is inactivate by default, the Key is optional in route context, and the service is optionally provided as Effect Context.
|
|
13
14
|
* Unless explicitly configured as `true`.
|
|
14
15
|
*/
|
|
15
16
|
export type RpcContextMap<Service, E> = {
|
|
@@ -22,7 +23,7 @@ export type RpcContextMap<Service, E> = {
|
|
|
22
23
|
|
|
23
24
|
export declare namespace RpcContextMap {
|
|
24
25
|
/**
|
|
25
|
-
* Middleware is active by default, and provides the Service at Key in route context, and the Service is provided as Effect
|
|
26
|
+
* Middleware is active by default, and provides the Service at Key in route context, and the Service is provided as Effect Context.
|
|
26
27
|
* Unless explicitly omitted.
|
|
27
28
|
*/
|
|
28
29
|
export type Inverted<Service, E> = {
|
|
@@ -97,7 +98,7 @@ export type GetEffectError<RequestContextMap extends Record<string, RpcContextMa
|
|
|
97
98
|
}
|
|
98
99
|
>
|
|
99
100
|
|
|
100
|
-
const tag =
|
|
101
|
+
const tag = Context.Service("RequestContextConfig")
|
|
101
102
|
|
|
102
103
|
export const makeMap = <const Config extends Record<string, RpcContextMap.Any>>(config: Config) => {
|
|
103
104
|
const cls = class {
|
|
@@ -109,7 +110,7 @@ export const makeMap = <const Config extends Record<string, RpcContextMap.Any>>(
|
|
|
109
110
|
return Object.assign(cls, {
|
|
110
111
|
config, /** Retrieves RequestContextConfig out of the Rpc annotations */
|
|
111
112
|
getConfig: (rpc: AnyWithProps): GetContextConfig<Config> => {
|
|
112
|
-
return
|
|
113
|
+
return Context.getOrElse(rpc.annotations, tag as any, () => ({}))
|
|
113
114
|
},
|
|
114
115
|
/** Adapter used when setting the dynamic prop on a middleware implementation */
|
|
115
116
|
get: <
|
package/src/rpc/RpcMiddleware.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
|
-
import { type Effect, type Schema, type Schema as S, type Scope, type
|
|
4
|
+
import { type Effect, type Schema, type Schema as S, type Scope, type Stream } from "effect"
|
|
5
5
|
import { type NonEmptyReadonlyArray } from "effect/Array"
|
|
6
6
|
import { type Rpc, RpcMiddleware } from "effect/unstable/rpc"
|
|
7
7
|
import { type TypeId } from "effect/unstable/rpc/RpcMiddleware"
|
|
8
|
+
import type * as Context from "../Context.js"
|
|
8
9
|
import { type GetEffectContext, type RpcContextMap } from "./RpcContextMap.js"
|
|
9
10
|
|
|
10
11
|
export type RpcMiddlewareV4<Provides, E, Requires> = RpcMiddleware.RpcMiddleware<Provides, E, Requires>
|
|
@@ -102,8 +103,8 @@ export declare namespace TagClass {
|
|
|
102
103
|
requires?: any
|
|
103
104
|
provides?: any
|
|
104
105
|
}
|
|
105
|
-
> extends
|
|
106
|
-
new(_: never):
|
|
106
|
+
> extends Context.Service<Self, Service> {
|
|
107
|
+
new(_: never): Context.ServiceClass.Shape<Name, Service>
|
|
107
108
|
readonly [TypeId]: TypeId
|
|
108
109
|
readonly optional: Optional<Options>
|
|
109
110
|
readonly error: FailureSchema<Options>
|
|
@@ -226,7 +227,7 @@ export type ExtractProvides<R extends Rpc.Any, Tag extends string> = R extends
|
|
|
226
227
|
Rpc.Rpc<Tag, infer _Payload, infer _Success, infer _Error, infer _Middleware, infer _Requires> ? _Middleware extends {
|
|
227
228
|
readonly provides: infer _P
|
|
228
229
|
} ? [_P] extends [never] ? never
|
|
229
|
-
: _P /*_P extends
|
|
230
|
+
: _P /*_P extends Context.Service<infer _I, infer _S> ? _I
|
|
230
231
|
: never */
|
|
231
232
|
: never
|
|
232
233
|
: never
|
package/src/rpc.ts
CHANGED
package/src/transform.ts
CHANGED
|
@@ -51,8 +51,8 @@ const encodeOptsAsNullable_ = (value: any, cacheMap: Map<any, any>): any => {
|
|
|
51
51
|
|
|
52
52
|
if (
|
|
53
53
|
value instanceof Date
|
|
54
|
-
|| value
|
|
55
|
-
|| value
|
|
54
|
+
|| typeof value === "function"
|
|
55
|
+
|| (typeof value === "object" && value !== null && "then" in value && typeof value.then === "function")
|
|
56
56
|
) {
|
|
57
57
|
return value
|
|
58
58
|
}
|
package/src/utils/gen.ts
CHANGED
|
@@ -15,7 +15,7 @@ export namespace EffectGenUtils {
|
|
|
15
15
|
: EG extends (..._: infer _3) => Generator<Yieldable<any, infer _, infer E, infer _R>, infer _A, infer _2> ? E
|
|
16
16
|
: never
|
|
17
17
|
|
|
18
|
-
export type
|
|
18
|
+
export type Context<EG> = EG extends Effect<infer _A, infer _E, infer R> ? R
|
|
19
19
|
// there could be a case where the generator function does not yield anything, so we need to handle that
|
|
20
20
|
: EG extends (..._: infer _3) => Generator<never, infer _A, infer _2> ? never
|
|
21
21
|
// v4: generators can yield Yieldable (Effect, Service, etc.), all have asEffect()
|
package/src/utils/logger.ts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
|
|
4
4
|
import { Effect, type LogLevel } from "effect"
|
|
5
|
-
import * as
|
|
5
|
+
import * as Context from "../Context.js"
|
|
6
6
|
|
|
7
7
|
type Levels = "info" | "debug" | "warn" | "error"
|
|
8
8
|
|
|
9
|
-
export class LogLevels extends
|
|
9
|
+
export class LogLevels extends Context.Reference("LogLevels", {
|
|
10
10
|
defaultValue: () => new Map<string, Levels>()
|
|
11
11
|
}) {}
|
|
12
12
|
|