@effect-app/infra 2.75.0 → 2.77.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 +18 -0
- package/dist/Emailer/service.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +1 -1
- package/dist/Operations.d.ts +1 -1
- package/dist/RequestFiberSet.d.ts +1 -1
- package/dist/Store/service.d.ts +2 -2
- package/dist/adapters/SQL/Model.d.ts +6 -6
- package/dist/adapters/ServiceBus.d.ts +1 -1
- package/dist/adapters/memQueue.d.ts +1 -1
- package/dist/api/layerUtils.d.ts +10 -2
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +25 -2
- package/dist/api/routing/middleware/ContextProvider.d.ts +14 -14
- package/dist/api/routing/middleware/ContextProvider.d.ts.map +1 -1
- package/dist/api/routing/middleware/ContextProvider.js +3 -2
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts +4 -4
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/DynamicMiddleware.js +24 -12
- package/dist/api/routing/middleware/dynamic-middleware.d.ts +6 -15
- package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/dynamic-middleware.js +4 -25
- package/dist/api/routing/middleware/generic-middleware.d.ts +10 -1
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +8 -9
- package/dist/api/routing/middleware/middleware.d.ts +8 -9
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +41 -43
- package/package.json +5 -5
- package/src/api/layerUtils.ts +39 -3
- package/src/api/routing/middleware/ContextProvider.ts +39 -51
- package/src/api/routing/middleware/DynamicMiddleware.ts +42 -31
- package/src/api/routing/middleware/dynamic-middleware.ts +31 -105
- package/src/api/routing/middleware/generic-middleware.ts +19 -12
- package/src/api/routing/middleware/middleware.ts +60 -77
- package/test/controller.test.ts +38 -20
- package/test/dist/controller.test.d.ts.map +1 -1
|
@@ -1,122 +1,44 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Array, Context, Effect, Option, type S } from "effect-app"
|
|
2
|
+
import { Array, type Context, Effect, type Option, type S } from "effect-app"
|
|
3
3
|
import { type GetEffectContext, type RPCContextMap } from "effect-app/client"
|
|
4
4
|
import { type Tag } from "effect-app/Context"
|
|
5
5
|
import { typedValuesOf } from "effect-app/utils"
|
|
6
|
-
import {
|
|
7
|
-
import { type ContextTagWithDefault } from "../../layerUtils.js"
|
|
6
|
+
import { type ContextTagWithDefault, mergeOptionContexts } from "../../layerUtils.js"
|
|
8
7
|
import { sort } from "../tsort.js"
|
|
9
8
|
|
|
10
9
|
export type ContextWithLayer<
|
|
11
10
|
Config,
|
|
12
|
-
Id,
|
|
13
11
|
Service,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
MakeR
|
|
12
|
+
Error,
|
|
13
|
+
Dependencies,
|
|
14
|
+
Thing extends ContextTagWithDefault<
|
|
15
|
+
any,
|
|
16
|
+
{
|
|
17
|
+
handle: (
|
|
18
|
+
...args: [config: Config, headers: Record<string, string>]
|
|
19
|
+
) => Effect<Option<Context<Service>>, Error, unknown>
|
|
20
|
+
},
|
|
21
|
+
any,
|
|
22
|
+
unknown,
|
|
23
|
+
any
|
|
27
24
|
>
|
|
25
|
+
> =
|
|
26
|
+
& Thing
|
|
28
27
|
& {
|
|
29
28
|
dependsOn?: Dependencies
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
export namespace ContextWithLayer {
|
|
33
|
-
export type Base<Config, Service, Error> =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
any,
|
|
41
|
-
any,
|
|
42
|
-
string,
|
|
43
|
-
any,
|
|
44
|
-
any
|
|
45
|
-
>
|
|
46
|
-
| ContextWithLayer<
|
|
47
|
-
Config,
|
|
48
|
-
any,
|
|
49
|
-
Service,
|
|
50
|
-
Error,
|
|
51
|
-
never,
|
|
52
|
-
any,
|
|
53
|
-
never,
|
|
54
|
-
any,
|
|
55
|
-
any,
|
|
56
|
-
any
|
|
57
|
-
>
|
|
58
|
-
| ContextWithLayer<
|
|
59
|
-
Config,
|
|
60
|
-
any,
|
|
61
|
-
Service,
|
|
62
|
-
Error,
|
|
63
|
-
any,
|
|
64
|
-
any,
|
|
65
|
-
never,
|
|
66
|
-
any,
|
|
67
|
-
any,
|
|
68
|
-
any
|
|
69
|
-
>
|
|
70
|
-
| ContextWithLayer<
|
|
71
|
-
Config,
|
|
72
|
-
any,
|
|
73
|
-
Service,
|
|
74
|
-
Error,
|
|
75
|
-
never,
|
|
76
|
-
any,
|
|
77
|
-
any,
|
|
78
|
-
any,
|
|
79
|
-
any,
|
|
80
|
-
any
|
|
81
|
-
>
|
|
32
|
+
export type Base<Config, Service, Error> = ContextWithLayer<
|
|
33
|
+
Config,
|
|
34
|
+
Service,
|
|
35
|
+
Error,
|
|
36
|
+
any,
|
|
37
|
+
any
|
|
38
|
+
>
|
|
82
39
|
}
|
|
83
40
|
|
|
84
|
-
|
|
85
|
-
function*<T extends readonly { maker: any; handle: Effect<Context<any>> }[]>(makers: T) {
|
|
86
|
-
let context = Context.empty()
|
|
87
|
-
for (const mw of makers) {
|
|
88
|
-
yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
|
|
89
|
-
const moreContext = yield* mw.handle.pipe(Effect.provide(context))
|
|
90
|
-
yield* InfraLogger.logDebug(
|
|
91
|
-
"Built context for middleware",
|
|
92
|
-
mw.maker.key ?? mw.maker,
|
|
93
|
-
(moreContext as any).toJSON().services
|
|
94
|
-
)
|
|
95
|
-
context = Context.merge(context, moreContext)
|
|
96
|
-
}
|
|
97
|
-
return context as Context.Context<Effect.Success<T[number]["handle"]>>
|
|
98
|
-
}
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
export const mergeOptionContexts = Effect.fnUntraced(
|
|
102
|
-
function*<T extends readonly { maker: any; handle: Effect<Option<Context<any>>> }[]>(makers: T) {
|
|
103
|
-
let context = Context.empty()
|
|
104
|
-
for (const mw of makers) {
|
|
105
|
-
yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
|
|
106
|
-
const moreContext = yield* mw.handle.pipe(Effect.provide(context))
|
|
107
|
-
yield* InfraLogger.logDebug(
|
|
108
|
-
"Built context for middleware",
|
|
109
|
-
mw.maker.key ?? mw.maker,
|
|
110
|
-
Option.map(moreContext, (c) => (c as any).toJSON().services)
|
|
111
|
-
)
|
|
112
|
-
if (moreContext.value) {
|
|
113
|
-
context = Context.merge(context, moreContext.value)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return context
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
|
|
41
|
+
// Effect Rpc Middleware: no substitute atm. though maybe something could be achieved with Wrap, we just don't have type safety on the Request input etc.
|
|
120
42
|
export const implementMiddleware = <T extends Record<string, RPCContextMap.Any>>() =>
|
|
121
43
|
<
|
|
122
44
|
TI extends {
|
|
@@ -146,13 +68,17 @@ export const implementMiddleware = <T extends Record<string, RPCContextMap.Any>>
|
|
|
146
68
|
GetEffectContext<T, typeof config>
|
|
147
69
|
>
|
|
148
70
|
}
|
|
149
|
-
)
|
|
71
|
+
)
|
|
72
|
+
}) as unknown as Effect<
|
|
73
|
+
(
|
|
150
74
|
config: { [K in keyof T]?: T[K]["contextActivation"] },
|
|
151
75
|
headers: Record<string, string>
|
|
152
76
|
) => Effect.Effect<
|
|
153
77
|
Context.Context<GetEffectContext<T, typeof config>>,
|
|
154
78
|
Effect.Error<ReturnType<Tag.Service<TI[keyof TI]>["handle"]>>,
|
|
155
79
|
Effect.Context<ReturnType<Tag.Service<TI[keyof TI]>["handle"]>>
|
|
156
|
-
|
|
157
|
-
|
|
80
|
+
>,
|
|
81
|
+
never,
|
|
82
|
+
Tag.Identifier<{ [K in keyof TI]: TI[K] }[keyof TI]>
|
|
83
|
+
>
|
|
158
84
|
})
|
|
@@ -3,10 +3,20 @@ import { type Array, Effect } from "effect-app"
|
|
|
3
3
|
import { type HttpHeaders, type HttpRouter } from "effect-app/http"
|
|
4
4
|
import { type ContextTagWithDefault } from "../../layerUtils.js"
|
|
5
5
|
|
|
6
|
+
export interface GenericMiddlewareOptions<A, E> {
|
|
7
|
+
// Effect rpc middleware does not support changing payload or headers, but we do..
|
|
8
|
+
readonly next: Effect.Effect<A, E, HttpRouter.HttpRouter.Provided>
|
|
9
|
+
readonly payload: unknown
|
|
10
|
+
readonly headers: HttpHeaders.Headers
|
|
11
|
+
// readonly clientId: number
|
|
12
|
+
readonly rpc: { _tag: string } // Rpc.AnyWithProps
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
export type GenericMiddlewareMaker = <A, E>(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
options: GenericMiddlewareOptions<A, E>
|
|
17
|
+
) => Effect.Effect<A, E, HttpRouter.HttpRouter.Provided>
|
|
18
|
+
|
|
19
|
+
export const genericMiddleware = (i: GenericMiddlewareMaker) => i
|
|
10
20
|
|
|
11
21
|
export const genericMiddlewareMaker = <
|
|
12
22
|
T extends Array<
|
|
@@ -21,17 +31,14 @@ export const genericMiddlewareMaker = <
|
|
|
21
31
|
effect: Effect.gen(function*() {
|
|
22
32
|
const middlewaresInstances = yield* Effect.all(middlewares)
|
|
23
33
|
|
|
24
|
-
return <A, E
|
|
25
|
-
|
|
26
|
-
moduleName: string
|
|
34
|
+
return <A, E>(
|
|
35
|
+
options: GenericMiddlewareOptions<A, E>
|
|
27
36
|
) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
effect = middleware(effect, moduleName)
|
|
32
|
-
}
|
|
33
|
-
return effect(input, headers)
|
|
37
|
+
let next = options.next
|
|
38
|
+
for (const middleware of (middlewaresInstances as any[]).toReversed()) {
|
|
39
|
+
next = middleware({ ...options, next })
|
|
34
40
|
}
|
|
41
|
+
return next
|
|
35
42
|
}
|
|
36
43
|
})
|
|
37
44
|
} as any
|
|
@@ -1,67 +1,49 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { Cause, Context, Effect, ParseResult } from "effect-app"
|
|
2
|
-
import { HttpHeaders, type HttpRouter, HttpServerRequest } from "effect-app/http"
|
|
3
3
|
import { pretty } from "effect-app/utils"
|
|
4
4
|
import { logError, reportError } from "../../../errorReporter.js"
|
|
5
5
|
import { InfraLogger } from "../../../logger.js"
|
|
6
|
+
import { genericMiddleware, RequestCacheLayers } from "../../routing.js"
|
|
6
7
|
|
|
7
8
|
const logRequestError = logError("Request")
|
|
8
9
|
const reportRequestError = reportError("Request")
|
|
9
10
|
|
|
10
11
|
export class DevMode extends Context.Reference<DevMode>()("DevMode", { defaultValue: () => false }) {}
|
|
12
|
+
// Effect Rpc Middleware: Wrap
|
|
13
|
+
export class RequestCacheMiddleware extends Effect.Service<RequestCacheMiddleware>()("RequestCacheMiddleware", {
|
|
14
|
+
effect: Effect.gen(function*() {
|
|
15
|
+
return genericMiddleware(Effect.fnUntraced(function*(options) {
|
|
16
|
+
return yield* options.next.pipe(Effect.provide(RequestCacheLayers))
|
|
17
|
+
}))
|
|
18
|
+
})
|
|
19
|
+
}) {}
|
|
11
20
|
|
|
21
|
+
// Effect Rpc Middleware: Wrap
|
|
12
22
|
export class ConfigureInterruptibility extends Effect.Service<ConfigureInterruptibility>()(
|
|
13
23
|
"ConfigureInterruptibility",
|
|
14
24
|
{
|
|
15
25
|
effect: Effect.gen(function*() {
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
|
|
23
|
-
Effect.uninterruptible
|
|
24
|
-
)
|
|
25
|
-
})
|
|
26
|
+
return genericMiddleware(Effect.fnUntraced(function*(options) {
|
|
27
|
+
return yield* options.next.pipe(
|
|
28
|
+
// TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
|
|
29
|
+
Effect.uninterruptible
|
|
30
|
+
)
|
|
31
|
+
}))
|
|
26
32
|
})
|
|
27
33
|
}
|
|
28
34
|
) {}
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
extends Effect.Service<CaptureHttpHeadersAsRpcHeaders>()("CaptureHttpHeadersAsRpcHeaders", {
|
|
32
|
-
effect: Effect.gen(function*() {
|
|
33
|
-
return <A, E>(
|
|
34
|
-
handle: (input: any, headers: HttpHeaders.Headers) => Effect.Effect<A, E, HttpRouter.HttpRouter.Provided>,
|
|
35
|
-
_moduleName: string
|
|
36
|
-
) =>
|
|
37
|
-
Effect.fnUntraced(function*(input: any, rpcHeaders: HttpHeaders.Headers) {
|
|
38
|
-
// merge in the request headers
|
|
39
|
-
// we should consider if we should merge them into rpc headers on the Protocol layer instead.
|
|
40
|
-
const httpReq = yield* HttpServerRequest.HttpServerRequest
|
|
41
|
-
const headers = HttpHeaders.merge(httpReq.headers, rpcHeaders)
|
|
42
|
-
return yield* handle(input, headers)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
})
|
|
46
|
-
{}
|
|
47
|
-
|
|
36
|
+
// Effect Rpc Middleware: Wrap
|
|
48
37
|
export class MiddlewareLogger extends Effect.Service<MiddlewareLogger>()("MiddlewareLogger", {
|
|
49
38
|
effect: Effect.gen(function*() {
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
moduleName: string
|
|
53
|
-
) =>
|
|
54
|
-
Effect.fnUntraced(function*(input: any, rpcHeaders: HttpHeaders.Headers) {
|
|
55
|
-
const devMode = yield* DevMode
|
|
56
|
-
// merge in the request headers
|
|
57
|
-
// we should consider if we should merge them into rpc headers on the Protocol layer instead.
|
|
58
|
-
const httpReq = yield* HttpServerRequest.HttpServerRequest
|
|
59
|
-
const headers = HttpHeaders.merge(httpReq.headers, rpcHeaders)
|
|
39
|
+
return genericMiddleware(Effect.fnUntraced(function*({ headers, next, payload, rpc }) {
|
|
40
|
+
const devMode = yield* DevMode
|
|
60
41
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
42
|
+
return yield* Effect
|
|
43
|
+
.annotateCurrentSpan(
|
|
44
|
+
"requestInput",
|
|
45
|
+
typeof payload === "object" && payload !== null
|
|
46
|
+
? Object.entries(payload).reduce((prev, [key, value]: [string, unknown]) => {
|
|
65
47
|
prev[key] = key === "password"
|
|
66
48
|
? "<redacted>"
|
|
67
49
|
: typeof value === "string" || typeof value === "number" || typeof value === "boolean"
|
|
@@ -77,44 +59,45 @@ export class MiddlewareLogger extends Effect.Service<MiddlewareLogger>()("Middle
|
|
|
77
59
|
: typeof value
|
|
78
60
|
return prev
|
|
79
61
|
}, {} as Record<string, string | number | boolean>)
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
|
|
62
|
+
: payload
|
|
63
|
+
)
|
|
64
|
+
.pipe(
|
|
65
|
+
// can't use andThen due to some being a function and effect
|
|
66
|
+
Effect.zipRight(next),
|
|
67
|
+
// TODO: support ParseResult if the error channel of the request allows it.. but who would want that?
|
|
68
|
+
Effect.catchAll((_) => ParseResult.isParseError(_) ? Effect.die(_) : Effect.fail(_)),
|
|
69
|
+
Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
|
|
70
|
+
Effect.tapDefect((cause) =>
|
|
71
|
+
Effect
|
|
72
|
+
.all([
|
|
73
|
+
reportRequestError(cause, {
|
|
74
|
+
action: rpc._tag
|
|
75
|
+
}),
|
|
76
|
+
InfraLogger
|
|
77
|
+
.logError("Finished request", cause)
|
|
78
|
+
.pipe(Effect.annotateLogs({
|
|
79
|
+
action: rpc._tag,
|
|
80
|
+
req: pretty(payload),
|
|
81
|
+
headers: pretty(headers)
|
|
82
|
+
// resHeaders: pretty(
|
|
83
|
+
// Object
|
|
84
|
+
// .entries(headers)
|
|
85
|
+
// .reduce((prev, [key, value]) => {
|
|
86
|
+
// prev[key] = value && typeof value === "string" ? snipString(value) : value
|
|
87
|
+
// return prev
|
|
88
|
+
// }, {} as Record<string, any>)
|
|
89
|
+
// )
|
|
90
|
+
}))
|
|
91
|
+
])
|
|
92
|
+
),
|
|
93
|
+
devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error"))
|
|
94
|
+
)
|
|
95
|
+
}))
|
|
113
96
|
})
|
|
114
97
|
}) {}
|
|
115
98
|
|
|
116
99
|
export const DefaultGenericMiddlewares = [
|
|
100
|
+
RequestCacheMiddleware,
|
|
117
101
|
ConfigureInterruptibility,
|
|
118
|
-
CaptureHttpHeadersAsRpcHeaders,
|
|
119
102
|
MiddlewareLogger
|
|
120
103
|
] as const
|
package/test/controller.test.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
|
-
import { type MakeContext, type MakeErrors, makeRouter
|
|
3
|
+
import { type MakeContext, type MakeErrors, makeRouter } from "@effect-app/infra/api/routing"
|
|
4
4
|
import type { RequestContext } from "@effect-app/infra/RequestContext"
|
|
5
5
|
import { expect, expectTypeOf, it } from "@effect/vitest"
|
|
6
6
|
import { type Array, Context, Effect, Layer, Option, S } from "effect-app"
|
|
7
7
|
import { InvalidStateError, makeRpcClient, type RPCContextMap, UnauthorizedError } from "effect-app/client"
|
|
8
|
-
import {
|
|
8
|
+
import { HttpServerRequest } from "effect-app/http"
|
|
9
9
|
import { Class, TaggedError } from "effect-app/Schema"
|
|
10
|
-
import { ContextProvider, DefaultGenericMiddlewares, makeMiddleware, mergeContextProviders, MergedContextProvider } from "../src/api/routing/middleware.js"
|
|
10
|
+
import { ContextProvider, DefaultGenericMiddlewares, genericMiddleware, implementMiddleware, makeMiddleware, mergeContextProviders, MergedContextProvider } from "../src/api/routing/middleware.js"
|
|
11
11
|
import { sort } from "../src/api/routing/tsort.js"
|
|
12
12
|
import { SomeService } from "./query.test.js"
|
|
13
13
|
|
|
@@ -76,11 +76,24 @@ class MyContextProvider extends Effect.Service<MyContextProvider>()("MyContextPr
|
|
|
76
76
|
})
|
|
77
77
|
}) {}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
80
|
+
class MyContextProvider2 extends Effect.Service<MyContextProvider2>()("MyContextProvider2", {
|
|
80
81
|
effect: Effect.gen(function*() {
|
|
82
|
+
yield* SomeService
|
|
83
|
+
if (Math.random() > 0.5) return yield* new CustomError1()
|
|
84
|
+
|
|
81
85
|
return Effect.gen(function*() {
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
// the only requiremeno you can have are the one provided by HttpRouter.HttpRouter.Provided
|
|
87
|
+
yield* HttpServerRequest.HttpServerRequest
|
|
88
|
+
|
|
89
|
+
// this is allowed here but mergeContextProviders/MergedContextProvider will trigger an error
|
|
90
|
+
// yield* SomeElse
|
|
91
|
+
|
|
92
|
+
// currently the effectful context provider cannot trigger an error when building the per request context
|
|
93
|
+
// this is allowed here but mergeContextProviders/MergedContextProvider will trigger an error
|
|
94
|
+
// if (Math.random() > 0.5) return yield* new CustomError2()
|
|
95
|
+
|
|
96
|
+
return Context.make(SomeElse, new SomeElse({ b: 2 }))
|
|
84
97
|
})
|
|
85
98
|
})
|
|
86
99
|
}) {}
|
|
@@ -90,9 +103,9 @@ export const contextProvider2 = ContextProvider(merged)
|
|
|
90
103
|
export const contextProvider3 = MergedContextProvider(MyContextProvider)
|
|
91
104
|
expectTypeOf(contextProvider2).toEqualTypeOf<typeof someContextProvider>()
|
|
92
105
|
expectTypeOf(contextProvider3).toEqualTypeOf<typeof contextProvider2>()
|
|
93
|
-
const merged2 = mergeContextProviders(MyContextProvider,
|
|
106
|
+
const merged2 = mergeContextProviders(MyContextProvider, MyContextProvider2)
|
|
94
107
|
export const contextProvider22 = ContextProvider(merged2)
|
|
95
|
-
export const contextProvider23 = MergedContextProvider(MyContextProvider,
|
|
108
|
+
export const contextProvider23 = MergedContextProvider(MyContextProvider, MyContextProvider2)
|
|
96
109
|
expectTypeOf(contextProvider23).toEqualTypeOf<typeof contextProvider22>()
|
|
97
110
|
|
|
98
111
|
export type RequestContextMap = {
|
|
@@ -124,8 +137,10 @@ class AllowAnonymous extends Effect.Service<AllowAnonymous>()("AllowAnonymous",
|
|
|
124
137
|
})
|
|
125
138
|
}) {}
|
|
126
139
|
|
|
140
|
+
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
127
141
|
class RequireRoles extends Effect.Service<RequireRoles>()("RequireRoles", {
|
|
128
142
|
effect: Effect.gen(function*() {
|
|
143
|
+
yield* Some
|
|
129
144
|
return {
|
|
130
145
|
handle: Effect.fn(
|
|
131
146
|
function*(cfg: { requireRoles?: readonly string[] }) {
|
|
@@ -154,24 +169,21 @@ class Test extends Effect.Service<Test>()("Test", {
|
|
|
154
169
|
})
|
|
155
170
|
}) {}
|
|
156
171
|
|
|
157
|
-
export class
|
|
172
|
+
export class BogusMiddleware extends Effect.Service<BogusMiddleware>()("BogusMiddleware", {
|
|
158
173
|
effect: Effect.gen(function*() {
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
) =>
|
|
163
|
-
Effect.fnUntraced(function*(input: any, headers: HttpHeaders.Headers) {
|
|
164
|
-
return yield* handle(input, headers)
|
|
165
|
-
})
|
|
174
|
+
return genericMiddleware(Effect.fnUntraced(function*(options) {
|
|
175
|
+
return yield* options.next
|
|
176
|
+
}))
|
|
166
177
|
})
|
|
167
178
|
}) {}
|
|
168
179
|
|
|
180
|
+
const contextProvider = MergedContextProvider(MyContextProvider2, MyContextProvider)
|
|
169
181
|
// TODO: eventually it might be nice if we have total control over order somehow..
|
|
170
182
|
// [ AddRequestNameToSpanContext, RequestCacheContext, UninterruptibleMiddleware, Dynamic(or individual, AllowAnonymous, RequireRoles, Test - or whichever order) ]
|
|
171
183
|
const middleware = makeMiddleware<RequestContextMap>()({
|
|
172
184
|
// TODO: I guess it makes sense to support just passing array of context providers too, like dynamicMiddlewares?
|
|
173
|
-
contextProvider
|
|
174
|
-
genericMiddlewares: [...DefaultGenericMiddlewares,
|
|
185
|
+
contextProvider,
|
|
186
|
+
genericMiddlewares: [...DefaultGenericMiddlewares, BogusMiddleware],
|
|
175
187
|
// or is the better api to use constructors outside, like how contextProvider is used now?
|
|
176
188
|
dynamicMiddlewares: {
|
|
177
189
|
requireRoles: RequireRoles,
|
|
@@ -202,8 +214,8 @@ const middleware = makeMiddleware<RequestContextMap>()({
|
|
|
202
214
|
|
|
203
215
|
const middleware2 = makeMiddleware<RequestContextMap>()({
|
|
204
216
|
// TODO: I guess it makes sense to support just passing array of context providers too, like dynamicMiddlewares?
|
|
205
|
-
contextProvider
|
|
206
|
-
genericMiddlewares: [...DefaultGenericMiddlewares,
|
|
217
|
+
contextProvider,
|
|
218
|
+
genericMiddlewares: [...DefaultGenericMiddlewares, BogusMiddleware],
|
|
207
219
|
// or is the better api to use constructors outside, like how contextProvider is used now?
|
|
208
220
|
dynamicMiddlewares: {
|
|
209
221
|
requireRoles: RequireRoles,
|
|
@@ -439,3 +451,9 @@ expectTypeOf({} as MakeErrors<typeof router2.make>).toEqualTypeOf<InvalidStateEr
|
|
|
439
451
|
expectTypeOf({} as makeContext2).toEqualTypeOf<
|
|
440
452
|
SomethingService | SomethingRepo | SomethingService2
|
|
441
453
|
>()
|
|
454
|
+
|
|
455
|
+
export const dynamicMiddlewares = implementMiddleware<RequestContextMap>()({
|
|
456
|
+
requireRoles: RequireRoles,
|
|
457
|
+
allowAnonymous: AllowAnonymous,
|
|
458
|
+
test: Test
|
|
459
|
+
})
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"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"}
|