@effect-app/infra 2.86.0 → 2.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/api/layerUtils.d.ts +1 -5
  3. package/dist/api/layerUtils.d.ts.map +1 -1
  4. package/dist/api/layerUtils.js +3 -11
  5. package/dist/api/routing/middleware/RouterMiddleware.d.ts +33 -0
  6. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  7. package/dist/api/routing/middleware/RouterMiddleware.js +5 -0
  8. package/dist/api/routing/middleware/RpcMiddleware.d.ts +199 -0
  9. package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -0
  10. package/dist/api/routing/middleware/RpcMiddleware.js +14 -0
  11. package/dist/api/routing/middleware/dynamic-middleware.d.ts +2 -12
  12. package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
  13. package/dist/api/routing/middleware/dynamic-middleware.js +2 -18
  14. package/dist/api/routing/middleware/generic-middleware.d.ts +4 -23
  15. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
  16. package/dist/api/routing/middleware/generic-middleware.js +13 -9
  17. package/dist/api/routing/middleware/middleware-api.d.ts +43 -7
  18. package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
  19. package/dist/api/routing/middleware/middleware-api.js +47 -22
  20. package/dist/api/routing/middleware/middleware.d.ts +3 -3
  21. package/dist/api/routing/middleware/middleware.js +2 -2
  22. package/dist/api/routing/middleware.d.ts +2 -1
  23. package/dist/api/routing/middleware.d.ts.map +1 -1
  24. package/dist/api/routing/middleware.js +3 -2
  25. package/dist/api/routing/tsort.d.ts +2 -2
  26. package/dist/api/routing/tsort.d.ts.map +1 -1
  27. package/dist/api/routing/tsort.js +1 -1
  28. package/package.json +9 -5
  29. package/src/api/layerUtils.ts +4 -18
  30. package/src/api/routing/middleware/RouterMiddleware.ts +149 -0
  31. package/src/api/routing/middleware/RpcMiddleware.ts +287 -0
  32. package/src/api/routing/middleware/dynamic-middleware.ts +5 -52
  33. package/src/api/routing/middleware/generic-middleware.ts +23 -34
  34. package/src/api/routing/middleware/middleware-api.ts +142 -59
  35. package/src/api/routing/middleware/middleware.ts +1 -1
  36. package/src/api/routing/middleware.ts +2 -1
  37. package/src/api/routing/tsort.ts +2 -2
  38. package/test/controller.test.ts +22 -58
  39. package/test/dist/controller.test.d.ts.map +1 -1
  40. package/test/dist/fixtures.d.ts +4 -2
  41. package/test/dist/fixtures.d.ts.map +1 -1
  42. package/test/dist/fixtures.js +21 -9
  43. package/test/dist/requires.test.d.ts.map +1 -1
  44. package/test/fixtures.ts +29 -12
  45. package/test/requires.test.ts +98 -17
  46. package/dist/api/routing/middleware/DynamicMiddleware.d.ts +0 -229
  47. package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +0 -1
  48. package/dist/api/routing/middleware/DynamicMiddleware.js +0 -168
  49. package/src/api/routing/middleware/DynamicMiddleware.ts +0 -715
@@ -1,13 +1,20 @@
1
- import { Array, Either, type NonEmptyArray } from "effect-app"
1
+ import { Rpc } from "@effect/rpc"
2
+ import { Context, Effect, Layer, type NonEmptyArray, type NonEmptyReadonlyArray } from "effect-app"
2
3
  import { type RPCContextMap } from "effect-app/client"
3
- import { type DynamicMiddlewareMaker, type GenericMiddlewareMaker, makeMiddleware, type makeMiddlewareBasic, type RequestContextMapProvider } from "../../routing.js"
4
+ import { type Simplify } from "effect-app/Types"
5
+ import { type LayerUtils } from "../../layerUtils.js"
6
+ import { type GenericMiddlewareMaker, genericMiddlewareMaker } from "./generic-middleware.js"
7
+ import { makeRpcEffect, type MiddlewareMakerId, type RPCHandlerFactory } from "./RouterMiddleware.js"
8
+ import { type AnyDynamic, type RpcDynamic, type TagClassAny } from "./RpcMiddleware.js"
4
9
 
5
- // TODO: ContextMap should be physical Tag (so typeof Tag), so that we can retrieve Identifier and Service separately.
6
- // in Service classes and TagId, the Id and Service are the same, but don't have to be in classic Tag or GenericTag.
7
- export const contextMap = <RequestContextMap>() => <K extends keyof RequestContextMap>(a: K) => ({
8
- key: a,
9
- settings: null as any as RequestContextMap[typeof a]
10
- })
10
+ // TODO: don't expect service when it's wrap/never
11
+ // perhaps RequestContextMap should be an object, instead of an interface, so that we don't need to provide anything here
12
+ export const contextMap =
13
+ <RequestContextMap extends Record<string, RPCContextMap.Any>>() =>
14
+ <K extends keyof RequestContextMap>(a: K, service: RequestContextMap[K]["service"]) => ({
15
+ key: a,
16
+ settings: { service } as any as RequestContextMap[typeof a]
17
+ })
11
18
 
12
19
  export interface MiddlewareM<
13
20
  RequestContext extends Record<string, RPCContextMap.Any>,
@@ -28,6 +35,13 @@ export interface MiddlewareM<
28
35
  >
29
36
  }
30
37
 
38
+ type GetDependsOnKeys<MW extends GenericMiddlewareMaker> = MW extends { dependsOn: NonEmptyReadonlyArray<TagClassAny> }
39
+ ? {
40
+ [K in keyof MW["dependsOn"]]: MW["dependsOn"][K] extends AnyDynamic ? MW["dependsOn"][K]["dynamic"]["key"]
41
+ : never
42
+ }[keyof MW["dependsOn"]]
43
+ : never
44
+
31
45
  export interface MiddlewareDynamic<
32
46
  RequestContext extends Record<string, RPCContextMap.Any>,
33
47
  Provided extends keyof RequestContext,
@@ -35,14 +49,17 @@ export interface MiddlewareDynamic<
35
49
  DynamicMiddlewareProviders,
36
50
  out MiddlewareR
37
51
  > {
38
- // TODO: this still allows to mix both types of middleware but with bad typing result
39
- // either have to block it, or implement the support properly.
40
- middleware<MW extends NonEmptyArray<DynamicMiddlewareMaker<RequestContext>> | NonEmptyArray<GenericMiddlewareMaker>>(
52
+ middleware<MW extends NonEmptyArray<GenericMiddlewareMaker>>(
41
53
  ...mw: MW
42
- ): [MW] extends [NonEmptyArray<DynamicMiddlewareMaker<RequestContext>>] ? DynamicMiddlewareMakerrsss<
54
+ ): MW extends NonEmptyArray<{ dynamic: RpcDynamic<any, RequestContext[keyof RequestContext]> }>
55
+ ? DynamicMiddlewareMakerrsss<
43
56
  RequestContext,
44
- Provided | MW[number]["dynamic"]["key"],
45
- Middlewares,
57
+ // when one dynamic middleware depends on another, substract the key, to enforce the dependency to be provided after.
58
+ Exclude<
59
+ Provided | MW[number]["dynamic"]["key"],
60
+ { [K in keyof MW]: GetDependsOnKeys<MW[K]> }[number]
61
+ >,
62
+ [...Middlewares, ...MW],
46
63
  & DynamicMiddlewareProviders
47
64
  & {
48
65
  [U in MW[number] as U["dynamic"]["key"]]: U
@@ -58,9 +75,6 @@ export interface MiddlewareDynamic<
58
75
  >
59
76
  }
60
77
 
61
- type GetDynamicMiddleware<T, RequestContext extends Record<string, RPCContextMap.Any>> = T extends
62
- RequestContextMapProvider<RequestContext> ? T : never
63
-
64
78
  type DynamicMiddlewareMakerrsss<
65
79
  RequestContext extends Record<string, RPCContextMap.Any>,
66
80
  Provided extends keyof RequestContext = never,
@@ -68,19 +82,18 @@ type DynamicMiddlewareMakerrsss<
68
82
  DynamicMiddlewareProviders = unknown,
69
83
  MiddlewareR = never
70
84
  > = keyof Omit<RequestContext, Provided> extends never ? [MiddlewareR] extends [never] ?
85
+ & {
86
+ MiddlewareR: MiddlewareR
87
+ Provided: Provided
88
+ Middlewares: Middlewares
89
+ DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
90
+ }
71
91
  & ReturnType<
72
92
  typeof makeMiddlewareBasic<
73
93
  RequestContext,
74
- GetDynamicMiddleware<DynamicMiddlewareProviders, RequestContext>,
75
94
  Middlewares
76
95
  >
77
96
  >
78
- // & {
79
- // MiddlewareR: MiddlewareR
80
- // Provided: Provided
81
- // Middlewares: Middlewares
82
- // DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
83
- // }
84
97
  & MiddlewareM<
85
98
  RequestContext,
86
99
  Provided,
@@ -88,50 +101,120 @@ type DynamicMiddlewareMakerrsss<
88
101
  DynamicMiddlewareProviders,
89
102
  MiddlewareR
90
103
  >
91
- : MiddlewareM<
92
- RequestContext,
93
- Provided,
94
- Middlewares,
95
- DynamicMiddlewareProviders,
96
- MiddlewareR
97
- >
98
- : MiddlewareDynamic<
99
- RequestContext,
100
- Provided,
101
- Middlewares,
102
- DynamicMiddlewareProviders,
103
- MiddlewareR
104
- >
104
+ :
105
+ & {
106
+ MiddlewareR: MiddlewareR
107
+ Provided: Provided
108
+ Middlewares: Middlewares
109
+ DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
110
+ }
111
+ & MiddlewareM<
112
+ RequestContext,
113
+ Provided,
114
+ Middlewares,
115
+ DynamicMiddlewareProviders,
116
+ MiddlewareR
117
+ >
118
+ :
119
+ & {
120
+ MiddlewareR: MiddlewareR
121
+ Provided: Provided
122
+ Middlewares: Middlewares
123
+ DynamicMiddlewareProviders: Simplify<DynamicMiddlewareProviders>
124
+ }
125
+ & MiddlewareDynamic<
126
+ RequestContext,
127
+ Provided,
128
+ Middlewares,
129
+ DynamicMiddlewareProviders,
130
+ MiddlewareR
131
+ >
105
132
 
106
- export const makeNewMiddleware: <
133
+ export const makeMiddleware: <
107
134
  RequestContextMap extends Record<string, RPCContextMap.Any>
108
135
  >() => DynamicMiddlewareMakerrsss<RequestContextMap> = () => {
109
- const make = makeMiddleware<any>()
110
- let capturedMiddlewares: (DynamicMiddlewareMaker<any> | GenericMiddlewareMaker)[] = []
136
+ let allMiddleware: GenericMiddlewareMaker[] = []
111
137
  const it = {
112
138
  middleware: (...middlewares: any[]) => {
113
139
  for (const mw of middlewares) {
114
- capturedMiddlewares = [mw, ...capturedMiddlewares]
115
- if (mw.dynamic) {
116
- console.log("Adding dynamic middleware", mw.key, mw.dynamic.key)
117
- } else {
118
- console.log("Adding generic middleware", mw.key)
119
- }
140
+ allMiddleware = [mw, ...allMiddleware]
120
141
  }
121
- const [genericMiddlewares, dyn] = Array.partitionMap(
122
- capturedMiddlewares,
123
- (mw) =>
124
- "dynamic" in mw && mw.dynamic
125
- ? Either.right(mw as DynamicMiddlewareMaker<any>)
126
- : Either.left(mw as GenericMiddlewareMaker)
127
- )
128
- const dynamicMiddlewares = dyn.reduce(
129
- (prev, cur) => ({ ...prev, [cur.dynamic.key]: cur }),
130
- {} as Record<string, any>
131
- )
132
142
  // TODO: support dynamic and generic intertwined. treat them as one
133
- return Object.assign(make({ genericMiddlewares, dynamicMiddlewares }), it)
143
+ return Object.assign(makeMiddlewareBasic<any, any>(...allMiddleware), it)
134
144
  }
135
145
  }
136
146
  return it as any
137
147
  }
148
+
149
+ export const makeMiddlewareBasic =
150
+ // by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
151
+ <
152
+ RequestContextMap extends Record<string, RPCContextMap.Any>,
153
+ // RequestContextProviders extends RequestContextMapProvider<RequestContextMap>, // how to resolve the dynamic middleware
154
+ GenericMiddlewareProviders extends ReadonlyArray<GenericMiddlewareMaker>
155
+ >(
156
+ ...make: GenericMiddlewareProviders
157
+ ) => {
158
+ const MiddlewareMaker = Context.GenericTag<
159
+ MiddlewareMakerId,
160
+ {
161
+ effect: RPCHandlerFactory<
162
+ RequestContextMap,
163
+ GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
164
+ >
165
+ _tag: "MiddlewareMaker"
166
+ }
167
+ >(
168
+ "MiddlewareMaker"
169
+ )
170
+
171
+ const middlewares = genericMiddlewareMaker(...make)
172
+
173
+ const l = Layer.scoped(
174
+ MiddlewareMaker,
175
+ middlewares
176
+ .effect
177
+ .pipe(
178
+ Effect.map((generic) => ({
179
+ _tag: "MiddlewareMaker" as const,
180
+ effect: makeRpcEffect<
181
+ RequestContextMap,
182
+ GenericMiddlewareMaker.Provided<GenericMiddlewareProviders[number]>
183
+ >()(
184
+ (schema, next, moduleName) => {
185
+ return (payload, headers) =>
186
+ Effect
187
+ .gen(function*() {
188
+ const basic = {
189
+ config: schema.config ?? {},
190
+ payload,
191
+ headers,
192
+ clientId: 0, // TODO: get the clientId from the request context
193
+ rpc: {
194
+ ...Rpc.fromTaggedRequest(schema as any),
195
+ key: `${moduleName}.${payload._tag}`,
196
+ _tag: `${moduleName}.${payload._tag}`
197
+ }
198
+ }
199
+ return yield* generic({
200
+ ...basic,
201
+ next: next(payload, headers) as any
202
+ })
203
+ }) as any // why?
204
+ }
205
+ )
206
+ }))
207
+ )
208
+ )
209
+
210
+ const middlewareLayer = l
211
+ .pipe(
212
+ Layer.provide(middlewares.dependencies as any)
213
+ ) as Layer.Layer<
214
+ MiddlewareMakerId,
215
+ LayerUtils.GetLayersError<typeof middlewares.dependencies>, // what could go wrong when building the dynamic middleware provider
216
+ LayerUtils.GetLayersContext<typeof middlewares.dependencies>
217
+ >
218
+
219
+ return Object.assign(MiddlewareMaker, { Default: middlewareLayer })
220
+ }
@@ -3,7 +3,7 @@ import { Cause, Context, Duration, Effect, Layer, ParseResult, Request } from "e
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 { Tag } from "../middleware.js"
6
+ import { Tag } from "./RpcMiddleware.js"
7
7
 
8
8
  const logRequestError = logError("Request")
9
9
  const reportRequestError = reportError("Request")
@@ -1,10 +1,11 @@
1
1
  // codegen:start {preset: barrel, include: ./middleware/*.ts, nodir: false }
2
2
  export * from "./middleware/ContextProvider.js"
3
3
  export * from "./middleware/dynamic-middleware.js"
4
- export * from "./middleware/DynamicMiddleware.js"
5
4
  export * from "./middleware/generic-middleware.js"
6
5
  export * from "./middleware/middleware-api.js"
7
6
  export * from "./middleware/middleware.js"
7
+ export * from "./middleware/RouterMiddleware.js"
8
+ export * from "./middleware/RpcMiddleware.js"
8
9
  // codegen:end
9
10
 
10
11
  export * as Middleware from "./middleware.js"
@@ -39,7 +39,7 @@ export function tsort(edges) {
39
39
  return sorted
40
40
  }
41
41
 
42
- export const createEdges = <T extends { dependsOn?: any[] }>(dep: readonly T[]) => {
42
+ export const createEdges = <T extends { dependsOn?: readonly any[] }>(dep: readonly T[]) => {
43
43
  const result = []
44
44
  dep.forEach((key) => {
45
45
  key.dependsOn?.forEach((n) => {
@@ -49,7 +49,7 @@ export const createEdges = <T extends { dependsOn?: any[] }>(dep: readonly T[])
49
49
  return result
50
50
  }
51
51
 
52
- export const sort = <T>(dep: readonly (T & { dependsOn?: any[] })[]): readonly T[] => {
52
+ export const sort = <T>(dep: readonly (T & { dependsOn?: readonly any[] })[]): readonly T[] => {
53
53
  const edges = createEdges(dep)
54
54
  const result = tsort(edges)
55
55
  return result.concat(dep.filter((v) => !result.includes(v)))
@@ -2,9 +2,9 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
3
  import { type MakeContext, type MakeErrors, makeRouter } from "@effect-app/infra/api/routing"
4
4
  import { expect, expectTypeOf, it } from "@effect/vitest"
5
- import { Context, Effect, Layer, S, Scope } from "effect-app"
5
+ import { Context, Effect, type Layer, S, Scope } from "effect-app"
6
6
  import { InvalidStateError, makeRpcClient, NotLoggedInError, UnauthorizedError } from "effect-app/client"
7
- import { DefaultGenericMiddlewares, implementMiddleware, makeMiddleware, makeNewMiddleware, Middleware, Tag } from "../src/api/routing/middleware.js"
7
+ import { DefaultGenericMiddlewares, makeMiddleware, Middleware, Tag } from "../src/api/routing/middleware.js"
8
8
  import { sort } from "../src/api/routing/tsort.js"
9
9
  import { AllowAnonymous, CustomError1, type RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
10
10
 
@@ -53,13 +53,13 @@ class MyContextProvider2 extends Middleware.Tag<MyContextProvider2>()("MyContext
53
53
  //
54
54
 
55
55
  const Str = Context.GenericTag<"str", "str">("str")
56
- const Str2 = Context.GenericTag<"str2", "str">("str2")
57
56
 
58
57
  export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
59
58
  provides: SomeService,
60
59
  wrap: true
61
60
  })({
62
61
  effect: Effect.gen(function*() {
62
+ yield* Str
63
63
  // yield* Effect.context<"test-dep">()
64
64
  return ({ next }) =>
65
65
  Effect.gen(function*() {
@@ -72,61 +72,31 @@ export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
72
72
 
73
73
  const genericMiddlewares = [
74
74
  ...DefaultGenericMiddlewares,
75
- // BogusMiddleware,
76
- MyContextProvider2,
77
- MyContextProvider
75
+ BogusMiddleware,
76
+ MyContextProvider2
78
77
  ] as const
79
78
 
80
- // TODO: eventually it might be nice if we have total control over order somehow..
81
- // [ AddRequestNameToSpanContext, RequestCacheContext, UninterruptibleMiddleware, Dynamic(or individual, AllowAnonymous, RequireRoles, Test - or whichever order) ]
82
- const middleware = makeMiddleware<RequestContextMap>()({
83
- genericMiddlewares,
84
-
85
- dynamicMiddlewares: {
86
- requireRoles: RequireRoles,
87
- allowAnonymous: AllowAnonymous,
88
- test: Test
89
- },
90
-
91
- dependencies: [Layer.effect(Str2, Str)],
92
- execute: (maker) =>
93
- Effect.gen(function*() {
94
- return maker(
95
- (_schema, handler) => (req, headers) =>
96
- // contextProvider and dynamicMiddlewares are already provided here.
97
- // aka this runs "last"
98
- Effect
99
- .gen(function*() {
100
- // you can use only HttpRouter.HttpRouter.Provided here as additional context
101
- // and what ContextProvider provides too
102
- // const someElse = yield* SomeElse
103
- yield* Some // provided by ContextProvider
104
- yield* Scope.Scope // provided by HttpRouter.HttpRouter.Provided
105
-
106
- return yield* handler(req, headers)
107
- })
108
- )
109
- })
110
- })
79
+ const middleware = makeMiddleware<RequestContextMap>()
80
+ .middleware(MyContextProvider)
81
+ .middleware(
82
+ RequireRoles,
83
+ Test
84
+ )
85
+ .middleware(AllowAnonymous)
86
+ .middleware(...genericMiddlewares)
87
+ // dependencies: [Layer.effect(Str2, Str)],
111
88
 
112
- const middleware2 = makeMiddleware<RequestContextMap>()({
113
- // TODO: I guess it makes sense to support just passing array of context providers too, like dynamicMiddlewares?
114
- genericMiddlewares: [...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2, MyContextProvider],
115
- // or is the better api to use constructors outside, like how contextProvider is used now?
116
- dynamicMiddlewares: {
117
- requireRoles: RequireRoles,
118
- allowAnonymous: AllowAnonymous,
119
- test: Test
120
- }
121
- })
89
+ const middleware2 = makeMiddleware<RequestContextMap>()
90
+ .middleware(MyContextProvider)
91
+ .middleware(RequireRoles, Test)
92
+ .middleware(AllowAnonymous)
93
+ .middleware(...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2)
122
94
 
123
- export const middleware3 = makeNewMiddleware<RequestContextMap>()
95
+ export const middleware3 = makeMiddleware<RequestContextMap>()
124
96
  .middleware(...genericMiddlewares)
125
97
  .middleware(AllowAnonymous, RequireRoles)
126
98
  .middleware(Test)
127
- // .middleware(BogusMiddleware)
128
-
129
- // expectTypeOf(middleware3).toExtend<typeof middleware2>()
99
+ .middleware(BogusMiddleware)
130
100
 
131
101
  export type RequestConfig = {
132
102
  /** Disable authentication requirement */
@@ -348,16 +318,10 @@ const router2 = r2.Router(Something)({
348
318
 
349
319
  // eslint-disable-next-line unused-imports/no-unused-vars
350
320
  const matched2 = matchAll({ router: router2 })
351
- expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<Some | SomeService>()
321
+ expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<Some | SomeService | "str">()
352
322
 
353
323
  type makeContext2 = MakeContext<typeof router2.make>
354
324
  expectTypeOf({} as MakeErrors<typeof router2.make>).toEqualTypeOf<InvalidStateError>()
355
325
  expectTypeOf({} as makeContext2).toEqualTypeOf<
356
326
  SomethingService | SomethingRepo | SomethingService2
357
327
  >()
358
-
359
- export const dynamicMiddlewares = implementMiddleware<RequestContextMap>()({
360
- requireRoles: RequireRoles,
361
- allowAnonymous: AllowAnonymous,
362
- test: Test
363
- })
@@ -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,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAoC,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACzG,OAAO,EAAqF,UAAU,EAAO,MAAM,kCAAkC,CAAA;AAErJ,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;;AAGrI,cAAM,iBAAkB,SAAQ,sBA0B9B;CAAG;;;;;;AAGL,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;;AAOL,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;AAoDD,eAAO,MAAM,WAAW;;;;;YAGL,CAAA;AAKnB,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;AAyJ/C,eAAO,MAAM,kBAAkB;;;;;;;;;;CAI7B,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,KAAK,iBAAiB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;;;;;;AAgCrI,cAAM,kBAAmB,SAAQ,uBAU/B;CAAG;;;;;;;AAML,qBAAa,eAAgB,SAAQ,oBAanC;CACD;AAwBD,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"}
@@ -68,14 +68,14 @@ declare const SomeElse_base: (abstract new (service: {
68
68
  export declare class SomeElse extends SomeElse_base {
69
69
  }
70
70
  export type RequestContextMap = {
71
- allowAnonymous: RPCContextMap.Inverted<UserProfile, typeof NotLoggedInError>;
71
+ allowAnonymous: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>;
72
72
  requireRoles: RPCContextMap.Custom<never, typeof UnauthorizedError, Array<string>>;
73
73
  test: RPCContextMap<never, typeof S.Never>;
74
74
  };
75
75
  declare const AllowAnonymous_base: Middleware.TagClass<AllowAnonymous, "AllowAnonymous", {
76
76
  readonly dynamic: {
77
77
  key: "allowAnonymous";
78
- settings: RPCContextMap.Inverted<UserProfile, typeof NotLoggedInError>;
78
+ settings: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>;
79
79
  };
80
80
  readonly requires: typeof SomeElse;
81
81
  }> & {
@@ -88,6 +88,7 @@ declare const RequireRoles_base: Middleware.TagClass<RequireRoles, "RequireRoles
88
88
  key: "requireRoles";
89
89
  settings: RPCContextMap.Custom<never, typeof UnauthorizedError, string[]>;
90
90
  };
91
+ readonly wrap: true;
91
92
  readonly dependsOn: readonly [typeof AllowAnonymous];
92
93
  }> & {
93
94
  Default: import("effect/Layer").Layer<RequireRoles, never, Some>;
@@ -95,6 +96,7 @@ declare const RequireRoles_base: Middleware.TagClass<RequireRoles, "RequireRoles
95
96
  export declare class RequireRoles extends RequireRoles_base {
96
97
  }
97
98
  declare const Test_base: Middleware.TagClass<Test, "Test", {
99
+ readonly wrap: true;
98
100
  readonly dynamic: {
99
101
  key: "test";
100
102
  settings: RPCContextMap<never, typeof S.Never>;
@@ -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,KAAK,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE3F,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,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,gBAAgB,CAAC,CAAA;IAC5E,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAClF,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAA;CAC3C,CAAA;;;;;;;;;;AAED,qBAAa,cAAe,SAAQ,mBAuBlC;CACD;;;;;;;;;;AAGD,qBAAa,YAAa,SAAQ,iBAoBhC;CACD;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SAMxB;CAAG;;;;AAEL,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAGxF,qBAAa,WAAY,SAAQ,gBAAgE;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,KAAK,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE3F,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,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC,OAAO,WAAW,CAAC,EAAE,OAAO,gBAAgB,CAAC,CAAA;IACrF,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAClF,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAA;CAC3C,CAAA;;;;;;;;;;AAED,qBAAa,cAAe,SAAQ,mBA4BlC;CACD;;;;;;;;;;;AAGD,qBAAa,YAAa,SAAQ,iBA6BhC;CACD;;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SASxB;CAAG;;;;AAEL,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAGxF,qBAAa,WAAY,SAAQ,gBAAgE;CAAG"}
@@ -12,7 +12,7 @@ export class Some extends Context.TagMakeId("Some", Effect.succeed({ a: 1 }))()
12
12
  export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b: 2 }))() {
13
13
  }
14
14
  export class AllowAnonymous extends Middleware.Tag()("AllowAnonymous", {
15
- dynamic: contextMap()("allowAnonymous"),
15
+ dynamic: contextMap()("allowAnonymous", [UserProfile]),
16
16
  requires: SomeElse
17
17
  })({
18
18
  effect: Effect.gen(function* () {
@@ -26,36 +26,48 @@ export class AllowAnonymous extends Middleware.Tag()("AllowAnonymous", {
26
26
  }
27
27
  return Option.none();
28
28
  }
29
- return Option.some(Context.make(UserProfile, { id: "whatever", roles: ["user", "manager"] }));
29
+ return Option.some(Context.make(UserProfile, new UserProfile({
30
+ id: "whatever",
31
+ roles: ["user", ...headers["x-is-manager"] === "true" ? ["manager"] : []]
32
+ })));
30
33
  });
31
34
  })
32
35
  }) {
33
36
  }
34
37
  // @effect-diagnostics-next-line missingEffectServiceDependency:off
35
38
  export class RequireRoles extends Middleware.Tag()("RequireRoles", {
36
- dynamic: contextMap()("requireRoles"),
39
+ dynamic: contextMap()("requireRoles", null), // TODO
40
+ wrap: true,
41
+ // wrap: true,
37
42
  // had to move this in here, because once you put it manually as a readonly static property on the class,
38
43
  // there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
39
44
  dependsOn: [AllowAnonymous]
40
45
  })({
41
46
  effect: Effect.gen(function* () {
42
47
  yield* Some;
43
- return Effect.fnUntraced(function* ({ config }) {
48
+ return Effect.fnUntraced(function* ({ config, next }) {
44
49
  // we don't know if the service will be provided or not, so we use option..
45
50
  const userProfile = yield* Effect.serviceOption(UserProfile);
46
51
  const { requireRoles } = config;
52
+ console.dir({
53
+ userProfile,
54
+ requireRoles
55
+ }, { depth: 5 });
47
56
  if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
48
57
  return yield* new UnauthorizedError({ message: "don't have the right roles" });
49
58
  }
50
- return Option.none();
59
+ return yield* next;
51
60
  });
52
61
  })
53
62
  }) {
54
63
  }
55
- export class Test extends Middleware.Tag()("Test", { dynamic: contextMap()("test") })({
64
+ export class Test extends Middleware.Tag()("Test", {
65
+ wrap: true,
66
+ dynamic: contextMap()("test", null) // TODO
67
+ })({
56
68
  effect: Effect.gen(function* () {
57
- return Effect.fn(function* () {
58
- return Option.none();
69
+ return Effect.fn(function* ({ next }) {
70
+ return yield* next;
59
71
  });
60
72
  })
61
73
  }) {
@@ -67,4 +79,4 @@ export class CustomError2 extends TaggedError()("CustomError1", {}) {
67
79
  const MakeSomeService = Effect.succeed({ a: 1 });
68
80
  export class SomeService extends Context.TagMakeId("SomeService", MakeSomeService)() {
69
81
  }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQXNCLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0YsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFFOUQsTUFBTSxPQUFPLFdBQVksU0FBUSxPQUFPLENBQUMsU0FBUyxDQUEyQixhQUFhLENBQUMsQ0FDekYsQ0FBQyxDQUFDLEtBQUssQ0FBYyxhQUFhLENBQUMsQ0FBQztJQUNsQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0NBQ3pCLENBQUMsQ0FDSDtDQUNBO0FBRUQsTUFBTSxPQUFPLElBQUssU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBUTtDQUFHO0FBQ3hGLE1BQU0sT0FBTyxRQUFTLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQVk7Q0FBRztBQVFwRyxNQUFNLE9BQU8sY0FBZSxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQWtCLENBQUMsZ0JBQWdCLEVBQUU7SUFDckYsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxnQkFBZ0IsQ0FBQztJQUMxRCxRQUFR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
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQXNCLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0YsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFFOUQsTUFBTSxPQUFPLFdBQVksU0FBUSxPQUFPLENBQUMsU0FBUyxDQUEyQixhQUFhLENBQUMsQ0FDekYsQ0FBQyxDQUFDLEtBQUssQ0FBYyxhQUFhLENBQUMsQ0FBQztJQUNsQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0NBQ3pCLENBQUMsQ0FDSDtDQUNBO0FBRUQsTUFBTSxPQUFPLElBQUssU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBUTtDQUFHO0FBQ3hGLE1BQU0sT0FBTyxRQUFTLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQVk7Q0FBRztBQVFwRyxNQUFNLE9BQU8sY0FBZSxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQWtCLENBQUMsZ0JBQWdCLEVBQUU7SUFDckYsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3pFLFFBQVEsRUFBRSxRQUFRO0NBQ25CLENBQUMsQ0FBQztJQUNELE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQ3RCLFFBQVEsQ0FBQyxFQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUMzQixLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUE7WUFDZixLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFBLENBQUMsNkNBQTZDO1lBQ2hFLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDdEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO29CQUMzQixPQUFPLEtBQUssQ0FBQyxDQUFDLElBQUksZ0JBQWdCLENBQUMsRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQTtnQkFDbEUsQ0FBQztnQkFDRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtZQUN0QixDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUNoQixPQUFPLENBQUMsSUFBSSxDQUNWLFdBQVcsRUFDWCxJQUFJLFdBQVcsQ0FBQztnQkFDZCxFQUFFLEVBQUUsVUFBVTtnQkFDZCxLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDMUUsQ0FBQyxDQUNILENBQ0YsQ0FBQTtRQUNILENBQUMsQ0FDRixDQUFBO0lBQ0gsQ0FBQyxDQUFDO0NBQ0gsQ0FBQztDQUNEO0FBRUQsbUVBQW1FO0FBQ25FLE1BQU0sT0FBTyxZQUFhLFNBQVEsVUFBVSxDQUFDLEdBQUcsRUFBZ0IsQ0FBQyxjQUFjLEVBQUU7SUFDL0UsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxjQUFjLEVBQUUsSUFBYSxDQUFDLEVBQUUsT0FBTztJQUNoRixJQUFJLEVBQUUsSUFBSTtJQUNWLGNBQWM7SUFDZCx5R0FBeUc7SUFDekcsNkhBQTZIO0lBQzdILFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztDQUM1QixDQUFDLENBQUM7SUFDRCxNQUFNLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDMUIsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFBO1FBQ1gsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUN0QixRQUFRLENBQUMsRUFBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7WUFDeEIsMkVBQTJFO1lBQzNFLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDNUQsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sQ0FBQTtZQUMvQixPQUFPLENBQUMsR0FBRyxDQUNUO2dCQUNFLFdBQVc7Z0JBQ1gsWUFBWTthQUNiLEVBQ0QsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQ2IsQ0FBQTtZQUNELElBQUksWUFBWSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDM0YsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLGlCQUFpQixDQUFDLEVBQUUsT0FBTyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQTtZQUNoRixDQUFDO1lBQ0QsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDcEIsQ0FBQyxDQUNGLENBQUE7SUFDSCxDQUFDLENBQUM7Q0FDSCxDQUFDO0NBQ0Q7QUFFRCxNQUFNLE9BQU8sSUFBSyxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQVEsQ0FBQyxNQUFNLEVBQUU7SUFDdkQsSUFBSSxFQUFFLElBQUk7SUFDVixPQUFPLEVBQUUsVUFBVSxFQUFxQixDQUFDLE1BQU0sRUFBRSxJQUFhLENBQUMsQ0FBQyxPQUFPO0NBQ3hFLENBQUMsQ0FBQztJQUNELE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUMsRUFBRSxJQUFJLEVBQUU7WUFDakMsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDcEIsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDLENBQUM7Q0FDSCxDQUFDO0NBQUc7QUFFTCxNQUFNLE9BQU8sWUFBYSxTQUFRLFdBQVcsRUFBb0IsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDO0NBQUc7QUFDeEYsTUFBTSxPQUFPLFlBQWEsU0FBUSxXQUFXLEVBQW9CLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztDQUFHO0FBRXhGLE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUNoRCxNQUFNLE9BQU8sV0FBWSxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUFlO0NBQUcifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,EAAK,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAqB,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAwD,IAAI,EAAE,QAAQ,EAAQ,MAAM,eAAe,CAAA;;;;;;;AAE1G,qBAAa,cAAe,SAAQ,mBAYlC;CACD;;;;;;;AAED,qBAAa,kBAAmB,SAAQ,uBAYtC;CACD;;;;;;;AAED,qBAAa,sBAAuB,SAAQ,2BAa1C;CACD"}
1
+ {"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,EAAK,MAAM,YAAY,CAAA;AAErD,OAAO,EAAkB,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAwD,IAAI,EAAE,QAAQ,EAAQ,MAAM,eAAe,CAAA;;;;;;AAE1G,qBAAa,cAAe,SAAQ,mBAUlC;CACD;;;;;;;AAED,qBAAa,kBAAmB,SAAQ,uBAYtC;CACD;;;;;;;AAED,qBAAa,sBAAuB,SAAQ,2BAa1C;CACD"}
package/test/fixtures.ts CHANGED
@@ -15,13 +15,13 @@ export class Some extends Context.TagMakeId("Some", Effect.succeed({ a: 1 }))<So
15
15
  export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b: 2 }))<SomeElse>() {}
16
16
 
17
17
  export type RequestContextMap = {
18
- allowAnonymous: RPCContextMap.Inverted<UserProfile, typeof NotLoggedInError>
18
+ allowAnonymous: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>
19
19
  requireRoles: RPCContextMap.Custom<never, typeof UnauthorizedError, Array<string>>
20
20
  test: RPCContextMap<never, typeof S.Never>
21
21
  }
22
22
 
23
23
  export class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnonymous", {
24
- dynamic: contextMap<RequestContextMap>()("allowAnonymous"),
24
+ dynamic: contextMap<RequestContextMap>()("allowAnonymous", [UserProfile]),
25
25
  requires: SomeElse
26
26
  })({
27
27
  effect: Effect.gen(function*() {
@@ -36,10 +36,15 @@ export class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnony
36
36
  }
37
37
  return Option.none()
38
38
  }
39
- return Option.some(Context.make(
40
- UserProfile,
41
- { id: "whatever", roles: ["user", "manager"] }
42
- ))
39
+ return Option.some(
40
+ Context.make(
41
+ UserProfile,
42
+ new UserProfile({
43
+ id: "whatever",
44
+ roles: ["user", ...headers["x-is-manager"] === "true" ? ["manager"] : []]
45
+ })
46
+ )
47
+ )
43
48
  }
44
49
  )
45
50
  })
@@ -48,7 +53,9 @@ export class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnony
48
53
 
49
54
  // @effect-diagnostics-next-line missingEffectServiceDependency:off
50
55
  export class RequireRoles extends Middleware.Tag<RequireRoles>()("RequireRoles", {
51
- dynamic: contextMap<RequestContextMap>()("requireRoles"),
56
+ dynamic: contextMap<RequestContextMap>()("requireRoles", null as never), // TODO
57
+ wrap: true,
58
+ // wrap: true,
52
59
  // had to move this in here, because once you put it manually as a readonly static property on the class,
53
60
  // there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
54
61
  dependsOn: [AllowAnonymous]
@@ -56,24 +63,34 @@ export class RequireRoles extends Middleware.Tag<RequireRoles>()("RequireRoles",
56
63
  effect: Effect.gen(function*() {
57
64
  yield* Some
58
65
  return Effect.fnUntraced(
59
- function*({ config }) {
66
+ function*({ config, next }) {
60
67
  // we don't know if the service will be provided or not, so we use option..
61
68
  const userProfile = yield* Effect.serviceOption(UserProfile)
62
69
  const { requireRoles } = config
70
+ console.dir(
71
+ {
72
+ userProfile,
73
+ requireRoles
74
+ },
75
+ { depth: 5 }
76
+ )
63
77
  if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
64
78
  return yield* new UnauthorizedError({ message: "don't have the right roles" })
65
79
  }
66
- return Option.none<Context<never>>()
80
+ return yield* next
67
81
  }
68
82
  )
69
83
  })
70
84
  }) {
71
85
  }
72
86
 
73
- export class Test extends Middleware.Tag<Test>()("Test", { dynamic: contextMap<RequestContextMap>()("test") })({
87
+ export class Test extends Middleware.Tag<Test>()("Test", {
88
+ wrap: true,
89
+ dynamic: contextMap<RequestContextMap>()("test", null as never) // TODO
90
+ })({
74
91
  effect: Effect.gen(function*() {
75
- return Effect.fn(function*() {
76
- return Option.none<Context<never>>()
92
+ return Effect.fn(function*({ next }) {
93
+ return yield* next
77
94
  })
78
95
  })
79
96
  }) {}