@effect-app/infra 2.88.0 → 2.89.1

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 (41) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/api/{routing/middleware/ContextProvider.d.ts → ContextProvider.d.ts} +1 -1
  3. package/dist/api/ContextProvider.d.ts.map +1 -0
  4. package/dist/api/ContextProvider.js +38 -0
  5. package/dist/api/routing/middleware/RouterMiddleware.d.ts +15 -10
  6. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  7. package/dist/api/routing/middleware/RouterMiddleware.js +2 -5
  8. package/dist/api/routing/middleware/RpcMiddleware.d.ts +6 -10
  9. package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -1
  10. package/dist/api/routing/middleware/RpcMiddleware.js +1 -1
  11. package/dist/api/routing/middleware/generic-middleware.d.ts +19 -17
  12. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
  13. package/dist/api/routing/middleware/generic-middleware.js +2 -2
  14. package/dist/api/routing/middleware/middleware-api.d.ts +31 -27
  15. package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
  16. package/dist/api/routing/middleware/middleware-api.js +31 -40
  17. package/dist/api/routing/middleware.d.ts +0 -1
  18. package/dist/api/routing/middleware.d.ts.map +1 -1
  19. package/dist/api/routing/middleware.js +1 -2
  20. package/dist/api/routing.d.ts +1 -1
  21. package/dist/api/routing.d.ts.map +1 -1
  22. package/dist/api/routing.js +12 -10
  23. package/package.json +6 -6
  24. package/src/api/{routing/middleware/ContextProvider.ts → ContextProvider.ts} +1 -1
  25. package/src/api/routing/middleware/RouterMiddleware.ts +22 -56
  26. package/src/api/routing/middleware/RpcMiddleware.ts +15 -11
  27. package/src/api/routing/middleware/generic-middleware.ts +44 -26
  28. package/src/api/routing/middleware/middleware-api.ts +91 -111
  29. package/src/api/routing/middleware.ts +0 -1
  30. package/src/api/routing.ts +22 -20
  31. package/test/contextProvider.test.ts +1 -1
  32. package/test/controller.test.ts +3 -4
  33. package/test/dist/controller.test.d.ts.map +1 -1
  34. package/test/dist/fixtures.d.ts +2 -2
  35. package/test/dist/fixtures.d.ts.map +1 -1
  36. package/test/dist/fixtures.js +7 -6
  37. package/test/dist/requires.test.d.ts.map +1 -1
  38. package/test/fixtures.ts +7 -5
  39. package/test/requires.test.ts +43 -22
  40. package/dist/api/routing/middleware/ContextProvider.d.ts.map +0 -1
  41. package/dist/api/routing/middleware/ContextProvider.js +0 -38
@@ -1,38 +1,41 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { type Rpc, type RpcMiddleware } from "@effect/rpc"
3
- import { type SuccessValue } from "@effect/rpc/RpcMiddleware"
4
- import { type Array, Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type Scope } from "effect-app"
2
+ import { type RpcMiddleware } from "@effect/rpc"
3
+ import { Context, Effect, type Layer, type NonEmptyReadonlyArray, Option, type S, type Scope } from "effect-app"
5
4
  import { type ContextTagArray } from "effect-app/client"
6
- import { type HttpHeaders } from "effect-app/http"
7
5
  import { InfraLogger } from "../../../logger.js"
8
- import { type TagClassAny } from "./RpcMiddleware.js"
6
+ import { type RpcMiddlewareWrap, type TagClassAny } from "./RpcMiddleware.js"
9
7
 
10
8
  // Effect rpc middleware does not support changing payload or headers, but we do..
11
9
 
12
- // it's like an Effect/rpc wrap middleware, but with fixed R to Scope.Scope
13
- export interface GenericMiddlewareOptions<E> {
14
- readonly clientId: number
15
- readonly rpc: Rpc.AnyWithProps
16
- readonly payload: unknown
17
- readonly headers: HttpHeaders.Headers
18
- readonly next: Effect.Effect<SuccessValue, E, Scope.Scope>
19
- }
20
-
21
- export type GenericMiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
10
+ export type MiddlewareMaker = TagClassAny & { Default: Layer.Layer.Any } // todo; and Layer..
22
11
 
23
- export namespace GenericMiddlewareMaker {
12
+ export namespace MiddlewareMaker {
24
13
  export type ApplyServices<A extends TagClassAny, R> = Exclude<R, Provided<A>> | Required<A>
25
14
 
26
15
  export type ApplyManyServices<A extends NonEmptyReadonlyArray<TagClassAny>, R> =
27
16
  | Exclude<R, { [K in keyof A]: Provided<A[K]> }[number]>
28
17
  | { [K in keyof A]: Required<A[K]> }[number]
29
18
 
19
+ export type ManyProvided<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
20
+ ? { [K in keyof A]: Provided<A[K]> }[number]
21
+ : Provided<A[number]>
22
+ export type ManyRequired<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
23
+ ? { [K in keyof A]: Required<A[K]> }[number]
24
+ : Required<A[number]>
25
+ export type ManyErrors<A extends ReadonlyArray<TagClassAny>> = A extends NonEmptyReadonlyArray<TagClassAny>
26
+ ? { [K in keyof A]: Errors<A[K]> }[number]
27
+ : Errors<A[number]>
28
+
30
29
  export type Provided<T> = T extends TagClassAny
31
30
  ? T extends { provides: Context.Tag<any, any> } ? Context.Tag.Identifier<T["provides"]>
32
31
  : T extends { provides: ContextTagArray } ? ContextTagArray.Identifier<T["provides"]>
33
32
  : never
34
33
  : never
35
34
 
35
+ export type Errors<T> = T extends TagClassAny ? T extends { failure: S.Schema.Any } ? S.Schema.Type<T["failure"]>
36
+ : never
37
+ : never
38
+
36
39
  export type Required<T> = T extends TagClassAny
37
40
  ? T extends { requires: Context.Tag<any, any> } ? Context.Tag.Identifier<T["requires"]>
38
41
  : T extends { requires: ContextTagArray } ? ContextTagArray.Identifier<T["requires"]>
@@ -40,11 +43,21 @@ export namespace GenericMiddlewareMaker {
40
43
  : never
41
44
  }
42
45
 
43
- export const genericMiddlewareMaker = <
44
- T extends Array<GenericMiddlewareMaker>
45
- >(...middlewares: T): {
46
- dependencies: { [K in keyof T]: T[K]["Default"] }
47
- effect: Effect.Effect<RpcMiddleware.RpcMiddlewareWrap<any, any>>
46
+ export const middlewareMaker = <
47
+ MiddlewareProviders extends ReadonlyArray<MiddlewareMaker>
48
+ >(middlewares: MiddlewareProviders): {
49
+ dependencies: { [K in keyof MiddlewareProviders]: MiddlewareProviders[K]["Default"] }
50
+ effect: Effect.Effect<
51
+ RpcMiddlewareWrap<
52
+ MiddlewareMaker.ManyProvided<MiddlewareProviders>,
53
+ MiddlewareMaker.ManyErrors<MiddlewareProviders>,
54
+ Exclude<
55
+ MiddlewareMaker.ManyRequired<MiddlewareProviders>,
56
+ MiddlewareMaker.ManyProvided<MiddlewareProviders>
57
+ > extends never ? never
58
+ : Exclude<MiddlewareMaker.ManyRequired<MiddlewareProviders>, MiddlewareMaker.ManyProvided<MiddlewareProviders>>
59
+ >
60
+ >
48
61
  } => {
49
62
  // we want to run them in reverse order because latter middlewares will provide context to former ones
50
63
  middlewares = middlewares.toReversed() as any
@@ -55,8 +68,14 @@ export const genericMiddlewareMaker = <
55
68
  const context = yield* Effect.context()
56
69
 
57
70
  // returns a Effect/RpcMiddlewareWrap with Scope in requirements
58
- return <E>(
59
- options: GenericMiddlewareOptions<E>
71
+ return (
72
+ options: Parameters<
73
+ RpcMiddlewareWrap<
74
+ MiddlewareMaker.ManyProvided<MiddlewareProviders>,
75
+ never,
76
+ Scope.Scope
77
+ >
78
+ >[0]
60
79
  ) => {
61
80
  // we start with the actual handler
62
81
  let handler = options.next
@@ -113,7 +132,7 @@ export const genericMiddlewareMaker = <
113
132
  )
114
133
  )
115
134
  )
116
- )
135
+ ) as any
117
136
  } else {
118
137
  // use the tag to get the middleware from context
119
138
  const middleware = Context.unsafeGet(context, tag) as RpcMiddleware.RpcMiddleware<any, any>
@@ -134,10 +153,9 @@ export const genericMiddlewareMaker = <
134
153
  )
135
154
  : Effect.zipRight(middleware(options), previous)
136
155
  )
137
- )
156
+ ) as any
138
157
  }
139
158
  }
140
-
141
159
  return handler
142
160
  }
143
161
  })
@@ -1,12 +1,11 @@
1
- import { Rpc } from "@effect/rpc"
2
- import { Context, Effect, Layer, type NonEmptyArray, type NonEmptyReadonlyArray } from "effect-app"
3
- import { type RPCContextMap } from "effect-app/client"
4
- import { type LayerUtils } from "../../layerUtils.js"
5
- import { type GenericMiddlewareMaker, genericMiddlewareMaker } from "./generic-middleware.js"
6
- import { makeRpcEffect, type RPCHandlerFactory } from "./RouterMiddleware.js"
7
- import { type AnyDynamic, type RpcDynamic, type TagClassAny } from "./RpcMiddleware.js"
8
-
9
- // adapter used when setting the dynamic prop on a middleware implementation
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { type AnyWithProps } from "@effect/rpc/Rpc"
3
+ import { Context, type Effect, type NonEmptyArray, type NonEmptyReadonlyArray, S } from "effect-app"
4
+ import { type GetContextConfig, type RPCContextMap } from "effect-app/client"
5
+ import { type MiddlewareMaker, middlewareMaker } from "./generic-middleware.js"
6
+ import { type AnyDynamic, type RpcDynamic, Tag, type TagClassAny } from "./RpcMiddleware.js"
7
+
8
+ /** Adapter used when setting the dynamic prop on a middleware implementation */
10
9
  export const contextMap = <
11
10
  RequestContextMap extends Record<string, RPCContextMap.Any>,
12
11
  Key extends (keyof RequestContextMap) & string
@@ -15,19 +14,26 @@ export const contextMap = <
15
14
  settings: { service: rcm[key]!["service"] } as RequestContextMap[Key]
16
15
  })
17
16
 
17
+ /** Retrieves RequestContextConfig out of the RPC annotations */
18
+ export const getConfig = <
19
+ RequestContextMap extends Record<string, RPCContextMap.Any>
20
+ >() =>
21
+ (rpc: AnyWithProps): GetContextConfig<RequestContextMap> => {
22
+ return Context.unsafeGet(rpc.annotations, Context.GenericTag("RequestContextConfig"))
23
+ }
24
+
18
25
  // the following implements sort of builder pattern
19
26
  // we support both sideways and upwards elimination of dependencies
20
27
 
21
28
  // it's for dynamic middlewares
22
- type GetDependsOnKeys<MW extends GenericMiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> }
23
- ? {
29
+ type GetDependsOnKeys<MW extends MiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> } ? {
24
30
  [K in keyof MW["dependsOn"]]: MW["dependsOn"][K] extends AnyDynamic ? MW["dependsOn"][K]["dynamic"]["key"]
25
31
  : never
26
32
  }[keyof MW["dependsOn"]]
27
33
  : never
28
34
 
29
35
  type FilterInDynamicMiddlewares<
30
- MWs extends ReadonlyArray<GenericMiddlewareMaker>,
36
+ MWs extends ReadonlyArray<MiddlewareMaker>,
31
37
  RequestContextMap extends Record<string, RPCContextMap.Any>
32
38
  > = {
33
39
  [K in keyof MWs]: MWs[K] extends { dynamic: RpcDynamic<any, RequestContextMap[keyof RequestContextMap]> } ? MWs[K]
@@ -39,13 +45,13 @@ type RecursiveHandleMWsSideways<
39
45
  R extends {
40
46
  rcm: Record<string, RPCContextMap.Any>
41
47
  provided: keyof R["rcm"] // that's fine
42
- middlewares: ReadonlyArray<GenericMiddlewareMaker>
48
+ middlewares: ReadonlyArray<MiddlewareMaker>
43
49
  dmp: any
44
50
  middlewareR: any
45
51
  }
46
52
  > = MWs extends [
47
- infer F extends GenericMiddlewareMaker,
48
- ...infer Rest extends ReadonlyArray<GenericMiddlewareMaker>
53
+ infer F extends MiddlewareMaker,
54
+ ...infer Rest extends ReadonlyArray<MiddlewareMaker>
49
55
  ] ? RecursiveHandleMWsSideways<Rest, {
50
56
  rcm: R["rcm"]
51
57
  // when one dynamic middleware depends on another, subtract the key to enforce the dependency to be provided after
@@ -62,18 +68,18 @@ type RecursiveHandleMWsSideways<
62
68
  & {
63
69
  [U in FilterInDynamicMiddlewares<[F], R["rcm"]>[number] as U["dynamic"]["key"]]: U
64
70
  }
65
- middlewareR: GenericMiddlewareMaker.ApplyManyServices<[F], R["middlewareR"]>
71
+ middlewareR: MiddlewareMaker.ApplyManyServices<[F], R["middlewareR"]>
66
72
  }>
67
73
  : R
68
74
 
69
75
  export interface BuildingMiddleware<
70
76
  RequestContextMap extends Record<string, RPCContextMap.Any>,
71
77
  Provided extends keyof RequestContextMap,
72
- Middlewares extends ReadonlyArray<GenericMiddlewareMaker>,
78
+ Middlewares extends ReadonlyArray<MiddlewareMaker>,
73
79
  DynamicMiddlewareProviders,
74
80
  out MiddlewareR extends { _tag: string } = never
75
81
  > {
76
- middleware<MWs extends NonEmptyArray<GenericMiddlewareMaker>>(
82
+ middleware<MWs extends NonEmptyArray<MiddlewareMaker>>(
77
83
  ...mw: MWs
78
84
  ): RecursiveHandleMWsSideways<MWs, {
79
85
  rcm: RequestContextMap
@@ -84,7 +90,7 @@ export interface BuildingMiddleware<
84
90
  }> extends infer Res extends {
85
91
  rcm: RequestContextMap
86
92
  provided: keyof RequestContextMap
87
- middlewares: ReadonlyArray<GenericMiddlewareMaker>
93
+ middlewares: ReadonlyArray<MiddlewareMaker>
88
94
  dmp: any
89
95
  middlewareR: any
90
96
  } ? MiddlewaresBuilder<
@@ -106,37 +112,32 @@ export interface BuildingMiddleware<
106
112
  export type MiddlewaresBuilder<
107
113
  RequestContextMap extends Record<string, RPCContextMap.Any>,
108
114
  Provided extends keyof RequestContextMap = never,
109
- Middlewares extends ReadonlyArray<GenericMiddlewareMaker> = [],
115
+ Middlewares extends ReadonlyArray<MiddlewareMaker> = [],
110
116
  DynamicMiddlewareProviders = unknown,
111
117
  MiddlewareR extends { _tag: string } = never
112
118
  > =
113
- // keyof Omit<RequestContextMap, Provided> extends never is true when all the dynamic middlewares are provided
119
+ & BuildingMiddleware<
120
+ RequestContextMap,
121
+ Provided,
122
+ Middlewares,
123
+ DynamicMiddlewareProviders,
124
+ MiddlewareR
125
+ >
126
+ & // keyof Omit<RequestContextMap, Provided> extends never is true when all the dynamic middlewares are provided
114
127
  // MiddlewareR is never when all the required services from generic & dynamic middlewares are provided
115
- keyof Omit<RequestContextMap, Provided> extends never ? [MiddlewareR] extends [never] ? ReturnType<
128
+ (keyof Omit<RequestContextMap, Provided> extends never ? [MiddlewareR] extends [never] ? ReturnType<
116
129
  typeof makeMiddlewareBasic<
117
130
  RequestContextMap,
118
131
  Middlewares
119
132
  >
120
133
  >
121
- : BuildingMiddleware<
122
- RequestContextMap,
123
- Provided,
124
- Middlewares,
125
- DynamicMiddlewareProviders,
126
- MiddlewareR
127
- >
128
- : BuildingMiddleware<
129
- RequestContextMap,
130
- Provided,
131
- Middlewares,
132
- DynamicMiddlewareProviders,
133
- MiddlewareR
134
- >
134
+ : {}
135
+ : {})
135
136
 
136
137
  export const makeMiddleware: <
137
138
  RequestContextMap extends Record<string, RPCContextMap.Any>
138
139
  >(rcm: RequestContextMap) => MiddlewaresBuilder<RequestContextMap> = (rcm) => {
139
- let allMiddleware: GenericMiddlewareMaker[] = []
140
+ let allMiddleware: MiddlewareMaker[] = []
140
141
  const it = {
141
142
  middleware: (...middlewares: any[]) => {
142
143
  for (const mw of middlewares) {
@@ -154,92 +155,71 @@ export const makeMiddleware: <
154
155
  }
155
156
 
156
157
  //
157
- export const MiddlewareMakerTag = "MiddlewareMaker" as const
158
-
159
- export interface MiddlewareMaker<E> {
160
- readonly effect: E
161
- readonly _tag: typeof MiddlewareMakerTag
158
+ export interface MiddlewareMakerId {
159
+ readonly _id: unique symbol
162
160
  }
163
161
 
164
- export type MiddlewareMakerId = Pick<MiddlewareMaker<any>, "_tag">
165
-
166
- export const buildMiddlewareMaker = <E>(eff: E) =>
167
- ({
168
- _tag: MiddlewareMakerTag,
169
- effect: eff
170
- }) satisfies MiddlewareMaker<E>
162
+ // TODO: actually end up with [Tag<A, A>, Tag<B, B>, ...]
163
+ type MakeTags<A> = Context.Tag<A, A>
171
164
 
172
165
  const makeMiddlewareBasic =
173
166
  // by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
174
167
  <
175
168
  RequestContextMap extends Record<string, RPCContextMap.Any>,
176
- GenericMiddlewareProviders extends ReadonlyArray<GenericMiddlewareMaker>
169
+ MiddlewareProviders extends ReadonlyArray<MiddlewareMaker>
177
170
  >(
178
171
  _rcm: RequestContextMap,
179
- ...make: GenericMiddlewareProviders
172
+ ...make: MiddlewareProviders
180
173
  ) => {
181
- const MiddlewareMaker = Context.GenericTag<
182
- MiddlewareMakerId,
183
- MiddlewareMaker<
184
- RPCHandlerFactory<
185
- RequestContextMap,
186
- GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
187
- >
188
- >
189
- >(
190
- MiddlewareMakerTag
191
- )
192
-
193
174
  // reverse middlewares and wrap one after the other
194
- const middlewares = genericMiddlewareMaker(...make)
195
-
196
- const l = Layer.scoped(
197
- MiddlewareMaker,
198
- middlewares
199
- .effect
200
- .pipe(
201
- Effect.map((generic) => (buildMiddlewareMaker(
202
- makeRpcEffect<
203
- RequestContextMap,
204
- GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
205
- >()(
206
- (schema, handler, moduleName) => {
207
- return (payload, headers) =>
208
- Effect
209
- .gen(function*() {
210
- // will be propagated to all the wrapped middlewares
211
- const basic = {
212
- config: schema.config ?? {},
213
- payload,
214
- headers,
215
- clientId: 0, // TODO: get the clientId from the request context
216
- rpc: {
217
- ...Rpc.fromTaggedRequest(schema as any),
218
- key: `${moduleName}.${payload._tag}`,
219
- _tag: `${moduleName}.${payload._tag}`
220
- }
221
- }
222
- return yield* generic({
223
- ...basic,
224
- next: handler(payload, headers) as any
225
- })
226
- }) as any // why? because: Type 'SuccessValue' is not assignable to type 'Success<Req>' :P
227
- }
228
- )
229
- )))
230
- )
175
+ const middleware = middlewareMaker(make)
176
+
177
+ const failures = make.map((_) => _.failure).filter(Boolean)
178
+ const provides = make.flatMap((_) => !_.provides ? [] : Array.isArray(_.provides) ? _.provides : [_.provides])
179
+ const requires = make
180
+ .flatMap((_) => !_.requires ? [] : Array.isArray(_.requires) ? _.requires : [_.requires])
181
+ .filter((_) => !provides.includes(_))
182
+
183
+ const MiddlewareMaker = Tag<MiddlewareMakerId>()("MiddlewareMaker", {
184
+ failure: (failures.length > 0
185
+ ? S.Union(...failures)
186
+ : S.Never) as unknown as MiddlewareMaker.ManyErrors<MiddlewareProviders> extends never ? never
187
+ : S.Schema<MiddlewareMaker.ManyErrors<MiddlewareProviders>>,
188
+ requires: (requires.length > 0
189
+ ? requires
190
+ : undefined) as unknown as Exclude<
191
+ MiddlewareMaker.ManyRequired<MiddlewareProviders>,
192
+ MiddlewareMaker.ManyProvided<MiddlewareProviders>
193
+ > extends never ? never : [
194
+ MakeTags<
195
+ Exclude<
196
+ MiddlewareMaker.ManyRequired<MiddlewareProviders>,
197
+ MiddlewareMaker.ManyProvided<MiddlewareProviders>
198
+ >
199
+ >
200
+ ],
201
+ provides: (provides.length > 0
202
+ ? provides
203
+ : undefined) as unknown as MiddlewareMaker.ManyProvided<MiddlewareProviders> extends never ? never : [
204
+ MakeTags<MiddlewareMaker.ManyProvided<MiddlewareProviders>>
205
+ ],
206
+ wrap: true
207
+ })(
208
+ middleware as {
209
+ dependencies: typeof middleware["dependencies"]
210
+ effect: Effect<
211
+ any, // TODO: why ?
212
+ Effect.Error<typeof middleware["effect"]>,
213
+ Effect.Context<typeof middleware["effect"]>
214
+ >
215
+ }
231
216
  )
232
217
 
233
- const middlewareLayer = l
234
- .pipe(
235
- Layer.provide(middlewares.dependencies as any)
236
- ) as Layer.Layer<
237
- MiddlewareMakerId,
238
- // what could go wrong when building the dynamic middleware provider
239
- LayerUtils.GetLayersError<typeof middlewares.dependencies>,
240
- LayerUtils.GetLayersContext<typeof middlewares.dependencies>
241
- >
242
-
243
218
  // add to the tag a default implementation
244
- return Object.assign(MiddlewareMaker, { Default: middlewareLayer })
219
+ return Object.assign(MiddlewareMaker, {
220
+ // tag to be used to retrieve the RequestContextConfig from RPC annotations
221
+ requestContext: Context.GenericTag<"RequestContextConfig", GetContextConfig<RequestContextMap>>(
222
+ "RequestContextConfig"
223
+ )
224
+ })
245
225
  }
@@ -1,5 +1,4 @@
1
1
  // codegen:start {preset: barrel, include: ./middleware/*.ts, nodir: false }
2
- export * from "./middleware/ContextProvider.js"
3
2
  export * from "./middleware/dynamic-middleware.js"
4
3
  export * from "./middleware/generic-middleware.js"
5
4
  export * from "./middleware/middleware-api.js"
@@ -167,13 +167,17 @@ export const makeRouter = <
167
167
  RequestContextMap extends Record<string, RPCContextMap.Any>,
168
168
  MakeMiddlewareE,
169
169
  MakeMiddlewareR,
170
- ContextProviderA
170
+ ContextProviderA,
171
+ ContextProviderE,
172
+ ContextProviderR
171
173
  >(
172
174
  middleware: RouterMiddleware<
173
175
  RequestContextMap,
174
176
  MakeMiddlewareE,
175
177
  MakeMiddlewareR,
176
- ContextProviderA
178
+ ContextProviderA,
179
+ ContextProviderE,
180
+ ContextProviderR
177
181
  >,
178
182
  devMode: boolean
179
183
  ) => {
@@ -370,7 +374,6 @@ export const makeRouter = <
370
374
  : make
371
375
 
372
376
  const controllers = yield* make
373
- const rpc = yield* middleware
374
377
 
375
378
  // return make.pipe(Effect.map((c) => controllers(c, dependencies)))
376
379
  const mapped = typedKeysOf(requestModules).reduce((acc, cur) => {
@@ -400,16 +403,12 @@ export const makeRouter = <
400
403
  }
401
404
  } as any
402
405
  : resource,
403
- rpc.effect(
404
- resource,
405
- (req, headers) =>
406
- handle(req, headers).pipe(
407
- Effect.withSpan("Request." + meta.moduleName + "." + resource._tag, {
408
- captureStackTrace: () => handler.stack
409
- })
410
- ),
411
- meta.moduleName
412
- ),
406
+ (payload: any, headers: any) =>
407
+ handle(payload, headers).pipe(
408
+ Effect.withSpan("Request." + resource._tag, {
409
+ captureStackTrace: () => handler.stack // capturing the handler stack is the main reason why we are doing the span here
410
+ })
411
+ ),
413
412
  meta.moduleName
414
413
  ] as const
415
414
  return acc
@@ -431,16 +430,19 @@ export const makeRouter = <
431
430
  ]
432
431
  }
433
432
 
434
- const rpcs = RpcGroup.make(
435
- ...typedValuesOf(mapped).map(([resource]) => {
436
- return Rpc.fromTaggedRequest(resource)
437
- })
438
- )
433
+ const rpcs = RpcGroup
434
+ .make(
435
+ ...typedValuesOf(mapped).map(([resource]) => {
436
+ return Rpc.fromTaggedRequest(resource).annotate(middleware.requestContext, resource.config ?? {})
437
+ })
438
+ )
439
+ .prefix(`${meta.moduleName}.`)
440
+ .middleware(middleware as any)
439
441
  const rpcLayer = rpcs.toLayer(Effect.gen(function*() {
440
442
  return typedValuesOf(mapped).reduce((acc, [resource, handler]) => {
441
- acc[resource._tag] = handler
443
+ acc[`${meta.moduleName}.${resource._tag}`] = handler
442
444
  return acc
443
- }, {} as Record<string, any>)
445
+ }, {} as Record<string, any>) as any // TODO
444
446
  })) as unknown as Layer<
445
447
  { [K in keyof RequestModules]: Rpc.Handler<K> },
446
448
  | Layer.Error<typeof middleware.Default>
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
3
  import { expectTypeOf, it } from "@effect/vitest"
4
4
  import { Context, Effect, Scope } from "effect-app"
5
- import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/routing.js"
5
+ import { ContextProvider, mergeContextProviders, MergedContextProvider } from "../src/api/ContextProvider.js"
6
6
  import { CustomError1, Some, SomeElse, SomeService } from "./fixtures.js"
7
7
 
8
8
  // @effect-diagnostics-next-line missingEffectServiceDependency:off
@@ -76,23 +76,22 @@ const genericMiddlewares = [
76
76
  ] as const
77
77
 
78
78
  const middleware = makeMiddleware<RequestContextMap>(RequestContextMap)
79
- .middleware(MyContextProvider)
80
79
  .middleware(
81
80
  RequireRoles,
82
81
  Test
83
82
  )
84
83
  // AllowAnonymous provided after RequireRoles so that RequireRoles can access what AllowAnonymous provides
85
84
  .middleware(AllowAnonymous)
85
+ .middleware(MyContextProvider)
86
86
  .middleware(...genericMiddlewares)
87
87
 
88
88
  const middlewareBis = makeMiddleware<RequestContextMap>(RequestContextMap)
89
- .middleware(MyContextProvider)
90
89
  .middleware(
91
90
  RequireRoles,
92
91
  Test
93
92
  )
94
93
  // testing sideways elimination
95
- .middleware(AllowAnonymous, ...genericMiddlewares)
94
+ .middleware(AllowAnonymous, MyContextProvider, ...genericMiddlewares)
96
95
 
97
96
  expectTypeOf(middleware).toEqualTypeOf<typeof middlewareBis>()
98
97
 
@@ -112,10 +111,10 @@ expectTypeOf(middlewareTrisWip).toEqualTypeOf<{
112
111
  // testing more sideways elimination]
113
112
  const middlewareQuater = makeMiddleware<RequestContextMap>(RequestContextMap)
114
113
  .middleware(
115
- MyContextProvider,
116
114
  RequireRoles,
117
115
  Test,
118
116
  AllowAnonymous,
117
+ MyContextProvider,
119
118
  ...genericMiddlewares
120
119
  )
121
120
 
@@ -1 +1 @@
1
- {"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAc,MAAM,+BAA+B,CAAA;AAE7F,OAAO,EAAW,MAAM,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAA6C,UAAU,EAAO,MAAM,kCAAkC,CAAA;AAE7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;AAgChI,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;AAML,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;AA4DD,eAAO,MAAM,WAAW;;;;;;YAIM,CAAA;AAE9B,MAAM,MAAM,aAAa,GAAG;IAC1B,yCAAyC;IACzC,cAAc,CAAC,EAAE,IAAI,CAAA;IACrB,iEAAiE;IACjE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B,CAAA;AACD,eAAO,MAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAI/B,CAAA;;;;;;;;;;AAEF,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;AACtE,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;;;AAEtE,qBAAa,WAAY,SAAQ,gBAEV;CAAG;;;;;;;;;;;;AAgB1B,qBAAa,YAAa,SAAQ,iBAET;CAAG;;;;;;;;;;;;AAE5B,qBAAa,aAAc,SAAQ,kBAEA;CAAG;;;;;AAItC,qBAAa,gBAAiB,SAAQ,qBAKpC;CAAG;;;;;AASL,qBAAa,aAAc,SAAQ,kBAOjC;CAAG;;;;;AAEL,qBAAa,iBAAkB,SAAQ,sBAKrC;CAAG;AAEL,eAAO,MAAQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAE,QAAQ;;;;;2HAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAAiC,CAAA;AAE1E,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgC,CAAA"}
1
+ {"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAc,MAAM,+BAA+B,CAAA;AAE7F,OAAO,EAAW,MAAM,EAAE,KAAK,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAA6C,UAAU,EAAO,MAAM,kCAAkC,CAAA;AAE7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;AAgChI,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;AAML,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;AA2DD,eAAO,MAAM,WAAW;;;;;;YAIM,CAAA;AAE9B,MAAM,MAAM,aAAa,GAAG;IAC1B,yCAAyC;IACzC,cAAc,CAAC,EAAE,IAAI,CAAA;IACrB,iEAAiE;IACjE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B,CAAA;AACD,eAAO,MAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAI/B,CAAA;;;;;;;;;;AAEF,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;AACtE,qBAAa,GAAI,SAAQ,QAA0C;CAAG;;;;;;;;;;;;AAEtE,qBAAa,WAAY,SAAQ,gBAEV;CAAG;;;;;;;;;;;;AAgB1B,qBAAa,YAAa,SAAQ,iBAET;CAAG;;;;;;;;;;;;AAE5B,qBAAa,aAAc,SAAQ,kBAEA;CAAG;;;;;AAItC,qBAAa,gBAAiB,SAAQ,qBAKpC;CAAG;;;;;AASL,qBAAa,aAAc,SAAQ,kBAOjC;CAAG;;;;;AAEL,qBAAa,iBAAkB,SAAQ,sBAKrC;CAAG;AAEL,eAAO,MAAQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAE,QAAQ;;;;;2HAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAAiC,CAAA;AAE1E,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgC,CAAA"}
@@ -37,7 +37,7 @@ declare const Some_base: (abstract new (service: {
37
37
  } & {
38
38
  use: <X>(body: (_: {
39
39
  a: number;
40
- }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, Some | R_3> : Effect.Effect<X, never, Some>;
40
+ }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, R_3 | Some> : Effect.Effect<X, never, Some>;
41
41
  };
42
42
  export declare class Some extends Some_base {
43
43
  }
@@ -63,7 +63,7 @@ declare const SomeElse_base: (abstract new (service: {
63
63
  } & {
64
64
  use: <X>(body: (_: {
65
65
  b: number;
66
- }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, R_3 | SomeElse> : Effect.Effect<X, never, SomeElse>;
66
+ }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, SomeElse | R_3> : Effect.Effect<X, never, SomeElse>;
67
67
  };
68
68
  export declare class SomeElse extends SomeElse_base {
69
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEtF,OAAO,EAAc,UAAU,EAAE,MAAM,uBAAuB,CAAA;;;;;;;;;;;;;AAE9D,qBAAa,WAAY,SAAQ,gBAKhC;CACA;;;;;;;;;;;;;;;;;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SAA2D;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AACxF,qBAAa,QAAS,SAAQ,aAAmE;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAEpG,qBAAa,WAAY,SAAQ,gBAAgE;CAAG;AAOpG,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAA;AAEV,KAAK,kBAAkB,GAAG,OAAO,iBAAiB,CAAA;AAClD,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;CAAG;;;;;;;AAEhE,qBAAa,cAAe,SAAQ,mBA4BlC;CACD;;;;;;;;AAID,qBAAa,YAAa,SAAQ,iBA6BhC;CACD;;;;;;;AAGD,qBAAa,IAAK,SAAQ,SASxB;CAAG;;;;AAEL,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG"}
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAU,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEtF,OAAO,EAAyB,UAAU,EAAE,MAAM,uBAAuB,CAAA;;;;;;;;;;;;;AAEzE,qBAAa,WAAY,SAAQ,gBAKhC;CACA;;;;;;;;;;;;;;;;;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SAA2D;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AACxF,qBAAa,QAAS,SAAQ,aAAmE;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAEpG,qBAAa,WAAY,SAAQ,gBAAgE;CAAG;AASpG,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAA;AAEV,KAAK,kBAAkB,GAAG,OAAO,iBAAiB,CAAA;AAClD,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;CAAG;;;;;;;AAEhE,qBAAa,cAAe,SAAQ,mBA4BlC;CACD;;;;;;;;AAID,qBAAa,YAAa,SAAQ,iBA6BhC;CACD;;;;;;;AAGD,qBAAa,IAAK,SAAQ,SASxB;CAAG;;;;AAEL,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG"}