@effect-app/infra 2.93.0 → 3.0.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.
- package/CHANGELOG.md +22 -0
- package/dist/Emailer/service.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +1 -1
- package/dist/Operations.d.ts +1 -1
- package/dist/RequestFiberSet.d.ts +1 -1
- package/dist/Store/service.d.ts +2 -2
- package/dist/adapters/SQL/Model.d.ts +6 -6
- package/dist/adapters/ServiceBus.d.ts +2 -2
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +13 -10
- package/dist/adapters/memQueue.d.ts +1 -1
- package/dist/api/ContextProvider.d.ts +3 -3
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +6 -6
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +4 -15
- package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RpcMiddleware.js +3 -4
- package/dist/api/routing/middleware/RpcMiddlewareX.d.ts +18 -0
- package/dist/api/routing/middleware/RpcMiddlewareX.d.ts.map +1 -0
- package/dist/api/routing/middleware/RpcMiddlewareX.js +16 -0
- package/dist/api/routing/middleware/generic-middleware.d.ts +22 -8
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +59 -62
- package/dist/api/routing/middleware/middleware-api.d.ts +51 -32
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +54 -24
- package/dist/api/routing/middleware/middleware-native.d.ts +23 -0
- package/dist/api/routing/middleware/middleware-native.d.ts.map +1 -0
- package/dist/api/routing/middleware/middleware-native.js +19 -0
- package/dist/api/routing/middleware/middleware.d.ts +7 -27
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +73 -88
- package/dist/api/routing/middleware.d.ts +1 -0
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +2 -1
- package/dist/api/routing.d.ts +1 -4
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +8 -8
- package/package.json +11 -3
- package/src/adapters/ServiceBus.ts +7 -5
- package/src/api/ContextProvider.ts +9 -7
- package/src/api/routing/middleware/RouterMiddleware.ts +9 -8
- package/src/api/routing/middleware/RpcMiddleware.ts +4 -51
- package/src/api/routing/middleware/RpcMiddlewareX.ts +70 -0
- package/src/api/routing/middleware/generic-middleware.ts +142 -107
- package/src/api/routing/middleware/middleware-api.ts +239 -61
- package/src/api/routing/middleware/middleware-native.ts +23 -0
- package/src/api/routing/middleware/middleware.ts +37 -40
- package/src/api/routing/middleware.ts +1 -0
- package/src/api/routing.ts +7 -13
- package/test/contextProvider.test.ts +4 -4
- package/test/controller.test.ts +41 -16
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +48 -32
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +76 -47
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -0
- package/test/fixtures.ts +71 -17
- package/test/requires.test.ts +15 -50
- package/test/rpc-multi-middleware.test.ts +134 -0
package/test/controller.test.ts
CHANGED
|
@@ -5,12 +5,13 @@ import { type RpcSerialization } from "@effect/rpc"
|
|
|
5
5
|
import { expect, expectTypeOf, it } from "@effect/vitest"
|
|
6
6
|
import { Context, Effect, Layer, S, Scope } from "effect-app"
|
|
7
7
|
import { InvalidStateError, makeRpcClient, NotLoggedInError, UnauthorizedError } from "effect-app/client"
|
|
8
|
-
import {
|
|
8
|
+
import { DefaultGenericMiddlewaresLive, makeMiddleware, Middleware, TagService } from "../src/api/routing/middleware.js"
|
|
9
|
+
import { DefaultGenericMiddlewares } from "../src/api/routing/middleware/middleware-native.js"
|
|
9
10
|
import { sort } from "../src/api/routing/tsort.js"
|
|
10
|
-
import { AllowAnonymous, CustomError1, RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
|
|
11
|
+
import { AllowAnonymous, AllowAnonymousLive, CustomError1, RequestContextMap, RequireRoles, RequireRolesLive, Some, SomeElse, SomeService, Test, TestLive } from "./fixtures.js"
|
|
11
12
|
|
|
12
13
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
13
|
-
class MyContextProvider extends Middleware.
|
|
14
|
+
class MyContextProvider extends Middleware.TagService<MyContextProvider>()("MyContextProvider", {
|
|
14
15
|
provides: [Some],
|
|
15
16
|
requires: [SomeElse]
|
|
16
17
|
})({
|
|
@@ -20,7 +21,7 @@ class MyContextProvider extends Middleware.Tag<MyContextProvider>()("MyContextPr
|
|
|
20
21
|
|
|
21
22
|
return Effect.fnUntraced(function*() {
|
|
22
23
|
yield* SomeElse
|
|
23
|
-
// the only requirements you can have are the one provided by
|
|
24
|
+
// the only requirements you can have are the one provided by HttpLayerRouter.Provided
|
|
24
25
|
yield* Scope.Scope
|
|
25
26
|
|
|
26
27
|
yield* Effect.logInfo("MyContextProviderGen", "this is a generator")
|
|
@@ -39,7 +40,7 @@ class MyContextProvider extends Middleware.Tag<MyContextProvider>()("MyContextPr
|
|
|
39
40
|
}) {}
|
|
40
41
|
|
|
41
42
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
42
|
-
class MyContextProvider3 extends Middleware.
|
|
43
|
+
class MyContextProvider3 extends Middleware.TagService<MyContextProvider3>()("MyContextProvider3", {
|
|
43
44
|
provides: [Some],
|
|
44
45
|
requires: [SomeElse]
|
|
45
46
|
})({
|
|
@@ -50,7 +51,7 @@ class MyContextProvider3 extends Middleware.Tag<MyContextProvider3>()("MyContext
|
|
|
50
51
|
|
|
51
52
|
return Effect.fnUntraced(function*() {
|
|
52
53
|
yield* SomeElse
|
|
53
|
-
// the only requirements you can have are the one provided by
|
|
54
|
+
// the only requirements you can have are the one provided by HttpLayerRouter.Provided
|
|
54
55
|
yield* Scope.Scope
|
|
55
56
|
|
|
56
57
|
yield* Effect.logInfo("MyContextProviderGen", "this is a generator")
|
|
@@ -71,23 +72,25 @@ class MyContextProvider3 extends Middleware.Tag<MyContextProvider3>()("MyContext
|
|
|
71
72
|
expectTypeOf(MyContextProvider3.Default).toEqualTypeOf<Layer.Layer<MyContextProvider3, CustomError1, never>>()
|
|
72
73
|
|
|
73
74
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
74
|
-
class MyContextProvider2
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
class MyContextProvider2
|
|
76
|
+
extends Middleware.TagService<MyContextProvider2>()("MyContextProvider2", { provides: SomeElse })({
|
|
77
|
+
effect: Effect.gen(function*() {
|
|
78
|
+
if (Math.random() > 0.5) return yield* new CustomError1()
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
return Effect.fnUntraced(function*() {
|
|
81
|
+
// we test without dependencies, so that we end up with an R of never.
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
return new SomeElse({ b: 2 })
|
|
84
|
+
})
|
|
82
85
|
})
|
|
83
86
|
})
|
|
84
|
-
|
|
87
|
+
{}
|
|
85
88
|
|
|
86
89
|
//
|
|
87
90
|
|
|
88
91
|
const Str = Context.GenericTag<"str", "str">("str")
|
|
89
92
|
|
|
90
|
-
export class BogusMiddleware extends
|
|
93
|
+
export class BogusMiddleware extends TagService<BogusMiddleware>()("BogusMiddleware", {
|
|
91
94
|
wrap: true
|
|
92
95
|
})({
|
|
93
96
|
effect: Effect.gen(function*() {
|
|
@@ -108,6 +111,12 @@ const genericMiddlewares = [
|
|
|
108
111
|
MyContextProvider2
|
|
109
112
|
] as const
|
|
110
113
|
|
|
114
|
+
const genericMiddlewaresLive = [
|
|
115
|
+
DefaultGenericMiddlewaresLive,
|
|
116
|
+
BogusMiddleware.Default,
|
|
117
|
+
MyContextProvider2.Default
|
|
118
|
+
] as const
|
|
119
|
+
|
|
111
120
|
const middleware = makeMiddleware<RequestContextMap>(RequestContextMap)
|
|
112
121
|
.middleware(
|
|
113
122
|
RequireRoles,
|
|
@@ -237,9 +246,25 @@ export class SomethingService2 extends Effect.Service<SomethingService2>()("Some
|
|
|
237
246
|
})
|
|
238
247
|
}) {}
|
|
239
248
|
|
|
240
|
-
|
|
249
|
+
const MiddlewaresLive = [
|
|
250
|
+
RequireRolesLive,
|
|
251
|
+
TestLive,
|
|
252
|
+
AllowAnonymousLive,
|
|
253
|
+
MyContextProvider.Default,
|
|
254
|
+
...genericMiddlewaresLive
|
|
255
|
+
] as const
|
|
241
256
|
|
|
242
|
-
export const
|
|
257
|
+
export const { Router, matchAll } = makeRouter(
|
|
258
|
+
Object.assign(middleware, {
|
|
259
|
+
Default: middleware.layer.pipe(Layer.provide(MiddlewaresLive))
|
|
260
|
+
}),
|
|
261
|
+
true
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
export const r2 = makeRouter(
|
|
265
|
+
Object.assign(middleware, { Default: middleware2.layer.pipe(Layer.provide(MiddlewaresLive)) }),
|
|
266
|
+
true
|
|
267
|
+
)
|
|
243
268
|
|
|
244
269
|
const router = Router(Something)({
|
|
245
270
|
dependencies: [
|
|
@@ -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,EAA0B,MAAM,+BAA+B,CAAA;AACzG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAE7D,OAAO,
|
|
1
|
+
{"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAA0B,MAAM,+BAA+B,CAAA;AACzG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAE7D,OAAO,EAAiD,UAAU,EAAc,MAAM,kCAAkC,CAAA;AAGxH,OAAO,EAAE,cAAc,EAAsB,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAoB,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAY,MAAM,eAAe,CAAA;;;;;;AAgEhL,cAAM,kBACJ,SAAQ,uBAUN;CACF;;;;;;AAMF,qBAAa,eAAgB,SAAQ,oBAYnC;CACD;AAgED,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;AAUL,eAAO,MAAQ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAE,QAAQ;;;;;yHAK9B,CAAA;AAED,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGd,CAAA"}
|
package/test/dist/fixtures.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Context, Effect, S, Scope } from "effect-app";
|
|
1
|
+
import { Context, Effect, Layer, S, Scope } from "effect-app";
|
|
2
2
|
import { NotLoggedInError, RPCContextMap, UnauthorizedError } from "effect-app/client";
|
|
3
|
-
import { Middleware } from "../src/api/routing.js";
|
|
4
3
|
declare const UserProfile_base: S.EnhancedClass<UserProfile, {
|
|
5
4
|
id: typeof S.String;
|
|
6
5
|
roles: S.Array$<typeof S.String> & {
|
|
@@ -23,12 +22,12 @@ declare const Some_base: (abstract new (service: {
|
|
|
23
22
|
a: number;
|
|
24
23
|
}>) & {
|
|
25
24
|
toLayer: {
|
|
26
|
-
():
|
|
27
|
-
<E_1, R_1>(eff: Effect.Effect<Omit<Some, keyof Context.TagClassShape<any, any>>, E_1, R_1>):
|
|
25
|
+
(): Layer.Layer<Some, never, never>;
|
|
26
|
+
<E_1, R_1>(eff: Effect.Effect<Omit<Some, keyof Context.TagClassShape<any, any>>, E_1, R_1>): Layer.Layer<Some, E_1, R_1>;
|
|
28
27
|
};
|
|
29
28
|
toLayerScoped: {
|
|
30
|
-
():
|
|
31
|
-
<E_1, R_2>(eff: Effect.Effect<Omit<Some, keyof Context.TagClassShape<any, any>>, E_1, R_2>):
|
|
29
|
+
(): Layer.Layer<Some, never, never>;
|
|
30
|
+
<E_1, R_2>(eff: Effect.Effect<Omit<Some, keyof Context.TagClassShape<any, any>>, E_1, R_2>): Layer.Layer<Some, E_1, Exclude<R_2, Scope.Scope>>;
|
|
32
31
|
};
|
|
33
32
|
of: (service: Context.TagClassShape<any, any>) => Some;
|
|
34
33
|
make: Effect.Effect<Some, never, never>;
|
|
@@ -37,7 +36,7 @@ declare const Some_base: (abstract new (service: {
|
|
|
37
36
|
} & {
|
|
38
37
|
use: <X>(body: (_: {
|
|
39
38
|
a: number;
|
|
40
|
-
}) => X) => X extends Effect.Effect<infer
|
|
39
|
+
}) => X) => X extends Effect.Effect<infer A_1, infer E_2, infer R_4> ? Effect.Effect<A_1, E_2, Some | R_4> : Effect.Effect<X, never, Some>;
|
|
41
40
|
};
|
|
42
41
|
export declare class Some extends Some_base {
|
|
43
42
|
}
|
|
@@ -49,12 +48,12 @@ declare const SomeElse_base: (abstract new (service: {
|
|
|
49
48
|
b: number;
|
|
50
49
|
}>) & {
|
|
51
50
|
toLayer: {
|
|
52
|
-
():
|
|
53
|
-
<E_1, R_1>(eff: Effect.Effect<Omit<SomeElse, keyof Context.TagClassShape<any, any>>, E_1, R_1>):
|
|
51
|
+
(): Layer.Layer<SomeElse, never, never>;
|
|
52
|
+
<E_1, R_1>(eff: Effect.Effect<Omit<SomeElse, keyof Context.TagClassShape<any, any>>, E_1, R_1>): Layer.Layer<SomeElse, E_1, R_1>;
|
|
54
53
|
};
|
|
55
54
|
toLayerScoped: {
|
|
56
|
-
():
|
|
57
|
-
<E_1, R_2>(eff: Effect.Effect<Omit<SomeElse, keyof Context.TagClassShape<any, any>>, E_1, R_2>):
|
|
55
|
+
(): Layer.Layer<SomeElse, never, never>;
|
|
56
|
+
<E_1, R_2>(eff: Effect.Effect<Omit<SomeElse, keyof Context.TagClassShape<any, any>>, E_1, R_2>): Layer.Layer<SomeElse, E_1, Exclude<R_2, Scope.Scope>>;
|
|
58
57
|
};
|
|
59
58
|
of: (service: Context.TagClassShape<any, any>) => SomeElse;
|
|
60
59
|
make: Effect.Effect<SomeElse, never, never>;
|
|
@@ -63,7 +62,7 @@ declare const SomeElse_base: (abstract new (service: {
|
|
|
63
62
|
} & {
|
|
64
63
|
use: <X>(body: (_: {
|
|
65
64
|
b: number;
|
|
66
|
-
}) => X) => X extends Effect.Effect<infer
|
|
65
|
+
}) => X) => X extends Effect.Effect<infer A_1, infer E_2, infer R_4> ? Effect.Effect<A_1, E_2, R_4 | SomeElse> : Effect.Effect<X, never, SomeElse>;
|
|
67
66
|
};
|
|
68
67
|
export declare class SomeElse extends SomeElse_base {
|
|
69
68
|
}
|
|
@@ -75,12 +74,12 @@ declare const SomeService_base: (abstract new (service: {
|
|
|
75
74
|
a: number;
|
|
76
75
|
}>) & {
|
|
77
76
|
toLayer: {
|
|
78
|
-
():
|
|
79
|
-
<E_1, R_1>(eff: Effect.Effect<Omit<SomeService, keyof Context.TagClassShape<any, any>>, E_1, R_1>):
|
|
77
|
+
(): Layer.Layer<SomeService, never, never>;
|
|
78
|
+
<E_1, R_1>(eff: Effect.Effect<Omit<SomeService, keyof Context.TagClassShape<any, any>>, E_1, R_1>): Layer.Layer<SomeService, E_1, R_1>;
|
|
80
79
|
};
|
|
81
80
|
toLayerScoped: {
|
|
82
|
-
():
|
|
83
|
-
<E_1, R_2>(eff: Effect.Effect<Omit<SomeService, keyof Context.TagClassShape<any, any>>, E_1, R_2>):
|
|
81
|
+
(): Layer.Layer<SomeService, never, never>;
|
|
82
|
+
<E_1, R_2>(eff: Effect.Effect<Omit<SomeService, keyof Context.TagClassShape<any, any>>, E_1, R_2>): Layer.Layer<SomeService, E_1, Exclude<R_2, Scope.Scope>>;
|
|
84
83
|
};
|
|
85
84
|
of: (service: Context.TagClassShape<any, any>) => SomeService;
|
|
86
85
|
make: Effect.Effect<SomeService, never, never>;
|
|
@@ -89,10 +88,30 @@ declare const SomeService_base: (abstract new (service: {
|
|
|
89
88
|
} & {
|
|
90
89
|
use: <X>(body: (_: {
|
|
91
90
|
a: number;
|
|
92
|
-
}) => X) => X extends Effect.Effect<infer
|
|
91
|
+
}) => X) => X extends Effect.Effect<infer A_1, infer E_2, infer R_4> ? Effect.Effect<A_1, E_2, R_4 | SomeService> : Effect.Effect<X, never, SomeService>;
|
|
93
92
|
};
|
|
94
93
|
export declare class SomeService extends SomeService_base {
|
|
95
94
|
}
|
|
95
|
+
declare const SomeMiddleware_base: import("../src/api/routing.js").TagClass<SomeMiddleware, "SomeMiddleware", {
|
|
96
|
+
readonly provides: typeof Some;
|
|
97
|
+
}>;
|
|
98
|
+
export declare class SomeMiddleware extends SomeMiddleware_base {
|
|
99
|
+
}
|
|
100
|
+
export declare const SomeMiddlewareLive: Layer.Layer<SomeMiddleware, never, never>;
|
|
101
|
+
declare const SomeMiddlewareWrap_base: import("../src/api/routing.js").TagClass<SomeMiddlewareWrap, "SomeMiddlewareWrap", {
|
|
102
|
+
readonly provides: typeof Some;
|
|
103
|
+
readonly wrap: true;
|
|
104
|
+
}>;
|
|
105
|
+
export declare class SomeMiddlewareWrap extends SomeMiddlewareWrap_base {
|
|
106
|
+
}
|
|
107
|
+
export declare const SomeMiddlewareWrapLive: Layer.Layer<SomeMiddlewareWrap, never, never>;
|
|
108
|
+
declare const SomeElseMiddleware_base: import("../src/api/routing.js").TagClass<SomeElseMiddleware, "SomeElseMiddleware", {
|
|
109
|
+
readonly provides: typeof SomeElse;
|
|
110
|
+
readonly wrap: true;
|
|
111
|
+
}>;
|
|
112
|
+
export declare class SomeElseMiddleware extends SomeElseMiddleware_base {
|
|
113
|
+
}
|
|
114
|
+
export declare const SomeElseMiddlewareLive: Layer.Layer<SomeElseMiddleware, never, never>;
|
|
96
115
|
export declare const RequestContextMap: {
|
|
97
116
|
readonly allowAnonymous: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>;
|
|
98
117
|
readonly requireRoles: RPCContextMap.Custom<never, typeof UnauthorizedError, string[]>;
|
|
@@ -101,31 +120,28 @@ export declare const RequestContextMap: {
|
|
|
101
120
|
type _RequestContextMap = typeof RequestContextMap;
|
|
102
121
|
export interface RequestContextMap extends _RequestContextMap {
|
|
103
122
|
}
|
|
104
|
-
declare const AllowAnonymous_base:
|
|
105
|
-
readonly dynamic:
|
|
123
|
+
declare const AllowAnonymous_base: import("../src/api/routing.js").TagClass<AllowAnonymous, "AllowAnonymous", {
|
|
124
|
+
readonly dynamic: import("../src/api/routing.js").RpcDynamic<"allowAnonymous", RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>>;
|
|
106
125
|
readonly requires: typeof SomeElse;
|
|
107
|
-
}
|
|
108
|
-
Default: import("effect/Layer").Layer<AllowAnonymous, never, never>;
|
|
109
|
-
};
|
|
126
|
+
}>;
|
|
110
127
|
export declare class AllowAnonymous extends AllowAnonymous_base {
|
|
111
128
|
}
|
|
112
|
-
declare const
|
|
113
|
-
|
|
129
|
+
export declare const AllowAnonymousLive: Layer.Layer<AllowAnonymous, never, never>;
|
|
130
|
+
declare const RequireRoles_base: import("../src/api/routing.js").TagClass<RequireRoles, "RequireRoles", {
|
|
131
|
+
readonly dynamic: import("../src/api/routing.js").RpcDynamic<"requireRoles", RPCContextMap.Custom<never, typeof UnauthorizedError, string[]>>;
|
|
114
132
|
readonly wrap: true;
|
|
115
133
|
readonly dependsOn: readonly [typeof AllowAnonymous];
|
|
116
|
-
}
|
|
117
|
-
Default: import("effect/Layer").Layer<RequireRoles, never, SomeService>;
|
|
118
|
-
};
|
|
134
|
+
}>;
|
|
119
135
|
export declare class RequireRoles extends RequireRoles_base {
|
|
120
136
|
}
|
|
121
|
-
declare const
|
|
137
|
+
export declare const RequireRolesLive: Layer.Layer<RequireRoles, never, SomeService>;
|
|
138
|
+
declare const Test_base: import("../src/api/routing.js").TagClass<Test, "Test", {
|
|
122
139
|
readonly wrap: true;
|
|
123
|
-
readonly dynamic:
|
|
124
|
-
}
|
|
125
|
-
Default: import("effect/Layer").Layer<Test, never, never>;
|
|
126
|
-
};
|
|
140
|
+
readonly dynamic: import("../src/api/routing.js").RpcDynamic<"test", RPCContextMap.RPCContextMap<never, typeof S.Never>>;
|
|
141
|
+
}>;
|
|
127
142
|
export declare class Test extends Test_base {
|
|
128
143
|
}
|
|
144
|
+
export declare const TestLive: Layer.Layer<Test, never, never>;
|
|
129
145
|
declare const CustomError1_base: S.TaggedErrorClass<NotLoggedInError, "CustomError1", {
|
|
130
146
|
readonly _tag: S.tag<"CustomError1">;
|
|
131
147
|
}>;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,CAAC,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;;;;;;;;;;;;;AAItF,qBAAa,WAAY,SAAQ,gBAKhC;CACA;;;;;;;;;;;;;;;;;;;;;;;;;AAED,qBAAa,IAAK,SAAQ,SAA2D;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AACxF,qBAAa,QAAS,SAAQ,aAAmE;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;AAEpG,qBAAa,WAAY,SAAQ,gBAAgE;CAAG;;;;AAEpG,qBAAa,cAAe,SAAQ,mBAElC;CAAG;AAEL,eAAO,MAAM,kBAAkB,2CAS9B,CAAA;;;;;AAGD,qBAAa,kBAAmB,SAAQ,uBAGtC;CACD;AAED,eAAO,MAAM,sBAAsB,+CAMlC,CAAA;;;;;AAED,qBAAa,kBAAmB,SAAQ,uBAGtC;CAAG;AAEL,eAAO,MAAM,sBAAsB,+CAUlC,CAAA;AASD,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAA;AAEV,KAAK,kBAAkB,GAAG,OAAO,iBAAiB,CAAA;AAClD,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;CAAG;;;;;AAEhE,qBAAa,cAAe,SAAQ,mBAGlC;CAAG;AAEL,eAAO,MAAM,kBAAkB,2CA0B9B,CAAA;;;;;;AAID,qBAAa,YAAa,SAAQ,iBAOhC;CAAG;AAEL,eAAO,MAAM,gBAAgB,+CAuB5B,CAAA;;;;;AAGD,qBAAa,IAAK,SAAQ,SAGxB;CAAG;AAEL,eAAO,MAAM,QAAQ,iCAOpB,CAAA;;;;AAED,qBAAa,YAAa,SAAQ,iBAAmD;CAAG;;;;AACxF,qBAAa,YAAa,SAAQ,iBAAmD;CAAG"}
|
package/test/dist/fixtures.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Context, Effect, Option, S, Scope } from "effect-app";
|
|
1
|
+
import { Context, Effect, Layer, Option, S, Scope } from "effect-app";
|
|
2
2
|
import { NotLoggedInError, RPCContextMap, UnauthorizedError } from "effect-app/client";
|
|
3
3
|
import { TaggedError } from "effect-app/Schema";
|
|
4
|
-
import { contextMap, getConfig,
|
|
4
|
+
import { contextMap, getConfig, Tag } from "../src/api/routing.js";
|
|
5
5
|
export class UserProfile extends Context.assignTag("UserProfile")(S.Class("UserProfile")({
|
|
6
6
|
id: S.String,
|
|
7
7
|
roles: S.Array(S.String)
|
|
@@ -14,6 +14,38 @@ export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b:
|
|
|
14
14
|
const MakeSomeService = Effect.succeed({ a: 1 });
|
|
15
15
|
export class SomeService extends Context.TagMakeId("SomeService", MakeSomeService)() {
|
|
16
16
|
}
|
|
17
|
+
export class SomeMiddleware extends Tag()("SomeMiddleware", {
|
|
18
|
+
provides: Some
|
|
19
|
+
}) {
|
|
20
|
+
}
|
|
21
|
+
export const SomeMiddlewareLive = Layer.effect(SomeMiddleware, Effect.gen(function* () {
|
|
22
|
+
// yield* Effect.context<"test-dep">()
|
|
23
|
+
return () => Effect.gen(function* () {
|
|
24
|
+
return new Some({ a: 1 });
|
|
25
|
+
});
|
|
26
|
+
}));
|
|
27
|
+
// functionally equivalent to the one above
|
|
28
|
+
export class SomeMiddlewareWrap extends Tag()("SomeMiddlewareWrap", {
|
|
29
|
+
provides: Some,
|
|
30
|
+
wrap: true
|
|
31
|
+
}) {
|
|
32
|
+
}
|
|
33
|
+
export const SomeMiddlewareWrapLive = Layer.effect(SomeMiddlewareWrap, Effect.gen(function* () {
|
|
34
|
+
// yield* Effect.context<"test-dep">()
|
|
35
|
+
return ({ next }) => next.pipe(Effect.provideService(Some, new Some({ a: 1 })));
|
|
36
|
+
}));
|
|
37
|
+
export class SomeElseMiddleware extends Tag()("SomeElseMiddleware", {
|
|
38
|
+
provides: SomeElse,
|
|
39
|
+
wrap: true
|
|
40
|
+
}) {
|
|
41
|
+
}
|
|
42
|
+
export const SomeElseMiddlewareLive = Layer.effect(SomeElseMiddleware, Effect.gen(function* () {
|
|
43
|
+
// yield* Effect.context<"test-dep">()
|
|
44
|
+
return ({ next }) => Effect.gen(function* () {
|
|
45
|
+
// yield* Effect.context<"test-dep2">()
|
|
46
|
+
return yield* next.pipe(Effect.provideService(SomeElse, new SomeElse({ b: 2 })));
|
|
47
|
+
});
|
|
48
|
+
}));
|
|
17
49
|
const requestConfig = getConfig();
|
|
18
50
|
// TODO: null as never sucks
|
|
19
51
|
// why [UserProfile] is needed? AllowAnonymous triggers an error if just UserProfile without []
|
|
@@ -25,71 +57,68 @@ export const RequestContextMap = {
|
|
|
25
57
|
requireRoles: RPCContextMap.makeCustom(null, UnauthorizedError, Array()),
|
|
26
58
|
test: RPCContextMap.make(null, S.Never)
|
|
27
59
|
};
|
|
28
|
-
export class AllowAnonymous extends
|
|
60
|
+
export class AllowAnonymous extends Tag()("AllowAnonymous", {
|
|
29
61
|
dynamic: contextMap(RequestContextMap, "allowAnonymous"),
|
|
30
62
|
requires: SomeElse
|
|
31
|
-
})({
|
|
32
|
-
effect: Effect.gen(function* () {
|
|
33
|
-
return Effect.fnUntraced(function* ({ headers, rpc }) {
|
|
34
|
-
yield* SomeElse;
|
|
35
|
-
yield* Scope.Scope; // provided by HttpRouter.HttpRouter.Provided
|
|
36
|
-
const isLoggedIn = !!headers["x-user"];
|
|
37
|
-
if (!isLoggedIn) {
|
|
38
|
-
if (!requestConfig(rpc).allowAnonymous) {
|
|
39
|
-
return yield* new NotLoggedInError({ message: "Not logged in" });
|
|
40
|
-
}
|
|
41
|
-
return Option.none();
|
|
42
|
-
}
|
|
43
|
-
return Option.some(Context.make(UserProfile, new UserProfile({
|
|
44
|
-
id: "whatever",
|
|
45
|
-
roles: ["user", ...headers["x-is-manager"] === "true" ? ["manager"] : []]
|
|
46
|
-
})));
|
|
47
|
-
});
|
|
48
|
-
})
|
|
49
63
|
}) {
|
|
50
64
|
}
|
|
65
|
+
export const AllowAnonymousLive = Layer.effect(AllowAnonymous, Effect.gen(function* () {
|
|
66
|
+
return Effect.fnUntraced(function* ({ headers, rpc }) {
|
|
67
|
+
yield* SomeElse;
|
|
68
|
+
yield* Scope.Scope; // provided by HttpLayerRouter.Provided
|
|
69
|
+
const isLoggedIn = !!headers["x-user"];
|
|
70
|
+
if (!isLoggedIn) {
|
|
71
|
+
if (!requestConfig(rpc).allowAnonymous) {
|
|
72
|
+
return yield* new NotLoggedInError({ message: "Not logged in" });
|
|
73
|
+
}
|
|
74
|
+
return Option.none();
|
|
75
|
+
}
|
|
76
|
+
return Option.some(Context.make(UserProfile, new UserProfile({
|
|
77
|
+
id: "whatever",
|
|
78
|
+
roles: ["user", ...headers["x-is-manager"] === "true" ? ["manager"] : []]
|
|
79
|
+
})));
|
|
80
|
+
});
|
|
81
|
+
}));
|
|
51
82
|
// TODO: don't expect service when it's wrap
|
|
52
83
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
53
|
-
export class RequireRoles extends
|
|
84
|
+
export class RequireRoles extends Tag()("RequireRoles", {
|
|
54
85
|
dynamic: contextMap(RequestContextMap, "requireRoles"),
|
|
55
86
|
wrap: true,
|
|
56
87
|
// wrap: true,
|
|
57
88
|
// had to move this in here, because once you put it manually as a readonly static property on the class,
|
|
58
89
|
// there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
|
|
59
90
|
dependsOn: [AllowAnonymous]
|
|
60
|
-
})({
|
|
61
|
-
effect: Effect.gen(function* () {
|
|
62
|
-
yield* SomeService;
|
|
63
|
-
return Effect.fnUntraced(function* ({ next, rpc }) {
|
|
64
|
-
// we don't know if the service will be provided or not, so we use option..
|
|
65
|
-
const userProfile = yield* Effect.serviceOption(UserProfile);
|
|
66
|
-
const { requireRoles } = requestConfig(rpc);
|
|
67
|
-
console.dir({
|
|
68
|
-
userProfile,
|
|
69
|
-
requireRoles
|
|
70
|
-
}, { depth: 5 });
|
|
71
|
-
if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
|
|
72
|
-
return yield* new UnauthorizedError({ message: "don't have the right roles" });
|
|
73
|
-
}
|
|
74
|
-
return yield* next;
|
|
75
|
-
});
|
|
76
|
-
})
|
|
77
91
|
}) {
|
|
78
92
|
}
|
|
93
|
+
export const RequireRolesLive = Layer.effect(RequireRoles, Effect.gen(function* () {
|
|
94
|
+
yield* SomeService;
|
|
95
|
+
return Effect.fnUntraced(function* ({ next, rpc }) {
|
|
96
|
+
// we don't know if the service will be provided or not, so we use option..
|
|
97
|
+
const userProfile = yield* Effect.serviceOption(UserProfile);
|
|
98
|
+
const { requireRoles } = requestConfig(rpc);
|
|
99
|
+
console.dir({
|
|
100
|
+
userProfile,
|
|
101
|
+
requireRoles
|
|
102
|
+
}, { depth: 5 });
|
|
103
|
+
if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
|
|
104
|
+
return yield* new UnauthorizedError({ message: "don't have the right roles" });
|
|
105
|
+
}
|
|
106
|
+
return yield* next;
|
|
107
|
+
});
|
|
108
|
+
}));
|
|
79
109
|
// TODO: don't expect service when it's wrap
|
|
80
|
-
export class Test extends
|
|
110
|
+
export class Test extends Tag()("Test", {
|
|
81
111
|
wrap: true,
|
|
82
112
|
dynamic: contextMap(RequestContextMap, "test")
|
|
83
|
-
})({
|
|
84
|
-
effect: Effect.gen(function* () {
|
|
85
|
-
return Effect.fn(function* ({ next }) {
|
|
86
|
-
return yield* next;
|
|
87
|
-
});
|
|
88
|
-
})
|
|
89
113
|
}) {
|
|
90
114
|
}
|
|
115
|
+
export const TestLive = Layer.effect(Test, Effect.gen(function* () {
|
|
116
|
+
return Effect.fn(function* ({ next }) {
|
|
117
|
+
return yield* next;
|
|
118
|
+
});
|
|
119
|
+
}));
|
|
91
120
|
export class CustomError1 extends TaggedError()("CustomError1", {}) {
|
|
92
121
|
}
|
|
93
122
|
export class CustomError2 extends TaggedError()("CustomError1", {}) {
|
|
94
123
|
}
|
|
95
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
124
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDckUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3RGLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUVsRSxNQUFNLE9BQU8sV0FBWSxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQTJCLGFBQWEsQ0FBQyxDQUN6RixDQUFDLENBQUMsS0FBSyxDQUFjLGFBQWEsQ0FBQyxDQUFDO0lBQ2xDLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTTtJQUNaLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7Q0FDekIsQ0FBQyxDQUNIO0NBQ0E7QUFFRCxNQUFNLE9BQU8sSUFBSyxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFRO0NBQUc7QUFDeEYsTUFBTSxPQUFPLFFBQVMsU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBWTtDQUFHO0FBQ3BHLE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUNoRCxNQUFNLE9B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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,
|
|
1
|
+
{"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,EAAE,CAAC,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEvE,OAAO,EAAkB,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAE,cAAc,EAAyC,YAAY,EAAoB,IAAI,EAAE,kBAAkB,EAA8D,kBAAkB,EAAe,IAAI,EAAY,MAAM,eAAe,CAAA;;;;;;;AAE5P,qBAAa,sBAAuB,SAAQ,2BAa1C;CACD;AAkBD,eAAO,MAAM,eAAe;;;;;;;;;;SAKK,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-multi-middleware.test.d.ts","sourceRoot":"","sources":["../rpc-multi-middleware.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAkD,MAAM,aAAa,CAAA;AAEvF,OAAO,EAA2B,KAAK,EAAE,MAAM,QAAQ,CAAA;AAOvD,OAAO,EAAoN,WAAW,EAAE,MAAM,eAAe,CAAA;AA8C7P,eAAO,MAAM,OAAO,uFAWO,CAAA;AAiB3B,eAAO,MAAM,YAAY,gLAItB,CAAA;AAEH,eAAO,MAAM,YAAY,+FAgByB,CAAA"}
|
package/test/fixtures.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Context, Effect, Option, S, Scope } from "effect-app"
|
|
1
|
+
import { Context, Effect, Layer, Option, S, Scope } from "effect-app"
|
|
2
2
|
import { NotLoggedInError, RPCContextMap, UnauthorizedError } from "effect-app/client"
|
|
3
3
|
import { TaggedError } from "effect-app/Schema"
|
|
4
|
-
import { contextMap, getConfig,
|
|
4
|
+
import { contextMap, getConfig, Tag } from "../src/api/routing.js"
|
|
5
5
|
|
|
6
6
|
export class UserProfile extends Context.assignTag<UserProfile, UserProfile>("UserProfile")(
|
|
7
7
|
S.Class<UserProfile>("UserProfile")({
|
|
@@ -16,6 +16,53 @@ export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b:
|
|
|
16
16
|
const MakeSomeService = Effect.succeed({ a: 1 })
|
|
17
17
|
export class SomeService extends Context.TagMakeId("SomeService", MakeSomeService)<SomeService>() {}
|
|
18
18
|
|
|
19
|
+
export class SomeMiddleware extends Tag<SomeMiddleware>()("SomeMiddleware", {
|
|
20
|
+
provides: Some
|
|
21
|
+
}) {}
|
|
22
|
+
|
|
23
|
+
export const SomeMiddlewareLive = Layer.effect(
|
|
24
|
+
SomeMiddleware,
|
|
25
|
+
Effect.gen(function*() {
|
|
26
|
+
// yield* Effect.context<"test-dep">()
|
|
27
|
+
return () =>
|
|
28
|
+
Effect.gen(function*() {
|
|
29
|
+
return new Some({ a: 1 })
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
// functionally equivalent to the one above
|
|
35
|
+
export class SomeMiddlewareWrap extends Tag<SomeMiddlewareWrap>()("SomeMiddlewareWrap", {
|
|
36
|
+
provides: Some,
|
|
37
|
+
wrap: true
|
|
38
|
+
}) {
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const SomeMiddlewareWrapLive = Layer.effect(
|
|
42
|
+
SomeMiddlewareWrap,
|
|
43
|
+
Effect.gen(function*() {
|
|
44
|
+
// yield* Effect.context<"test-dep">()
|
|
45
|
+
return ({ next }) => next.pipe(Effect.provideService(Some, new Some({ a: 1 })))
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
export class SomeElseMiddleware extends Tag<SomeElseMiddleware>()("SomeElseMiddleware", {
|
|
50
|
+
provides: SomeElse,
|
|
51
|
+
wrap: true
|
|
52
|
+
}) {}
|
|
53
|
+
|
|
54
|
+
export const SomeElseMiddlewareLive = Layer.effect(
|
|
55
|
+
SomeElseMiddleware,
|
|
56
|
+
Effect.gen(function*() {
|
|
57
|
+
// yield* Effect.context<"test-dep">()
|
|
58
|
+
return ({ next }) =>
|
|
59
|
+
Effect.gen(function*() {
|
|
60
|
+
// yield* Effect.context<"test-dep2">()
|
|
61
|
+
return yield* next.pipe(Effect.provideService(SomeElse, new SomeElse({ b: 2 })))
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
)
|
|
65
|
+
|
|
19
66
|
const requestConfig = getConfig<RequestContextMap>()
|
|
20
67
|
|
|
21
68
|
// TODO: null as never sucks
|
|
@@ -32,15 +79,18 @@ export const RequestContextMap = {
|
|
|
32
79
|
type _RequestContextMap = typeof RequestContextMap
|
|
33
80
|
export interface RequestContextMap extends _RequestContextMap {}
|
|
34
81
|
|
|
35
|
-
export class AllowAnonymous extends
|
|
82
|
+
export class AllowAnonymous extends Tag<AllowAnonymous>()("AllowAnonymous", {
|
|
36
83
|
dynamic: contextMap(RequestContextMap, "allowAnonymous"),
|
|
37
84
|
requires: SomeElse
|
|
38
|
-
})
|
|
39
|
-
|
|
85
|
+
}) {}
|
|
86
|
+
|
|
87
|
+
export const AllowAnonymousLive = Layer.effect(
|
|
88
|
+
AllowAnonymous,
|
|
89
|
+
Effect.gen(function*() {
|
|
40
90
|
return Effect.fnUntraced(
|
|
41
91
|
function*({ headers, rpc }) {
|
|
42
92
|
yield* SomeElse
|
|
43
|
-
yield* Scope.Scope // provided by
|
|
93
|
+
yield* Scope.Scope // provided by HttpLayerRouter.Provided
|
|
44
94
|
const isLoggedIn = !!headers["x-user"]
|
|
45
95
|
if (!isLoggedIn) {
|
|
46
96
|
if (!requestConfig(rpc).allowAnonymous) {
|
|
@@ -60,20 +110,22 @@ export class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnony
|
|
|
60
110
|
}
|
|
61
111
|
)
|
|
62
112
|
})
|
|
63
|
-
|
|
64
|
-
}
|
|
113
|
+
)
|
|
65
114
|
|
|
66
115
|
// TODO: don't expect service when it's wrap
|
|
67
116
|
// @effect-diagnostics-next-line missingEffectServiceDependency:off
|
|
68
|
-
export class RequireRoles extends
|
|
117
|
+
export class RequireRoles extends Tag<RequireRoles>()("RequireRoles", {
|
|
69
118
|
dynamic: contextMap(RequestContextMap, "requireRoles"),
|
|
70
119
|
wrap: true,
|
|
71
120
|
// wrap: true,
|
|
72
121
|
// had to move this in here, because once you put it manually as a readonly static property on the class,
|
|
73
122
|
// there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
|
|
74
123
|
dependsOn: [AllowAnonymous]
|
|
75
|
-
})
|
|
76
|
-
|
|
124
|
+
}) {}
|
|
125
|
+
|
|
126
|
+
export const RequireRolesLive = Layer.effect(
|
|
127
|
+
RequireRoles,
|
|
128
|
+
Effect.gen(function*() {
|
|
77
129
|
yield* SomeService
|
|
78
130
|
return Effect.fnUntraced(
|
|
79
131
|
function*({ next, rpc }) {
|
|
@@ -94,20 +146,22 @@ export class RequireRoles extends Middleware.Tag<RequireRoles>()("RequireRoles",
|
|
|
94
146
|
}
|
|
95
147
|
)
|
|
96
148
|
})
|
|
97
|
-
|
|
98
|
-
}
|
|
149
|
+
)
|
|
99
150
|
|
|
100
151
|
// TODO: don't expect service when it's wrap
|
|
101
|
-
export class Test extends
|
|
152
|
+
export class Test extends Tag<Test>()("Test", {
|
|
102
153
|
wrap: true,
|
|
103
154
|
dynamic: contextMap(RequestContextMap, "test")
|
|
104
|
-
})
|
|
105
|
-
|
|
155
|
+
}) {}
|
|
156
|
+
|
|
157
|
+
export const TestLive = Layer.effect(
|
|
158
|
+
Test,
|
|
159
|
+
Effect.gen(function*() {
|
|
106
160
|
return Effect.fn(function*({ next }) {
|
|
107
161
|
return yield* next
|
|
108
162
|
})
|
|
109
163
|
})
|
|
110
|
-
|
|
164
|
+
)
|
|
111
165
|
|
|
112
166
|
export class CustomError1 extends TaggedError<NotLoggedInError>()("CustomError1", {}) {}
|
|
113
167
|
export class CustomError2 extends TaggedError<NotLoggedInError>()("CustomError1", {}) {}
|