@effect-app/infra 2.88.0 → 2.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/api/{routing/middleware/ContextProvider.d.ts → ContextProvider.d.ts} +1 -1
- package/dist/api/ContextProvider.d.ts.map +1 -0
- package/dist/api/ContextProvider.js +38 -0
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +15 -10
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.js +2 -5
- package/dist/api/routing/middleware/RpcMiddleware.d.ts +6 -10
- package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/RpcMiddleware.js +1 -1
- package/dist/api/routing/middleware/generic-middleware.d.ts +19 -17
- package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/generic-middleware.js +2 -2
- package/dist/api/routing/middleware/middleware-api.d.ts +31 -27
- package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware-api.js +31 -40
- package/dist/api/routing/middleware.d.ts +0 -1
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +1 -2
- package/dist/api/routing.d.ts +1 -1
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +12 -10
- package/package.json +6 -6
- package/src/api/{routing/middleware/ContextProvider.ts → ContextProvider.ts} +1 -1
- package/src/api/routing/middleware/RouterMiddleware.ts +22 -56
- package/src/api/routing/middleware/RpcMiddleware.ts +15 -11
- package/src/api/routing/middleware/generic-middleware.ts +44 -26
- package/src/api/routing/middleware/middleware-api.ts +91 -111
- package/src/api/routing/middleware.ts +0 -1
- package/src/api/routing.ts +22 -20
- package/test/contextProvider.test.ts +1 -1
- package/test/controller.test.ts +3 -4
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +2 -2
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +7 -6
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/fixtures.ts +7 -5
- package/test/requires.test.ts +43 -22
- package/dist/api/routing/middleware/ContextProvider.d.ts.map +0 -1
- package/dist/api/routing/middleware/ContextProvider.js +0 -38
package/test/dist/fixtures.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, 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, Middleware } from "../src/api/routing.js";
|
|
4
|
+
import { contextMap, getConfig, Middleware } 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,7 @@ 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
|
+
const requestConfig = getConfig();
|
|
17
18
|
// TODO: null as never sucks
|
|
18
19
|
// why [UserProfile] is needed? AllowAnonymous triggers an error if just UserProfile without []
|
|
19
20
|
// [] requires return Context, non [] requires return the Service instance
|
|
@@ -29,12 +30,12 @@ export class AllowAnonymous extends Middleware.Tag()("AllowAnonymous", {
|
|
|
29
30
|
requires: SomeElse
|
|
30
31
|
})({
|
|
31
32
|
effect: Effect.gen(function* () {
|
|
32
|
-
return Effect.fnUntraced(function* ({
|
|
33
|
+
return Effect.fnUntraced(function* ({ headers, rpc }) {
|
|
33
34
|
yield* SomeElse;
|
|
34
35
|
yield* Scope.Scope; // provided by HttpRouter.HttpRouter.Provided
|
|
35
36
|
const isLoggedIn = !!headers["x-user"];
|
|
36
37
|
if (!isLoggedIn) {
|
|
37
|
-
if (!
|
|
38
|
+
if (!requestConfig(rpc).allowAnonymous) {
|
|
38
39
|
return yield* new NotLoggedInError({ message: "Not logged in" });
|
|
39
40
|
}
|
|
40
41
|
return Option.none();
|
|
@@ -59,10 +60,10 @@ export class RequireRoles extends Middleware.Tag()("RequireRoles", {
|
|
|
59
60
|
})({
|
|
60
61
|
effect: Effect.gen(function* () {
|
|
61
62
|
yield* SomeService;
|
|
62
|
-
return Effect.fnUntraced(function* ({
|
|
63
|
+
return Effect.fnUntraced(function* ({ next, rpc }) {
|
|
63
64
|
// we don't know if the service will be provided or not, so we use option..
|
|
64
65
|
const userProfile = yield* Effect.serviceOption(UserProfile);
|
|
65
|
-
const { requireRoles } =
|
|
66
|
+
const { requireRoles } = requestConfig(rpc);
|
|
66
67
|
console.dir({
|
|
67
68
|
userProfile,
|
|
68
69
|
requireRoles
|
|
@@ -91,4 +92,4 @@ export class CustomError1 extends TaggedError()("CustomError1", {}) {
|
|
|
91
92
|
}
|
|
92
93
|
export class CustomError2 extends TaggedError()("CustomError1", {}) {
|
|
93
94
|
}
|
|
94
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDdEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLHVCQUF1QixDQUFBO0FBRXpFLE1BQU0sT0FBTyxXQUFZLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBMkIsYUFBYSxDQUFDLENBQ3pGLENBQUMsQ0FBQyxLQUFLLENBQWMsYUFBYSxDQUFDLENBQUM7SUFDbEMsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNO0lBQ1osS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztDQUN6QixDQUFDLENBQ0g7Q0FDQTtBQUVELE1BQU0sT0FBTyxJQUFLLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQVE7Q0FBRztBQUN4RixNQUFNLE9BQU8sUUFBUyxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFZO0NBQUc7QUFDcEcsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0FBQ2hELE1BQU0sT0FBTyxXQUFZLFNB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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"requires.test.d.ts","sourceRoot":"","sources":["../requires.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,EAAK,MAAM,YAAY,CAAA;AAG9D,OAAO,EAAkB,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAmD,IAAI,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAA;;;;;;AAElH,qBAAa,cAAe,SAAQ,mBAUlC;CACD;;;;;;;AAGD,qBAAa,kBAAmB,SAAQ,uBAQtC;CACD;;;;;;;AAED,qBAAa,kBAAmB,SAAQ,uBAYtC;CACD;;;;;;;AAED,qBAAa,sBAAuB,SAAQ,2BAa1C;CACD"}
|
package/test/fixtures.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, 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, Middleware } from "../src/api/routing.js"
|
|
4
|
+
import { contextMap, getConfig, Middleware } 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,8 @@ 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
|
+
const requestConfig = getConfig<RequestContextMap>()
|
|
20
|
+
|
|
19
21
|
// TODO: null as never sucks
|
|
20
22
|
// why [UserProfile] is needed? AllowAnonymous triggers an error if just UserProfile without []
|
|
21
23
|
// [] requires return Context, non [] requires return the Service instance
|
|
@@ -36,12 +38,12 @@ export class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnony
|
|
|
36
38
|
})({
|
|
37
39
|
effect: Effect.gen(function*() {
|
|
38
40
|
return Effect.fnUntraced(
|
|
39
|
-
function*({
|
|
41
|
+
function*({ headers, rpc }) {
|
|
40
42
|
yield* SomeElse
|
|
41
43
|
yield* Scope.Scope // provided by HttpRouter.HttpRouter.Provided
|
|
42
44
|
const isLoggedIn = !!headers["x-user"]
|
|
43
45
|
if (!isLoggedIn) {
|
|
44
|
-
if (!
|
|
46
|
+
if (!requestConfig(rpc).allowAnonymous) {
|
|
45
47
|
return yield* new NotLoggedInError({ message: "Not logged in" })
|
|
46
48
|
}
|
|
47
49
|
return Option.none()
|
|
@@ -74,10 +76,10 @@ export class RequireRoles extends Middleware.Tag<RequireRoles>()("RequireRoles",
|
|
|
74
76
|
effect: Effect.gen(function*() {
|
|
75
77
|
yield* SomeService
|
|
76
78
|
return Effect.fnUntraced(
|
|
77
|
-
function*({
|
|
79
|
+
function*({ next, rpc }) {
|
|
78
80
|
// we don't know if the service will be provided or not, so we use option..
|
|
79
81
|
const userProfile = yield* Effect.serviceOption(UserProfile)
|
|
80
|
-
const { requireRoles } =
|
|
82
|
+
const { requireRoles } = requestConfig(rpc)
|
|
81
83
|
console.dir(
|
|
82
84
|
{
|
|
83
85
|
userProfile,
|
package/test/requires.test.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { Rpc } from "@effect/rpc"
|
|
2
|
+
import { type SuccessValue } from "@effect/rpc/RpcMiddleware"
|
|
1
3
|
import { describe, expect, expectTypeOf, it } from "@effect/vitest"
|
|
2
|
-
import { Effect, Either, Layer, S } from "effect-app"
|
|
4
|
+
import { Context, Effect, Either, Layer, S } from "effect-app"
|
|
3
5
|
import { NotLoggedInError, UnauthorizedError } from "effect-app/client"
|
|
6
|
+
import { HttpHeaders } from "effect-app/http"
|
|
4
7
|
import { makeMiddleware, Middleware } from "../src/api/routing.js"
|
|
5
8
|
import { AllowAnonymous, RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
|
|
6
9
|
|
|
@@ -85,27 +88,41 @@ const _middleware3Bis = makeMiddleware(RequestContextMap)
|
|
|
85
88
|
|
|
86
89
|
expectTypeOf(_middlewareSideways).toEqualTypeOf<typeof middleware3>()
|
|
87
90
|
expectTypeOf(_middlewareSidewaysFully).toEqualTypeOf<typeof _middlewareSideways>()
|
|
88
|
-
expectTypeOf(_middleware3Bis).toEqualTypeOf<typeof middleware3>()
|
|
91
|
+
// expectTypeOf(_middleware3Bis).toEqualTypeOf<typeof middleware3>() // is not the same because SomeMiddlewareWrap is not SomeMiddleware
|
|
89
92
|
|
|
90
93
|
type Default = typeof middleware3["Default"]
|
|
91
94
|
type LayerContext = Layer.Layer.Context<Default>
|
|
92
95
|
expectTypeOf({} as LayerContext).toEqualTypeOf<SomeService>()
|
|
93
96
|
|
|
97
|
+
class TestRequest extends S.TaggedRequest<Test>("Test")("Test", {
|
|
98
|
+
payload: {},
|
|
99
|
+
success: S.Void,
|
|
100
|
+
failure: S.Never
|
|
101
|
+
}) {}
|
|
102
|
+
|
|
94
103
|
const testSuite = (_mw: typeof middleware3) =>
|
|
95
104
|
describe("middleware" + _mw, () => {
|
|
96
105
|
it.effect(
|
|
97
106
|
"works",
|
|
98
107
|
Effect.fn(function*() {
|
|
108
|
+
const defaultReq = {
|
|
109
|
+
headers: HttpHeaders.unsafeFromRecord({}),
|
|
110
|
+
payload: { _tag: "Test" },
|
|
111
|
+
clientId: 0,
|
|
112
|
+
rpc: { ...Rpc.fromTaggedRequest(TestRequest), annotations: Context.make(_mw.requestContext, {}) },
|
|
113
|
+
next: Effect.void as unknown as Effect<SuccessValue, never, any>
|
|
114
|
+
}
|
|
99
115
|
const layer = _mw.Default.pipe(Layer.provide(SomeService.toLayer()))
|
|
100
116
|
yield* Effect
|
|
101
117
|
.gen(function*() {
|
|
102
118
|
const mw = yield* _mw
|
|
103
|
-
const mwM = mw
|
|
104
|
-
Object.assign({},
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
const mwM = mw(
|
|
120
|
+
Object.assign({ ...defaultReq }, {
|
|
121
|
+
headers: { "x-user": "test-user", "x-is-manager": "true" },
|
|
122
|
+
rpc: { ...defaultReq.rpc, annotations: Context.make(_mw.requestContext, { requireRoles: ["manager"] }) }
|
|
123
|
+
})
|
|
107
124
|
)
|
|
108
|
-
yield* mwM
|
|
125
|
+
yield* mwM
|
|
109
126
|
})
|
|
110
127
|
.pipe(
|
|
111
128
|
Effect.scoped,
|
|
@@ -116,12 +133,10 @@ const testSuite = (_mw: typeof middleware3) =>
|
|
|
116
133
|
yield* Effect
|
|
117
134
|
.gen(function*() {
|
|
118
135
|
const mw = yield* _mw
|
|
119
|
-
const mwM = mw
|
|
120
|
-
Object.assign({},
|
|
121
|
-
(_req) => Effect.void,
|
|
122
|
-
"some-module"
|
|
136
|
+
const mwM = mw(
|
|
137
|
+
Object.assign({ ...defaultReq }, {})
|
|
123
138
|
)
|
|
124
|
-
yield* mwM
|
|
139
|
+
yield* mwM
|
|
125
140
|
})
|
|
126
141
|
.pipe(
|
|
127
142
|
Effect.scoped,
|
|
@@ -135,12 +150,15 @@ const testSuite = (_mw: typeof middleware3) =>
|
|
|
135
150
|
yield* Effect
|
|
136
151
|
.gen(function*() {
|
|
137
152
|
const mw = yield* _mw
|
|
138
|
-
const mwM = mw
|
|
139
|
-
Object.assign({},
|
|
140
|
-
|
|
141
|
-
|
|
153
|
+
const mwM = mw(
|
|
154
|
+
Object.assign({ ...defaultReq }, {
|
|
155
|
+
rpc: {
|
|
156
|
+
...defaultReq.rpc,
|
|
157
|
+
annotations: Context.make(_mw.requestContext, { requireRoles: ["manager"] })
|
|
158
|
+
}
|
|
159
|
+
})
|
|
142
160
|
)
|
|
143
|
-
yield* mwM
|
|
161
|
+
yield* mwM
|
|
144
162
|
})
|
|
145
163
|
.pipe(
|
|
146
164
|
Effect.scoped,
|
|
@@ -154,12 +172,15 @@ const testSuite = (_mw: typeof middleware3) =>
|
|
|
154
172
|
yield* Effect
|
|
155
173
|
.gen(function*() {
|
|
156
174
|
const mw = yield* _mw
|
|
157
|
-
const mwM = mw
|
|
158
|
-
Object.assign({},
|
|
159
|
-
|
|
160
|
-
|
|
175
|
+
const mwM = mw(
|
|
176
|
+
Object.assign({ ...defaultReq }, { headers: { "x-user": "test-user" } }, {
|
|
177
|
+
rpc: {
|
|
178
|
+
...defaultReq.rpc,
|
|
179
|
+
annotations: Context.make(_mw.requestContext, { requireRoles: ["manager"] })
|
|
180
|
+
}
|
|
181
|
+
})
|
|
161
182
|
)
|
|
162
|
-
yield* mwM
|
|
183
|
+
yield* mwM
|
|
163
184
|
})
|
|
164
185
|
.pipe(
|
|
165
186
|
Effect.scoped,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextProvider.d.ts","sourceRoot":"","sources":["../../../../src/api/routing/middleware/ContextProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Context, Effect, Layer, pipe } from "effect-app";
|
|
3
|
-
import { mergeContexts } from "../../layerUtils.js";
|
|
4
|
-
// Note: the type here must be aligned with MergedContextProvider
|
|
5
|
-
export const mergeContextProviders = (
|
|
6
|
-
// long life to reverse mapped types
|
|
7
|
-
...deps) => ({
|
|
8
|
-
dependencies: deps.map((_) => _.Default),
|
|
9
|
-
effect: Effect.gen(function* () {
|
|
10
|
-
// uses the tags to request the context providers
|
|
11
|
-
const makers = yield* Effect.all(deps);
|
|
12
|
-
return Effect
|
|
13
|
-
.gen(function* () {
|
|
14
|
-
const services = makers.map((handle, i) => ({
|
|
15
|
-
maker: deps[i],
|
|
16
|
-
handle: handle[Symbol.toStringTag] === "GeneratorFunction" ? Effect.fnUntraced(handle)() : handle
|
|
17
|
-
}));
|
|
18
|
-
// services are effects which return some Context.Context<...>
|
|
19
|
-
const context = yield* mergeContexts(services);
|
|
20
|
-
return context;
|
|
21
|
-
});
|
|
22
|
-
})
|
|
23
|
-
});
|
|
24
|
-
// Effect Rpc Middleware: for single tag providing, we could use Provides, for providing Context or Layer (bad boy) we could use Wrap..
|
|
25
|
-
export const ContextProvider = (input) => {
|
|
26
|
-
const ctx = Context.GenericTag("ContextProvider");
|
|
27
|
-
const e = input.effect.pipe(Effect.map((eg) => eg[Symbol.toStringTag] === "GeneratorFunction" ? Effect.fnUntraced(eg)() : eg));
|
|
28
|
-
const l = Layer.scoped(ctx, e);
|
|
29
|
-
return Object.assign(ctx, {
|
|
30
|
-
Default: l.pipe(input.dependencies ? Layer.provide(input.dependencies) : (_) => _)
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
// Note: the type here must be aligned with mergeContextProviders
|
|
34
|
-
export const MergedContextProvider = (
|
|
35
|
-
// long life to reverse mapped types
|
|
36
|
-
...deps) => pipe(deps, (_) => mergeContextProviders(..._), (_) => ContextProvider(_));
|
|
37
|
-
export const EmptyContextProvider = ContextProvider({ effect: Effect.succeed(Effect.succeed(Context.empty())) });
|
|
38
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29udGV4dFByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwaS9yb3V0aW5nL21pZGRsZXdhcmUvQ29udGV4dFByb3ZpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHVEQUF1RDtBQUN2RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQThCLElBQUksRUFBYyxNQUFNLFlBQVksQ0FBQTtBQUtqRyxPQUFPLEVBQWdFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBd0VqSCxpRUFBaUU7QUFDakUsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUc7QUFHbkMsb0NBQW9DO0FBQ3BDLEdBQUcsSUFBcUIsRUFheEIsRUFBRSxDQUFDLENBQUM7SUFDSixZQUFZLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUUsQ0FBUyxDQUFDLE9BQU8sQ0FBUTtJQUN4RCxNQUFNLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDMUIsaURBQWlEO1FBQ2pELE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBYSxDQUFDLENBQUE7UUFDL0MsT0FBTyxNQUFNO2FBQ1YsR0FBRyxDQUFDLFFBQVEsQ0FBQztZQUNaLE1BQU0sUUFBUSxHQUFJLE1BQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FDcEQ7Z0JBQ0UsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ2QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssbUJBQW1CLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTTthQUNsRyxDQUNGLENBQUMsQ0FBQTtZQUNGLDhEQUE4RDtZQUM5RCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyxhQUFhLENBQUMsUUFBZSxDQUFDLENBQUE7WUFDckQsT0FBTyxPQUFPLENBQUE7UUFDaEIsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQVE7Q0FDVixDQUFDLENBQUE7QUFFRix1SUFBdUk7QUFDdkksTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLENBTzdCLEtBWUMsRUFDRCxFQUFFO0lBQ0YsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FJNUIsaUJBQWlCLENBQ2xCLENBQUE7SUFDRCxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDekIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUUsRUFBVSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FDbEgsQ0FBQTtJQUNELE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQVEsQ0FBQyxDQUFBO0lBQ3JDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7UUFDeEIsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQ2IsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBT3pFO0tBQ0YsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBRUQsaUVBQWlFO0FBQ2pFLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHO0FBR25DLG9DQUFvQztBQUNwQyxHQUFHLElBQXFCLEVBQ3hCLEVBQUUsQ0FDRixJQUFJLENBQ0YsSUFBcUQsRUFDckQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ2xDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBUSxDQUFDLENBZWpDLENBQUE7QUFFSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxlQUFlLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFBIn0=
|