@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
|
@@ -2,57 +2,66 @@ import { Rpc } from "@effect/rpc";
|
|
|
2
2
|
import { Context, Effect, Layer } from "effect-app";
|
|
3
3
|
import { genericMiddlewareMaker } from "./generic-middleware.js";
|
|
4
4
|
import { makeRpcEffect } from "./RouterMiddleware.js";
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
settings: { service }
|
|
5
|
+
// adapter used when setting the dynamic prop on a middleware implementation
|
|
6
|
+
export const contextMap = (rcm, key) => ({
|
|
7
|
+
key,
|
|
8
|
+
settings: { service: rcm[key]["service"] }
|
|
10
9
|
});
|
|
11
|
-
export const makeMiddleware = () => {
|
|
10
|
+
export const makeMiddleware = (rcm) => {
|
|
12
11
|
let allMiddleware = [];
|
|
13
12
|
const it = {
|
|
14
13
|
middleware: (...middlewares) => {
|
|
15
14
|
for (const mw of middlewares) {
|
|
15
|
+
// recall that we run middlewares in reverse order
|
|
16
16
|
allMiddleware = [mw, ...allMiddleware];
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
return allMiddleware.filter((m) => !!m.dynamic).length !== Object.keys(rcm).length
|
|
19
|
+
// for sure, until all the dynamic middlewares are provided it's non sensical to call makeMiddlewareBasic
|
|
20
|
+
? it
|
|
21
|
+
// actually, we don't know yet if MiddlewareR is never, but we can't easily check it at runtime
|
|
22
|
+
: Object.assign(makeMiddlewareBasic(rcm, ...allMiddleware), it);
|
|
20
23
|
}
|
|
21
24
|
};
|
|
22
25
|
return it;
|
|
23
26
|
};
|
|
24
|
-
|
|
27
|
+
//
|
|
28
|
+
export const MiddlewareMakerTag = "MiddlewareMaker";
|
|
29
|
+
export const buildMiddlewareMaker = (eff) => ({
|
|
30
|
+
_tag: MiddlewareMakerTag,
|
|
31
|
+
effect: eff
|
|
32
|
+
});
|
|
33
|
+
const makeMiddlewareBasic =
|
|
25
34
|
// by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
|
|
26
|
-
(...make) => {
|
|
27
|
-
const MiddlewareMaker = Context.GenericTag(
|
|
35
|
+
(_rcm, ...make) => {
|
|
36
|
+
const MiddlewareMaker = Context.GenericTag(MiddlewareMakerTag);
|
|
37
|
+
// reverse middlewares and wrap one after the other
|
|
28
38
|
const middlewares = genericMiddlewareMaker(...make);
|
|
29
39
|
const l = Layer.scoped(MiddlewareMaker, middlewares
|
|
30
40
|
.effect
|
|
31
|
-
.pipe(Effect.map((generic) => ({
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
53
|
-
}))));
|
|
41
|
+
.pipe(Effect.map((generic) => (buildMiddlewareMaker(makeRpcEffect()((schema, handler, moduleName) => {
|
|
42
|
+
return (payload, headers) => Effect
|
|
43
|
+
.gen(function* () {
|
|
44
|
+
// will be propagated to all the wrapped middlewares
|
|
45
|
+
const basic = {
|
|
46
|
+
config: schema.config ?? {},
|
|
47
|
+
payload,
|
|
48
|
+
headers,
|
|
49
|
+
clientId: 0, // TODO: get the clientId from the request context
|
|
50
|
+
rpc: {
|
|
51
|
+
...Rpc.fromTaggedRequest(schema),
|
|
52
|
+
key: `${moduleName}.${payload._tag}`,
|
|
53
|
+
_tag: `${moduleName}.${payload._tag}`
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return yield* generic({
|
|
57
|
+
...basic,
|
|
58
|
+
next: handler(payload, headers)
|
|
59
|
+
});
|
|
60
|
+
}); // why? because: Type 'SuccessValue' is not assignable to type 'Success<Req>' :P
|
|
61
|
+
}))))));
|
|
54
62
|
const middlewareLayer = l
|
|
55
63
|
.pipe(Layer.provide(middlewares.dependencies));
|
|
64
|
+
// add to the tag a default implementation
|
|
56
65
|
return Object.assign(MiddlewareMaker, { Default: middlewareLayer });
|
|
57
66
|
};
|
|
58
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS1hcGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBpL3JvdXRpbmcvbWlkZGxld2FyZS9taWRkbGV3YXJlLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ2pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBa0QsTUFBTSxZQUFZLENBQUE7QUFHbkcsT0FBTyxFQUErQixzQkFBc0IsRUFBRSxNQUFNLHlCQUF5QixDQUFBO0FBQzdGLE9BQU8sRUFBRSxhQUFhLEVBQTBCLE1BQU0sdUJBQXVCLENBQUE7QUFHN0UsNEVBQTRFO0FBQzVFLE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxDQUd4QixHQUFzQixFQUFFLEdBQVEsRUFBMkMsRUFBRSxDQUFDLENBQUM7SUFDL0UsR0FBRztJQUNILFFBQVEsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFFLENBQUMsU0FBUyxDQUFDLEVBQTRCO0NBQ3RFLENBQUMsQ0FBQTtBQXdIRixNQUFNLENBQUMsTUFBTSxjQUFjLEdBRTBDLENBQUMsR0FBRyxFQUFFLEVBQUU7SUFDM0UsSUFBSSxhQUFhLEdBQTZCLEVBQUUsQ0FBQTtJQUNoRCxNQUFNLEVBQUUsR0FBRztRQUNULFVBQVUsRUFBRSxDQUFDLEdBQUcsV0FBa0IsRUFBRSxFQUFFO1lBQ3BDLEtBQUssTUFBTSxFQUFFLElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQzdCLGtEQUFrRDtnQkFDbEQsYUFBYSxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsYUFBYSxDQUFDLENBQUE7WUFDeEMsQ0FBQztZQUNELE9BQU8sYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFD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
|
|
@@ -10,20 +10,20 @@ declare const RequestCacheMiddleware_base: import("./RpcMiddleware.js").TagClass
|
|
|
10
10
|
};
|
|
11
11
|
export declare class RequestCacheMiddleware extends RequestCacheMiddleware_base {
|
|
12
12
|
}
|
|
13
|
-
declare const
|
|
13
|
+
declare const ConfigureInterruptibilityMiddleware_base: import("./RpcMiddleware.js").TagClass<ConfigureInterruptibilityMiddleware, "ConfigureInterruptibilityMiddleware", {
|
|
14
14
|
readonly wrap: true;
|
|
15
15
|
}> & {
|
|
16
|
-
Default: Layer.Layer<
|
|
16
|
+
Default: Layer.Layer<ConfigureInterruptibilityMiddleware, never, never>;
|
|
17
17
|
};
|
|
18
|
-
export declare class
|
|
18
|
+
export declare class ConfigureInterruptibilityMiddleware extends ConfigureInterruptibilityMiddleware_base {
|
|
19
19
|
}
|
|
20
|
-
declare const
|
|
20
|
+
declare const LoggerMiddleware_base: import("./RpcMiddleware.js").TagClass<LoggerMiddleware, "LoggerMiddleware", {
|
|
21
21
|
readonly wrap: true;
|
|
22
22
|
}> & {
|
|
23
|
-
Default: Layer.Layer<
|
|
23
|
+
Default: Layer.Layer<LoggerMiddleware, never, never>;
|
|
24
24
|
};
|
|
25
|
-
export declare class
|
|
25
|
+
export declare class LoggerMiddleware extends LoggerMiddleware_base {
|
|
26
26
|
}
|
|
27
|
-
export declare const DefaultGenericMiddlewares: readonly [typeof RequestCacheMiddleware, typeof
|
|
27
|
+
export declare const DefaultGenericMiddlewares: readonly [typeof RequestCacheMiddleware, typeof ConfigureInterruptibilityMiddleware, typeof LoggerMiddleware];
|
|
28
28
|
export {};
|
|
29
29
|
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../../src/api/routing/middleware/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,OAAO,EAAoB,KAAK,EAAwB,MAAM,YAAY,CAAA;AAS1F,eAAO,MAAM,kBAAkB,kCAM9B,CAAA;;AAED,qBAAa,OAAQ,SAAQ,YAAsE;CAAG;;;;;;AAEtG,qBAAa,sBAAuB,SAAQ,2BAE1C;CACD;;;;;;AAED,qBAAa,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../../src/api/routing/middleware/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,OAAO,EAAoB,KAAK,EAAwB,MAAM,YAAY,CAAA;AAS1F,eAAO,MAAM,kBAAkB,kCAM9B,CAAA;;AAED,qBAAa,OAAQ,SAAQ,YAAsE;CAAG;;;;;;AAEtG,qBAAa,sBAAuB,SAAQ,2BAE1C;CACD;;;;;;AAED,qBAAa,mCACX,SAAQ,wCAON;CAEH;;;;;;AAED,qBAAa,gBAAiB,SAAQ,qBA0DpC;CACD;AAED,eAAO,MAAM,yBAAyB,+GAI5B,CAAA"}
|
|
@@ -13,13 +13,13 @@ export class RequestCacheMiddleware extends Tag()("RequestCacheMiddleware", { wr
|
|
|
13
13
|
effect: Effect.succeed(({ next }) => next.pipe(Effect.provide(RequestCacheLayers)))
|
|
14
14
|
}) {
|
|
15
15
|
}
|
|
16
|
-
export class
|
|
16
|
+
export class ConfigureInterruptibilityMiddleware extends Tag()("ConfigureInterruptibilityMiddleware", { wrap: true })({
|
|
17
17
|
effect: Effect.succeed(({ next }) => next.pipe(
|
|
18
18
|
// TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
|
|
19
19
|
Effect.uninterruptible))
|
|
20
20
|
}) {
|
|
21
21
|
}
|
|
22
|
-
export class
|
|
22
|
+
export class LoggerMiddleware extends Tag()("LoggerMiddleware", { wrap: true })({
|
|
23
23
|
effect: Effect.gen(function* () {
|
|
24
24
|
const devMode = yield* DevMode;
|
|
25
25
|
return ({ headers, next, payload, rpc }) => Effect
|
|
@@ -74,7 +74,7 @@ export class MiddlewareLogger extends Tag()("MiddlewareLogger", { wrap: true })(
|
|
|
74
74
|
}
|
|
75
75
|
export const DefaultGenericMiddlewares = [
|
|
76
76
|
RequestCacheMiddleware,
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
ConfigureInterruptibilityMiddleware,
|
|
78
|
+
LoggerMiddleware
|
|
79
79
|
];
|
|
80
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcGkvcm91dGluZy9taWRkbGV3YXJlL21pZGRsZXdhcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDMUYsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUV4QyxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDM0MsTUFBTSxrQkFBa0IsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUE7QUFFakQsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FDOUMsS0FBSyxDQUFDLGVBQWUsQ0FDbkIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUNwRSxFQUNELEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFDN0IsS0FBSyxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUMvQixDQUFBO0FBRUQsTUFBTSxPQUFPLE9BQVEsU0FBUSxPQUFPLENBQUMsU0FBUyxFQUFXLENBQUMsU0FBUyxFQUFFLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0NBQUc7QUFFdEcsTUFBTSxPQUFPLHNCQUF1QixTQUFRLEdBQUcsRUFBMEIsQ0FBQyx3QkFBd0IsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xILE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztDQUNwRixDQUFDO0NBQ0Q7QUFFRCxNQUFNLE9BQU8sbUNBQ1gsU0FBUSxHQUFHLEVBQXVDLENBQUMscUNBQXFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN4RyxNQUFNLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUNsQyxJQUFJLENBQUMsSUFBSTtJQUNQLG1IQUFtSDtJQUNuSCxNQUFNLENBQUMsZUFBZSxDQUN2QixDQUNGO0NBQ0YsQ0FBQztDQUVIO0FBRUQsTUFBTSxPQUFPLGdCQUFpQixTQUFRLEdBQUcsRUFBb0IsQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hHLE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUMxQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUE7UUFDOUIsT0FBTyxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUN6QyxNQUFNO2FBQ0gsbUJBQW1CLENBQUM7WUFDbkIsY0FBYyxFQUFFLEdBQUcsQ0FBQyxJQUFJO1lBQ3hCLGNBQWMsRUFBRSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksT0FBTyxLQUFLLElBQUk7Z0JBQzdELENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQW9CLEVBQUUsRUFBRTtvQkFDekUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsS0FBSyxVQUFVO3dCQUM1QixDQUFDLENBQUMsWUFBWTt3QkFDZCxDQUFDLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTOzRCQUN0RixDQUFDLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRztnQ0FDL0MsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDO2dDQUNuQyxDQUFDLENBQUMsS0FBSzs0QkFDVCxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0NBQ3RCLENBQUMsQ0FBQyxTQUFTLEtBQUssQ0FBQyxNQUFNLEdBQUc7Z0NBQzFCLENBQUMsQ0FBQyxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssS0FBSyxTQUFTO29DQUN2QyxDQUFDLENBQUMsR0FBRyxLQUFLLEVBQUU7b0NBQ1osQ0FBQyxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLO3dDQUNwQyxDQUFDLENBQUMsVUFBVSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sR0FBRzt3Q0FDeEMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxDQUFBO29CQUNoQixPQUFPLElBQUksQ0FBQTtnQkFDYixDQUFDLEVBQUUsRUFBK0MsQ0FBQztnQkFDbkQsQ0FBQyxDQUFDLE9BQU87U0FDWixDQUFDO2FBQ0QsSUFBSTtRQUNILDREQUE0RDtRQUM1RCxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztRQUNyQixxR0FBcUc7UUFDckcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNwRixNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFDOUYsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQ3pCLE1BQU07YUFDSCxHQUFHLENBQUM7WUFDSCxrQkFBa0IsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3hCLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSTthQUNqQixDQUFDO1lBQ0YsV0FBVztpQkFDUixRQUFRLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxDQUFDO2lCQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQztnQkFDeEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJO2dCQUNoQixHQUFHLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQztnQkFDcEIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUM7Z0JBQ3hCLHNCQUFzQjtnQkFDdEIsV0FBVztnQkFDWCx3QkFBd0I7Z0JBQ3hCLHdDQUF3QztnQkFDeEMsbUZBQW1GO2dCQUNuRixvQkFBb0I7Z0JBQ3BCLG9DQUFvQztnQkFDcEMsSUFBSTthQUNMLENBQUMsQ0FBQztTQUNOLENBQUMsQ0FDTCxFQUNELE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FDdEYsQ0FBQTtJQUNQLENBQUMsQ0FBQztDQUNILENBQUM7Q0FDRDtBQUVELE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHO0lBQ3ZDLHNCQUFzQjtJQUN0QixtQ0FBbUM7SUFDbkMsZ0JBQWdCO0NBQ1IsQ0FBQSJ9
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.88.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"proper-lockfile": "^4.1.2",
|
|
14
14
|
"pure-rand": "7.0.1",
|
|
15
15
|
"query-string": "^9.2.2",
|
|
16
|
-
"effect-app": "2.52.
|
|
16
|
+
"effect-app": "2.52.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@azure/cosmos": "^4.5.0",
|
|
@@ -5,42 +5,10 @@ import { type Effect, type Request, type S, type Scope } from "effect-app"
|
|
|
5
5
|
import type { GetEffectContext, RPCContextMap } from "effect-app/client/req"
|
|
6
6
|
import type * as EffectRequest from "effect/Request"
|
|
7
7
|
import { type ContextTagWithDefault } from "../../layerUtils.js"
|
|
8
|
-
import { type
|
|
8
|
+
import { type MiddlewareMaker, type MiddlewareMakerId } from "./middleware-api.js"
|
|
9
9
|
|
|
10
10
|
// module:
|
|
11
11
|
//
|
|
12
|
-
export type MakeRPCHandlerFactory<
|
|
13
|
-
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
14
|
-
MiddlewareR
|
|
15
|
-
> = <
|
|
16
|
-
T extends {
|
|
17
|
-
config?: Partial<Record<keyof RequestContextMap, any>>
|
|
18
|
-
},
|
|
19
|
-
Req extends S.TaggedRequest.All,
|
|
20
|
-
HandlerR
|
|
21
|
-
>(
|
|
22
|
-
schema: T & S.Schema<Req, any, never>,
|
|
23
|
-
next: (
|
|
24
|
-
request: Req,
|
|
25
|
-
headers: any
|
|
26
|
-
) => Effect.Effect<
|
|
27
|
-
EffectRequest.Request.Success<Req>,
|
|
28
|
-
EffectRequest.Request.Error<Req>,
|
|
29
|
-
// dynamic middlewares removes the dynamic context from HandlerR
|
|
30
|
-
Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>
|
|
31
|
-
>,
|
|
32
|
-
moduleName: string
|
|
33
|
-
) => (
|
|
34
|
-
req: Req,
|
|
35
|
-
headers: any
|
|
36
|
-
) => Effect.Effect<
|
|
37
|
-
Request.Request.Success<Req>,
|
|
38
|
-
Request.Request.Error<Req> | RequestContextMapErrors<RequestContextMap>,
|
|
39
|
-
// the middleware will remove from HandlerR the dynamic context, but will also add some requirements
|
|
40
|
-
| MiddlewareR
|
|
41
|
-
// & S.Schema<Req, any, never> is useless here but useful when creating the middleware
|
|
42
|
-
| Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>
|
|
43
|
-
>
|
|
44
12
|
|
|
45
13
|
export type RPCHandlerFactory<
|
|
46
14
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
@@ -53,7 +21,7 @@ export type RPCHandlerFactory<
|
|
|
53
21
|
HandlerR
|
|
54
22
|
>(
|
|
55
23
|
schema: T & S.Schema<Req, any, never>,
|
|
56
|
-
|
|
24
|
+
handler: (
|
|
57
25
|
request: Req,
|
|
58
26
|
headers: any
|
|
59
27
|
) => Effect.Effect<
|
|
@@ -67,29 +35,17 @@ export type RPCHandlerFactory<
|
|
|
67
35
|
headers: any
|
|
68
36
|
) => Effect.Effect<
|
|
69
37
|
Request.Request.Success<Req>,
|
|
70
|
-
Request.Request.Error<Req>
|
|
71
|
-
|
|
|
38
|
+
| Request.Request.Error<Req>
|
|
39
|
+
| RequestContextMapErrors<RequestContextMap>,
|
|
40
|
+
| Scope.Scope // the context provider may require Scope to run
|
|
72
41
|
| Exclude<
|
|
73
42
|
// the middleware will remove from HandlerR the dynamic context
|
|
74
|
-
// & S.Schema<Req, any, never> is useless here but useful when creating the middleware
|
|
75
43
|
Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>,
|
|
76
|
-
// the context provider provides additional stuff both to the middleware and the
|
|
44
|
+
// the context provider provides additional stuff both to the middleware and the handler
|
|
77
45
|
ContextProviderA
|
|
78
46
|
>
|
|
79
47
|
>
|
|
80
48
|
|
|
81
|
-
export type RequestContextMapProvider<RequestContextMap extends Record<string, RPCContextMap.Any>> = {
|
|
82
|
-
[K in keyof RequestContextMap]: ContextWithLayer.Base<
|
|
83
|
-
{ [K in keyof RequestContextMap]?: RequestContextMap[K]["contextActivation"] },
|
|
84
|
-
RequestContextMap[K]["service"],
|
|
85
|
-
S.Schema.Type<RequestContextMap[K]["error"]>
|
|
86
|
-
>
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface MiddlewareMakerId {
|
|
90
|
-
_tag: "MiddlewareMaker"
|
|
91
|
-
}
|
|
92
|
-
|
|
93
49
|
export type RouterMiddleware<
|
|
94
50
|
RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middlware provide dynamically to the next, or raise errors.
|
|
95
51
|
MakeMiddlewareE, // what the middleware construction can fail with
|
|
@@ -97,10 +53,7 @@ export type RouterMiddleware<
|
|
|
97
53
|
ContextProviderA // what the context provider provides
|
|
98
54
|
> = ContextTagWithDefault<
|
|
99
55
|
MiddlewareMakerId,
|
|
100
|
-
|
|
101
|
-
_tag: "MiddlewareMaker"
|
|
102
|
-
effect: RPCHandlerFactory<RequestContextMap, ContextProviderA>
|
|
103
|
-
},
|
|
56
|
+
MiddlewareMaker<RPCHandlerFactory<RequestContextMap, ContextProviderA>>,
|
|
104
57
|
MakeMiddlewareE,
|
|
105
58
|
MakeMiddlewareR
|
|
106
59
|
>
|
|
@@ -114,36 +67,5 @@ export function makeRpcEffect<
|
|
|
114
67
|
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
115
68
|
ContextProviderA
|
|
116
69
|
>() {
|
|
117
|
-
return (
|
|
118
|
-
cb: <
|
|
119
|
-
T extends {
|
|
120
|
-
config?: Partial<Record<keyof RequestContextMap, any>>
|
|
121
|
-
},
|
|
122
|
-
Req extends S.TaggedRequest.All,
|
|
123
|
-
HandlerR
|
|
124
|
-
>(
|
|
125
|
-
schema: T & S.Schema<Req, any, never>,
|
|
126
|
-
next: (
|
|
127
|
-
request: Req,
|
|
128
|
-
headers: any
|
|
129
|
-
) => Effect.Effect<
|
|
130
|
-
EffectRequest.Request.Success<Req>,
|
|
131
|
-
EffectRequest.Request.Error<Req>,
|
|
132
|
-
HandlerR
|
|
133
|
-
>,
|
|
134
|
-
moduleName: string
|
|
135
|
-
) => (
|
|
136
|
-
req: Req,
|
|
137
|
-
headers: any
|
|
138
|
-
) => Effect.Effect<
|
|
139
|
-
Request.Request.Success<Req>,
|
|
140
|
-
Request.Request.Error<Req> | RequestContextMapErrors<RequestContextMap>,
|
|
141
|
-
| Scope.Scope // the context provider may require Scope to run
|
|
142
|
-
| Exclude<
|
|
143
|
-
// it can also be removed from HandlerR
|
|
144
|
-
Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>,
|
|
145
|
-
ContextProviderA
|
|
146
|
-
>
|
|
147
|
-
>
|
|
148
|
-
) => cb
|
|
70
|
+
return (cb: RPCHandlerFactory<RequestContextMap, ContextProviderA>) => cb
|
|
149
71
|
}
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { type Rpc, RpcMiddleware } from "@effect/rpc"
|
|
5
5
|
import { type SuccessValue, type TypeId } from "@effect/rpc/RpcMiddleware"
|
|
6
6
|
import { type Context, type Effect, Layer, type NonEmptyReadonlyArray, type Option, type S, type Schema, type Scope, Unify } from "effect-app"
|
|
7
|
-
import type { AnyService,
|
|
7
|
+
import type { AnyService, ContextTagArray, RPCContextMap } from "effect-app/client/req"
|
|
8
8
|
import { type HttpHeaders } from "effect-app/http"
|
|
9
9
|
import { type TagUnify, type TagUnifyIgnore } from "effect/Context"
|
|
10
10
|
import { type LayerUtils } from "../../layerUtils.js"
|
|
11
11
|
|
|
12
|
-
// updated to support Scope.Scope
|
|
12
|
+
// updated to support Scope.Scope and Requires
|
|
13
13
|
export interface RpcMiddleware<Provides, E, Requires> {
|
|
14
14
|
(options: {
|
|
15
15
|
readonly clientId: number
|
|
@@ -47,7 +47,7 @@ export type DependsOn = {
|
|
|
47
47
|
readonly dependsOn: NonEmptyReadonlyArray<AnyDynamic> | undefined
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
interface RpcOptionsDynamic<Key extends string, A extends RPCContextMap.Any> extends RpcOptionsOriginal {
|
|
51
51
|
readonly dynamic: RpcDynamic<Key, A>
|
|
52
52
|
readonly dependsOn?: NonEmptyReadonlyArray<AnyDynamic> | undefined
|
|
53
53
|
}
|
|
@@ -86,8 +86,8 @@ export interface RpcMiddlewareDynamicNormal<A, E, R, Config> {
|
|
|
86
86
|
export interface TagClassAny extends Context.Tag<any, any> {
|
|
87
87
|
readonly [TypeId]: TypeId
|
|
88
88
|
readonly optional: boolean
|
|
89
|
-
readonly provides?: Context.Tag<any, any> |
|
|
90
|
-
readonly requires?: Context.Tag<any, any> |
|
|
89
|
+
readonly provides?: Context.Tag<any, any> | ContextTagArray | undefined
|
|
90
|
+
readonly requires?: Context.Tag<any, any> | ContextTagArray | undefined
|
|
91
91
|
readonly failure: Schema.Schema.All
|
|
92
92
|
readonly requiredForClient: boolean
|
|
93
93
|
readonly wrap: boolean
|
|
@@ -105,9 +105,9 @@ export declare namespace TagClass {
|
|
|
105
105
|
readonly optional?: false
|
|
106
106
|
} ? Context.Tag.Identifier<Options["provides"]>
|
|
107
107
|
: Options extends {
|
|
108
|
-
readonly provides:
|
|
108
|
+
readonly provides: ContextTagArray
|
|
109
109
|
readonly optional?: false
|
|
110
|
-
} ?
|
|
110
|
+
} ? ContextTagArray.Identifier<Options["provides"]>
|
|
111
111
|
: never
|
|
112
112
|
|
|
113
113
|
/**
|
|
@@ -118,8 +118,8 @@ export declare namespace TagClass {
|
|
|
118
118
|
readonly requires: Context.Tag<any, any>
|
|
119
119
|
} ? Context.Tag.Identifier<Options["requires"]>
|
|
120
120
|
: Options extends {
|
|
121
|
-
readonly requires:
|
|
122
|
-
} ?
|
|
121
|
+
readonly requires: ContextTagArray
|
|
122
|
+
} ? ContextTagArray.Identifier<Options["requires"]>
|
|
123
123
|
: never
|
|
124
124
|
|
|
125
125
|
/**
|
|
@@ -130,7 +130,8 @@ export declare namespace TagClass {
|
|
|
130
130
|
? Context.Tag.Service<Options["provides"]>
|
|
131
131
|
: Options extends { readonly dynamic: RpcDynamic<any, infer A> }
|
|
132
132
|
? Options extends { wrap: true } ? void : AnyService.Bla<A["service"]>
|
|
133
|
-
: Options extends { readonly provides:
|
|
133
|
+
: Options extends { readonly provides: ContextTagArray }
|
|
134
|
+
? Context.Context<ContextTagArray.Identifier<Options["provides"]>>
|
|
134
135
|
: void
|
|
135
136
|
|
|
136
137
|
/**
|
|
@@ -191,10 +192,10 @@ export declare namespace TagClass {
|
|
|
191
192
|
readonly optional: Optional<Options>
|
|
192
193
|
readonly failure: FailureSchema<Options>
|
|
193
194
|
readonly provides: Options extends { readonly provides: Context.Tag<any, any> } ? Options["provides"]
|
|
194
|
-
: Options extends { readonly provides:
|
|
195
|
+
: Options extends { readonly provides: ContextTagArray } ? Options["provides"]
|
|
195
196
|
: undefined
|
|
196
197
|
readonly requires: Options extends { readonly requires: Context.Tag<any, any> } ? Options["requires"]
|
|
197
|
-
: Options extends { readonly requires:
|
|
198
|
+
: Options extends { readonly requires: ContextTagArray } ? Options["requires"]
|
|
198
199
|
: undefined
|
|
199
200
|
readonly dynamic: Options extends RpcOptionsDynamic<any, any> ? Options["dynamic"]
|
|
200
201
|
: undefined
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { type ContextTagWithDefault } from "../../layerUtils.js"
|
|
3
|
-
import { type RpcMiddlewareDynamicNormal, type RpcMiddlewareDynamicWrap } from "./RpcMiddleware.js"
|
|
4
|
-
|
|
5
|
-
export type RpcMiddlewareDynamic<A, E, R, Config> = [A] extends [void] ? RpcMiddlewareDynamicWrap<E, R, Config>
|
|
6
|
-
: RpcMiddlewareDynamicNormal<A, E, R, Config>
|
|
7
|
-
|
|
8
|
-
export type ContextWithLayer<
|
|
9
|
-
Config,
|
|
10
|
-
Service,
|
|
11
|
-
Error,
|
|
12
|
-
Dependencies,
|
|
13
|
-
Id,
|
|
14
|
-
LayerE,
|
|
15
|
-
LayerR
|
|
16
|
-
> =
|
|
17
|
-
& (
|
|
18
|
-
| ContextTagWithDefault<
|
|
19
|
-
Id,
|
|
20
|
-
// todo
|
|
21
|
-
RpcMiddlewareDynamic<Service, Error, any, Config>,
|
|
22
|
-
LayerE,
|
|
23
|
-
LayerR
|
|
24
|
-
>
|
|
25
|
-
| ContextTagWithDefault<
|
|
26
|
-
Id,
|
|
27
|
-
// todo
|
|
28
|
-
RpcMiddlewareDynamic<Service, Error, never, Config>,
|
|
29
|
-
LayerE,
|
|
30
|
-
LayerR
|
|
31
|
-
>
|
|
32
|
-
)
|
|
33
|
-
& {
|
|
34
|
-
dependsOn?: Dependencies
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export namespace ContextWithLayer {
|
|
38
|
-
export type Base<Config, Service, Error> = ContextWithLayer<
|
|
39
|
-
Config,
|
|
40
|
-
Service,
|
|
41
|
-
Error,
|
|
42
|
-
any,
|
|
43
|
-
any,
|
|
44
|
-
any,
|
|
45
|
-
any
|
|
46
|
-
>
|
|
47
|
-
}
|
|
@@ -2,36 +2,40 @@
|
|
|
2
2
|
import { type Rpc, type RpcMiddleware } from "@effect/rpc"
|
|
3
3
|
import { type SuccessValue } from "@effect/rpc/RpcMiddleware"
|
|
4
4
|
import { type Array, Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type Scope } from "effect-app"
|
|
5
|
-
import { type
|
|
5
|
+
import { type ContextTagArray } from "effect-app/client"
|
|
6
6
|
import { type HttpHeaders } from "effect-app/http"
|
|
7
7
|
import { InfraLogger } from "../../../logger.js"
|
|
8
8
|
import { type TagClassAny } from "./RpcMiddleware.js"
|
|
9
9
|
|
|
10
|
+
// Effect rpc middleware does not support changing payload or headers, but we do..
|
|
11
|
+
|
|
12
|
+
// it's like an Effect/rpc wrap middleware, but with fixed R to Scope.Scope
|
|
10
13
|
export interface GenericMiddlewareOptions<E> {
|
|
11
|
-
// Effect rpc middleware does not support changing payload or headers, but we do..
|
|
12
|
-
readonly next: Effect.Effect<SuccessValue, E, Scope.Scope>
|
|
13
|
-
readonly payload: unknown
|
|
14
|
-
readonly headers: HttpHeaders.Headers
|
|
15
14
|
readonly clientId: number
|
|
16
15
|
readonly rpc: Rpc.AnyWithProps
|
|
16
|
+
readonly payload: unknown
|
|
17
|
+
readonly headers: HttpHeaders.Headers
|
|
18
|
+
readonly next: Effect.Effect<SuccessValue, E, Scope.Scope>
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export type GenericMiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
|
|
20
22
|
|
|
21
23
|
export namespace GenericMiddlewareMaker {
|
|
22
24
|
export type ApplyServices<A extends TagClassAny, R> = Exclude<R, Provided<A>> | Required<A>
|
|
25
|
+
|
|
23
26
|
export type ApplyManyServices<A extends NonEmptyReadonlyArray<TagClassAny>, R> =
|
|
24
27
|
| Exclude<R, { [K in keyof A]: Provided<A[K]> }[number]>
|
|
25
28
|
| { [K in keyof A]: Required<A[K]> }[number]
|
|
29
|
+
|
|
26
30
|
export type Provided<T> = T extends TagClassAny
|
|
27
31
|
? T extends { provides: Context.Tag<any, any> } ? Context.Tag.Identifier<T["provides"]>
|
|
28
|
-
: T extends { provides:
|
|
32
|
+
: T extends { provides: ContextTagArray } ? ContextTagArray.Identifier<T["provides"]>
|
|
29
33
|
: never
|
|
30
34
|
: never
|
|
31
35
|
|
|
32
36
|
export type Required<T> = T extends TagClassAny
|
|
33
37
|
? T extends { requires: Context.Tag<any, any> } ? Context.Tag.Identifier<T["requires"]>
|
|
34
|
-
: T extends { requires:
|
|
38
|
+
: T extends { requires: ContextTagArray } ? ContextTagArray.Identifier<T["requires"]>
|
|
35
39
|
: never
|
|
36
40
|
: never
|
|
37
41
|
}
|
|
@@ -42,26 +46,41 @@ export const genericMiddlewareMaker = <
|
|
|
42
46
|
dependencies: { [K in keyof T]: T[K]["Default"] }
|
|
43
47
|
effect: Effect.Effect<RpcMiddleware.RpcMiddlewareWrap<any, any>>
|
|
44
48
|
} => {
|
|
45
|
-
// we want to run them in reverse order
|
|
49
|
+
// we want to run them in reverse order because latter middlewares will provide context to former ones
|
|
46
50
|
middlewares = middlewares.toReversed() as any
|
|
51
|
+
|
|
47
52
|
return {
|
|
48
53
|
dependencies: middlewares.map((_) => _.Default),
|
|
49
54
|
effect: Effect.gen(function*() {
|
|
50
55
|
const context = yield* Effect.context()
|
|
56
|
+
|
|
57
|
+
// returns a Effect/RpcMiddlewareWrap with Scope in requirements
|
|
51
58
|
return <E>(
|
|
52
59
|
options: GenericMiddlewareOptions<E>
|
|
53
60
|
) => {
|
|
61
|
+
// we start with the actual handler
|
|
54
62
|
let handler = options.next
|
|
55
|
-
|
|
63
|
+
|
|
64
|
+
// inspired from Effect/RpcMiddleware
|
|
56
65
|
for (const tag of middlewares) {
|
|
57
66
|
if (tag.wrap) {
|
|
67
|
+
// use the tag to get the middleware from context
|
|
58
68
|
const middleware = Context.unsafeGet(context, tag)
|
|
69
|
+
|
|
70
|
+
// wrap the current handler, allowing the middleware to run before and after it
|
|
59
71
|
handler = InfraLogger.logDebug("Applying middleware wrap " + tag.key).pipe(
|
|
60
72
|
Effect.zipRight(middleware({ ...options, next: handler }))
|
|
61
73
|
) as any
|
|
62
74
|
} else if (tag.optional) {
|
|
75
|
+
// use the tag to get the middleware from context
|
|
76
|
+
// if the middleware fails to run, we will ignore the error
|
|
63
77
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
78
|
+
|
|
64
79
|
const previous = handler
|
|
80
|
+
|
|
81
|
+
// set the previous handler to run after the middleware
|
|
82
|
+
// if the middleware is not present, we just return the previous handler
|
|
83
|
+
// otherwise the middleware will provide some context to be provided to the previous handler
|
|
65
84
|
handler = InfraLogger.logDebug("Applying middleware optional " + tag.key).pipe(
|
|
66
85
|
Effect.zipRight(Effect.matchEffect(middleware(options), {
|
|
67
86
|
onFailure: () => previous,
|
|
@@ -74,24 +93,35 @@ export const genericMiddlewareMaker = <
|
|
|
74
93
|
}))
|
|
75
94
|
)
|
|
76
95
|
} else if (tag.dynamic) {
|
|
96
|
+
// use the tag to get the middleware from context
|
|
77
97
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
98
|
+
|
|
78
99
|
const previous = handler
|
|
100
|
+
|
|
101
|
+
// set the previous handler to run after the middleware
|
|
102
|
+
// we do expect the middleware to be present, but the context might not be available
|
|
103
|
+
// if it is, we provide it to the previous handler
|
|
79
104
|
handler = InfraLogger.logDebug("Applying middleware dynamic " + tag.key, tag.dynamic).pipe(
|
|
80
105
|
Effect.zipRight(
|
|
81
106
|
middleware(options).pipe(
|
|
82
|
-
Effect.flatMap((
|
|
83
|
-
Option.isSome(
|
|
84
|
-
? Context.isContext(
|
|
85
|
-
? Effect.provide(previous,
|
|
86
|
-
: Effect.provideService(previous, tag.dynamic!.settings.service!, /* TODO */
|
|
107
|
+
Effect.flatMap((o) =>
|
|
108
|
+
Option.isSome(o)
|
|
109
|
+
? Context.isContext(o.value)
|
|
110
|
+
? Effect.provide(previous, o.value)
|
|
111
|
+
: Effect.provideService(previous, tag.dynamic!.settings.service!, /* TODO */ o.value)
|
|
87
112
|
: previous
|
|
88
113
|
)
|
|
89
114
|
)
|
|
90
115
|
)
|
|
91
116
|
)
|
|
92
117
|
} else {
|
|
118
|
+
// use the tag to get the middleware from context
|
|
93
119
|
const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
|
|
120
|
+
|
|
94
121
|
const previous = handler
|
|
122
|
+
|
|
123
|
+
// set the previous handler to run after the middleware
|
|
124
|
+
// we do expect both the middleware and the context to be present
|
|
95
125
|
handler = InfraLogger.logDebug("Applying middleware " + tag.key).pipe(
|
|
96
126
|
Effect.zipRight(
|
|
97
127
|
tag.provides !== undefined
|
|
@@ -107,6 +137,7 @@ export const genericMiddlewareMaker = <
|
|
|
107
137
|
)
|
|
108
138
|
}
|
|
109
139
|
}
|
|
140
|
+
|
|
110
141
|
return handler
|
|
111
142
|
}
|
|
112
143
|
})
|