@effect-app/infra 2.87.2 → 2.88.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 +13 -1
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -22
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.js +1 -1
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +13 -13
- 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/dynamic-middleware.d.ts +1 -9
- package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.d.ts +8 -8
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +23 -7
- package/dist/api/routing/middleware/middleware-api.d.ts +59 -30
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +44 -35
- package/dist/api/routing/middleware/middleware.d.ts +7 -7
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +5 -5
- package/package.json +2 -2
- package/src/api/routing/middleware/RouterMiddleware.ts +8 -86
- package/src/api/routing/middleware/RpcMiddleware.ts +13 -12
- package/src/api/routing/middleware/dynamic-middleware.ts +0 -47
- package/src/api/routing/middleware/generic-middleware.ts +45 -14
- package/src/api/routing/middleware/middleware-api.ts +147 -101
- package/src/api/routing/middleware/middleware.ts +5 -5
- package/test/contextProvider.test.ts +27 -24
- package/test/controller.test.ts +44 -9
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +39 -45
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +21 -9
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/fixtures.ts +22 -13
- package/test/layerUtils.test.ts +1 -2
- package/test/requires.test.ts +119 -97
|
@@ -3,37 +3,22 @@ import { Context, Effect, Layer, type NonEmptyArray, type NonEmptyReadonlyArray
|
|
|
3
3
|
import { type RPCContextMap } from "effect-app/client"
|
|
4
4
|
import { type LayerUtils } from "../../layerUtils.js"
|
|
5
5
|
import { type GenericMiddlewareMaker, genericMiddlewareMaker } from "./generic-middleware.js"
|
|
6
|
-
import { makeRpcEffect, type
|
|
6
|
+
import { makeRpcEffect, type RPCHandlerFactory } from "./RouterMiddleware.js"
|
|
7
7
|
import { type AnyDynamic, type RpcDynamic, type TagClassAny } from "./RpcMiddleware.js"
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
export interface MiddlewareM<
|
|
19
|
-
RequestContext extends Record<string, RPCContextMap.Any>,
|
|
20
|
-
Provided extends keyof RequestContext,
|
|
21
|
-
Middlewares extends ReadonlyArray<GenericMiddlewareMaker>,
|
|
22
|
-
DynamicMiddlewareProviders,
|
|
23
|
-
// out MiddlewareR = never
|
|
24
|
-
MiddlewareR = never
|
|
25
|
-
> {
|
|
26
|
-
middleware<MW extends NonEmptyArray<GenericMiddlewareMaker>>(
|
|
27
|
-
...mw: MW
|
|
28
|
-
): DynamicMiddlewareMakerrsss<
|
|
29
|
-
RequestContext,
|
|
30
|
-
Provided,
|
|
31
|
-
[...Middlewares, ...MW],
|
|
32
|
-
DynamicMiddlewareProviders,
|
|
33
|
-
GenericMiddlewareMaker.ApplyManyServices<MW, MiddlewareR>
|
|
34
|
-
>
|
|
35
|
-
}
|
|
9
|
+
// adapter used when setting the dynamic prop on a middleware implementation
|
|
10
|
+
export const contextMap = <
|
|
11
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
12
|
+
Key extends (keyof RequestContextMap) & string
|
|
13
|
+
>(rcm: RequestContextMap, key: Key): RpcDynamic<Key, RequestContextMap[Key]> => ({
|
|
14
|
+
key,
|
|
15
|
+
settings: { service: rcm[key]!["service"] } as RequestContextMap[Key]
|
|
16
|
+
})
|
|
36
17
|
|
|
18
|
+
// the following implements sort of builder pattern
|
|
19
|
+
// we support both sideways and upwards elimination of dependencies
|
|
20
|
+
|
|
21
|
+
// it's for dynamic middlewares
|
|
37
22
|
type GetDependsOnKeys<MW extends GenericMiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> }
|
|
38
23
|
? {
|
|
39
24
|
[K in keyof MW["dependsOn"]]: MW["dependsOn"][K] extends AnyDynamic ? MW["dependsOn"][K]["dynamic"]["key"]
|
|
@@ -41,112 +26,171 @@ type GetDependsOnKeys<MW extends GenericMiddlewareMaker> = MW extends { dependsO
|
|
|
41
26
|
}[keyof MW["dependsOn"]]
|
|
42
27
|
: never
|
|
43
28
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
type FilterInDynamicMiddlewares<
|
|
30
|
+
MWs extends ReadonlyArray<GenericMiddlewareMaker>,
|
|
31
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
32
|
+
> = {
|
|
33
|
+
[K in keyof MWs]: MWs[K] extends { dynamic: RpcDynamic<any, RequestContextMap[keyof RequestContextMap]> } ? MWs[K]
|
|
34
|
+
: never
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type RecursiveHandleMWsSideways<
|
|
38
|
+
MWs,
|
|
39
|
+
R extends {
|
|
40
|
+
rcm: Record<string, RPCContextMap.Any>
|
|
41
|
+
provided: keyof R["rcm"] // that's fine
|
|
42
|
+
middlewares: ReadonlyArray<GenericMiddlewareMaker>
|
|
43
|
+
dmp: any
|
|
44
|
+
middlewareR: any
|
|
45
|
+
}
|
|
46
|
+
> = MWs extends [
|
|
47
|
+
infer F extends GenericMiddlewareMaker,
|
|
48
|
+
...infer Rest extends ReadonlyArray<GenericMiddlewareMaker>
|
|
49
|
+
] ? RecursiveHandleMWsSideways<Rest, {
|
|
50
|
+
rcm: R["rcm"]
|
|
51
|
+
// when one dynamic middleware depends on another, subtract the key to enforce the dependency to be provided after
|
|
52
|
+
// (if already provided, it would have to be re-provided anyway, so better to provide it after)
|
|
53
|
+
provided: Exclude<
|
|
54
|
+
R["provided"] | FilterInDynamicMiddlewares<[F], R["rcm"]>[number]["dynamic"]["key"],
|
|
55
|
+
// F is fine here because only dynamic middlewares will have 'dependsOn' prop
|
|
56
|
+
GetDependsOnKeys<F>
|
|
57
|
+
>
|
|
58
|
+
middlewares: [...R["middlewares"], F]
|
|
59
|
+
dmp: [FilterInDynamicMiddlewares<[F], R["rcm"]>[number]] extends [never] ? R["dmp"]
|
|
60
|
+
:
|
|
61
|
+
& R["dmp"]
|
|
62
|
+
& {
|
|
63
|
+
[U in FilterInDynamicMiddlewares<[F], R["rcm"]>[number] as U["dynamic"]["key"]]: U
|
|
64
|
+
}
|
|
65
|
+
middlewareR: GenericMiddlewareMaker.ApplyManyServices<[F], R["middlewareR"]>
|
|
66
|
+
}>
|
|
67
|
+
: R
|
|
68
|
+
|
|
69
|
+
export interface BuildingMiddleware<
|
|
70
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
71
|
+
Provided extends keyof RequestContextMap,
|
|
47
72
|
Middlewares extends ReadonlyArray<GenericMiddlewareMaker>,
|
|
48
73
|
DynamicMiddlewareProviders,
|
|
49
|
-
out MiddlewareR
|
|
74
|
+
out MiddlewareR extends { _tag: string } = never
|
|
50
75
|
> {
|
|
51
|
-
middleware<
|
|
52
|
-
...mw:
|
|
53
|
-
):
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
[...Middlewares, ...MW],
|
|
72
|
-
DynamicMiddlewareProviders,
|
|
73
|
-
GenericMiddlewareMaker.ApplyManyServices<MW, MiddlewareR>
|
|
76
|
+
middleware<MWs extends NonEmptyArray<GenericMiddlewareMaker>>(
|
|
77
|
+
...mw: MWs
|
|
78
|
+
): RecursiveHandleMWsSideways<MWs, {
|
|
79
|
+
rcm: RequestContextMap
|
|
80
|
+
provided: Provided
|
|
81
|
+
middlewares: Middlewares
|
|
82
|
+
dmp: DynamicMiddlewareProviders
|
|
83
|
+
middlewareR: MiddlewareR
|
|
84
|
+
}> extends infer Res extends {
|
|
85
|
+
rcm: RequestContextMap
|
|
86
|
+
provided: keyof RequestContextMap
|
|
87
|
+
middlewares: ReadonlyArray<GenericMiddlewareMaker>
|
|
88
|
+
dmp: any
|
|
89
|
+
middlewareR: any
|
|
90
|
+
} ? MiddlewaresBuilder<
|
|
91
|
+
Res["rcm"],
|
|
92
|
+
Res["provided"],
|
|
93
|
+
Res["middlewares"],
|
|
94
|
+
Res["dmp"],
|
|
95
|
+
Res["middlewareR"]
|
|
74
96
|
>
|
|
97
|
+
: never
|
|
98
|
+
|
|
99
|
+
// helps debugging what are the missing requirements (type only)
|
|
100
|
+
missing: {
|
|
101
|
+
missingDynamicMiddlewares: Exclude<keyof RequestContextMap, Provided>
|
|
102
|
+
missingContext: MiddlewareR
|
|
103
|
+
}
|
|
75
104
|
}
|
|
76
105
|
|
|
77
|
-
type
|
|
78
|
-
|
|
79
|
-
Provided extends keyof
|
|
106
|
+
export type MiddlewaresBuilder<
|
|
107
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
108
|
+
Provided extends keyof RequestContextMap = never,
|
|
80
109
|
Middlewares extends ReadonlyArray<GenericMiddlewareMaker> = [],
|
|
81
110
|
DynamicMiddlewareProviders = unknown,
|
|
82
|
-
MiddlewareR = never
|
|
83
|
-
> =
|
|
84
|
-
|
|
111
|
+
MiddlewareR extends { _tag: string } = never
|
|
112
|
+
> =
|
|
113
|
+
// keyof Omit<RequestContextMap, Provided> extends never is true when all the dynamic middlewares are provided
|
|
114
|
+
// 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<
|
|
85
116
|
typeof makeMiddlewareBasic<
|
|
86
|
-
|
|
117
|
+
RequestContextMap,
|
|
87
118
|
Middlewares
|
|
88
119
|
>
|
|
89
120
|
>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
: MiddlewareDynamic<
|
|
105
|
-
RequestContext,
|
|
106
|
-
Provided,
|
|
107
|
-
Middlewares,
|
|
108
|
-
DynamicMiddlewareProviders,
|
|
109
|
-
MiddlewareR
|
|
110
|
-
>
|
|
121
|
+
: BuildingMiddleware<
|
|
122
|
+
RequestContextMap,
|
|
123
|
+
Provided,
|
|
124
|
+
Middlewares,
|
|
125
|
+
DynamicMiddlewareProviders,
|
|
126
|
+
MiddlewareR
|
|
127
|
+
>
|
|
128
|
+
: BuildingMiddleware<
|
|
129
|
+
RequestContextMap,
|
|
130
|
+
Provided,
|
|
131
|
+
Middlewares,
|
|
132
|
+
DynamicMiddlewareProviders,
|
|
133
|
+
MiddlewareR
|
|
134
|
+
>
|
|
111
135
|
|
|
112
136
|
export const makeMiddleware: <
|
|
113
137
|
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
114
|
-
>() =>
|
|
138
|
+
>(rcm: RequestContextMap) => MiddlewaresBuilder<RequestContextMap> = (rcm) => {
|
|
115
139
|
let allMiddleware: GenericMiddlewareMaker[] = []
|
|
116
140
|
const it = {
|
|
117
141
|
middleware: (...middlewares: any[]) => {
|
|
118
142
|
for (const mw of middlewares) {
|
|
143
|
+
// recall that we run middlewares in reverse order
|
|
119
144
|
allMiddleware = [mw, ...allMiddleware]
|
|
120
145
|
}
|
|
121
|
-
|
|
122
|
-
|
|
146
|
+
return allMiddleware.filter((m) => !!m.dynamic).length !== Object.keys(rcm).length
|
|
147
|
+
// for sure, until all the dynamic middlewares are provided it's non sensical to call makeMiddlewareBasic
|
|
148
|
+
? it
|
|
149
|
+
// actually, we don't know yet if MiddlewareR is never, but we can't easily check it at runtime
|
|
150
|
+
: Object.assign(makeMiddlewareBasic<any, any>(rcm, ...allMiddleware), it)
|
|
123
151
|
}
|
|
124
152
|
}
|
|
125
153
|
return it as any
|
|
126
154
|
}
|
|
127
155
|
|
|
128
|
-
|
|
156
|
+
//
|
|
157
|
+
export const MiddlewareMakerTag = "MiddlewareMaker" as const
|
|
158
|
+
|
|
159
|
+
export interface MiddlewareMaker<E> {
|
|
160
|
+
readonly effect: E
|
|
161
|
+
readonly _tag: typeof MiddlewareMakerTag
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type MiddlewareMakerId = Pick<MiddlewareMaker<any>, "_tag">
|
|
165
|
+
|
|
166
|
+
export const buildMiddlewareMaker = <E>(eff: E) =>
|
|
167
|
+
({
|
|
168
|
+
_tag: MiddlewareMakerTag,
|
|
169
|
+
effect: eff
|
|
170
|
+
}) satisfies MiddlewareMaker<E>
|
|
171
|
+
|
|
172
|
+
const makeMiddlewareBasic =
|
|
129
173
|
// by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
|
|
130
174
|
<
|
|
131
175
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
132
|
-
// RequestContextProviders extends RequestContextMapProvider<RequestContextMap>, // how to resolve the dynamic middleware
|
|
133
176
|
GenericMiddlewareProviders extends ReadonlyArray<GenericMiddlewareMaker>
|
|
134
177
|
>(
|
|
178
|
+
_rcm: RequestContextMap,
|
|
135
179
|
...make: GenericMiddlewareProviders
|
|
136
180
|
) => {
|
|
137
181
|
const MiddlewareMaker = Context.GenericTag<
|
|
138
182
|
MiddlewareMakerId,
|
|
139
|
-
|
|
140
|
-
|
|
183
|
+
MiddlewareMaker<
|
|
184
|
+
RPCHandlerFactory<
|
|
141
185
|
RequestContextMap,
|
|
142
186
|
GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
|
|
143
187
|
>
|
|
144
|
-
|
|
145
|
-
}
|
|
188
|
+
>
|
|
146
189
|
>(
|
|
147
|
-
|
|
190
|
+
MiddlewareMakerTag
|
|
148
191
|
)
|
|
149
192
|
|
|
193
|
+
// reverse middlewares and wrap one after the other
|
|
150
194
|
const middlewares = genericMiddlewareMaker(...make)
|
|
151
195
|
|
|
152
196
|
const l = Layer.scoped(
|
|
@@ -154,16 +198,16 @@ export const makeMiddlewareBasic =
|
|
|
154
198
|
middlewares
|
|
155
199
|
.effect
|
|
156
200
|
.pipe(
|
|
157
|
-
Effect.map((generic) => (
|
|
158
|
-
|
|
159
|
-
effect: makeRpcEffect<
|
|
201
|
+
Effect.map((generic) => (buildMiddlewareMaker(
|
|
202
|
+
makeRpcEffect<
|
|
160
203
|
RequestContextMap,
|
|
161
204
|
GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
|
|
162
205
|
>()(
|
|
163
|
-
(schema,
|
|
206
|
+
(schema, handler, moduleName) => {
|
|
164
207
|
return (payload, headers) =>
|
|
165
208
|
Effect
|
|
166
209
|
.gen(function*() {
|
|
210
|
+
// will be propagated to all the wrapped middlewares
|
|
167
211
|
const basic = {
|
|
168
212
|
config: schema.config ?? {},
|
|
169
213
|
payload,
|
|
@@ -177,12 +221,12 @@ export const makeMiddlewareBasic =
|
|
|
177
221
|
}
|
|
178
222
|
return yield* generic({
|
|
179
223
|
...basic,
|
|
180
|
-
next:
|
|
224
|
+
next: handler(payload, headers) as any
|
|
181
225
|
})
|
|
182
|
-
}) as any // why?
|
|
226
|
+
}) as any // why? because: Type 'SuccessValue' is not assignable to type 'Success<Req>' :P
|
|
183
227
|
}
|
|
184
228
|
)
|
|
185
|
-
|
|
229
|
+
)))
|
|
186
230
|
)
|
|
187
231
|
)
|
|
188
232
|
|
|
@@ -191,9 +235,11 @@ export const makeMiddlewareBasic =
|
|
|
191
235
|
Layer.provide(middlewares.dependencies as any)
|
|
192
236
|
) as Layer.Layer<
|
|
193
237
|
MiddlewareMakerId,
|
|
194
|
-
|
|
238
|
+
// what could go wrong when building the dynamic middleware provider
|
|
239
|
+
LayerUtils.GetLayersError<typeof middlewares.dependencies>,
|
|
195
240
|
LayerUtils.GetLayersContext<typeof middlewares.dependencies>
|
|
196
241
|
>
|
|
197
242
|
|
|
243
|
+
// add to the tag a default implementation
|
|
198
244
|
return Object.assign(MiddlewareMaker, { Default: middlewareLayer })
|
|
199
245
|
}
|
|
@@ -23,8 +23,8 @@ export class RequestCacheMiddleware extends Tag<RequestCacheMiddleware>()("Reque
|
|
|
23
23
|
}) {
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export class
|
|
27
|
-
extends Tag<
|
|
26
|
+
export class ConfigureInterruptibilityMiddleware
|
|
27
|
+
extends Tag<ConfigureInterruptibilityMiddleware>()("ConfigureInterruptibilityMiddleware", { wrap: true })({
|
|
28
28
|
effect: Effect.succeed(({ next }) =>
|
|
29
29
|
next.pipe(
|
|
30
30
|
// TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
|
|
@@ -35,7 +35,7 @@ export class ConfigureInterruptibility
|
|
|
35
35
|
{
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export class
|
|
38
|
+
export class LoggerMiddleware extends Tag<LoggerMiddleware>()("LoggerMiddleware", { wrap: true })({
|
|
39
39
|
effect: Effect.gen(function*() {
|
|
40
40
|
const devMode = yield* DevMode
|
|
41
41
|
return ({ headers, next, payload, rpc }) =>
|
|
@@ -98,6 +98,6 @@ export class MiddlewareLogger extends Tag<MiddlewareLogger>()("MiddlewareLogger"
|
|
|
98
98
|
|
|
99
99
|
export const DefaultGenericMiddlewares = [
|
|
100
100
|
RequestCacheMiddleware,
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
ConfigureInterruptibilityMiddleware,
|
|
102
|
+
LoggerMiddleware
|
|
103
103
|
] as const
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
|
-
import { expectTypeOf } from "@effect/vitest"
|
|
3
|
+
import { expectTypeOf, it } from "@effect/vitest"
|
|
4
4
|
import { Context, Effect, Scope } from "effect-app"
|
|
5
5
|
import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/routing.js"
|
|
6
6
|
import { CustomError1, Some, SomeElse, SomeService } from "./fixtures.js"
|
|
@@ -119,33 +119,36 @@ export const someContextProviderGen = ContextProvider({
|
|
|
119
119
|
}
|
|
120
120
|
})
|
|
121
121
|
})
|
|
122
|
-
expectTypeOf(someContextProvider).toEqualTypeOf<typeof someContextProviderGen>()
|
|
123
122
|
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
it("works", () => {
|
|
124
|
+
expectTypeOf(someContextProvider).toEqualTypeOf<typeof someContextProviderGen>()
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
expectTypeOf(contextProvider2).toEqualTypeOf<typeof someContextProvider>()
|
|
130
|
-
expectTypeOf(contextProvider3).toEqualTypeOf<typeof contextProvider2>()
|
|
126
|
+
const merged = mergeContextProviders(MyContextProvider)
|
|
127
|
+
const mergedGen = mergeContextProviders(MyContextProviderGen)
|
|
131
128
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
expectTypeOf(
|
|
135
|
-
expectTypeOf(
|
|
129
|
+
const contextProvider2 = ContextProvider(merged)
|
|
130
|
+
const contextProvider3 = MergedContextProvider(MyContextProvider)
|
|
131
|
+
expectTypeOf(contextProvider2).toEqualTypeOf<typeof someContextProvider>()
|
|
132
|
+
expectTypeOf(contextProvider3).toEqualTypeOf<typeof contextProvider2>()
|
|
136
133
|
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
const contextProvider2Gen = ContextProvider(mergedGen)
|
|
135
|
+
const contextProvider3Gen = MergedContextProvider(MyContextProviderGen)
|
|
136
|
+
expectTypeOf(contextProvider2Gen).toEqualTypeOf<typeof someContextProvider>()
|
|
137
|
+
expectTypeOf(contextProvider3Gen).toEqualTypeOf<typeof contextProvider2Gen>()
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export const contextProvider23 = MergedContextProvider(MyContextProvider, MyContextProvider2)
|
|
143
|
-
expectTypeOf(contextProvider23).toEqualTypeOf<typeof contextProvider22>()
|
|
139
|
+
expectTypeOf(contextProvider2Gen).toEqualTypeOf<typeof contextProvider2>()
|
|
140
|
+
expectTypeOf(contextProvider3Gen).toEqualTypeOf<typeof contextProvider3>()
|
|
144
141
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
expectTypeOf(
|
|
142
|
+
const merged2 = mergeContextProviders(MyContextProvider, MyContextProvider2)
|
|
143
|
+
const contextProvider22 = ContextProvider(merged2)
|
|
144
|
+
const contextProvider23 = MergedContextProvider(MyContextProvider, MyContextProvider2)
|
|
145
|
+
expectTypeOf(contextProvider23).toEqualTypeOf<typeof contextProvider22>()
|
|
149
146
|
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
const merged2Gen = mergeContextProviders(MyContextProviderGen, MyContextProvider2Gen)
|
|
148
|
+
const contextProvider22Gen = ContextProvider(merged2Gen)
|
|
149
|
+
const contextProvider23Gen = MergedContextProvider(MyContextProviderGen, MyContextProvider2Gen)
|
|
150
|
+
expectTypeOf(contextProvider23Gen).toEqualTypeOf<typeof contextProvider22Gen>()
|
|
151
|
+
|
|
152
|
+
expectTypeOf(contextProvider22Gen).toEqualTypeOf<typeof contextProvider22>()
|
|
153
|
+
expectTypeOf(contextProvider23Gen).toEqualTypeOf<typeof contextProvider23>()
|
|
154
|
+
})
|
package/test/controller.test.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Context, Effect, type Layer, S, Scope } from "effect-app"
|
|
|
6
6
|
import { InvalidStateError, makeRpcClient, NotLoggedInError, UnauthorizedError } from "effect-app/client"
|
|
7
7
|
import { DefaultGenericMiddlewares, makeMiddleware, Middleware, Tag } from "../src/api/routing/middleware.js"
|
|
8
8
|
import { sort } from "../src/api/routing/tsort.js"
|
|
9
|
-
import { AllowAnonymous, CustomError1,
|
|
9
|
+
import { AllowAnonymous, CustomError1, RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
|
|
10
10
|
|
|
11
11
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
12
12
|
class MyContextProvider extends Middleware.Tag<MyContextProvider>()("MyContextProvider", {
|
|
@@ -55,7 +55,6 @@ class MyContextProvider2 extends Middleware.Tag<MyContextProvider2>()("MyContext
|
|
|
55
55
|
const Str = Context.GenericTag<"str", "str">("str")
|
|
56
56
|
|
|
57
57
|
export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
|
|
58
|
-
provides: SomeService,
|
|
59
58
|
wrap: true
|
|
60
59
|
})({
|
|
61
60
|
effect: Effect.gen(function*() {
|
|
@@ -64,7 +63,7 @@ export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
|
|
|
64
63
|
return ({ next }) =>
|
|
65
64
|
Effect.gen(function*() {
|
|
66
65
|
// yield* Effect.context<"test-dep2">()
|
|
67
|
-
return yield* next
|
|
66
|
+
return yield* next
|
|
68
67
|
})
|
|
69
68
|
})
|
|
70
69
|
}) {
|
|
@@ -76,23 +75,59 @@ const genericMiddlewares = [
|
|
|
76
75
|
MyContextProvider2
|
|
77
76
|
] as const
|
|
78
77
|
|
|
79
|
-
const middleware = makeMiddleware<RequestContextMap>()
|
|
78
|
+
const middleware = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
80
79
|
.middleware(MyContextProvider)
|
|
81
80
|
.middleware(
|
|
82
81
|
RequireRoles,
|
|
83
82
|
Test
|
|
84
83
|
)
|
|
84
|
+
// AllowAnonymous provided after RequireRoles so that RequireRoles can access what AllowAnonymous provides
|
|
85
85
|
.middleware(AllowAnonymous)
|
|
86
86
|
.middleware(...genericMiddlewares)
|
|
87
|
-
// dependencies: [Layer.effect(Str2, Str)],
|
|
88
87
|
|
|
89
|
-
const
|
|
88
|
+
const middlewareBis = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
89
|
+
.middleware(MyContextProvider)
|
|
90
|
+
.middleware(
|
|
91
|
+
RequireRoles,
|
|
92
|
+
Test
|
|
93
|
+
)
|
|
94
|
+
// testing sideways elimination
|
|
95
|
+
.middleware(AllowAnonymous, ...genericMiddlewares)
|
|
96
|
+
|
|
97
|
+
expectTypeOf(middleware).toEqualTypeOf<typeof middlewareBis>()
|
|
98
|
+
|
|
99
|
+
const middlewareTrisWip = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
100
|
+
.middleware(
|
|
101
|
+
MyContextProvider,
|
|
102
|
+
RequireRoles,
|
|
103
|
+
Test
|
|
104
|
+
)
|
|
105
|
+
.missing
|
|
106
|
+
|
|
107
|
+
expectTypeOf(middlewareTrisWip).toEqualTypeOf<{
|
|
108
|
+
missingDynamicMiddlewares: "allowAnonymous"
|
|
109
|
+
missingContext: SomeElse
|
|
110
|
+
}>()
|
|
111
|
+
|
|
112
|
+
// testing more sideways elimination]
|
|
113
|
+
const middlewareQuater = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
114
|
+
.middleware(
|
|
115
|
+
MyContextProvider,
|
|
116
|
+
RequireRoles,
|
|
117
|
+
Test,
|
|
118
|
+
AllowAnonymous,
|
|
119
|
+
...genericMiddlewares
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
expectTypeOf(middleware).toEqualTypeOf<typeof middlewareQuater>()
|
|
123
|
+
|
|
124
|
+
const middleware2 = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
90
125
|
.middleware(MyContextProvider)
|
|
91
126
|
.middleware(RequireRoles, Test)
|
|
92
127
|
.middleware(AllowAnonymous)
|
|
93
128
|
.middleware(...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2)
|
|
94
129
|
|
|
95
|
-
export const middleware3 = makeMiddleware<RequestContextMap>()
|
|
130
|
+
export const middleware3 = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
96
131
|
.middleware(...genericMiddlewares)
|
|
97
132
|
.middleware(AllowAnonymous, RequireRoles)
|
|
98
133
|
.middleware(Test)
|
|
@@ -246,7 +281,7 @@ it("sorts based on requirements", () => {
|
|
|
246
281
|
|
|
247
282
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
248
283
|
const matched = matchAll({ router })
|
|
249
|
-
expectTypeOf({} as Layer.Context<typeof matched>).toEqualTypeOf<SomeService |
|
|
284
|
+
expectTypeOf({} as Layer.Context<typeof matched>).toEqualTypeOf<SomeService | "str">()
|
|
250
285
|
|
|
251
286
|
type makeContext = MakeContext<typeof router.make>
|
|
252
287
|
expectTypeOf({} as MakeErrors<typeof router.make>).toEqualTypeOf<InvalidStateError>()
|
|
@@ -307,7 +342,7 @@ const router2 = r2.Router(Something)({
|
|
|
307
342
|
|
|
308
343
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
309
344
|
const matched2 = matchAll({ router: router2 })
|
|
310
|
-
expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<
|
|
345
|
+
expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<SomeService | "str">()
|
|
311
346
|
|
|
312
347
|
type makeContext2 = MakeContext<typeof router2.make>
|
|
313
348
|
expectTypeOf({} as MakeErrors<typeof router2.make>).toEqualTypeOf<InvalidStateError>()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextProvider.test.d.ts","sourceRoot":"","sources":["../contextProvider.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"contextProvider.test.d.ts","sourceRoot":"","sources":["../contextProvider.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAY,WAAW,EAAE,MAAM,eAAe,CAAA;AA8EzE,eAAO,MAAM,mBAAmB;;CAkB9B,CAAA;AACF,eAAO,MAAM,sBAAsB;;CAkBjC,CAAA"}
|
|
@@ -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,
|
|
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;AA4DD,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"}
|