@effect-app/infra 2.85.0 → 2.87.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 +17 -0
- package/dist/api/layerUtils.d.ts +4 -8
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +3 -11
- package/dist/api/routing/middleware/ContextProvider.d.ts +2 -2
- package/dist/api/routing/middleware/ContextProvider.d.ts.map +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +33 -0
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -0
- package/dist/api/routing/middleware/RouterMiddleware.js +5 -0
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +199 -0
- package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -0
- package/dist/api/routing/middleware/RpcMiddleware.js +14 -0
- package/dist/api/routing/middleware/dynamic-middleware.d.ts +3 -13
- package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/dynamic-middleware.js +2 -18
- package/dist/api/routing/middleware/generic-middleware.d.ts +15 -22
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +13 -9
- package/dist/api/routing/middleware/middleware-api.d.ts +55 -8
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +50 -14
- package/dist/api/routing/middleware/middleware.d.ts +8 -7
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +6 -5
- package/dist/api/routing/middleware.d.ts +2 -1
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +3 -2
- package/dist/api/routing/tsort.d.ts +2 -2
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/tsort.js +1 -1
- package/dist/api/routing.d.ts +0 -1
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +2 -3
- package/package.json +9 -5
- package/src/api/layerUtils.ts +7 -21
- package/src/api/routing/middleware/ContextProvider.ts +5 -5
- package/src/api/routing/middleware/RouterMiddleware.ts +149 -0
- package/src/api/routing/middleware/RpcMiddleware.ts +287 -0
- package/src/api/routing/middleware/dynamic-middleware.ts +9 -54
- package/src/api/routing/middleware/generic-middleware.ts +33 -33
- package/src/api/routing/middleware/middleware-api.ts +202 -32
- package/src/api/routing/middleware/middleware.ts +13 -5
- package/src/api/routing/middleware.ts +2 -1
- package/src/api/routing/tsort.ts +2 -2
- package/src/api/routing.ts +1 -9
- package/test/contextProvider.test.ts +1 -2
- package/test/controller.test.ts +35 -155
- 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 +146 -0
- package/test/dist/fixtures.d.ts.map +1 -0
- package/test/dist/fixtures.js +82 -0
- package/test/dist/layerUtils.test.d.ts.map +1 -0
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/requires.d.ts +21 -0
- package/test/dist/requires.d.ts.map +1 -0
- package/test/dist/requires.js +27 -0
- package/test/dist/requires.test.d.ts.map +1 -0
- package/test/fixtures.ts +102 -0
- package/test/layerUtils.test.ts +19 -0
- package/test/query.test.ts +2 -4
- package/test/requires.test.ts +156 -0
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts +0 -215
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/DynamicMiddleware.js +0 -168
- package/src/api/routing/middleware/DynamicMiddleware.ts +0 -693
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { type Rpc, type RpcMiddleware } from "@effect/rpc"
|
|
3
|
-
import { type SuccessValue
|
|
4
|
-
import { type Array, Context, Effect, type Layer, type NonEmptyReadonlyArray,
|
|
5
|
-
import { type
|
|
3
|
+
import { type SuccessValue } from "@effect/rpc/RpcMiddleware"
|
|
4
|
+
import { type Array, Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type Scope } from "effect-app"
|
|
5
|
+
import { type ContextRepr } from "effect-app/client"
|
|
6
6
|
import { type HttpHeaders } from "effect-app/http"
|
|
7
|
-
import { type Tag } from "effect/Context"
|
|
8
7
|
import { InfraLogger } from "../../../logger.js"
|
|
9
|
-
import { type
|
|
10
|
-
|
|
11
|
-
export type ContextRepr = NonEmptyReadonlyArray<Context.Tag<any, any>>
|
|
12
|
-
export namespace ContextRepr {
|
|
13
|
-
export type Identifier<A> = A extends ContextRepr ? Tag.Identifier<A[number]> : never
|
|
14
|
-
export type Service<A> = A extends ContextRepr ? Tag.Service<A[number]> : never
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface TagClassAny extends Context.Tag<any, any> {
|
|
18
|
-
readonly [TypeId]: TypeId
|
|
19
|
-
readonly optional: boolean
|
|
20
|
-
readonly provides?: Context.Tag<any, any> | ContextRepr | undefined
|
|
21
|
-
readonly failure: Schema.Schema.All
|
|
22
|
-
readonly requiredForClient: boolean
|
|
23
|
-
readonly wrap: boolean
|
|
24
|
-
}
|
|
8
|
+
import { type TagClassAny } from "./RpcMiddleware.js"
|
|
25
9
|
|
|
26
10
|
export interface GenericMiddlewareOptions<E> {
|
|
27
11
|
// Effect rpc middleware does not support changing payload or headers, but we do..
|
|
@@ -33,19 +17,24 @@ export interface GenericMiddlewareOptions<E> {
|
|
|
33
17
|
}
|
|
34
18
|
|
|
35
19
|
export type GenericMiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
|
|
36
|
-
export type DynamicMiddlewareMaker<RequestContext extends Record<string, RPCContextMap.Any>> =
|
|
37
|
-
& TagClassDynamicAny<RequestContext>
|
|
38
|
-
& { Default: Layer.Layer.Any } // todo; and Layer..
|
|
39
20
|
|
|
40
21
|
export namespace GenericMiddlewareMaker {
|
|
22
|
+
export type ApplyServices<A extends TagClassAny, R> = Exclude<R, Provided<A>> | Required<A>
|
|
23
|
+
export type ApplyManyServices<A extends NonEmptyReadonlyArray<TagClassAny>, R> =
|
|
24
|
+
| Exclude<R, { [K in keyof A]: Provided<A[K]> }[number]>
|
|
25
|
+
| { [K in keyof A]: Required<A[K]> }[number]
|
|
41
26
|
export type Provided<T> = T extends TagClassAny
|
|
42
27
|
? T extends { provides: Context.Tag<any, any> } ? Context.Tag.Identifier<T["provides"]>
|
|
43
28
|
: T extends { provides: ContextRepr } ? ContextRepr.Identifier<T["provides"]>
|
|
44
29
|
: never
|
|
45
30
|
: never
|
|
46
|
-
}
|
|
47
31
|
|
|
48
|
-
export
|
|
32
|
+
export type Required<T> = T extends TagClassAny
|
|
33
|
+
? T extends { requires: Context.Tag<any, any> } ? Context.Tag.Identifier<T["requires"]>
|
|
34
|
+
: T extends { requires: ContextRepr } ? ContextRepr.Identifier<T["requires"]>
|
|
35
|
+
: never
|
|
36
|
+
: never
|
|
37
|
+
}
|
|
49
38
|
|
|
50
39
|
export const genericMiddlewareMaker = <
|
|
51
40
|
T extends Array<GenericMiddlewareMaker>
|
|
@@ -59,11 +48,6 @@ export const genericMiddlewareMaker = <
|
|
|
59
48
|
dependencies: middlewares.map((_) => _.Default),
|
|
60
49
|
effect: Effect.gen(function*() {
|
|
61
50
|
const context = yield* Effect.context()
|
|
62
|
-
// const middlewares: readonly (RpcMiddlewareWrap<any, any> | RpcMiddleware.RpcMiddleware<any, any>)[] =
|
|
63
|
-
// (yield* Effect.all(
|
|
64
|
-
// middlewares
|
|
65
|
-
// )) as any
|
|
66
|
-
|
|
67
51
|
return <E>(
|
|
68
52
|
options: GenericMiddlewareOptions<E>
|
|
69
53
|
) => {
|
|
@@ -72,13 +56,13 @@ export const genericMiddlewareMaker = <
|
|
|
72
56
|
for (const tag of middlewares) {
|
|
73
57
|
if (tag.wrap) {
|
|
74
58
|
const middleware = Context.unsafeGet(context, tag)
|
|
75
|
-
handler = InfraLogger.logDebug("Applying middleware " + tag.key).pipe(
|
|
76
|
-
Effect.zipRight(middleware({ ...options, next: handler
|
|
59
|
+
handler = InfraLogger.logDebug("Applying middleware wrap " + tag.key).pipe(
|
|
60
|
+
Effect.zipRight(middleware({ ...options, next: handler }))
|
|
77
61
|
) as any
|
|
78
62
|
} else if (tag.optional) {
|
|
79
63
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
80
64
|
const previous = handler
|
|
81
|
-
handler = InfraLogger.logDebug("Applying middleware " + tag.key).pipe(
|
|
65
|
+
handler = InfraLogger.logDebug("Applying middleware optional " + tag.key).pipe(
|
|
82
66
|
Effect.zipRight(Effect.matchEffect(middleware(options), {
|
|
83
67
|
onFailure: () => previous,
|
|
84
68
|
onSuccess: tag.provides !== undefined
|
|
@@ -89,6 +73,22 @@ export const genericMiddlewareMaker = <
|
|
|
89
73
|
: (_) => previous
|
|
90
74
|
}))
|
|
91
75
|
)
|
|
76
|
+
} else if (tag.dynamic) {
|
|
77
|
+
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
78
|
+
const previous = handler
|
|
79
|
+
handler = InfraLogger.logDebug("Applying middleware dynamic " + tag.key, tag.dynamic).pipe(
|
|
80
|
+
Effect.zipRight(
|
|
81
|
+
middleware(options).pipe(
|
|
82
|
+
Effect.flatMap((value) =>
|
|
83
|
+
Option.isSome(value)
|
|
84
|
+
? Context.isContext(value.value)
|
|
85
|
+
? Effect.provide(previous, value.value)
|
|
86
|
+
: Effect.provideService(previous, tag.dynamic!.settings.service!, /* TODO */ value.value)
|
|
87
|
+
: previous
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
92
|
} else {
|
|
93
93
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
94
94
|
const previous = handler
|
|
@@ -1,50 +1,220 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Rpc } from "@effect/rpc"
|
|
2
|
+
import { Context, Effect, Layer, type NonEmptyArray, type NonEmptyReadonlyArray } from "effect-app"
|
|
2
3
|
import { type RPCContextMap } from "effect-app/client"
|
|
3
|
-
import { type
|
|
4
|
+
import { type Simplify } from "effect-app/Types"
|
|
5
|
+
import { type LayerUtils } from "../../layerUtils.js"
|
|
6
|
+
import { type GenericMiddlewareMaker, genericMiddlewareMaker } from "./generic-middleware.js"
|
|
7
|
+
import { makeRpcEffect, type MiddlewareMakerId, type RPCHandlerFactory } from "./RouterMiddleware.js"
|
|
8
|
+
import { type AnyDynamic, type RpcDynamic, type TagClassAny } from "./RpcMiddleware.js"
|
|
4
9
|
|
|
5
|
-
// TODO:
|
|
6
|
-
//
|
|
7
|
-
export const contextMap =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
// TODO: don't expect service when it's wrap/never
|
|
11
|
+
// perhaps RequestContextMap should be an object, instead of an interface, so that we don't need to provide anything here
|
|
12
|
+
export const contextMap =
|
|
13
|
+
<RequestContextMap extends Record<string, RPCContextMap.Any>>() =>
|
|
14
|
+
<K extends keyof RequestContextMap>(a: K, service: RequestContextMap[K]["service"]) => ({
|
|
15
|
+
key: a,
|
|
16
|
+
settings: { service } as any as RequestContextMap[typeof a]
|
|
17
|
+
})
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
export interface MiddlewareM<
|
|
20
|
+
RequestContext extends Record<string, RPCContextMap.Any>,
|
|
21
|
+
Provided extends keyof RequestContext,
|
|
22
|
+
Middlewares extends ReadonlyArray<GenericMiddlewareMaker>,
|
|
23
|
+
DynamicMiddlewareProviders,
|
|
24
|
+
// out MiddlewareR = never
|
|
25
|
+
MiddlewareR = never
|
|
26
|
+
> {
|
|
27
|
+
middleware<MW extends NonEmptyArray<GenericMiddlewareMaker>>(
|
|
28
|
+
...mw: MW
|
|
29
|
+
): DynamicMiddlewareMakerrsss<
|
|
30
|
+
RequestContext,
|
|
31
|
+
Provided,
|
|
32
|
+
[...Middlewares, ...MW],
|
|
33
|
+
DynamicMiddlewareProviders,
|
|
34
|
+
GenericMiddlewareMaker.ApplyManyServices<MW, MiddlewareR>
|
|
35
|
+
>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type GetDependsOnKeys<MW extends GenericMiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> }
|
|
39
|
+
? {
|
|
40
|
+
[K in keyof MW["dependsOn"]]: MW["dependsOn"][K] extends AnyDynamic ? MW["dependsOn"][K]["dynamic"]["key"]
|
|
41
|
+
: never
|
|
42
|
+
}[keyof MW["dependsOn"]]
|
|
43
|
+
: never
|
|
44
|
+
|
|
45
|
+
export interface MiddlewareDynamic<
|
|
13
46
|
RequestContext extends Record<string, RPCContextMap.Any>,
|
|
14
47
|
Provided extends keyof RequestContext,
|
|
15
|
-
Middlewares extends
|
|
16
|
-
DynamicMiddlewareProviders
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
48
|
+
Middlewares extends ReadonlyArray<GenericMiddlewareMaker>,
|
|
49
|
+
DynamicMiddlewareProviders,
|
|
50
|
+
out MiddlewareR
|
|
51
|
+
> {
|
|
52
|
+
middleware<MW extends NonEmptyArray<GenericMiddlewareMaker>>(
|
|
53
|
+
...mw: MW
|
|
54
|
+
): MW extends NonEmptyArray<{ dynamic: RpcDynamic<any, RequestContext[keyof RequestContext]> }>
|
|
55
|
+
? DynamicMiddlewareMakerrsss<
|
|
23
56
|
RequestContext,
|
|
24
|
-
|
|
25
|
-
|
|
57
|
+
// when one dynamic middleware depends on another, substract the key, to enforce the dependency to be provided after.
|
|
58
|
+
Exclude<
|
|
59
|
+
Provided | MW[number]["dynamic"]["key"],
|
|
60
|
+
{ [K in keyof MW]: GetDependsOnKeys<MW[K]> }[number]
|
|
61
|
+
>,
|
|
62
|
+
[...Middlewares, ...MW],
|
|
26
63
|
& DynamicMiddlewareProviders
|
|
27
64
|
& {
|
|
28
|
-
[
|
|
65
|
+
[U in MW[number] as U["dynamic"]["key"]]: U
|
|
66
|
+
},
|
|
67
|
+
GenericMiddlewareMaker.ApplyManyServices<MW, MiddlewareR>
|
|
68
|
+
>
|
|
69
|
+
: DynamicMiddlewareMakerrsss<
|
|
70
|
+
RequestContext,
|
|
71
|
+
Provided,
|
|
72
|
+
[...Middlewares, ...MW],
|
|
73
|
+
DynamicMiddlewareProviders,
|
|
74
|
+
GenericMiddlewareMaker.ApplyManyServices<MW, MiddlewareR>
|
|
75
|
+
>
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
type DynamicMiddlewareMakerrsss<
|
|
79
|
+
RequestContext extends Record<string, RPCContextMap.Any>,
|
|
80
|
+
Provided extends keyof RequestContext = never,
|
|
81
|
+
Middlewares extends ReadonlyArray<GenericMiddlewareMaker> = [],
|
|
82
|
+
DynamicMiddlewareProviders = unknown,
|
|
83
|
+
MiddlewareR = never
|
|
84
|
+
> = keyof Omit<RequestContext, Provided> extends never ? [MiddlewareR] extends [never] ?
|
|
85
|
+
& {
|
|
86
|
+
MiddlewareR: MiddlewareR
|
|
87
|
+
Provided: Provided
|
|
88
|
+
Middlewares: Middlewares
|
|
89
|
+
DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
|
|
29
90
|
}
|
|
91
|
+
& ReturnType<
|
|
92
|
+
typeof makeMiddlewareBasic<
|
|
93
|
+
RequestContext,
|
|
94
|
+
Middlewares
|
|
95
|
+
>
|
|
96
|
+
>
|
|
97
|
+
& MiddlewareM<
|
|
98
|
+
RequestContext,
|
|
99
|
+
Provided,
|
|
100
|
+
Middlewares,
|
|
101
|
+
DynamicMiddlewareProviders,
|
|
102
|
+
MiddlewareR
|
|
103
|
+
>
|
|
104
|
+
:
|
|
105
|
+
& {
|
|
106
|
+
MiddlewareR: MiddlewareR
|
|
107
|
+
Provided: Provided
|
|
108
|
+
Middlewares: Middlewares
|
|
109
|
+
DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
|
|
110
|
+
}
|
|
111
|
+
& MiddlewareM<
|
|
112
|
+
RequestContext,
|
|
113
|
+
Provided,
|
|
114
|
+
Middlewares,
|
|
115
|
+
DynamicMiddlewareProviders,
|
|
116
|
+
MiddlewareR
|
|
117
|
+
>
|
|
118
|
+
:
|
|
119
|
+
& {
|
|
120
|
+
MiddlewareR: MiddlewareR
|
|
121
|
+
Provided: Provided
|
|
122
|
+
Middlewares: Middlewares
|
|
123
|
+
DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
|
|
124
|
+
}
|
|
125
|
+
& MiddlewareDynamic<
|
|
126
|
+
RequestContext,
|
|
127
|
+
Provided,
|
|
128
|
+
Middlewares,
|
|
129
|
+
DynamicMiddlewareProviders,
|
|
130
|
+
MiddlewareR
|
|
30
131
|
>
|
|
31
|
-
}
|
|
32
132
|
|
|
33
|
-
export const
|
|
133
|
+
export const makeMiddleware: <
|
|
34
134
|
RequestContextMap extends Record<string, RPCContextMap.Any>
|
|
35
|
-
>() => <
|
|
36
|
-
|
|
37
|
-
) => DynamicMiddlewareMakerrsss<RequestContextMap, never, Middlewares, never> = () => (...genericMiddlewares) => {
|
|
38
|
-
const dynamicMiddlewares: Record<string, any> = {} as any
|
|
39
|
-
const make = makeMiddleware<any>()
|
|
135
|
+
>() => DynamicMiddlewareMakerrsss<RequestContextMap> = () => {
|
|
136
|
+
let allMiddleware: GenericMiddlewareMaker[] = []
|
|
40
137
|
const it = {
|
|
41
|
-
|
|
42
|
-
for (const
|
|
43
|
-
|
|
44
|
-
dynamicMiddlewares[a.dynamic.key] = a
|
|
138
|
+
middleware: (...middlewares: any[]) => {
|
|
139
|
+
for (const mw of middlewares) {
|
|
140
|
+
allMiddleware = [mw, ...allMiddleware]
|
|
45
141
|
}
|
|
46
|
-
|
|
142
|
+
// TODO: support dynamic and generic intertwined. treat them as one
|
|
143
|
+
return Object.assign(makeMiddlewareBasic<any, any>(...allMiddleware), it)
|
|
47
144
|
}
|
|
48
145
|
}
|
|
49
146
|
return it as any
|
|
50
147
|
}
|
|
148
|
+
|
|
149
|
+
export const makeMiddlewareBasic =
|
|
150
|
+
// by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
|
|
151
|
+
<
|
|
152
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
153
|
+
// RequestContextProviders extends RequestContextMapProvider<RequestContextMap>, // how to resolve the dynamic middleware
|
|
154
|
+
GenericMiddlewareProviders extends ReadonlyArray<GenericMiddlewareMaker>
|
|
155
|
+
>(
|
|
156
|
+
...make: GenericMiddlewareProviders
|
|
157
|
+
) => {
|
|
158
|
+
const MiddlewareMaker = Context.GenericTag<
|
|
159
|
+
MiddlewareMakerId,
|
|
160
|
+
{
|
|
161
|
+
effect: RPCHandlerFactory<
|
|
162
|
+
RequestContextMap,
|
|
163
|
+
GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
|
|
164
|
+
>
|
|
165
|
+
_tag: "MiddlewareMaker"
|
|
166
|
+
}
|
|
167
|
+
>(
|
|
168
|
+
"MiddlewareMaker"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
const middlewares = genericMiddlewareMaker(...make)
|
|
172
|
+
|
|
173
|
+
const l = Layer.scoped(
|
|
174
|
+
MiddlewareMaker,
|
|
175
|
+
middlewares
|
|
176
|
+
.effect
|
|
177
|
+
.pipe(
|
|
178
|
+
Effect.map((generic) => ({
|
|
179
|
+
_tag: "MiddlewareMaker" as const,
|
|
180
|
+
effect: makeRpcEffect<
|
|
181
|
+
RequestContextMap,
|
|
182
|
+
GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
|
|
183
|
+
>()(
|
|
184
|
+
(schema, next, moduleName) => {
|
|
185
|
+
return (payload, headers) =>
|
|
186
|
+
Effect
|
|
187
|
+
.gen(function*() {
|
|
188
|
+
const basic = {
|
|
189
|
+
config: schema.config ?? {},
|
|
190
|
+
payload,
|
|
191
|
+
headers,
|
|
192
|
+
clientId: 0, // TODO: get the clientId from the request context
|
|
193
|
+
rpc: {
|
|
194
|
+
...Rpc.fromTaggedRequest(schema as any),
|
|
195
|
+
key: `${moduleName}.${payload._tag}`,
|
|
196
|
+
_tag: `${moduleName}.${payload._tag}`
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return yield* generic({
|
|
200
|
+
...basic,
|
|
201
|
+
next: next(payload, headers) as any
|
|
202
|
+
})
|
|
203
|
+
}) as any // why?
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
}))
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
const middlewareLayer = l
|
|
211
|
+
.pipe(
|
|
212
|
+
Layer.provide(middlewares.dependencies as any)
|
|
213
|
+
) as Layer.Layer<
|
|
214
|
+
MiddlewareMakerId,
|
|
215
|
+
LayerUtils.GetLayersError<typeof middlewares.dependencies>, // what could go wrong when building the dynamic middleware provider
|
|
216
|
+
LayerUtils.GetLayersContext<typeof middlewares.dependencies>
|
|
217
|
+
>
|
|
218
|
+
|
|
219
|
+
return Object.assign(MiddlewareMaker, { Default: middlewareLayer })
|
|
220
|
+
}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Cause, Context, Effect, ParseResult } from "effect-app"
|
|
2
|
+
import { Cause, Context, Duration, Effect, Layer, ParseResult, Request } from "effect-app"
|
|
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 {
|
|
6
|
+
import { Tag } from "./RpcMiddleware.js"
|
|
7
7
|
|
|
8
8
|
const logRequestError = logError("Request")
|
|
9
9
|
const reportRequestError = reportError("Request")
|
|
10
10
|
|
|
11
|
+
export const RequestCacheLayers = Layer.mergeAll(
|
|
12
|
+
Layer.setRequestCache(
|
|
13
|
+
Request.makeCache({ capacity: 500, timeToLive: Duration.hours(8) })
|
|
14
|
+
),
|
|
15
|
+
Layer.setRequestCaching(true),
|
|
16
|
+
Layer.setRequestBatching(true)
|
|
17
|
+
)
|
|
18
|
+
|
|
11
19
|
export class DevMode extends Context.Reference<DevMode>()("DevMode", { defaultValue: () => false }) {}
|
|
12
20
|
|
|
13
21
|
export class RequestCacheMiddleware extends Tag<RequestCacheMiddleware>()("RequestCacheMiddleware", { wrap: true })({
|
|
14
|
-
effect: Effect.succeed((
|
|
22
|
+
effect: Effect.succeed(({ next }) => next.pipe(Effect.provide(RequestCacheLayers)))
|
|
15
23
|
}) {
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
export class ConfigureInterruptibility
|
|
19
27
|
extends Tag<ConfigureInterruptibility>()("ConfigureInterruptibility", { wrap: true })({
|
|
20
|
-
effect: Effect.succeed((
|
|
21
|
-
|
|
28
|
+
effect: Effect.succeed(({ next }) =>
|
|
29
|
+
next.pipe(
|
|
22
30
|
// TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
|
|
23
31
|
Effect.uninterruptible
|
|
24
32
|
)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// codegen:start {preset: barrel, include: ./middleware/*.ts, nodir: false }
|
|
2
2
|
export * from "./middleware/ContextProvider.js"
|
|
3
3
|
export * from "./middleware/dynamic-middleware.js"
|
|
4
|
-
export * from "./middleware/DynamicMiddleware.js"
|
|
5
4
|
export * from "./middleware/generic-middleware.js"
|
|
6
5
|
export * from "./middleware/middleware-api.js"
|
|
7
6
|
export * from "./middleware/middleware.js"
|
|
7
|
+
export * from "./middleware/RouterMiddleware.js"
|
|
8
|
+
export * from "./middleware/RpcMiddleware.js"
|
|
8
9
|
// codegen:end
|
|
9
10
|
|
|
10
11
|
export * as Middleware from "./middleware.js"
|
package/src/api/routing/tsort.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function tsort(edges) {
|
|
|
39
39
|
return sorted
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export const createEdges = <T extends { dependsOn?: any[] }>(dep: readonly T[]) => {
|
|
42
|
+
export const createEdges = <T extends { dependsOn?: readonly any[] }>(dep: readonly T[]) => {
|
|
43
43
|
const result = []
|
|
44
44
|
dep.forEach((key) => {
|
|
45
45
|
key.dependsOn?.forEach((n) => {
|
|
@@ -49,7 +49,7 @@ export const createEdges = <T extends { dependsOn?: any[] }>(dep: readonly T[])
|
|
|
49
49
|
return result
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export const sort = <T>(dep: readonly (T & { dependsOn?: any[] })[]): readonly T[] => {
|
|
52
|
+
export const sort = <T>(dep: readonly (T & { dependsOn?: readonly any[] })[]): readonly T[] => {
|
|
53
53
|
const edges = createEdges(dep)
|
|
54
54
|
const result = tsort(edges)
|
|
55
55
|
return result.concat(dep.filter((v) => !result.includes(v)))
|
package/src/api/routing.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
5
|
import { determineMethod, isCommand } from "@effect-app/infra/api/routing/utils"
|
|
6
6
|
import { Rpc, RpcGroup, RpcServer } from "@effect/rpc"
|
|
7
|
-
import { type Array,
|
|
7
|
+
import { type Array, Effect, Layer, type NonEmptyReadonlyArray, Predicate, S, Schedule, Schema, type Scope } from "effect-app"
|
|
8
8
|
import type { GetEffectContext, GetEffectError, RPCContextMap } from "effect-app/client/req"
|
|
9
9
|
import { type HttpHeaders, HttpRouter } from "effect-app/http"
|
|
10
10
|
import { typedKeysOf, typedValuesOf } from "effect-app/utils"
|
|
@@ -819,11 +819,3 @@ export type MakeHandlers<Make, Handlers extends Record<string, any>> = Make exte
|
|
|
819
819
|
* @since 3.9.0
|
|
820
820
|
*/
|
|
821
821
|
export type MakeDepsOut<Make> = Contravariant.Type<MakeDeps<Make>[Layer.LayerTypeId]["_ROut"]>
|
|
822
|
-
|
|
823
|
-
export const RequestCacheLayers = Layer.mergeAll(
|
|
824
|
-
Layer.setRequestCache(
|
|
825
|
-
Request.makeCache({ capacity: 500, timeToLive: Duration.hours(8) })
|
|
826
|
-
),
|
|
827
|
-
Layer.setRequestCaching(true),
|
|
828
|
-
Layer.setRequestBatching(true)
|
|
829
|
-
)
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
import { expectTypeOf } from "@effect/vitest"
|
|
4
4
|
import { Context, Effect, Scope } from "effect-app"
|
|
5
5
|
import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/routing.js"
|
|
6
|
-
import { CustomError1, Some, SomeElse } from "./
|
|
7
|
-
import { SomeService } from "./query.test.js"
|
|
6
|
+
import { CustomError1, Some, SomeElse, SomeService } from "./fixtures.js"
|
|
8
7
|
|
|
9
8
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
10
9
|
class MyContextProvider extends Effect.Service<MyContextProvider>()("MyContextProvider", {
|