@effect-app/infra 2.88.0 → 2.89.1
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 +17 -0
- package/dist/api/{routing/middleware/ContextProvider.d.ts → ContextProvider.d.ts} +1 -1
- package/dist/api/ContextProvider.d.ts.map +1 -0
- package/dist/api/ContextProvider.js +38 -0
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +15 -10
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.js +2 -5
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +6 -10
- package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RpcMiddleware.js +1 -1
- package/dist/api/routing/middleware/generic-middleware.d.ts +19 -17
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +2 -2
- package/dist/api/routing/middleware/middleware-api.d.ts +31 -27
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +31 -40
- package/dist/api/routing/middleware.d.ts +0 -1
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +1 -2
- package/dist/api/routing.d.ts +1 -1
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +12 -10
- package/package.json +6 -6
- package/src/api/{routing/middleware/ContextProvider.ts → ContextProvider.ts} +1 -1
- package/src/api/routing/middleware/RouterMiddleware.ts +22 -56
- package/src/api/routing/middleware/RpcMiddleware.ts +15 -11
- package/src/api/routing/middleware/generic-middleware.ts +44 -26
- package/src/api/routing/middleware/middleware-api.ts +91 -111
- package/src/api/routing/middleware.ts +0 -1
- package/src/api/routing.ts +22 -20
- package/test/contextProvider.test.ts +1 -1
- package/test/controller.test.ts +3 -4
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +2 -2
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +7 -6
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/fixtures.ts +7 -5
- package/test/requires.test.ts +43 -22
- package/dist/api/routing/middleware/ContextProvider.d.ts.map +0 -1
- package/dist/api/routing/middleware/ContextProvider.js +0 -38
|
@@ -1,38 +1,41 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { type
|
|
3
|
-
import { type
|
|
4
|
-
import { type Array, Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type Scope } from "effect-app"
|
|
2
|
+
import { type RpcMiddleware } from "@effect/rpc"
|
|
3
|
+
import { Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type S, type Scope } from "effect-app"
|
|
5
4
|
import { type ContextTagArray } from "effect-app/client"
|
|
6
|
-
import { type HttpHeaders } from "effect-app/http"
|
|
7
5
|
import { InfraLogger } from "../../../logger.js"
|
|
8
|
-
import { type TagClassAny } from "./RpcMiddleware.js"
|
|
6
|
+
import { type RpcMiddlewareWrap, type TagClassAny } from "./RpcMiddleware.js"
|
|
9
7
|
|
|
10
8
|
// Effect rpc middleware does not support changing payload or headers, but we do..
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
export interface GenericMiddlewareOptions<E> {
|
|
14
|
-
readonly clientId: number
|
|
15
|
-
readonly rpc: Rpc.AnyWithProps
|
|
16
|
-
readonly payload: unknown
|
|
17
|
-
readonly headers: HttpHeaders.Headers
|
|
18
|
-
readonly next: Effect.Effect<SuccessValue, E, Scope.Scope>
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type GenericMiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
|
|
10
|
+
export type MiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
|
|
22
11
|
|
|
23
|
-
export namespace
|
|
12
|
+
export namespace MiddlewareMaker {
|
|
24
13
|
export type ApplyServices<A extends TagClassAny, R> = Exclude<R, Provided<A>> | Required<A>
|
|
25
14
|
|
|
26
15
|
export type ApplyManyServices<A extends NonEmptyReadonlyArray<TagClassAny>, R> =
|
|
27
16
|
| Exclude<R, { [K in keyof A]: Provided<A[K]> }[number]>
|
|
28
17
|
| { [K in keyof A]: Required<A[K]> }[number]
|
|
29
18
|
|
|
19
|
+
export type ManyProvided<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
|
|
20
|
+
? { [K in keyof A]: Provided<A[K]> }[number]
|
|
21
|
+
: Provided<A[number]>
|
|
22
|
+
export type ManyRequired<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
|
|
23
|
+
? { [K in keyof A]: Required<A[K]> }[number]
|
|
24
|
+
: Required<A[number]>
|
|
25
|
+
export type ManyErrors<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
|
|
26
|
+
? { [K in keyof A]: Errors<A[K]> }[number]
|
|
27
|
+
: Errors<A[number]>
|
|
28
|
+
|
|
30
29
|
export type Provided<T> = T extends TagClassAny
|
|
31
30
|
? T extends { provides: Context.Tag<any, any> } ? Context.Tag.Identifier<T["provides"]>
|
|
32
31
|
: T extends { provides: ContextTagArray } ? ContextTagArray.Identifier<T["provides"]>
|
|
33
32
|
: never
|
|
34
33
|
: never
|
|
35
34
|
|
|
35
|
+
export type Errors<T> = T extends TagClassAny ? T extends { failure: S.Schema.Any } ? S.Schema.Type<T["failure"]>
|
|
36
|
+
: never
|
|
37
|
+
: never
|
|
38
|
+
|
|
36
39
|
export type Required<T> = T extends TagClassAny
|
|
37
40
|
? T extends { requires: Context.Tag<any, any> } ? Context.Tag.Identifier<T["requires"]>
|
|
38
41
|
: T extends { requires: ContextTagArray } ? ContextTagArray.Identifier<T["requires"]>
|
|
@@ -40,11 +43,21 @@ export namespace GenericMiddlewareMaker {
|
|
|
40
43
|
: never
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
export const
|
|
44
|
-
|
|
45
|
-
>(
|
|
46
|
-
dependencies: { [K in keyof
|
|
47
|
-
effect: Effect.Effect<
|
|
46
|
+
export const middlewareMaker = <
|
|
47
|
+
MiddlewareProviders extends ReadonlyArray<MiddlewareMaker>
|
|
48
|
+
>(middlewares: MiddlewareProviders): {
|
|
49
|
+
dependencies: { [K in keyof MiddlewareProviders]: MiddlewareProviders[K]["Default"] }
|
|
50
|
+
effect: Effect.Effect<
|
|
51
|
+
RpcMiddlewareWrap<
|
|
52
|
+
MiddlewareMaker.ManyProvided<MiddlewareProviders>,
|
|
53
|
+
MiddlewareMaker.ManyErrors<MiddlewareProviders>,
|
|
54
|
+
Exclude<
|
|
55
|
+
MiddlewareMaker.ManyRequired<MiddlewareProviders>,
|
|
56
|
+
MiddlewareMaker.ManyProvided<MiddlewareProviders>
|
|
57
|
+
> extends never ? never
|
|
58
|
+
: Exclude<MiddlewareMaker.ManyRequired<MiddlewareProviders>, MiddlewareMaker.ManyProvided<MiddlewareProviders>>
|
|
59
|
+
>
|
|
60
|
+
>
|
|
48
61
|
} => {
|
|
49
62
|
// we want to run them in reverse order because latter middlewares will provide context to former ones
|
|
50
63
|
middlewares = middlewares.toReversed() as any
|
|
@@ -55,8 +68,14 @@ export const genericMiddlewareMaker = <
|
|
|
55
68
|
const context = yield* Effect.context()
|
|
56
69
|
|
|
57
70
|
// returns a Effect/RpcMiddlewareWrap with Scope in requirements
|
|
58
|
-
return
|
|
59
|
-
options:
|
|
71
|
+
return (
|
|
72
|
+
options: Parameters<
|
|
73
|
+
RpcMiddlewareWrap<
|
|
74
|
+
MiddlewareMaker.ManyProvided<MiddlewareProviders>,
|
|
75
|
+
never,
|
|
76
|
+
Scope.Scope
|
|
77
|
+
>
|
|
78
|
+
>[0]
|
|
60
79
|
) => {
|
|
61
80
|
// we start with the actual handler
|
|
62
81
|
let handler = options.next
|
|
@@ -113,7 +132,7 @@ export const genericMiddlewareMaker = <
|
|
|
113
132
|
)
|
|
114
133
|
)
|
|
115
134
|
)
|
|
116
|
-
)
|
|
135
|
+
) as any
|
|
117
136
|
} else {
|
|
118
137
|
// use the tag to get the middleware from context
|
|
119
138
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
@@ -134,10 +153,9 @@ export const genericMiddlewareMaker = <
|
|
|
134
153
|
)
|
|
135
154
|
: Effect.zipRight(middleware(options), previous)
|
|
136
155
|
)
|
|
137
|
-
)
|
|
156
|
+
) as any
|
|
138
157
|
}
|
|
139
158
|
}
|
|
140
|
-
|
|
141
159
|
return handler
|
|
142
160
|
}
|
|
143
161
|
})
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { type
|
|
4
|
-
import { type
|
|
5
|
-
import { type
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// adapter used when setting the dynamic prop on a middleware implementation
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { type AnyWithProps } from "@effect/rpc/Rpc"
|
|
3
|
+
import { Context, type Effect, type NonEmptyArray, type NonEmptyReadonlyArray, S } from "effect-app"
|
|
4
|
+
import { type GetContextConfig, type RPCContextMap } from "effect-app/client"
|
|
5
|
+
import { type MiddlewareMaker, middlewareMaker } from "./generic-middleware.js"
|
|
6
|
+
import { type AnyDynamic, type RpcDynamic, Tag, type TagClassAny } from "./RpcMiddleware.js"
|
|
7
|
+
|
|
8
|
+
/** Adapter used when setting the dynamic prop on a middleware implementation */
|
|
10
9
|
export const contextMap = <
|
|
11
10
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
12
11
|
Key extends (keyof RequestContextMap) & string
|
|
@@ -15,19 +14,26 @@ export const contextMap = <
|
|
|
15
14
|
settings: { service: rcm[key]!["service"] } as RequestContextMap[Key]
|
|
16
15
|
})
|
|
17
16
|
|
|
17
|
+
/** Retrieves RequestContextConfig out of the RPC annotations */
|
|
18
|
+
export const getConfig = <
|
|
19
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
20
|
+
>() =>
|
|
21
|
+
(rpc: AnyWithProps): GetContextConfig<RequestContextMap> => {
|
|
22
|
+
return Context.unsafeGet(rpc.annotations, Context.GenericTag("RequestContextConfig"))
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
// the following implements sort of builder pattern
|
|
19
26
|
// we support both sideways and upwards elimination of dependencies
|
|
20
27
|
|
|
21
28
|
// it's for dynamic middlewares
|
|
22
|
-
type GetDependsOnKeys<MW extends
|
|
23
|
-
? {
|
|
29
|
+
type GetDependsOnKeys<MW extends MiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> } ? {
|
|
24
30
|
[K in keyof MW["dependsOn"]]: MW["dependsOn"][K] extends AnyDynamic ? MW["dependsOn"][K]["dynamic"]["key"]
|
|
25
31
|
: never
|
|
26
32
|
}[keyof MW["dependsOn"]]
|
|
27
33
|
: never
|
|
28
34
|
|
|
29
35
|
type FilterInDynamicMiddlewares<
|
|
30
|
-
MWs extends ReadonlyArray<
|
|
36
|
+
MWs extends ReadonlyArray<MiddlewareMaker>,
|
|
31
37
|
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
32
38
|
> = {
|
|
33
39
|
[K in keyof MWs]: MWs[K] extends { dynamic: RpcDynamic<any, RequestContextMap[keyof RequestContextMap]> } ? MWs[K]
|
|
@@ -39,13 +45,13 @@ type RecursiveHandleMWsSideways<
|
|
|
39
45
|
R extends {
|
|
40
46
|
rcm: Record<string, RPCContextMap.Any>
|
|
41
47
|
provided: keyof R["rcm"] // that's fine
|
|
42
|
-
middlewares: ReadonlyArray<
|
|
48
|
+
middlewares: ReadonlyArray<MiddlewareMaker>
|
|
43
49
|
dmp: any
|
|
44
50
|
middlewareR: any
|
|
45
51
|
}
|
|
46
52
|
> = MWs extends [
|
|
47
|
-
infer F extends
|
|
48
|
-
...infer Rest extends ReadonlyArray<
|
|
53
|
+
infer F extends MiddlewareMaker,
|
|
54
|
+
...infer Rest extends ReadonlyArray<MiddlewareMaker>
|
|
49
55
|
] ? RecursiveHandleMWsSideways<Rest, {
|
|
50
56
|
rcm: R["rcm"]
|
|
51
57
|
// when one dynamic middleware depends on another, subtract the key to enforce the dependency to be provided after
|
|
@@ -62,18 +68,18 @@ type RecursiveHandleMWsSideways<
|
|
|
62
68
|
& {
|
|
63
69
|
[U in FilterInDynamicMiddlewares<[F], R["rcm"]>[number] as U["dynamic"]["key"]]: U
|
|
64
70
|
}
|
|
65
|
-
middlewareR:
|
|
71
|
+
middlewareR: MiddlewareMaker.ApplyManyServices<[F], R["middlewareR"]>
|
|
66
72
|
}>
|
|
67
73
|
: R
|
|
68
74
|
|
|
69
75
|
export interface BuildingMiddleware<
|
|
70
76
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
71
77
|
Provided extends keyof RequestContextMap,
|
|
72
|
-
Middlewares extends ReadonlyArray<
|
|
78
|
+
Middlewares extends ReadonlyArray<MiddlewareMaker>,
|
|
73
79
|
DynamicMiddlewareProviders,
|
|
74
80
|
out MiddlewareR extends { _tag: string } = never
|
|
75
81
|
> {
|
|
76
|
-
middleware<MWs extends NonEmptyArray<
|
|
82
|
+
middleware<MWs extends NonEmptyArray<MiddlewareMaker>>(
|
|
77
83
|
...mw: MWs
|
|
78
84
|
): RecursiveHandleMWsSideways<MWs, {
|
|
79
85
|
rcm: RequestContextMap
|
|
@@ -84,7 +90,7 @@ export interface BuildingMiddleware<
|
|
|
84
90
|
}> extends infer Res extends {
|
|
85
91
|
rcm: RequestContextMap
|
|
86
92
|
provided: keyof RequestContextMap
|
|
87
|
-
middlewares: ReadonlyArray<
|
|
93
|
+
middlewares: ReadonlyArray<MiddlewareMaker>
|
|
88
94
|
dmp: any
|
|
89
95
|
middlewareR: any
|
|
90
96
|
} ? MiddlewaresBuilder<
|
|
@@ -106,37 +112,32 @@ export interface BuildingMiddleware<
|
|
|
106
112
|
export type MiddlewaresBuilder<
|
|
107
113
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
108
114
|
Provided extends keyof RequestContextMap = never,
|
|
109
|
-
Middlewares extends ReadonlyArray<
|
|
115
|
+
Middlewares extends ReadonlyArray<MiddlewareMaker> = [],
|
|
110
116
|
DynamicMiddlewareProviders = unknown,
|
|
111
117
|
MiddlewareR extends { _tag: string } = never
|
|
112
118
|
> =
|
|
113
|
-
|
|
119
|
+
& BuildingMiddleware<
|
|
120
|
+
RequestContextMap,
|
|
121
|
+
Provided,
|
|
122
|
+
Middlewares,
|
|
123
|
+
DynamicMiddlewareProviders,
|
|
124
|
+
MiddlewareR
|
|
125
|
+
>
|
|
126
|
+
& // keyof Omit<RequestContextMap, Provided> extends never is true when all the dynamic middlewares are provided
|
|
114
127
|
// MiddlewareR is never when all the required services from generic & dynamic middlewares are provided
|
|
115
|
-
keyof Omit<RequestContextMap, Provided> extends never ? [MiddlewareR] extends [never] ? ReturnType<
|
|
128
|
+
(keyof Omit<RequestContextMap, Provided> extends never ? [MiddlewareR] extends [never] ? ReturnType<
|
|
116
129
|
typeof makeMiddlewareBasic<
|
|
117
130
|
RequestContextMap,
|
|
118
131
|
Middlewares
|
|
119
132
|
>
|
|
120
133
|
>
|
|
121
|
-
:
|
|
122
|
-
|
|
123
|
-
Provided,
|
|
124
|
-
Middlewares,
|
|
125
|
-
DynamicMiddlewareProviders,
|
|
126
|
-
MiddlewareR
|
|
127
|
-
>
|
|
128
|
-
: BuildingMiddleware<
|
|
129
|
-
RequestContextMap,
|
|
130
|
-
Provided,
|
|
131
|
-
Middlewares,
|
|
132
|
-
DynamicMiddlewareProviders,
|
|
133
|
-
MiddlewareR
|
|
134
|
-
>
|
|
134
|
+
: {}
|
|
135
|
+
: {})
|
|
135
136
|
|
|
136
137
|
export const makeMiddleware: <
|
|
137
138
|
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
138
139
|
>(rcm: RequestContextMap) => MiddlewaresBuilder<RequestContextMap> = (rcm) => {
|
|
139
|
-
let allMiddleware:
|
|
140
|
+
let allMiddleware: MiddlewareMaker[] = []
|
|
140
141
|
const it = {
|
|
141
142
|
middleware: (...middlewares: any[]) => {
|
|
142
143
|
for (const mw of middlewares) {
|
|
@@ -154,92 +155,71 @@ export const makeMiddleware: <
|
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
//
|
|
157
|
-
export
|
|
158
|
-
|
|
159
|
-
export interface MiddlewareMaker<E> {
|
|
160
|
-
readonly effect: E
|
|
161
|
-
readonly _tag: typeof MiddlewareMakerTag
|
|
158
|
+
export interface MiddlewareMakerId {
|
|
159
|
+
readonly _id: unique symbol
|
|
162
160
|
}
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
export const buildMiddlewareMaker = <E>(eff: E) =>
|
|
167
|
-
({
|
|
168
|
-
_tag: MiddlewareMakerTag,
|
|
169
|
-
effect: eff
|
|
170
|
-
}) satisfies MiddlewareMaker<E>
|
|
162
|
+
// TODO: actually end up with [Tag<A, A>, Tag<B, B>, ...]
|
|
163
|
+
type MakeTags<A> = Context.Tag<A, A>
|
|
171
164
|
|
|
172
165
|
const makeMiddlewareBasic =
|
|
173
166
|
// by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
|
|
174
167
|
<
|
|
175
168
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
176
|
-
|
|
169
|
+
MiddlewareProviders extends ReadonlyArray<MiddlewareMaker>
|
|
177
170
|
>(
|
|
178
171
|
_rcm: RequestContextMap,
|
|
179
|
-
...make:
|
|
172
|
+
...make: MiddlewareProviders
|
|
180
173
|
) => {
|
|
181
|
-
const MiddlewareMaker = Context.GenericTag<
|
|
182
|
-
MiddlewareMakerId,
|
|
183
|
-
MiddlewareMaker<
|
|
184
|
-
RPCHandlerFactory<
|
|
185
|
-
RequestContextMap,
|
|
186
|
-
GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
|
|
187
|
-
>
|
|
188
|
-
>
|
|
189
|
-
>(
|
|
190
|
-
MiddlewareMakerTag
|
|
191
|
-
)
|
|
192
|
-
|
|
193
174
|
// reverse middlewares and wrap one after the other
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
175
|
+
const middleware = middlewareMaker(make)
|
|
176
|
+
|
|
177
|
+
const failures = make.map((_) => _.failure).filter(Boolean)
|
|
178
|
+
const provides = make.flatMap((_) => !_.provides ? [] : Array.isArray(_.provides) ? _.provides : [_.provides])
|
|
179
|
+
const requires = make
|
|
180
|
+
.flatMap((_) => !_.requires ? [] : Array.isArray(_.requires) ? _.requires : [_.requires])
|
|
181
|
+
.filter((_) => !provides.includes(_))
|
|
182
|
+
|
|
183
|
+
const MiddlewareMaker = Tag<MiddlewareMakerId>()("MiddlewareMaker", {
|
|
184
|
+
failure: (failures.length > 0
|
|
185
|
+
? S.Union(...failures)
|
|
186
|
+
: S.Never) as unknown as MiddlewareMaker.ManyErrors<MiddlewareProviders> extends never ? never
|
|
187
|
+
: S.Schema<MiddlewareMaker.ManyErrors<MiddlewareProviders>>,
|
|
188
|
+
requires: (requires.length > 0
|
|
189
|
+
? requires
|
|
190
|
+
: undefined) as unknown as Exclude<
|
|
191
|
+
MiddlewareMaker.ManyRequired<MiddlewareProviders>,
|
|
192
|
+
MiddlewareMaker.ManyProvided<MiddlewareProviders>
|
|
193
|
+
> extends never ? never : [
|
|
194
|
+
MakeTags<
|
|
195
|
+
Exclude<
|
|
196
|
+
MiddlewareMaker.ManyRequired<MiddlewareProviders>,
|
|
197
|
+
MiddlewareMaker.ManyProvided<MiddlewareProviders>
|
|
198
|
+
>
|
|
199
|
+
>
|
|
200
|
+
],
|
|
201
|
+
provides: (provides.length > 0
|
|
202
|
+
? provides
|
|
203
|
+
: undefined) as unknown as MiddlewareMaker.ManyProvided<MiddlewareProviders> extends never ? never : [
|
|
204
|
+
MakeTags<MiddlewareMaker.ManyProvided<MiddlewareProviders>>
|
|
205
|
+
],
|
|
206
|
+
wrap: true
|
|
207
|
+
})(
|
|
208
|
+
middleware as {
|
|
209
|
+
dependencies: typeof middleware["dependencies"]
|
|
210
|
+
effect: Effect<
|
|
211
|
+
any, // TODO: why ?
|
|
212
|
+
Effect.Error<typeof middleware["effect"]>,
|
|
213
|
+
Effect.Context<typeof middleware["effect"]>
|
|
214
|
+
>
|
|
215
|
+
}
|
|
231
216
|
)
|
|
232
217
|
|
|
233
|
-
const middlewareLayer = l
|
|
234
|
-
.pipe(
|
|
235
|
-
Layer.provide(middlewares.dependencies as any)
|
|
236
|
-
) as Layer.Layer<
|
|
237
|
-
MiddlewareMakerId,
|
|
238
|
-
// what could go wrong when building the dynamic middleware provider
|
|
239
|
-
LayerUtils.GetLayersError<typeof middlewares.dependencies>,
|
|
240
|
-
LayerUtils.GetLayersContext<typeof middlewares.dependencies>
|
|
241
|
-
>
|
|
242
|
-
|
|
243
218
|
// add to the tag a default implementation
|
|
244
|
-
return Object.assign(MiddlewareMaker, {
|
|
219
|
+
return Object.assign(MiddlewareMaker, {
|
|
220
|
+
// tag to be used to retrieve the RequestContextConfig from RPC annotations
|
|
221
|
+
requestContext: Context.GenericTag<"RequestContextConfig", GetContextConfig<RequestContextMap>>(
|
|
222
|
+
"RequestContextConfig"
|
|
223
|
+
)
|
|
224
|
+
})
|
|
245
225
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// codegen:start {preset: barrel, include: ./middleware/*.ts, nodir: false }
|
|
2
|
-
export * from "./middleware/ContextProvider.js"
|
|
3
2
|
export * from "./middleware/dynamic-middleware.js"
|
|
4
3
|
export * from "./middleware/generic-middleware.js"
|
|
5
4
|
export * from "./middleware/middleware-api.js"
|
package/src/api/routing.ts
CHANGED
|
@@ -167,13 +167,17 @@ export const makeRouter = <
|
|
|
167
167
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
168
168
|
MakeMiddlewareE,
|
|
169
169
|
MakeMiddlewareR,
|
|
170
|
-
ContextProviderA
|
|
170
|
+
ContextProviderA,
|
|
171
|
+
ContextProviderE,
|
|
172
|
+
ContextProviderR
|
|
171
173
|
>(
|
|
172
174
|
middleware: RouterMiddleware<
|
|
173
175
|
RequestContextMap,
|
|
174
176
|
MakeMiddlewareE,
|
|
175
177
|
MakeMiddlewareR,
|
|
176
|
-
ContextProviderA
|
|
178
|
+
ContextProviderA,
|
|
179
|
+
ContextProviderE,
|
|
180
|
+
ContextProviderR
|
|
177
181
|
>,
|
|
178
182
|
devMode: boolean
|
|
179
183
|
) => {
|
|
@@ -370,7 +374,6 @@ export const makeRouter = <
|
|
|
370
374
|
: make
|
|
371
375
|
|
|
372
376
|
const controllers = yield* make
|
|
373
|
-
const rpc = yield* middleware
|
|
374
377
|
|
|
375
378
|
// return make.pipe(Effect.map((c) => controllers(c, dependencies)))
|
|
376
379
|
const mapped = typedKeysOf(requestModules).reduce((acc, cur) => {
|
|
@@ -400,16 +403,12 @@ export const makeRouter = <
|
|
|
400
403
|
}
|
|
401
404
|
} as any
|
|
402
405
|
: resource,
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
})
|
|
410
|
-
),
|
|
411
|
-
meta.moduleName
|
|
412
|
-
),
|
|
406
|
+
(payload: any, headers: any) =>
|
|
407
|
+
handle(payload, headers).pipe(
|
|
408
|
+
Effect.withSpan("Request." + resource._tag, {
|
|
409
|
+
captureStackTrace: () => handler.stack // capturing the handler stack is the main reason why we are doing the span here
|
|
410
|
+
})
|
|
411
|
+
),
|
|
413
412
|
meta.moduleName
|
|
414
413
|
] as const
|
|
415
414
|
return acc
|
|
@@ -431,16 +430,19 @@ export const makeRouter = <
|
|
|
431
430
|
]
|
|
432
431
|
}
|
|
433
432
|
|
|
434
|
-
const rpcs = RpcGroup
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
433
|
+
const rpcs = RpcGroup
|
|
434
|
+
.make(
|
|
435
|
+
...typedValuesOf(mapped).map(([resource]) => {
|
|
436
|
+
return Rpc.fromTaggedRequest(resource).annotate(middleware.requestContext, resource.config ?? {})
|
|
437
|
+
})
|
|
438
|
+
)
|
|
439
|
+
.prefix(`${meta.moduleName}.`)
|
|
440
|
+
.middleware(middleware as any)
|
|
439
441
|
const rpcLayer = rpcs.toLayer(Effect.gen(function*() {
|
|
440
442
|
return typedValuesOf(mapped).reduce((acc, [resource, handler]) => {
|
|
441
|
-
acc[resource._tag] = handler
|
|
443
|
+
acc[`${meta.moduleName}.${resource._tag}`] = handler
|
|
442
444
|
return acc
|
|
443
|
-
}, {} as Record<string, any>)
|
|
445
|
+
}, {} as Record<string, any>) as any // TODO
|
|
444
446
|
})) as unknown as Layer<
|
|
445
447
|
{ [K in keyof RequestModules]: Rpc.Handler<K> },
|
|
446
448
|
| Layer.Error<typeof middleware.Default>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
3
|
import { expectTypeOf, it } from "@effect/vitest"
|
|
4
4
|
import { Context, Effect, Scope } from "effect-app"
|
|
5
|
-
import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/
|
|
5
|
+
import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/ContextProvider.js"
|
|
6
6
|
import { CustomError1, Some, SomeElse, SomeService } from "./fixtures.js"
|
|
7
7
|
|
|
8
8
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
package/test/controller.test.ts
CHANGED
|
@@ -76,23 +76,22 @@ const genericMiddlewares = [
|
|
|
76
76
|
] as const
|
|
77
77
|
|
|
78
78
|
const middleware = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
79
|
-
.middleware(MyContextProvider)
|
|
80
79
|
.middleware(
|
|
81
80
|
RequireRoles,
|
|
82
81
|
Test
|
|
83
82
|
)
|
|
84
83
|
// AllowAnonymous provided after RequireRoles so that RequireRoles can access what AllowAnonymous provides
|
|
85
84
|
.middleware(AllowAnonymous)
|
|
85
|
+
.middleware(MyContextProvider)
|
|
86
86
|
.middleware(...genericMiddlewares)
|
|
87
87
|
|
|
88
88
|
const middlewareBis = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
89
|
-
.middleware(MyContextProvider)
|
|
90
89
|
.middleware(
|
|
91
90
|
RequireRoles,
|
|
92
91
|
Test
|
|
93
92
|
)
|
|
94
93
|
// testing sideways elimination
|
|
95
|
-
.middleware(AllowAnonymous, ...genericMiddlewares)
|
|
94
|
+
.middleware(AllowAnonymous, MyContextProvider, ...genericMiddlewares)
|
|
96
95
|
|
|
97
96
|
expectTypeOf(middleware).toEqualTypeOf<typeof middlewareBis>()
|
|
98
97
|
|
|
@@ -112,10 +111,10 @@ expectTypeOf(middlewareTrisWip).toEqualTypeOf<{
|
|
|
112
111
|
// testing more sideways elimination]
|
|
113
112
|
const middlewareQuater = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
114
113
|
.middleware(
|
|
115
|
-
MyContextProvider,
|
|
116
114
|
RequireRoles,
|
|
117
115
|
Test,
|
|
118
116
|
AllowAnonymous,
|
|
117
|
+
MyContextProvider,
|
|
119
118
|
...genericMiddlewares
|
|
120
119
|
)
|
|
121
120
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAc,MAAM,+BAA+B,CAAA;AAE7F,OAAO,EAAW,MAAM,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAA6C,UAAU,EAAO,MAAM,kCAAkC,CAAA;AAE7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;AAgChI,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;AAML,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;
|
|
1
|
+
{"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAc,MAAM,+BAA+B,CAAA;AAE7F,OAAO,EAAW,MAAM,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAA6C,UAAU,EAAO,MAAM,kCAAkC,CAAA;AAE7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;AAgChI,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;AAML,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;AA2DD,eAAO,MAAM,WAAW;;;;;;YAIM,CAAA;AAE9B,MAAM,MAAM,aAAa,GAAG;IAC1B,yCAAyC;IACzC,cAAc,CAAC,EAAE,IAAI,CAAA;IACrB,iEAAiE;IACjE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B,CAAA;AACD,eAAO,MAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAI/B,CAAA;;;;;;;;;;AAEF,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;AACtE,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;;;AAEtE,qBAAa,WAAY,SAAQ,gBAEV;CAAG;;;;;;;;;;;;AAgB1B,qBAAa,YAAa,SAAQ,iBAET;CAAG;;;;;;;;;;;;AAE5B,qBAAa,aAAc,SAAQ,kBAEA;CAAG;;;;;AAItC,qBAAa,gBAAiB,SAAQ,qBAKpC;CAAG;;;;;AASL,qBAAa,aAAc,SAAQ,kBAOjC;CAAG;;;;;AAEL,qBAAa,iBAAkB,SAAQ,sBAKrC;CAAG;AAEL,eAAO,MAAQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAE,QAAQ;;;;;2HAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAAiC,CAAA;AAE1E,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgC,CAAA"}
|
package/test/dist/fixtures.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ declare const Some_base: (abstract new (service: {
|
|
|
37
37
|
} & {
|
|
38
38
|
use: <X>(body: (_: {
|
|
39
39
|
a: number;
|
|
40
|
-
}) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1,
|
|
40
|
+
}) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, R_3 | Some> : Effect.Effect<X, never, Some>;
|
|
41
41
|
};
|
|
42
42
|
export declare class Some extends Some_base {
|
|
43
43
|
}
|
|
@@ -63,7 +63,7 @@ declare const SomeElse_base: (abstract new (service: {
|
|
|
63
63
|
} & {
|
|
64
64
|
use: <X>(body: (_: {
|
|
65
65
|
b: number;
|
|
66
|
-
}) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1,
|
|
66
|
+
}) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, SomeElse | R_3> : Effect.Effect<X, never, SomeElse>;
|
|
67
67
|
};
|
|
68
68
|
export declare class SomeElse extends SomeElse_base {
|
|
69
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEtF,OAAO,
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEtF,OAAO,EAAyB,UAAU,EAAE,MAAM,uBAAuB,CAAA;;;;;;;;;;;;;AAEzE,qBAAa,WAAY,SAAQ,gBAKhC;CACA;;;;;;;;;;;;;;;;;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SAA2D;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AACxF,qBAAa,QAAS,SAAQ,aAAmE;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAEpG,qBAAa,WAAY,SAAQ,gBAAgE;CAAG;AASpG,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAA;AAEV,KAAK,kBAAkB,GAAG,OAAO,iBAAiB,CAAA;AAClD,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;CAAG;;;;;;;AAEhE,qBAAa,cAAe,SAAQ,mBA4BlC;CACD;;;;;;;;AAID,qBAAa,YAAa,SAAQ,iBA6BhC;CACD;;;;;;;AAGD,qBAAa,IAAK,SAAQ,SASxB;CAAG;;;;AAEL,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG"}
|