@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.
- package/CHANGELOG.md +17 -0
- package/dist/api/layerUtils.d.ts +1 -5
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +3 -11
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +33 -0
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -0
- package/dist/api/routing/middleware/RouterMiddleware.js +5 -0
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +199 -0
- package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -0
- package/dist/api/routing/middleware/RpcMiddleware.js +14 -0
- package/dist/api/routing/middleware/dynamic-middleware.d.ts +2 -12
- package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/dynamic-middleware.js +2 -18
- package/dist/api/routing/middleware/generic-middleware.d.ts +4 -23
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +13 -9
- package/dist/api/routing/middleware/middleware-api.d.ts +27 -7
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +47 -22
- package/dist/api/routing/middleware/middleware.d.ts +3 -3
- package/dist/api/routing/middleware/middleware.js +2 -2
- package/dist/api/routing/middleware.d.ts +2 -1
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +3 -2
- package/dist/api/routing/tsort.d.ts +2 -2
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/tsort.js +1 -1
- package/package.json +9 -5
- package/src/api/layerUtils.ts +4 -18
- package/src/api/routing/middleware/RouterMiddleware.ts +149 -0
- package/src/api/routing/middleware/RpcMiddleware.ts +287 -0
- package/src/api/routing/middleware/dynamic-middleware.ts +5 -52
- package/src/api/routing/middleware/generic-middleware.ts +23 -34
- package/src/api/routing/middleware/middleware-api.ts +107 -45
- package/src/api/routing/middleware/middleware.ts +1 -1
- package/src/api/routing/middleware.ts +2 -1
- package/src/api/routing/tsort.ts +2 -2
- package/test/controller.test.ts +22 -58
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +4 -2
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +21 -9
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/fixtures.ts +29 -12
- package/test/requires.test.ts +98 -17
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts +0 -229
- package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/DynamicMiddleware.js +0 -168
- package/src/api/routing/middleware/DynamicMiddleware.ts +0 -715
package/src/api/routing/tsort.ts
CHANGED
|
@@ -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)))
|
package/test/controller.test.ts
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
76
|
-
MyContextProvider2
|
|
77
|
-
MyContextProvider
|
|
75
|
+
BogusMiddleware,
|
|
76
|
+
MyContextProvider2
|
|
78
77
|
] as const
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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 =
|
|
95
|
+
export const middleware3 = makeMiddleware<RequestContextMap>()
|
|
124
96
|
.middleware(...genericMiddlewares)
|
|
125
97
|
.middleware(AllowAnonymous, RequireRoles)
|
|
126
98
|
.middleware(Test)
|
|
127
|
-
|
|
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,
|
|
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"}
|
package/test/dist/fixtures.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/test/dist/fixtures.js
CHANGED
|
@@ -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, {
|
|
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
|
|
59
|
+
return yield* next;
|
|
51
60
|
});
|
|
52
61
|
})
|
|
53
62
|
}) {
|
|
54
63
|
}
|
|
55
|
-
export class Test extends Middleware.Tag()("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
|
|
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,
|
|
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,
|
|
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(
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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", {
|
|
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
|
|
92
|
+
return Effect.fn(function*({ next }) {
|
|
93
|
+
return yield* next
|
|
77
94
|
})
|
|
78
95
|
})
|
|
79
96
|
}) {}
|
package/test/requires.test.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { expectTypeOf, it } from "@effect/vitest"
|
|
2
|
-
import { Effect, Layer, S } from "effect-app"
|
|
3
|
-
import {
|
|
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 (
|
|
12
|
+
return () =>
|
|
13
13
|
Effect.gen(function*() {
|
|
14
|
-
|
|
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 =
|
|
52
|
+
const middleware3 = makeMiddleware<RequestContextMap>()
|
|
54
53
|
.middleware(RequiresSomeMiddleware)
|
|
55
54
|
.middleware(SomeMiddleware)
|
|
56
|
-
.middleware(
|
|
55
|
+
.middleware(RequireRoles)
|
|
56
|
+
.middleware(AllowAnonymous, Test)
|
|
57
57
|
.middleware(SomeElseMiddleware)
|
|
58
|
-
.middleware(Test)
|
|
59
58
|
|
|
60
|
-
|
|
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(
|
|
67
|
-
|
|
68
|
-
|
|
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(
|
|
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
|
})
|