@effect-app/infra 2.86.0 → 2.87.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 (49) hide show
  1. package/CHANGELOG.md +17 -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 +27 -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 +107 -45
  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
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQXNCLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0YsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFFOUQsTUFBTSxPQUFPLFdBQVksU0FBUSxPQUFPLENBQUMsU0FBUyxDQUEyQixhQUFhLENBQUMsQ0FDekYsQ0FBQyxDQUFDLEtBQUssQ0FBYyxhQUFhLENBQUMsQ0FBQztJQUNsQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0NBQ3pCLENBQUMsQ0FDSDtDQUNBO0FBRUQsTUFBTSxPQUFPLElBQUssU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBUTtDQUFHO0FBQ3hGLE1BQU0sT0FBTyxRQUFTLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQVk7Q0FBRztBQVFwRyxNQUFNLE9BQU8sY0FBZSxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQWtCLENBQUMsZ0JBQWdCLEVBQUU7SUFDckYsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFdBQVcs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
@@ -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
  }) {}
@@ -1,18 +1,17 @@
1
- import { expectTypeOf, it } from "@effect/vitest"
2
- import { Effect, Layer, S } from "effect-app"
3
- import { makeNewMiddleware, Middleware } from "../src/api/routing.js"
1
+ import { expect, expectTypeOf, it } from "@effect/vitest"
2
+ import { Effect, Either, Layer, S } from "effect-app"
3
+ import { NotLoggedInError, UnauthorizedError } from "effect-app/client"
4
+ import { makeMiddleware, Middleware } from "../src/api/routing.js"
4
5
  import { AllowAnonymous, type RequestContextMap, RequireRoles, Some, SomeElse, Test } from "./fixtures.js"
5
6
 
6
7
  export class SomeMiddleware extends Middleware.Tag<SomeMiddleware>()("SomeMiddleware", {
7
- provides: Some,
8
- wrap: true
8
+ provides: Some
9
9
  })({
10
10
  effect: Effect.gen(function*() {
11
11
  // yield* Effect.context<"test-dep">()
12
- return ({ next }) =>
12
+ return () =>
13
13
  Effect.gen(function*() {
14
- // yield* Effect.context<"test-dep2">()
15
- return yield* next.pipe(Effect.provideService(Some, new Some({ a: 1 })))
14
+ return new Some({ a: 1 })
16
15
  })
17
16
  })
18
17
  }) {
@@ -34,7 +33,7 @@ export class SomeElseMiddleware extends Middleware.Tag<SomeElseMiddleware>()("So
34
33
  }
35
34
 
36
35
  export class RequiresSomeMiddleware extends Middleware.Tag<RequiresSomeMiddleware>()("RequiresSomeMiddleware", {
37
- requires: Some,
36
+ requires: [Some],
38
37
  wrap: true
39
38
  })({
40
39
  effect: Effect.gen(function*() {
@@ -50,26 +49,108 @@ export class RequiresSomeMiddleware extends Middleware.Tag<RequiresSomeMiddlewar
50
49
  }
51
50
 
52
51
  it("requires gets enforced", async () => {
53
- const middleware3 = makeNewMiddleware<RequestContextMap>()
52
+ const middleware3 = makeMiddleware<RequestContextMap>()
54
53
  .middleware(RequiresSomeMiddleware)
55
54
  .middleware(SomeMiddleware)
56
- .middleware(AllowAnonymous, RequireRoles)
55
+ .middleware(RequireRoles)
56
+ .middleware(AllowAnonymous, Test)
57
57
  .middleware(SomeElseMiddleware)
58
- .middleware(Test)
59
58
 
60
- type LayerContext = Layer.Layer.Context<typeof middleware3["Default"]>
59
+ const layer = middleware3.Default.pipe(Layer.provide(Layer.succeed(Some, new Some({ a: 1 }))))
60
+
61
+ type Default = typeof middleware3["Default"]
62
+ type LayerContext = Layer.Layer.Context<Default>
61
63
  expectTypeOf({} as LayerContext).toEqualTypeOf<Some>()
62
64
 
63
65
  await Effect
64
66
  .gen(function*() {
65
67
  const mw = yield* middleware3
66
- const mwM = mw.effect(Object.assign({}, S.Any, { config: {} }), (_req) => Effect.void, "some-module")
67
- yield* mwM({}, { "x-user": "test-user" })
68
- // console.log({ v })
68
+ const mwM = mw.effect(
69
+ Object.assign({}, S.Any, { config: { requireRoles: ["manager"] } }),
70
+ (_req) => Effect.void,
71
+ "some-module"
72
+ )
73
+ yield* mwM({}, { "x-user": "test-user", "x-is-manager": "true" })
69
74
  })
70
75
  .pipe(
71
76
  Effect.scoped,
72
- Effect.provide(middleware3.Default.pipe(Layer.provide(Layer.succeed(Some, new Some({ a: 1 }))))),
77
+ Effect.provide(layer),
73
78
  Effect.runPromise
74
79
  )
80
+
81
+ await Effect
82
+ .gen(function*() {
83
+ const mw = yield* middleware3
84
+ const mwM = mw.effect(
85
+ Object.assign({}, S.Any, { config: { allowAnonymous: true } }),
86
+ (_req) => Effect.void,
87
+ "some-module"
88
+ )
89
+ yield* mwM({}, {})
90
+ })
91
+ .pipe(
92
+ Effect.scoped,
93
+ Effect.provide(layer),
94
+ Effect.runPromise
95
+ )
96
+
97
+ expect(
98
+ await Effect
99
+ .gen(function*() {
100
+ const mw = yield* middleware3
101
+ const mwM = mw.effect(
102
+ Object.assign({}, S.Any, { config: {} }),
103
+ (_req) => Effect.void,
104
+ "some-module"
105
+ )
106
+ yield* mwM({}, {})
107
+ })
108
+ .pipe(
109
+ Effect.scoped,
110
+ Effect.provide(layer),
111
+ Effect.either,
112
+ Effect.runPromise
113
+ )
114
+ )
115
+ .toEqual(Either.left(new NotLoggedInError()))
116
+
117
+ expect(
118
+ await Effect
119
+ .gen(function*() {
120
+ const mw = yield* middleware3
121
+ const mwM = mw.effect(
122
+ Object.assign({}, S.Any, { config: { requireRoles: ["manager"] } }),
123
+ (_req) => Effect.void,
124
+ "some-module"
125
+ )
126
+ yield* mwM({}, {})
127
+ })
128
+ .pipe(
129
+ Effect.scoped,
130
+ Effect.provide(layer),
131
+ Effect.either,
132
+ Effect.runPromise
133
+ )
134
+ )
135
+ .toEqual(Either.left(new NotLoggedInError()))
136
+
137
+ expect(
138
+ await Effect
139
+ .gen(function*() {
140
+ const mw = yield* middleware3
141
+ const mwM = mw.effect(
142
+ Object.assign({}, S.Any, { config: { requireRoles: ["manager"] } }),
143
+ (_req) => Effect.void,
144
+ "some-module"
145
+ )
146
+ yield* mwM({}, { "x-user": "test-user" })
147
+ })
148
+ .pipe(
149
+ Effect.scoped,
150
+ Effect.provide(layer),
151
+ Effect.either,
152
+ Effect.runPromise
153
+ )
154
+ )
155
+ .toEqual(Either.left(new UnauthorizedError({ message: "don't have the right roles" })))
75
156
  })