@effect-app/infra 2.85.0 → 2.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/api/layerUtils.d.ts +4 -8
  3. package/dist/api/layerUtils.d.ts.map +1 -1
  4. package/dist/api/layerUtils.js +3 -11
  5. package/dist/api/routing/middleware/ContextProvider.d.ts +2 -2
  6. package/dist/api/routing/middleware/ContextProvider.d.ts.map +1 -1
  7. package/dist/api/routing/middleware/RouterMiddleware.d.ts +33 -0
  8. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  9. package/dist/api/routing/middleware/RouterMiddleware.js +5 -0
  10. package/dist/api/routing/middleware/RpcMiddleware.d.ts +199 -0
  11. package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -0
  12. package/dist/api/routing/middleware/RpcMiddleware.js +14 -0
  13. package/dist/api/routing/middleware/dynamic-middleware.d.ts +3 -13
  14. package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -1
  15. package/dist/api/routing/middleware/dynamic-middleware.js +2 -18
  16. package/dist/api/routing/middleware/generic-middleware.d.ts +15 -22
  17. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
  18. package/dist/api/routing/middleware/generic-middleware.js +13 -9
  19. package/dist/api/routing/middleware/middleware-api.d.ts +55 -8
  20. package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
  21. package/dist/api/routing/middleware/middleware-api.js +50 -14
  22. package/dist/api/routing/middleware/middleware.d.ts +8 -7
  23. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  24. package/dist/api/routing/middleware/middleware.js +6 -5
  25. package/dist/api/routing/middleware.d.ts +2 -1
  26. package/dist/api/routing/middleware.d.ts.map +1 -1
  27. package/dist/api/routing/middleware.js +3 -2
  28. package/dist/api/routing/tsort.d.ts +2 -2
  29. package/dist/api/routing/tsort.d.ts.map +1 -1
  30. package/dist/api/routing/tsort.js +1 -1
  31. package/dist/api/routing.d.ts +0 -1
  32. package/dist/api/routing.d.ts.map +1 -1
  33. package/dist/api/routing.js +2 -3
  34. package/package.json +9 -5
  35. package/src/api/layerUtils.ts +7 -21
  36. package/src/api/routing/middleware/ContextProvider.ts +5 -5
  37. package/src/api/routing/middleware/RouterMiddleware.ts +149 -0
  38. package/src/api/routing/middleware/RpcMiddleware.ts +287 -0
  39. package/src/api/routing/middleware/dynamic-middleware.ts +9 -54
  40. package/src/api/routing/middleware/generic-middleware.ts +33 -33
  41. package/src/api/routing/middleware/middleware-api.ts +202 -32
  42. package/src/api/routing/middleware/middleware.ts +13 -5
  43. package/src/api/routing/middleware.ts +2 -1
  44. package/src/api/routing/tsort.ts +2 -2
  45. package/src/api/routing.ts +1 -9
  46. package/test/contextProvider.test.ts +1 -2
  47. package/test/controller.test.ts +35 -155
  48. package/test/dist/contextProvider.test.d.ts.map +1 -1
  49. package/test/dist/controller.test.d.ts.map +1 -1
  50. package/test/dist/fixtures.d.ts +146 -0
  51. package/test/dist/fixtures.d.ts.map +1 -0
  52. package/test/dist/fixtures.js +82 -0
  53. package/test/dist/layerUtils.test.d.ts.map +1 -0
  54. package/test/dist/query.test.d.ts.map +1 -1
  55. package/test/dist/requires.d.ts +21 -0
  56. package/test/dist/requires.d.ts.map +1 -0
  57. package/test/dist/requires.js +27 -0
  58. package/test/dist/requires.test.d.ts.map +1 -0
  59. package/test/fixtures.ts +102 -0
  60. package/test/layerUtils.test.ts +19 -0
  61. package/test/query.test.ts +2 -4
  62. package/test/requires.test.ts +156 -0
  63. package/dist/api/routing/middleware/DynamicMiddleware.d.ts +0 -215
  64. package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +0 -1
  65. package/dist/api/routing/middleware/DynamicMiddleware.js +0 -168
  66. package/src/api/routing/middleware/DynamicMiddleware.ts +0 -693
@@ -1,46 +1,24 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
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
- import type { RequestContext } from "@effect-app/infra/RequestContext"
5
4
  import { expect, expectTypeOf, it } from "@effect/vitest"
6
- import { type Array, Context, Effect, Layer, Option, S, Scope } from "effect-app"
7
- import { InvalidStateError, makeRpcClient, type RPCContextMap, UnauthorizedError } from "effect-app/client"
8
- import { Class, TaggedError } from "effect-app/Schema"
9
- import { contextMap, DefaultGenericMiddlewares, implementMiddleware, makeMiddleware, makeNewMiddleware, Middleware, Tag } from "../src/api/routing/middleware.js"
5
+ import { Context, Effect, type Layer, S, Scope } from "effect-app"
6
+ import { InvalidStateError, makeRpcClient, NotLoggedInError, UnauthorizedError } from "effect-app/client"
7
+ import { DefaultGenericMiddlewares, makeMiddleware, Middleware, Tag } from "../src/api/routing/middleware.js"
10
8
  import { sort } from "../src/api/routing/tsort.js"
11
- import { SomeService } from "./query.test.js"
12
-
13
- export class UserProfile extends Context.assignTag<UserProfile, UserProfile>("UserProfile")(
14
- Class<UserProfile>("UserProfile")({
15
- id: S.String,
16
- roles: S.Array(S.String)
17
- })
18
- ) {
19
- }
20
-
21
- export class NotLoggedInError extends TaggedError<NotLoggedInError>()("NotLoggedInError", {
22
- message: S.String
23
- }) {}
24
-
25
- export class CustomError1 extends TaggedError<NotLoggedInError>()("CustomError1", {}) {}
26
- export class CustomError2 extends TaggedError<NotLoggedInError>()("CustomError1", {}) {}
27
-
28
- export interface CTX {
29
- context: RequestContext
30
- }
31
-
32
- export class Some extends Context.TagMakeId("Some", Effect.succeed({ a: 1 }))<Some>() {}
33
- export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b: 2 }))<SomeElse>() {}
9
+ import { AllowAnonymous, CustomError1, type RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
34
10
 
35
11
  // @effect-diagnostics-next-line missingEffectServiceDependency:off
36
12
  class MyContextProvider extends Middleware.Tag<MyContextProvider>()("MyContextProvider", {
37
- provides: [Some]
13
+ provides: [Some],
14
+ requires: [SomeElse]
38
15
  })({
39
16
  effect: Effect.gen(function*() {
40
17
  yield* SomeService
41
18
  if (Math.random() > 0.5) return yield* new CustomError1()
42
19
 
43
20
  return Effect.fnUntraced(function*() {
21
+ yield* SomeElse
44
22
  // the only requirements you can have are the one provided by HttpRouter.HttpRouter.Provided
45
23
  yield* Scope.Scope
46
24
 
@@ -74,81 +52,19 @@ class MyContextProvider2 extends Middleware.Tag<MyContextProvider2>()("MyContext
74
52
 
75
53
  //
76
54
 
77
- export type RequestContextMap = {
78
- allowAnonymous: RPCContextMap.Inverted<UserProfile, typeof NotLoggedInError>
79
- requireRoles: RPCContextMap.Custom<never, typeof UnauthorizedError, Array<string>>
80
- test: RPCContextMap<never, typeof S.Never>
81
- }
82
-
83
55
  const Str = Context.GenericTag<"str", "str">("str")
84
- const Str2 = Context.GenericTag<"str2", "str">("str2")
85
-
86
- class AllowAnonymous extends Middleware.Tag<AllowAnonymous>()("AllowAnonymous", {
87
- dynamic: contextMap<RequestContextMap>()("allowAnonymous")
88
- })({
89
- effect: Effect.gen(function*() {
90
- return Effect.fnUntraced(
91
- function*(options) {
92
- yield* Scope.Scope // provided by HttpRouter.HttpRouter.Provided
93
- const isLoggedIn = !!options.headers["x-user"]
94
- if (!isLoggedIn) {
95
- if (!options.config.allowAnonymous) {
96
- return yield* new NotLoggedInError({ message: "Not logged in" })
97
- }
98
- return Option.none()
99
- }
100
- return Option.some(Context.make(
101
- UserProfile,
102
- { id: "whatever", roles: ["user", "manager"] }
103
- ))
104
- }
105
- )
106
- })
107
- }) {
108
- }
109
-
110
- // @effect-diagnostics-next-line missingEffectServiceDependency:off
111
- class RequireRoles extends Middleware.Tag<RequireRoles>()("RequireRoles", {
112
- dynamic: contextMap<RequestContextMap>()("requireRoles"),
113
- // had to move this in here, because once you put it manually as a readonly static property on the class,
114
- // there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
115
- dependsOn: [AllowAnonymous]
116
- })({
117
- effect: Effect.gen(function*() {
118
- yield* Some
119
- return Effect.fnUntraced(
120
- function*(options) {
121
- // we don't know if the service will be provided or not, so we use option..
122
- const userProfile = yield* Effect.serviceOption(UserProfile)
123
- const { requireRoles } = options.config
124
- if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
125
- return yield* new UnauthorizedError({ message: "don't have the right roles" })
126
- }
127
- return Option.none<Context<never>>()
128
- }
129
- )
130
- })
131
- }) {
132
- }
133
-
134
- class Test extends Middleware.Tag<Test>()("Test", { dynamic: contextMap<RequestContextMap>()("test") })({
135
- effect: Effect.gen(function*() {
136
- return Effect.fn(function*(_options) {
137
- return Option.none<Context<never>>()
138
- })
139
- })
140
- }) {}
141
56
 
142
57
  export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
143
58
  provides: SomeService,
144
59
  wrap: true
145
60
  })({
146
61
  effect: Effect.gen(function*() {
62
+ yield* Str
147
63
  // yield* Effect.context<"test-dep">()
148
- return (options) =>
64
+ return ({ next }) =>
149
65
  Effect.gen(function*() {
150
66
  // yield* Effect.context<"test-dep2">()
151
- return yield* options.next.pipe(Effect.provideService(SomeService, null as any))
67
+ return yield* next.pipe(Effect.provideService(SomeService, null as any))
152
68
  })
153
69
  })
154
70
  }) {
@@ -156,61 +72,31 @@ export class BogusMiddleware extends Tag<BogusMiddleware>()("BogusMiddleware", {
156
72
 
157
73
  const genericMiddlewares = [
158
74
  ...DefaultGenericMiddlewares,
159
- // BogusMiddleware,
160
- MyContextProvider2,
161
- MyContextProvider
75
+ BogusMiddleware,
76
+ MyContextProvider2
162
77
  ] as const
163
78
 
164
- // TODO: eventually it might be nice if we have total control over order somehow..
165
- // [ AddRequestNameToSpanContext, RequestCacheContext, UninterruptibleMiddleware, Dynamic(or individual, AllowAnonymous, RequireRoles, Test - or whichever order) ]
166
- const middleware = makeMiddleware<RequestContextMap>()({
167
- genericMiddlewares,
168
-
169
- dynamicMiddlewares: {
170
- requireRoles: RequireRoles,
171
- allowAnonymous: AllowAnonymous,
172
- test: Test
173
- },
174
-
175
- dependencies: [Layer.effect(Str2, Str)],
176
- execute: (maker) =>
177
- Effect.gen(function*() {
178
- return maker(
179
- (_schema, handler) => (req, headers) =>
180
- // contextProvider and dynamicMiddlewares are already provided here.
181
- // aka this runs "last"
182
- Effect
183
- .gen(function*() {
184
- // you can use only HttpRouter.HttpRouter.Provided here as additional context
185
- // and what ContextProvider provides too
186
- // const someElse = yield* SomeElse
187
- yield* Some // provided by ContextProvider
188
- yield* Scope.Scope // provided by HttpRouter.HttpRouter.Provided
189
-
190
- return yield* handler(req, headers)
191
- })
192
- )
193
- })
194
- })
195
-
196
- const middleware2 = makeMiddleware<RequestContextMap>()({
197
- // TODO: I guess it makes sense to support just passing array of context providers too, like dynamicMiddlewares?
198
- genericMiddlewares: [...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2, MyContextProvider],
199
- // or is the better api to use constructors outside, like how contextProvider is used now?
200
- dynamicMiddlewares: {
201
- requireRoles: RequireRoles,
202
- allowAnonymous: AllowAnonymous,
203
- test: Test
204
- }
205
- })
206
-
207
- export const middleware3 = makeNewMiddleware<RequestContextMap>()(
208
- ...genericMiddlewares
209
- )
210
- .addDynamicMiddleware(AllowAnonymous, RequireRoles)
211
- .addDynamicMiddleware(Test)
212
-
213
- expectTypeOf(middleware3).toEqualTypeOf<typeof middleware2>()
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)],
88
+
89
+ const middleware2 = makeMiddleware<RequestContextMap>()
90
+ .middleware(MyContextProvider)
91
+ .middleware(RequireRoles, Test)
92
+ .middleware(AllowAnonymous)
93
+ .middleware(...DefaultGenericMiddlewares, BogusMiddleware, MyContextProvider2)
94
+
95
+ export const middleware3 = makeMiddleware<RequestContextMap>()
96
+ .middleware(...genericMiddlewares)
97
+ .middleware(AllowAnonymous, RequireRoles)
98
+ .middleware(Test)
99
+ .middleware(BogusMiddleware)
214
100
 
215
101
  export type RequestConfig = {
216
102
  /** Disable authentication requirement */
@@ -360,7 +246,7 @@ it("sorts based on requirements", () => {
360
246
 
361
247
  // eslint-disable-next-line unused-imports/no-unused-vars
362
248
  const matched = matchAll({ router })
363
- expectTypeOf({} as Layer.Context<typeof matched>).toEqualTypeOf<SomeService | "str">()
249
+ expectTypeOf({} as Layer.Context<typeof matched>).toEqualTypeOf<SomeService | Some | "str">()
364
250
 
365
251
  type makeContext = MakeContext<typeof router.make>
366
252
  expectTypeOf({} as MakeErrors<typeof router.make>).toEqualTypeOf<InvalidStateError>()
@@ -432,16 +318,10 @@ const router2 = r2.Router(Something)({
432
318
 
433
319
  // eslint-disable-next-line unused-imports/no-unused-vars
434
320
  const matched2 = matchAll({ router: router2 })
435
- expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<SomeService>()
321
+ expectTypeOf({} as Layer.Context<typeof matched2>).toEqualTypeOf<Some | SomeService | "str">()
436
322
 
437
323
  type makeContext2 = MakeContext<typeof router2.make>
438
324
  expectTypeOf({} as MakeErrors<typeof router2.make>).toEqualTypeOf<InvalidStateError>()
439
325
  expectTypeOf({} as makeContext2).toEqualTypeOf<
440
326
  SomethingService | SomethingRepo | SomethingService2
441
327
  >()
442
-
443
- export const dynamicMiddlewares = implementMiddleware<RequestContextMap>()({
444
- requireRoles: RequireRoles,
445
- allowAnonymous: AllowAnonymous,
446
- test: Test
447
- })
@@ -1 +1 @@
1
- {"version":3,"file":"contextProvider.test.d.ts","sourceRoot":"","sources":["../contextProvider.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AA8E7C,eAAO,MAAM,mBAAmB;;CAkB9B,CAAA;AACF,eAAO,MAAM,sBAAsB;;CAkBjC,CAAA;AAMF,eAAO,MAAM,gBAAgB;;CAA0B,CAAA;AACvD,eAAO,MAAM,gBAAgB,kMAA2C,CAAA;AAIxE,eAAO,MAAM,mBAAmB;;CAA6B,CAAA;AAC7D,eAAO,MAAM,mBAAmB,kMAA8C,CAAA;AAQ9E,eAAO,MAAM,iBAAiB;;CAA2B,CAAA;AACzD,eAAO,MAAM,iBAAiB,6MAA+D,CAAA;AAI7F,eAAO,MAAM,oBAAoB;;CAA8B,CAAA;AAC/D,eAAO,MAAM,oBAAoB,6MAAqE,CAAA"}
1
+ {"version":3,"file":"contextProvider.test.d.ts","sourceRoot":"","sources":["../contextProvider.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AA8EzE,eAAO,MAAM,mBAAmB;;CAkB9B,CAAA;AACF,eAAO,MAAM,sBAAsB;;CAkBjC,CAAA;AAMF,eAAO,MAAM,gBAAgB;;CAA0B,CAAA;AACvD,eAAO,MAAM,gBAAgB,kMAA2C,CAAA;AAIxE,eAAO,MAAM,mBAAmB;;CAA6B,CAAA;AAC7D,eAAO,MAAM,mBAAmB,kMAA8C,CAAA;AAQ9E,eAAO,MAAM,iBAAiB;;CAA2B,CAAA;AACzD,eAAO,MAAM,iBAAiB,6MAA+D,CAAA;AAI7F,eAAO,MAAM,oBAAoB;;CAA8B,CAAA;AAC/D,eAAO,MAAM,oBAAoB,6MAAqE,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../controller.test.ts"],"names":[],"mappings":"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"}
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"}
@@ -0,0 +1,146 @@
1
+ import { Context, Effect, S, Scope } from "effect-app";
2
+ import { NotLoggedInError, type RPCContextMap, UnauthorizedError } from "effect-app/client";
3
+ import { Middleware } from "../src/api/routing.js";
4
+ declare const UserProfile_base: S.EnhancedClass<UserProfile, {
5
+ id: typeof S.String;
6
+ roles: S.Array$<typeof S.String> & {
7
+ withDefault: S.PropertySignature<":", readonly string[], never, ":", readonly string[], true, never>;
8
+ };
9
+ }, {
10
+ readonly id: string;
11
+ readonly roles: readonly string[];
12
+ }, never, {
13
+ readonly id: string;
14
+ readonly roles: readonly string[];
15
+ }, {}, {}> & Context.Tag<UserProfile, UserProfile>;
16
+ export declare class UserProfile extends UserProfile_base {
17
+ }
18
+ declare const Some_base: (abstract new (service: {
19
+ a: number;
20
+ }) => Readonly<{
21
+ a: number;
22
+ }> & Context.TagClassShape<"Some", {
23
+ a: number;
24
+ }>) & {
25
+ toLayer: {
26
+ (): import("effect/Layer").Layer<Some, never, never>;
27
+ <E_1, R_1>(eff: Effect.Effect<Omit<Some, keyof Context.TagClassShape<any, any>>, E_1, R_1>): import("effect/Layer").Layer<Some, E_1, R_1>;
28
+ };
29
+ toLayerScoped: {
30
+ (): import("effect/Layer").Layer<Some, never, never>;
31
+ <E_1, R_2>(eff: Effect.Effect<Context.TagClassShape<any, any>, E_1, R_2>): import("effect/Layer").Layer<Some, E_1, Exclude<R_2, Scope.Scope>>;
32
+ };
33
+ of: (service: Context.TagClassShape<any, any>) => Some;
34
+ make: Effect.Effect<Some, never, never>;
35
+ } & Context.Tag<Some, Some> & {
36
+ a: Effect.Effect<number, never, Some>;
37
+ } & {
38
+ use: <X>(body: (_: {
39
+ a: number;
40
+ }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, Some | R_3> : Effect.Effect<X, never, Some>;
41
+ };
42
+ export declare class Some extends Some_base {
43
+ }
44
+ declare const SomeElse_base: (abstract new (service: {
45
+ b: number;
46
+ }) => Readonly<{
47
+ b: number;
48
+ }> & Context.TagClassShape<"SomeElse", {
49
+ b: number;
50
+ }>) & {
51
+ toLayer: {
52
+ (): import("effect/Layer").Layer<SomeElse, never, never>;
53
+ <E_1, R_1>(eff: Effect.Effect<Omit<SomeElse, keyof Context.TagClassShape<any, any>>, E_1, R_1>): import("effect/Layer").Layer<SomeElse, E_1, R_1>;
54
+ };
55
+ toLayerScoped: {
56
+ (): import("effect/Layer").Layer<SomeElse, never, never>;
57
+ <E_1, R_2>(eff: Effect.Effect<Context.TagClassShape<any, any>, E_1, R_2>): import("effect/Layer").Layer<SomeElse, E_1, Exclude<R_2, Scope.Scope>>;
58
+ };
59
+ of: (service: Context.TagClassShape<any, any>) => SomeElse;
60
+ make: Effect.Effect<SomeElse, never, never>;
61
+ } & Context.Tag<SomeElse, SomeElse> & {
62
+ b: Effect.Effect<number, never, SomeElse>;
63
+ } & {
64
+ use: <X>(body: (_: {
65
+ b: number;
66
+ }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, R_3 | SomeElse> : Effect.Effect<X, never, SomeElse>;
67
+ };
68
+ export declare class SomeElse extends SomeElse_base {
69
+ }
70
+ export type RequestContextMap = {
71
+ allowAnonymous: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>;
72
+ requireRoles: RPCContextMap.Custom<never, typeof UnauthorizedError, Array<string>>;
73
+ test: RPCContextMap<never, typeof S.Never>;
74
+ };
75
+ declare const AllowAnonymous_base: Middleware.TagClass<AllowAnonymous, "AllowAnonymous", {
76
+ readonly dynamic: {
77
+ key: "allowAnonymous";
78
+ settings: RPCContextMap.Inverted<[typeof UserProfile], typeof NotLoggedInError>;
79
+ };
80
+ readonly requires: typeof SomeElse;
81
+ }> & {
82
+ Default: import("effect/Layer").Layer<AllowAnonymous, never, never>;
83
+ };
84
+ export declare class AllowAnonymous extends AllowAnonymous_base {
85
+ }
86
+ declare const RequireRoles_base: Middleware.TagClass<RequireRoles, "RequireRoles", {
87
+ readonly dynamic: {
88
+ key: "requireRoles";
89
+ settings: RPCContextMap.Custom<never, typeof UnauthorizedError, string[]>;
90
+ };
91
+ readonly wrap: true;
92
+ readonly dependsOn: readonly [typeof AllowAnonymous];
93
+ }> & {
94
+ Default: import("effect/Layer").Layer<RequireRoles, never, Some>;
95
+ };
96
+ export declare class RequireRoles extends RequireRoles_base {
97
+ }
98
+ declare const Test_base: Middleware.TagClass<Test, "Test", {
99
+ readonly wrap: true;
100
+ readonly dynamic: {
101
+ key: "test";
102
+ settings: RPCContextMap<never, typeof S.Never>;
103
+ };
104
+ }> & {
105
+ Default: import("effect/Layer").Layer<Test, never, never>;
106
+ };
107
+ export declare class Test extends Test_base {
108
+ }
109
+ declare const CustomError1_base: S.TaggedErrorClass<NotLoggedInError, "CustomError1", {
110
+ readonly _tag: S.tag<"CustomError1">;
111
+ }>;
112
+ export declare class CustomError1 extends CustomError1_base {
113
+ }
114
+ declare const CustomError2_base: S.TaggedErrorClass<NotLoggedInError, "CustomError1", {
115
+ readonly _tag: S.tag<"CustomError1">;
116
+ }>;
117
+ export declare class CustomError2 extends CustomError2_base {
118
+ }
119
+ declare const SomeService_base: (abstract new (service: {
120
+ a: number;
121
+ }) => Readonly<{
122
+ a: number;
123
+ }> & Context.TagClassShape<"SomeService", {
124
+ a: number;
125
+ }>) & {
126
+ toLayer: {
127
+ (): import("effect/Layer").Layer<SomeService, never, never>;
128
+ <E_1, R_1>(eff: Effect.Effect<Omit<SomeService, keyof Context.TagClassShape<any, any>>, E_1, R_1>): import("effect/Layer").Layer<SomeService, E_1, R_1>;
129
+ };
130
+ toLayerScoped: {
131
+ (): import("effect/Layer").Layer<SomeService, never, never>;
132
+ <E_1, R_2>(eff: Effect.Effect<Context.TagClassShape<any, any>, E_1, R_2>): import("effect/Layer").Layer<SomeService, E_1, Exclude<R_2, Scope.Scope>>;
133
+ };
134
+ of: (service: Context.TagClassShape<any, any>) => SomeService;
135
+ make: Effect.Effect<SomeService, never, never>;
136
+ } & Context.Tag<SomeService, SomeService> & {
137
+ a: Effect.Effect<number, never, SomeService>;
138
+ } & {
139
+ use: <X>(body: (_: {
140
+ a: number;
141
+ }) => X) => X extends Effect.Effect<infer A, infer E_1, infer R_3> ? Effect.Effect<A, E_1, R_3 | SomeService> : Effect.Effect<X, never, SomeService>;
142
+ };
143
+ export declare class SomeService extends SomeService_base {
144
+ }
145
+ export {};
146
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +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,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"}
@@ -0,0 +1,82 @@
1
+ import { Context, Effect, Option, S, Scope } from "effect-app";
2
+ import { NotLoggedInError, UnauthorizedError } from "effect-app/client";
3
+ import { TaggedError } from "effect-app/Schema";
4
+ import { contextMap, Middleware } from "../src/api/routing.js";
5
+ export class UserProfile extends Context.assignTag("UserProfile")(S.Class("UserProfile")({
6
+ id: S.String,
7
+ roles: S.Array(S.String)
8
+ })) {
9
+ }
10
+ export class Some extends Context.TagMakeId("Some", Effect.succeed({ a: 1 }))() {
11
+ }
12
+ export class SomeElse extends Context.TagMakeId("SomeElse", Effect.succeed({ b: 2 }))() {
13
+ }
14
+ export class AllowAnonymous extends Middleware.Tag()("AllowAnonymous", {
15
+ dynamic: contextMap()("allowAnonymous", [UserProfile]),
16
+ requires: SomeElse
17
+ })({
18
+ effect: Effect.gen(function* () {
19
+ return Effect.fnUntraced(function* ({ config, headers }) {
20
+ yield* SomeElse;
21
+ yield* Scope.Scope; // provided by HttpRouter.HttpRouter.Provided
22
+ const isLoggedIn = !!headers["x-user"];
23
+ if (!isLoggedIn) {
24
+ if (!config.allowAnonymous) {
25
+ return yield* new NotLoggedInError({ message: "Not logged in" });
26
+ }
27
+ return Option.none();
28
+ }
29
+ return Option.some(Context.make(UserProfile, new UserProfile({
30
+ id: "whatever",
31
+ roles: ["user", ...headers["x-is-manager"] === "true" ? ["manager"] : []]
32
+ })));
33
+ });
34
+ })
35
+ }) {
36
+ }
37
+ // @effect-diagnostics-next-line missingEffectServiceDependency:off
38
+ export class RequireRoles extends Middleware.Tag()("RequireRoles", {
39
+ dynamic: contextMap()("requireRoles", null), // TODO
40
+ wrap: true,
41
+ // wrap: true,
42
+ // had to move this in here, because once you put it manually as a readonly static property on the class,
43
+ // there's a weird issue where the fluent api stops behaving properly after adding this middleware via `addDynamicMiddleware`
44
+ dependsOn: [AllowAnonymous]
45
+ })({
46
+ effect: Effect.gen(function* () {
47
+ yield* Some;
48
+ return Effect.fnUntraced(function* ({ config, next }) {
49
+ // we don't know if the service will be provided or not, so we use option..
50
+ const userProfile = yield* Effect.serviceOption(UserProfile);
51
+ const { requireRoles } = config;
52
+ console.dir({
53
+ userProfile,
54
+ requireRoles
55
+ }, { depth: 5 });
56
+ if (requireRoles && !userProfile.value?.roles?.some((role) => requireRoles.includes(role))) {
57
+ return yield* new UnauthorizedError({ message: "don't have the right roles" });
58
+ }
59
+ return yield* next;
60
+ });
61
+ })
62
+ }) {
63
+ }
64
+ export class Test extends Middleware.Tag()("Test", {
65
+ wrap: true,
66
+ dynamic: contextMap()("test", null) // TODO
67
+ })({
68
+ effect: Effect.gen(function* () {
69
+ return Effect.fn(function* ({ next }) {
70
+ return yield* next;
71
+ });
72
+ })
73
+ }) {
74
+ }
75
+ export class CustomError1 extends TaggedError()("CustomError1", {}) {
76
+ }
77
+ export class CustomError2 extends TaggedError()("CustomError1", {}) {
78
+ }
79
+ const MakeSomeService = Effect.succeed({ a: 1 });
80
+ export class SomeService extends Context.TagMakeId("SomeService", MakeSomeService)() {
81
+ }
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9maXh0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQXNCLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0YsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUE7QUFFOUQsTUFBTSxPQUFPLFdBQVksU0FBUSxPQUFPLENBQUMsU0FBUyxDQUEyQixhQUFhLENBQUMsQ0FDekYsQ0FBQyxDQUFDLEtBQUssQ0FBYyxhQUFhLENBQUMsQ0FBQztJQUNsQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0NBQ3pCLENBQUMsQ0FDSDtDQUNBO0FBRUQsTUFBTSxPQUFPLElBQUssU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBUTtDQUFHO0FBQ3hGLE1BQU0sT0FBTyxRQUFTLFNBQVEsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQVk7Q0FBRztBQVFwRyxNQUFNLE9BQU8sY0FBZSxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQWtCLENBQUMsZ0JBQWdCLEVBQUU7SUFDckYsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3pFLFFBQVEsRUFBRSxRQUFRO0NBQ25CLENBQUMsQ0FBQztJQUNELE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQ3RCLFFBQVEsQ0FBQyxFQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUMzQixLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUE7WUFDZixLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFBLENBQUMsNkNBQTZDO1lBQ2hFLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDdEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO29CQUMzQixPQUFPLEtBQUssQ0FBQyxDQUFDLElBQUksZ0JBQWdCLENBQUMsRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQTtnQkFDbEUsQ0FBQztnQkFDRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtZQUN0QixDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUNoQixPQUFPLENBQUMsSUFBSSxDQUNWLFdBQVcsRUFDWCxJQUFJLFdBQVcsQ0FBQztnQkFDZCxFQUFFLEVBQUUsVUFBVTtnQkFDZCxLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDMUUsQ0FBQyxDQUNILENBQ0YsQ0FBQTtRQUNILENBQUMsQ0FDRixDQUFBO0lBQ0gsQ0FBQyxDQUFDO0NBQ0gsQ0FBQztDQUNEO0FBRUQsbUVBQW1FO0FBQ25FLE1BQU0sT0FBTyxZQUFhLFNBQVEsVUFBVSxDQUFDLEdBQUcsRUFBZ0IsQ0FBQyxjQUFjLEVBQUU7SUFDL0UsT0FBTyxFQUFFLFVBQVUsRUFBcUIsQ0FBQyxjQUFjLEVBQUUsSUFBYSxDQUFDLEVBQUUsT0FBTztJQUNoRixJQUFJLEVBQUUsSUFBSTtJQUNWLGNBQWM7SUFDZCx5R0FBeUc7SUFDekcsNkhBQTZIO0lBQzdILFNBQVMsRUFBRSxDQUFDLGNBQWMsQ0FBQztDQUM1QixDQUFDLENBQUM7SUFDRCxNQUFNLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFDMUIsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFBO1FBQ1gsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUN0QixRQUFRLENBQUMsRUFBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7WUFDeEIsMkVBQTJFO1lBQzNFLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDNUQsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sQ0FBQTtZQUMvQixPQUFPLENBQUMsR0FBRyxDQUNUO2dCQUNFLFdBQVc7Z0JBQ1gsWUFBWTthQUNiLEVBQ0QsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQ2IsQ0FBQTtZQUNELElBQUksWUFBWSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDM0YsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLGlCQUFpQixDQUFDLEVBQUUsT0FBTyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQTtZQUNoRixDQUFDO1lBQ0QsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDcEIsQ0FBQyxDQUNGLENBQUE7SUFDSCxDQUFDLENBQUM7Q0FDSCxDQUFDO0NBQ0Q7QUFFRCxNQUFNLE9BQU8sSUFBSyxTQUFRLFVBQVUsQ0FBQyxHQUFHLEVBQVEsQ0FBQyxNQUFNLEVBQUU7SUFDdkQsSUFBSSxFQUFFLElBQUk7SUFDVixPQUFPLEVBQUUsVUFBVSxFQUFxQixDQUFDLE1BQU0sRUFBRSxJQUFhLENBQUMsQ0FBQyxPQUFPO0NBQ3hFLENBQUMsQ0FBQztJQUNELE1BQU0sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUMsRUFBRSxJQUFJLEVBQUU7WUFDakMsT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUE7UUFDcEIsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDLENBQUM7Q0FDSCxDQUFDO0NBQUc7QUFFTCxNQUFNLE9BQU8sWUFBYSxTQUFRLFdBQVcsRUFBb0IsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDO0NBQUc7QUFDeEYsTUFBTSxPQUFPLFlBQWEsU0FBUSxXQUFXLEVBQW9CLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztDQUFHO0FBRXhGLE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUNoRCxNQUFNLE9BQU8sV0FBWSxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUFlO0NBQUcifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerUtils.test.d.ts","sourceRoot":"","sources":["../layerUtils.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"query.test.d.ts","sourceRoot":"","sources":["../query.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAQ,KAAK,EAAgB,CAAC,EAAU,MAAM,YAAY,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYlF,qBAAa,SAAU,SAAQ,cAM7B;CAAG;AACL,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IAEjC,UAAiB,OAAQ,SAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,SAAS,CAAC;KAAG;CACvE;;;;;;;;;;;;;;;;;;;;;;;;;AAGD,qBAAa,WAAY,SAAQ,gBAAgE;CAAG"}
1
+ {"version":3,"file":"query.test.d.ts","sourceRoot":"","sources":["../query.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqC,CAAC,EAAU,MAAM,YAAY,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAazE,qBAAa,SAAU,SAAQ,cAM7B;CAAG;AACL,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IAEjC,UAAiB,OAAQ,SAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,SAAS,CAAC;KAAG;CACvE"}
@@ -0,0 +1,21 @@
1
+ import { type RPCContextMap } from "effect-app/client";
2
+ import { type DynamicMiddlewareMaker, type GenericMiddlewareMaker, type makeMiddlewareBasic, type RequestContextMapProvider } from "../src/api/routing.js";
3
+ export interface MiddlewareM<RequestContext extends Record<string, RPCContextMap.Any>, Provided extends keyof RequestContext, Middlewares extends ReadonlyArray<GenericMiddlewareMaker>, DynamicMiddlewareProviders, MiddlewareR = never> {
4
+ middleware: <MW extends GenericMiddlewareMaker>(mw: MW) => DynamicMiddlewareMakerrsss<RequestContext, Provided, [
5
+ ...Middlewares,
6
+ MW
7
+ ], DynamicMiddlewareProviders, GenericMiddlewareMaker.ApplyServices<MW, MiddlewareR>>;
8
+ }
9
+ export interface Dynamic<RequestContext extends Record<string, RPCContextMap.Any>, Provided extends keyof RequestContext, Middlewares extends ReadonlyArray<GenericMiddlewareMaker>, DynamicMiddlewareProviders, out MiddlewareR> extends MiddlewareM<RequestContext, Provided, Middlewares, DynamicMiddlewareProviders, MiddlewareR> {
10
+ middleware: <MW extends DynamicMiddlewareMaker<RequestContext> | GenericMiddlewareMaker>(mw: MW) => MW extends DynamicMiddlewareMaker<RequestContext> ? DynamicMiddlewareMakerrsss<RequestContext, Provided | MW["dynamic"]["key"], Middlewares, DynamicMiddlewareProviders & {
11
+ [K in MW["dynamic"]["key"]]: MW;
12
+ }, GenericMiddlewareMaker.ApplyServices<MW, MiddlewareR>> : DynamicMiddlewareMakerrsss<RequestContext, Provided, [
13
+ ...Middlewares,
14
+ MW
15
+ ], DynamicMiddlewareProviders, GenericMiddlewareMaker.ApplyServices<MW, MiddlewareR>>;
16
+ }
17
+ type GetDynamicMiddleware<T, RequestContext extends Record<string, RPCContextMap.Any>> = T extends RequestContextMapProvider<RequestContext> ? T : never;
18
+ type DynamicMiddlewareMakerrsss<RequestContext extends Record<string, RPCContextMap.Any>, Provided extends keyof RequestContext = never, Middlewares extends ReadonlyArray<GenericMiddlewareMaker> = [], DynamicMiddlewareProviders = unknown, MiddlewareR = never> = keyof Omit<RequestContext, Provided> extends never ? [MiddlewareR] extends [never] ? ReturnType<typeof makeMiddlewareBasic<RequestContext, GetDynamicMiddleware<DynamicMiddlewareProviders, RequestContext>, Middlewares>> & MiddlewareM<RequestContext, Provided, Middlewares, DynamicMiddlewareProviders, MiddlewareR> : MiddlewareM<RequestContext, Provided, Middlewares, DynamicMiddlewareProviders, MiddlewareR> : Dynamic<RequestContext, Provided, Middlewares, DynamicMiddlewareProviders, MiddlewareR>;
19
+ export declare const makeNewMiddleware: <RequestContextMap extends Record<string, RPCContextMap.Any>>() => DynamicMiddlewareMakerrsss<RequestContextMap>;
20
+ export {};
21
+ //# sourceMappingURL=requires.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requires.d.ts","sourceRoot":"","sources":["../requires.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Array, Either } from "effect-app";
2
+ import { makeMiddleware } from "../src/api/routing.js";
3
+ export const makeNewMiddleware = () => {
4
+ const make = makeMiddleware();
5
+ let capturedMiddlewares = [];
6
+ const it = {
7
+ middleware: (...middlewares) => {
8
+ for (const mw of middlewares) {
9
+ capturedMiddlewares = [mw, ...capturedMiddlewares];
10
+ if (mw.dynamic) {
11
+ console.log("Adding dynamic middleware", mw.key, mw.dynamic.key);
12
+ }
13
+ else {
14
+ console.log("Adding generic middleware", mw.key);
15
+ }
16
+ }
17
+ const [genericMiddlewares, dyn] = Array.partitionMap(capturedMiddlewares, (mw) => "dynamic" in mw && mw.dynamic
18
+ ? Either.right(mw)
19
+ : Either.left(mw));
20
+ const dynamicMiddlewares = dyn.reduce((prev, cur) => ({ ...prev, [cur.dynamic.key]: cur }), {});
21
+ // TODO: support dynamic and generic intertwined. treat them as one
22
+ return Object.assign(make({ genericMiddlewares, dynamicMiddlewares }), it);
23
+ }
24
+ };
25
+ return it;
26
+ };
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWlyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9yZXF1aXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUUxQyxPQUFPLEVBQTRELGNBQWMsRUFBNEQsTUFBTSx1QkFBdUIsQ0FBQTtBQWtIMUssTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBRXlCLEdBQUcsRUFBRTtJQUMxRCxNQUFNLElBQUksR0FBRyxjQUFjLEVBQU8sQ0FBQTtJQUNsQyxJQUFJLG1CQUFtQixHQUE2RCxFQUFFLENBQUE7SUFDdEYsTUFBTSxFQUFFLEdBQUc7UUFDVCxVQUFVLEVBQUUsQ0FBQyxHQUFHLFdBQWtCLEVBQUUsRUFBRTtZQUNwQyxLQUFLLE1BQU0sRUFBRSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUM3QixtQkFBbUIsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLG1CQUFtQixDQUFDLENBQUE7Z0JBQ2xELElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNsRSxDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ2xELENBQUM7WUFDSCxDQUFDO1lBQ0QsTUFBTSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQ2xELG1CQUFtQixFQUNuQixDQUFDLEVBQUUsRUFBRSxFQUFFLENBQ0wsU0FBUyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsT0FBTztnQkFDM0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBaUMsQ0FBQztnQkFDakQsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBNEIsQ0FBQyxDQUNoRCxDQUFBO1lBQ0QsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUNuQyxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFDcEQsRUFBeUIsQ0FDMUIsQ0FBQTtZQUNELG1FQUFtRTtZQUNuRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBQzVFLENBQUM7S0FDRixDQUFBO0lBQ0QsT0FBTyxFQUFTLENBQUE7QUFDbEIsQ0FBQyxDQUFBIn0=
@@ -0,0 +1 @@
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"}