@effect-app/infra 2.76.0 → 2.78.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/Emailer/service.d.ts +1 -1
  3. package/dist/MainFiberSet.d.ts +1 -1
  4. package/dist/Operations.d.ts +1 -1
  5. package/dist/RequestFiberSet.d.ts +1 -1
  6. package/dist/Store/service.d.ts +2 -2
  7. package/dist/adapters/SQL/Model.d.ts +6 -6
  8. package/dist/adapters/ServiceBus.d.ts +1 -1
  9. package/dist/adapters/memQueue.d.ts +1 -1
  10. package/dist/api/layerUtils.d.ts +10 -2
  11. package/dist/api/layerUtils.d.ts.map +1 -1
  12. package/dist/api/layerUtils.js +25 -2
  13. package/dist/api/routing/middleware/ContextProvider.d.ts.map +1 -1
  14. package/dist/api/routing/middleware/ContextProvider.js +3 -2
  15. package/dist/api/routing/middleware/DynamicMiddleware.d.ts +4 -4
  16. package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +1 -1
  17. package/dist/api/routing/middleware/DynamicMiddleware.js +18 -12
  18. package/dist/api/routing/middleware/dynamic-middleware.d.ts +1 -9
  19. package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
  20. package/dist/api/routing/middleware/dynamic-middleware.js +4 -25
  21. package/dist/api/routing/middleware/generic-middleware.d.ts +10 -1
  22. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
  23. package/dist/api/routing/middleware/generic-middleware.js +8 -9
  24. package/dist/api/routing/middleware/middleware.d.ts +4 -10
  25. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  26. package/dist/api/routing/middleware/middleware.js +36 -48
  27. package/package.json +5 -5
  28. package/src/api/layerUtils.ts +39 -2
  29. package/src/api/routing/middleware/ContextProvider.ts +2 -2
  30. package/src/api/routing/middleware/DynamicMiddleware.ts +36 -30
  31. package/src/api/routing/middleware/dynamic-middleware.ts +3 -39
  32. package/src/api/routing/middleware/generic-middleware.ts +19 -12
  33. package/src/api/routing/middleware/middleware.ts +55 -86
  34. package/test/controller.test.ts +5 -9
  35. package/test/dist/controller.test.d.ts.map +1 -1
@@ -1,82 +1,71 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { Cause, Context, Effect, ParseResult } from "effect-app";
2
- import { HttpHeaders, 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 { RequestCacheLayers } from "../../routing.js";
6
+ import { genericMiddleware, RequestCacheLayers } from "../../routing.js";
7
7
  const logRequestError = logError("Request");
8
8
  const reportRequestError = reportError("Request");
9
9
  export class DevMode extends Context.Reference()("DevMode", { defaultValue: () => false }) {
10
10
  }
11
+ // Effect Rpc Middleware: Wrap
11
12
  export class RequestCacheMiddleware extends Effect.Service()("RequestCacheMiddleware", {
12
13
  effect: Effect.gen(function* () {
13
- return (handle, _moduleName) => Effect.fnUntraced(function* (input, headers) {
14
- return yield* handle(input, headers).pipe(Effect.provide(RequestCacheLayers));
15
- });
14
+ return genericMiddleware(Effect.fnUntraced(function* (options) {
15
+ return yield* options.next.pipe(Effect.provide(RequestCacheLayers));
16
+ }));
16
17
  })
17
18
  }) {
18
19
  }
20
+ // Effect Rpc Middleware: Wrap
19
21
  export class ConfigureInterruptibility extends Effect.Service()("ConfigureInterruptibility", {
20
22
  effect: Effect.gen(function* () {
21
- return (handle, _moduleName) => Effect.fnUntraced(function* (input, headers) {
22
- return yield* handle(input, headers).pipe(
23
+ return genericMiddleware(Effect.fnUntraced(function* (options) {
24
+ return yield* options.next.pipe(
23
25
  // TODO: make this depend on query/command, and consider if middleware also should be affected. right now it's not.
24
26
  Effect.uninterruptible);
25
- });
26
- })
27
- }) {
28
- }
29
- export class CaptureHttpHeadersAsRpcHeaders extends Effect.Service()("CaptureHttpHeadersAsRpcHeaders", {
30
- effect: Effect.gen(function* () {
31
- return (handle, _moduleName) => Effect.fnUntraced(function* (input, rpcHeaders) {
32
- // merge in the request headers
33
- // we should consider if we should merge them into rpc headers on the Protocol layer instead.
34
- const httpReq = yield* HttpServerRequest.HttpServerRequest;
35
- const headers = HttpHeaders.merge(httpReq.headers, rpcHeaders);
36
- return yield* handle(input, headers);
37
- });
27
+ }));
38
28
  })
39
29
  }) {
40
30
  }
31
+ // Effect Rpc Middleware: Wrap
41
32
  export class MiddlewareLogger extends Effect.Service()("MiddlewareLogger", {
42
33
  effect: Effect.gen(function* () {
43
- return (handle, moduleName) => Effect.fnUntraced(function* (input, rpcHeaders) {
34
+ return genericMiddleware(Effect.fnUntraced(function* ({ headers, next, payload, rpc }) {
44
35
  const devMode = yield* DevMode;
45
- // merge in the request headers
46
- // we should consider if we should merge them into rpc headers on the Protocol layer instead.
47
- const httpReq = yield* HttpServerRequest.HttpServerRequest;
48
- const headers = HttpHeaders.merge(httpReq.headers, rpcHeaders);
49
36
  return yield* Effect
50
- .annotateCurrentSpan("requestInput", Object.entries(input).reduce((prev, [key, value]) => {
51
- prev[key] = key === "password"
52
- ? "<redacted>"
53
- : typeof value === "string" || typeof value === "number" || typeof value === "boolean"
54
- ? typeof value === "string" && value.length > 256
55
- ? (value.substring(0, 253) + "...")
56
- : value
57
- : Array.isArray(value)
58
- ? `Array[${value.length}]`
59
- : value === null || value === undefined
60
- ? `${value}`
61
- : typeof value === "object" && value
62
- ? `Object[${Object.keys(value).length}]`
63
- : typeof value;
64
- return prev;
65
- }, {}))
37
+ .annotateCurrentSpan("requestInput", typeof payload === "object" && payload !== null
38
+ ? Object.entries(payload).reduce((prev, [key, value]) => {
39
+ prev[key] = key === "password"
40
+ ? "<redacted>"
41
+ : typeof value === "string" || typeof value === "number" || typeof value === "boolean"
42
+ ? typeof value === "string" && value.length > 256
43
+ ? (value.substring(0, 253) + "...")
44
+ : value
45
+ : Array.isArray(value)
46
+ ? `Array[${value.length}]`
47
+ : value === null || value === undefined
48
+ ? `${value}`
49
+ : typeof value === "object" && value
50
+ ? `Object[${Object.keys(value).length}]`
51
+ : typeof value;
52
+ return prev;
53
+ }, {})
54
+ : payload)
66
55
  .pipe(
67
56
  // can't use andThen due to some being a function and effect
68
- Effect.zipRight(handle(input, headers)),
57
+ Effect.zipRight(next),
69
58
  // TODO: support ParseResult if the error channel of the request allows it.. but who would want that?
70
59
  Effect.catchAll((_) => ParseResult.isParseError(_) ? Effect.die(_) : Effect.fail(_)), Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void), Effect.tapDefect((cause) => Effect
71
60
  .all([
72
61
  reportRequestError(cause, {
73
- action: `${moduleName}.${input._tag}`
62
+ action: rpc._tag
74
63
  }),
75
64
  InfraLogger
76
65
  .logError("Finished request", cause)
77
66
  .pipe(Effect.annotateLogs({
78
- action: `${moduleName}.${input._tag}`,
79
- req: pretty(input),
67
+ action: rpc._tag,
68
+ req: pretty(payload),
80
69
  headers: pretty(headers)
81
70
  // resHeaders: pretty(
82
71
  // Object
@@ -88,14 +77,13 @@ export class MiddlewareLogger extends Effect.Service()("MiddlewareLogger", {
88
77
  // )
89
78
  }))
90
79
  ])), devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")));
91
- });
80
+ }));
92
81
  })
93
82
  }) {
94
83
  }
95
84
  export const DefaultGenericMiddlewares = [
96
85
  RequestCacheMiddleware,
97
86
  ConfigureInterruptibility,
98
- CaptureHttpHeadersAsRpcHeaders,
99
87
  MiddlewareLogger
100
88
  ];
101
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcGkvcm91dGluZy9taWRkbGV3YXJlL21pZGRsZXdhcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFtQixpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQ2pGLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFBO0FBQ2pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUVyRCxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDM0MsTUFBTSxrQkFBa0IsR0FBRyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUE7QUFFakQsTUFBTSxPQUFPLE9BQVEsU0FBUSxPQUFPLENBQUMsU0FBUyxFQUFXLENBQUMsU0FBUyxFQUFFLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0NBQUc7QUFFdEcsTUFBTSxPQUFPLHNCQUF1QixTQUFRLE1BQU0sQ0FBQyxPQUFPLEVBQTBCLENBQUMsd0JBQXdCLEVBQUU7SUFDN0csTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1FBQzFCLE9BQU8sQ0FDTCxNQUF5RyxFQUN6RyxXQUFtQixFQUNuQixFQUFFLENBQ0YsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBQyxLQUFVLEVBQUUsT0FBNEI7WUFDbEUsT0FBTyxLQUFLLENBQUMsQ0FBQyxNQUFN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
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcGkvcm91dGluZy9taWRkbGV3YXJlL21pZGRsZXdhcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDaEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ2hELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBRXhFLE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUMzQyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUVqRCxNQUFNLE9BQU8sT0FBUSxTQUFRLE9BQU8sQ0FBQyxTQUFTLEVBQVcsQ0FBQyxTQUFTLEVBQUUsRUFBRSxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7Q0FBRztBQUN0Ryw4QkFBOEI7QUFDOUIsTUFBTSxPQUFPLHNCQUF1QixTQUFRLE1BQU0sQ0FBQyxPQUFPLEVBQTBCLENBQUMsd0JBQXdCLEVBQUU7SUFDN0csTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO1FBQzFCLE9BQU8saUJBQWlCLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBQyxPQUFPO1lBQzFELE9BQU8sS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "2.76.0",
3
+ "version": "2.78.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.49.0"
16
+ "effect-app": "2.50.0"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@azure/cosmos": "^4.5.0",
@@ -38,10 +38,10 @@
38
38
  "peerDependencies": {
39
39
  "@azure/cosmos": "^4.5.0",
40
40
  "@azure/service-bus": "^7.9.5",
41
- "@effect/experimental": "^0.54.1",
41
+ "@effect/experimental": "^0.54.3",
42
42
  "@effect/platform": "^0.90.0",
43
43
  "@effect/rpc-http": "^0.52.4",
44
- "@effect/rpc": "^0.68.0",
44
+ "@effect/rpc": "^0.68.1",
45
45
  "@effect/sql": "^0.44.0",
46
46
  "@effect/vitest": "^0.25.0",
47
47
  "@sendgrid/helpers": "^8.0.0",
@@ -51,7 +51,7 @@
51
51
  "jwt-decode": "^4.0.0",
52
52
  "redis": "^3.1.2",
53
53
  "redlock": "^4.2.0",
54
- "effect": "^3.17.2",
54
+ "effect": "^3.17.4",
55
55
  "express": "^5.1.0"
56
56
  },
57
57
  "typesVersions": {
@@ -1,4 +1,5 @@
1
- import { type Context, type Layer, type NonEmptyReadonlyArray } from "effect-app"
1
+ import { Context, Effect, type Layer, type NonEmptyReadonlyArray, Option } from "effect-app"
2
+ import { InfraLogger } from "../logger.js"
2
3
 
3
4
  export namespace LayerUtils {
4
5
  export type GetLayersSuccess<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
@@ -27,7 +28,43 @@ export type ContextTagWithDefault<Id, A, LayerE, LayerR, Tag = unknown> =
27
28
  }
28
29
 
29
30
  export namespace ContextTagWithDefault {
30
- export type Base<A> = ContextTagWithDefault<any, any, A, any, any>
31
+ export type Base<A> = ContextTagWithDefault<any, A, any, any, any>
31
32
  }
32
33
 
33
34
  export type GetContext<T> = T extends Context.Context<infer Y> ? Y : never
35
+
36
+ export const mergeContexts = Effect.fnUntraced(
37
+ function*<T extends readonly { maker: any; handle: Effect<Context<any>> }[]>(makers: T) {
38
+ let context = Context.empty()
39
+ for (const mw of makers) {
40
+ yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
41
+ const moreContext = yield* mw.handle.pipe(Effect.provide(context))
42
+ yield* InfraLogger.logDebug(
43
+ "Built context for middleware",
44
+ mw.maker.key ?? mw.maker,
45
+ (moreContext as any).toJSON().services
46
+ )
47
+ context = Context.merge(context, moreContext)
48
+ }
49
+ return context as Context.Context<Effect.Success<T[number]["handle"]>>
50
+ }
51
+ )
52
+
53
+ export const mergeOptionContexts = Effect.fnUntraced(
54
+ function*<T extends readonly { maker: any; handle: Effect<Option<Context<any>>> }[]>(makers: T) {
55
+ let context = Context.empty()
56
+ for (const mw of makers) {
57
+ yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
58
+ const moreContext = yield* mw.handle.pipe(Effect.provide(context))
59
+ yield* InfraLogger.logDebug(
60
+ "Built context for middleware",
61
+ mw.maker.key ?? mw.maker,
62
+ Option.map(moreContext, (c) => (c as any).toJSON().services)
63
+ )
64
+ if (moreContext.value) {
65
+ context = Context.merge(context, moreContext.value)
66
+ }
67
+ }
68
+ return context
69
+ }
70
+ )
@@ -1,8 +1,7 @@
1
1
  import { type Array, Context, Effect, Layer, type NonEmptyArray, pipe, type Scope } from "effect-app"
2
2
  import { type HttpRouter } from "effect-app/http"
3
3
  import { type Tag } from "effect/Context"
4
- import { type ContextTagWithDefault, type GetContext, type LayerUtils } from "../../layerUtils.js"
5
- import { mergeContexts } from "./dynamic-middleware.js"
4
+ import { type ContextTagWithDefault, type GetContext, type LayerUtils, mergeContexts } from "../../layerUtils.js"
6
5
 
7
6
  // the context provider provides additional stuff
8
7
  export type ContextProviderShape<ContextProviderA, ContextProviderR extends HttpRouter.HttpRouter.Provided> = Effect<
@@ -71,6 +70,7 @@ export const mergeContextProviders = <
71
70
  }) as any
72
71
  })
73
72
 
73
+ // Effect Rpc Middleware: for single tag providing, we could use Provides, for providing Context or Layer (bad boy) we could use Wrap..
74
74
  export const ContextProvider = <
75
75
  ContextProviderA,
76
76
  MakeContextProviderE,
@@ -23,7 +23,7 @@ export type MakeRPCHandlerFactory<
23
23
  HandlerR
24
24
  >(
25
25
  schema: T & S.Schema<Req, any, never>,
26
- handler: (
26
+ next: (
27
27
  request: Req,
28
28
  headers: any
29
29
  ) => Effect.Effect<
@@ -56,7 +56,7 @@ export type RPCHandlerFactory<
56
56
  HandlerR
57
57
  >(
58
58
  schema: T & S.Schema<Req, any, never>,
59
- handler: (
59
+ next: (
60
60
  request: Req,
61
61
  headers: any
62
62
  ) => Effect.Effect<
@@ -76,7 +76,7 @@ export type RPCHandlerFactory<
76
76
  // the middleware will remove from HandlerR the dynamic context
77
77
  // & S.Schema<Req, any, never> is useless here but useful when creating the middleware
78
78
  Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>,
79
- // the context provider provides additional stuff both to the middleware and the handler
79
+ // the context provider provides additional stuff both to the middleware and the next
80
80
  ContextProviderA
81
81
  >
82
82
  >
@@ -90,7 +90,7 @@ type RequestContextMapProvider<RequestContextMap extends Record<string, RPCConte
90
90
  }
91
91
 
92
92
  export interface MiddlewareMake<
93
- RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middleware provide dynamically to the handler, or raise errors.
93
+ RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middleware provide dynamically to the next, or raise errors.
94
94
  //
95
95
  // ContextProvider is a service that builds additional context for each request.
96
96
  ContextProviderA, // what the context provider provides
@@ -117,9 +117,9 @@ export interface MiddlewareMake<
117
117
  MakeContextProviderR
118
118
  >
119
119
 
120
- /* dependencies for the main middleware running just before the handler is called */
120
+ /* dependencies for the main middleware running just before the next is called */
121
121
  dependencies?: MiddlewareDependencies
122
- // this actually builds "the middleware", i.e. returns the augmented handler factory when yielded...
122
+ // this actually builds "the middleware", i.e. returns the augmented next factory when yielded...
123
123
  execute?: (
124
124
  maker: (
125
125
  // MiddlewareR is set to ContextProviderA | HttpRouter.HttpRouter.Provided because that's what, at most
@@ -138,7 +138,7 @@ export interface MiddlewareMakerId {
138
138
  }
139
139
 
140
140
  export type Middleware<
141
- RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middlware provide dynamically to the handler, or raise errors.
141
+ RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middlware provide dynamically to the next, or raise errors.
142
142
  MakeMiddlewareE, // what the middleware construction can fail with
143
143
  MakeMiddlewareR, // what the middlware requires to be constructed
144
144
  ContextProviderA // what the context provider provides
@@ -190,7 +190,6 @@ export const makeMiddleware =
190
190
  MiddlewareDependencies
191
191
  >
192
192
  ) => {
193
- // type Id = MiddlewareMakerId &
194
193
  const MiddlewareMaker = Context.GenericTag<
195
194
  MiddlewareMakerId,
196
195
  {
@@ -216,35 +215,42 @@ export const makeMiddleware =
216
215
  ) => cb)
217
216
  : Effect.succeed<
218
217
  MakeRPCHandlerFactory<RequestContextMap, ContextProviderA | HttpRouter.HttpRouter.Provided>
219
- >((_schema, handle) => (req, headers) => handle(req, headers)),
218
+ >((_schema, next) => (payload, headers) => next(payload, headers)),
220
219
  contextProvider: make.contextProvider // uses the middleware.contextProvider tag to get the context provider service
221
220
  })
222
221
  .pipe(
223
222
  Effect.map(({ contextProvider, dynamicMiddlewares, generic, middleware }) => ({
224
223
  _tag: "MiddlewareMaker" as const,
225
224
  effect: makeRpcEffect<RequestContextMap, ContextProviderA>()(
226
- (schema, handler, moduleName) => {
227
- const h = middleware(schema, handler as any, moduleName)
228
- return generic(
229
- Effect.fnUntraced(function*(req, headers) {
230
- yield* Effect.annotateCurrentSpan(
231
- "request.name",
232
- moduleName ? `${moduleName}.${req._tag}` : req._tag
233
- )
225
+ (schema, next, moduleName) => {
226
+ const h = middleware(schema, next as any, moduleName)
227
+ return (payload, headers) =>
228
+ Effect.gen(function*() {
229
+ return yield* generic({
230
+ payload,
231
+ headers,
232
+ rpc: { _tag: `${moduleName}.${payload._tag}` }, // todo: make moduleName part of the tag on S.Req creation.
233
+ next: Effect.gen(function*() {
234
+ yield* Effect.annotateCurrentSpan(
235
+ "request.name",
236
+ moduleName ? `${moduleName}.${payload._tag}` : payload._tag
237
+ )
234
238
 
235
- // the contextProvider is an Effect that builds the context for the request
236
- return yield* contextProvider.pipe(
237
- Effect.flatMap((contextProviderContext) =>
238
- // the dynamicMiddlewares is an Effect that builds the dynamiuc context for the request
239
- dynamicMiddlewares(schema.config ?? {}, headers).pipe(
240
- Effect.flatMap((dynamicContext) => h(req, headers).pipe(Effect.provide(dynamicContext))),
241
- Effect.provide(contextProviderContext)
239
+ // the contextProvider is an Effect that builds the context for the request
240
+ return yield* contextProvider.pipe(
241
+ Effect.flatMap((contextProviderContext) =>
242
+ // the dynamicMiddlewares is an Effect that builds the dynamiuc context for the request
243
+ dynamicMiddlewares(schema.config ?? {}, headers).pipe(
244
+ Effect.flatMap((dynamicContext) =>
245
+ h(payload, headers).pipe(Effect.provide(dynamicContext))
246
+ ),
247
+ Effect.provide(contextProviderContext)
248
+ )
249
+ )
242
250
  )
243
- )
244
- )
245
- }) as any,
246
- moduleName
247
- )
251
+ }) as any
252
+ })
253
+ }) as any // why?
248
254
  }
249
255
  )
250
256
  }))
@@ -291,7 +297,7 @@ function makeRpcEffect<
291
297
  HandlerR
292
298
  >(
293
299
  schema: T & S.Schema<Req, any, never>,
294
- handler: (
300
+ next: (
295
301
  request: Req,
296
302
  headers: any
297
303
  ) => Effect.Effect<
@@ -1,10 +1,9 @@
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 { InfraLogger } from "../../../logger.js"
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<
@@ -39,42 +38,7 @@ export namespace ContextWithLayer {
39
38
  >
40
39
  }
41
40
 
42
- export const mergeContexts = Effect.fnUntraced(
43
- function*<T extends readonly { maker: any; handle: Effect<Context<any>> }[]>(makers: T) {
44
- let context = Context.empty()
45
- for (const mw of makers) {
46
- yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
47
- const moreContext = yield* mw.handle.pipe(Effect.provide(context))
48
- yield* InfraLogger.logDebug(
49
- "Built context for middleware",
50
- mw.maker.key ?? mw.maker,
51
- (moreContext as any).toJSON().services
52
- )
53
- context = Context.merge(context, moreContext)
54
- }
55
- return context as Context.Context<Effect.Success<T[number]["handle"]>>
56
- }
57
- )
58
-
59
- export const mergeOptionContexts = Effect.fnUntraced(
60
- function*<T extends readonly { maker: any; handle: Effect<Option<Context<any>>> }[]>(makers: T) {
61
- let context = Context.empty()
62
- for (const mw of makers) {
63
- yield* InfraLogger.logDebug("Building context for middleware", mw.maker.key ?? mw.maker)
64
- const moreContext = yield* mw.handle.pipe(Effect.provide(context))
65
- yield* InfraLogger.logDebug(
66
- "Built context for middleware",
67
- mw.maker.key ?? mw.maker,
68
- Option.map(moreContext, (c) => (c as any).toJSON().services)
69
- )
70
- if (moreContext.value) {
71
- context = Context.merge(context, moreContext.value)
72
- }
73
- }
74
- return context
75
- }
76
- )
77
-
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.
78
42
  export const implementMiddleware = <T extends Record<string, RPCContextMap.Any>>() =>
79
43
  <
80
44
  TI extends {
@@ -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
- handle: (input: any, headers: HttpHeaders.Headers) => Effect.Effect<A, E, HttpRouter.HttpRouter.Provided>,
8
- moduleName: string
9
- ) => (input: any, headers: HttpHeaders.Headers) => Effect.Effect<A, E, HttpRouter.HttpRouter.Provided>
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, R>(
25
- handle: (input: any, headers: HttpHeaders.Headers) => Effect.Effect<A, E, R>,
26
- moduleName: string
34
+ return <A, E>(
35
+ options: GenericMiddlewareOptions<A, E>
27
36
  ) => {
28
- return (input: any, headers: HttpHeaders.Headers) => {
29
- let effect = handle
30
- for (const middleware of (middlewaresInstances as any[]).toReversed()) {
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