@effect-app/infra 2.73.4 → 2.75.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 (54) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/QueueMaker/errors.d.ts +1 -1
  3. package/dist/QueueMaker/errors.d.ts.map +1 -1
  4. package/dist/api/layerUtils.d.ts +22 -0
  5. package/dist/api/layerUtils.d.ts.map +1 -0
  6. package/dist/api/layerUtils.js +2 -0
  7. package/dist/api/routing/middleware/ContextProvider.d.ts +41 -0
  8. package/dist/api/routing/middleware/ContextProvider.d.ts.map +1 -0
  9. package/dist/api/routing/middleware/ContextProvider.js +27 -0
  10. package/dist/api/routing/middleware/DynamicMiddleware.d.ts +61 -0
  11. package/dist/api/routing/middleware/DynamicMiddleware.d.ts.map +1 -0
  12. package/dist/api/routing/middleware/DynamicMiddleware.js +45 -0
  13. package/dist/api/routing/middleware/dynamic-middleware.d.ts +26 -0
  14. package/dist/api/routing/middleware/dynamic-middleware.d.ts.map +1 -0
  15. package/dist/api/routing/middleware/dynamic-middleware.js +39 -0
  16. package/dist/api/routing/middleware/generic-middleware.d.ts +9 -0
  17. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -0
  18. package/dist/api/routing/middleware/generic-middleware.js +20 -0
  19. package/dist/api/routing/middleware/middleware.d.ts +23 -0
  20. package/dist/api/routing/middleware/middleware.d.ts.map +1 -0
  21. package/dist/api/routing/middleware/middleware.js +91 -0
  22. package/dist/api/routing/middleware.d.ts +6 -0
  23. package/dist/api/routing/middleware.d.ts.map +1 -0
  24. package/dist/api/routing/middleware.js +8 -0
  25. package/dist/api/routing/tsort.d.ts +8 -0
  26. package/dist/api/routing/tsort.d.ts.map +1 -0
  27. package/dist/api/routing/tsort.js +51 -0
  28. package/dist/api/routing.d.ts +36 -46
  29. package/dist/api/routing.d.ts.map +1 -1
  30. package/dist/api/routing.js +7 -56
  31. package/package.json +33 -5
  32. package/src/api/layerUtils.ts +34 -0
  33. package/src/api/routing/middleware/ContextProvider.ts +148 -0
  34. package/src/api/routing/middleware/DynamicMiddleware.ts +317 -0
  35. package/src/api/routing/middleware/dynamic-middleware.ts +158 -0
  36. package/src/api/routing/middleware/generic-middleware.ts +38 -0
  37. package/src/api/routing/middleware/middleware.ts +120 -0
  38. package/src/api/routing/middleware.ts +7 -0
  39. package/src/api/routing/tsort.ts +56 -0
  40. package/src/api/routing.ts +47 -118
  41. package/test/controller.test.ts +212 -51
  42. package/test/dist/controller.legacy2.test.d.ts.map +1 -0
  43. package/test/dist/controller.legacy3.test.d.ts.map +1 -0
  44. package/test/dist/controller.test copy.d.ts +169 -0
  45. package/test/dist/controller.test copy.d.ts.map +1 -0
  46. package/test/dist/controller.test copy.js +152 -0
  47. package/test/dist/controller.test.d.ts.map +1 -1
  48. package/test/dist/controller6.test.d.ts.map +1 -0
  49. package/test/dist/controller7.test.d.ts.map +1 -0
  50. package/test/dist/filterApi.test.d.ts.map +1 -0
  51. package/dist/api/routing/DynamicMiddleware.d.ts +0 -91
  52. package/dist/api/routing/DynamicMiddleware.d.ts.map +0 -1
  53. package/dist/api/routing/DynamicMiddleware.js +0 -56
  54. package/src/api/routing/DynamicMiddleware.ts +0 -415
@@ -1,415 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
- /* eslint-disable @typescript-eslint/no-unsafe-return */
3
- /* eslint-disable @typescript-eslint/no-explicit-any */
4
- import { type Array, Context, Effect, Layer, type NonEmptyArray, pipe, type Request, type S } from "effect-app"
5
- import type { GetEffectContext, RPCContextMap } from "effect-app/client/req"
6
- import { type HttpRouter } from "effect-app/http"
7
- import type * as EffectRequest from "effect/Request"
8
- import { type LayersUtils } from "../routing.js"
9
-
10
- // utils:
11
- //
12
- type GetContext<T> = T extends Context.Context<infer Y> ? Y : never
13
-
14
- // module:
15
- //
16
- export type MakeRPCHandlerFactory<
17
- RequestContextMap extends Record<string, RPCContextMap.Any>,
18
- MiddlewareR
19
- > = <
20
- T extends {
21
- config?: Partial<Record<keyof RequestContextMap, any>>
22
- },
23
- Req extends S.TaggedRequest.All,
24
- HandlerR
25
- >(
26
- schema: T & S.Schema<Req, any, never>,
27
- handler: (
28
- request: Req,
29
- headers: any
30
- ) => Effect.Effect<
31
- EffectRequest.Request.Success<Req>,
32
- EffectRequest.Request.Error<Req>,
33
- HandlerR
34
- >,
35
- moduleName?: string
36
- ) => (
37
- req: Req,
38
- headers: any
39
- ) => Effect.Effect<
40
- Request.Request.Success<Req>,
41
- Request.Request.Error<Req> | RequestContextMapErrors<RequestContextMap>,
42
- // the middleware will remove from HandlerR the dynamic context, but will also add some requirements
43
- | MiddlewareR
44
- // & S.Schema<Req, any, never> is useless here but useful when creating the middleware
45
- | Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>
46
- >
47
-
48
- export type RPCHandlerFactory<
49
- RequestContextMap extends Record<string, RPCContextMap.Any>,
50
- ContextProviderA
51
- > = <
52
- T extends {
53
- config?: Partial<Record<keyof RequestContextMap, any>>
54
- },
55
- Req extends S.TaggedRequest.All,
56
- HandlerR
57
- >(
58
- schema: T & S.Schema<Req, any, never>,
59
- handler: (
60
- request: Req,
61
- headers: any
62
- ) => Effect.Effect<
63
- EffectRequest.Request.Success<Req>,
64
- EffectRequest.Request.Error<Req>,
65
- HandlerR
66
- >,
67
- moduleName?: string
68
- ) => (
69
- req: Req,
70
- headers: any
71
- ) => Effect.Effect<
72
- Request.Request.Success<Req>,
73
- Request.Request.Error<Req> | RequestContextMapErrors<RequestContextMap>,
74
- | HttpRouter.HttpRouter.Provided // because of the context provider and the middleware (Middleware)
75
- | Exclude<
76
- // the middleware will remove from HandlerR the dynamic context
77
- // & S.Schema<Req, any, never> is useless here but useful when creating the middleware
78
- Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>,
79
- // the context provider provides additional stuff both to the middleware and the handler
80
- ContextProviderA
81
- >
82
- >
83
-
84
- // the context provider provides additional stuff
85
- export type ContextProviderShape<ContextProviderA, ContextProviderR extends HttpRouter.HttpRouter.Provided> = Effect<
86
- Context.Context<ContextProviderA>,
87
- never, // no errors are allowed
88
- ContextProviderR
89
- >
90
-
91
- export interface ContextProviderId {
92
- _tag: "ContextProvider"
93
- }
94
-
95
- export interface MiddlewareMake<
96
- RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middleware provide dynamically to the handler, or raise errors.
97
- MakeMiddlewareE, // what the middleware construction can fail with
98
- MakeMiddlewareR, // what the middleware requires to be constructed
99
- MiddlewareDependencies extends NonEmptyArray<Layer.Layer.Any>, // layers provided for the middleware to be constructed
100
- //
101
- // ContextProvider is a service that builds additional context for each request.
102
- ContextProviderA, // what the context provider provides
103
- ContextProviderR extends HttpRouter.HttpRouter.Provided, // what the context provider requires
104
- MakeContextProviderE, // what the context provider construction can fail with
105
- MakeContextProviderR // what the context provider construction requires
106
- > {
107
- dependencies?: MiddlewareDependencies
108
- contextProvider:
109
- & Context.Tag<
110
- ContextProviderId,
111
- ContextProviderShape<ContextProviderA, ContextProviderR>
112
- >
113
- & {
114
- Default: Layer.Layer<ContextProviderId, MakeContextProviderE, MakeContextProviderR>
115
- }
116
- // this actually builds "the middleware", i.e. returns the augmented handler factory when yielded...
117
- execute: (
118
- maker: (
119
- // MiddlewareR is set to ContextProviderA | HttpRouter.HttpRouter.Provided because that's what, at most
120
- // a middleware can additionally require to get executed
121
- cb: MakeRPCHandlerFactory<RequestContextMap, ContextProviderA | HttpRouter.HttpRouter.Provided>
122
- ) => MakeRPCHandlerFactory<RequestContextMap, ContextProviderA | HttpRouter.HttpRouter.Provided>
123
- ) => Effect<
124
- MakeRPCHandlerFactory<RequestContextMap, ContextProviderA | HttpRouter.HttpRouter.Provided>,
125
- MakeMiddlewareE,
126
- MakeMiddlewareR // ...that's why MakeMiddlewareR is here
127
- >
128
- }
129
-
130
- // Note: the type here must be aligned with MergedContextProvider
131
- export const mergeContextProviders = <
132
- // TDeps is an array of services whit Default implementation
133
- // each service is an effect which builds some context for each request
134
- TDeps extends Array.NonEmptyReadonlyArray<
135
- & (
136
- // E = never => the context provided cannot trigger errors
137
- // can't put HttpRouter.HttpRouter.Provided as R here because of variance
138
- // (TDeps is an input type parameter so it's contravariant therefore Effect's R becomes contravariant too)
139
- | Context.Tag<any, Effect<Context.Context<any>, never, any> & { _tag: any }>
140
- | Context.Tag<any, Effect<Context.Context<any>, never, never> & { _tag: any }>
141
- )
142
- & {
143
- new(...args: any[]): any
144
- Default: Layer.Layer<Effect<Context.Context<any>> & { _tag: any }, any, any>
145
- }
146
- >
147
- >(
148
- ...deps: {
149
- [K in keyof TDeps]: TDeps[K]["Service"] extends Effect<Context.Context<any>, never, HttpRouter.HttpRouter.Provided>
150
- ? TDeps[K]
151
- : `HttpRouter.HttpRouter.Provided are the only requirements ${TDeps[K]["Service"][
152
- "_tag"
153
- ]}'s returned effect can have`
154
- }
155
- ): {
156
- dependencies: { [K in keyof TDeps]: TDeps[K]["Default"] }
157
- effect: Effect.Effect<
158
- Effect.Effect<
159
- Context.Context<GetContext<Effect.Success<InstanceType<TDeps[number]>>>>,
160
- never,
161
- Effect.Context<InstanceType<TDeps[number]>>
162
- >,
163
- LayersUtils.GetLayersError<{ [K in keyof TDeps]: TDeps[K]["Default"] }>,
164
- InstanceType<TDeps[number]>
165
- >
166
- } => ({
167
- dependencies: deps.map((_) => _.Default) as any,
168
- effect: Effect.gen(function*() {
169
- const services = yield* Effect.all(deps)
170
- // services are effects which return some Context.Context<...>
171
- // @effect-diagnostics effect/returnEffectInGen:off
172
- return Effect.all(services as any[]).pipe(
173
- Effect.map((_) => Context.mergeAll(..._ as any))
174
- )
175
- }) as any
176
- })
177
-
178
- export interface MiddlewareMakerId {
179
- _tag: "MiddlewareMaker"
180
- }
181
-
182
- export const ContextProvider = <
183
- ContextProviderA,
184
- MakeContextProviderE,
185
- MakeContextProviderR,
186
- ContextProviderR extends HttpRouter.HttpRouter.Provided,
187
- Dependencies extends NonEmptyArray<Layer.Layer.Any>
188
- >(
189
- input: {
190
- effect: Effect<Effect<ContextProviderA, never, ContextProviderR>, MakeContextProviderE, MakeContextProviderR>
191
- dependencies?: Dependencies
192
- }
193
- ) => {
194
- const ctx = Context.GenericTag<
195
- ContextProviderId,
196
- Effect<ContextProviderA, never, ContextProviderR>
197
- >(
198
- "ContextProvider"
199
- )
200
- const l = Layer.effect(ctx, input.effect)
201
- return Object.assign(ctx, {
202
- Default: l.pipe(
203
- input.dependencies ? Layer.provide(input.dependencies) as any : (_) => _
204
- ) as Layer.Layer<
205
- ContextProviderId,
206
- | MakeContextProviderE
207
- | LayersUtils.GetLayersError<Dependencies>,
208
- | Exclude<MakeContextProviderR, LayersUtils.GetLayersSuccess<Dependencies>>
209
- | LayersUtils.GetLayersContext<Dependencies>
210
- >
211
- })
212
- }
213
-
214
- // Note: the type here must be aligned with mergeContextProviders
215
- export const MergedContextProvider = <
216
- // TDeps is an array of services whit Default implementation
217
- // each service is an effect which builds some context for each request
218
- TDeps extends Array.NonEmptyReadonlyArray<
219
- & (
220
- // E = never => the context provided cannot trigger errors
221
- // can't put HttpRouter.HttpRouter.Provided as R here because of variance
222
- // (TDeps is an input type parameter so it's contravariant therefore Effect's R becomes contravariant too)
223
- | Context.Tag<any, Effect<Context.Context<any>, never, any> & { _tag: any }>
224
- | Context.Tag<any, Effect<Context.Context<any>, never, never> & { _tag: any }>
225
- )
226
- & {
227
- new(...args: any[]): any
228
- Default: Layer.Layer<Effect<Context.Context<any>> & { _tag: any }, any, any>
229
- }
230
- >
231
- >(
232
- ...deps: {
233
- [K in keyof TDeps]: TDeps[K]["Service"] extends Effect<Context.Context<any>, never, HttpRouter.HttpRouter.Provided>
234
- ? TDeps[K]
235
- : `HttpRouter.HttpRouter.Provided are the only requirements ${TDeps[K]["Service"][
236
- "_tag"
237
- ]}'s returned effect can have`
238
- }
239
- ) =>
240
- pipe(
241
- deps as [Parameters<typeof mergeContextProviders>[0]],
242
- (_) => mergeContextProviders(..._),
243
- (_) => ContextProvider(_ as any)
244
- ) as unknown as
245
- & Context.Tag<
246
- ContextProviderId,
247
- Effect.Effect<
248
- Context.Context<GetContext<Effect.Success<InstanceType<TDeps[number]>>>>,
249
- never,
250
- Effect.Context<InstanceType<TDeps[number]>>
251
- >
252
- >
253
- & {
254
- Default: Layer.Layer<
255
- ContextProviderId,
256
- LayersUtils.GetLayersError<{ [K in keyof TDeps]: TDeps[K]["Default"] }>,
257
- | Exclude<
258
- InstanceType<TDeps[number]>,
259
- LayersUtils.GetLayersSuccess<{ [K in keyof TDeps]: TDeps[K]["Default"] }>
260
- >
261
- | LayersUtils.GetLayersContext<{ [K in keyof TDeps]: TDeps[K]["Default"] }>
262
- >
263
- }
264
-
265
- export const EmptyContextProvider = ContextProvider({ effect: Effect.succeed(Effect.succeed(Context.empty())) })
266
-
267
- export type Middleware<
268
- RequestContextMap extends Record<string, RPCContextMap.Any>, // what services will the middlware provide dynamically to the handler, or raise errors.
269
- MakeMiddlewareE, // what the middleware construction can fail with
270
- MakeMiddlewareR, // what the middlware requires to be constructed
271
- ContextProviderA // what the context provider provides
272
- > =
273
- & Context.Tag<
274
- MiddlewareMakerId,
275
- MiddlewareMakerId & {
276
- effect: RPCHandlerFactory<RequestContextMap, ContextProviderA>
277
- }
278
- >
279
- & {
280
- Default: Layer.Layer<
281
- MiddlewareMakerId,
282
- MakeMiddlewareE,
283
- MakeMiddlewareR
284
- >
285
- }
286
-
287
- export type RequestContextMapErrors<RequestContextMap extends Record<string, RPCContextMap.Any>> = S.Schema.Type<
288
- RequestContextMap[keyof RequestContextMap]["error"]
289
- >
290
-
291
- // factory for middlewares
292
- export const makeMiddleware =
293
- // by setting RequestContextMap beforehand, execute contextual typing does not fuck up itself to anys
294
- <
295
- RequestContextMap extends Record<string, RPCContextMap.Any>
296
- >() =>
297
- <
298
- MakeMiddlewareE, // what the middleware construction can fail with
299
- MakeMiddlewareR, // what the middlware requires to be constructed
300
- MiddlewareDependencies extends NonEmptyArray<Layer.Layer.Any>, // layers provided for the middlware to be constructed
301
- //
302
- // ContextProvider is a service that builds additional context for each request.
303
- ContextProviderA, // what the context provider provides
304
- ContextProviderR extends HttpRouter.HttpRouter.Provided, // what the context provider requires
305
- MakeContextProviderE, // what the context provider construction can fail with
306
- MakeContextProviderR // what the context provider construction requires
307
- >(
308
- make: MiddlewareMake<
309
- RequestContextMap,
310
- MakeMiddlewareE,
311
- MakeMiddlewareR,
312
- MiddlewareDependencies,
313
- ContextProviderA,
314
- ContextProviderR,
315
- MakeContextProviderE,
316
- MakeContextProviderR
317
- >
318
- ) => {
319
- // type Id = MiddlewareMakerId &
320
- const MiddlewareMaker = Context.GenericTag<
321
- MiddlewareMakerId,
322
- {
323
- effect: RPCHandlerFactory<RequestContextMap, ContextProviderA>
324
- _tag: "MiddlewareMaker"
325
- }
326
- >(
327
- "MiddlewareMaker"
328
- )
329
-
330
- const l = Layer.effect(
331
- MiddlewareMaker,
332
- Effect
333
- .all({
334
- middleware: make.execute((
335
- cb: MakeRPCHandlerFactory<RequestContextMap, HttpRouter.HttpRouter.Provided | ContextProviderA>
336
- ) => cb),
337
- contextProvider: make.contextProvider // uses the middleware.contextProvider tag to get the context provider service
338
- })
339
- .pipe(
340
- Effect.map(({ contextProvider, middleware }) => ({
341
- _tag: "MiddlewareMaker" as const,
342
- effect: makeRpcEffect<RequestContextMap, ContextProviderA>()(
343
- (schema, handler, moduleName) => {
344
- const h = middleware(schema, handler, moduleName)
345
- return (req, headers) =>
346
- // the contextProvider is an Effect that builds the context for the request
347
- contextProvider.pipe(
348
- Effect.flatMap((ctx) =>
349
- h(req, headers)
350
- .pipe(
351
- Effect.provide(ctx),
352
- // TODO: make this depend on query/command, and consider if middleware also should be affected or not.
353
- Effect.uninterruptible
354
- )
355
- )
356
- )
357
- }
358
- )
359
- }))
360
- )
361
- )
362
- const middlewareLayer = l
363
- .pipe(
364
- make.dependencies ? Layer.provide(make.dependencies) as any : (_) => _,
365
- Layer.provide(make.contextProvider.Default)
366
- ) as Layer.Layer<
367
- MiddlewareMakerId,
368
- | MakeMiddlewareE // what the middleware construction can fail with
369
- | Layer.Error<typeof make.contextProvider.Default>, // what could go wrong when building the context provider
370
- | LayersUtils.GetLayersContext<MiddlewareDependencies> // what's needed to build layers
371
- | Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>> // what layers provides
372
- | Layer.Context<typeof make.contextProvider.Default> // what's needed to build the contextProvider
373
- >
374
-
375
- return Object.assign(MiddlewareMaker, { Default: middlewareLayer })
376
- }
377
-
378
- // it just provides the right types without cluttering the implementation with them
379
- function makeRpcEffect<
380
- RequestContextMap extends Record<string, RPCContextMap.Any>,
381
- ContextProviderA
382
- >() {
383
- return (
384
- cb: <
385
- T extends {
386
- config?: Partial<Record<keyof RequestContextMap, any>>
387
- },
388
- Req extends S.TaggedRequest.All,
389
- HandlerR
390
- >(
391
- schema: T & S.Schema<Req, any, never>,
392
- handler: (
393
- request: Req,
394
- headers: any
395
- ) => Effect.Effect<
396
- EffectRequest.Request.Success<Req>,
397
- EffectRequest.Request.Error<Req>,
398
- HandlerR
399
- >,
400
- moduleName?: string
401
- ) => (
402
- req: Req,
403
- headers: any
404
- ) => Effect.Effect<
405
- Request.Request.Success<Req>,
406
- Request.Request.Error<Req> | RequestContextMapErrors<RequestContextMap>,
407
- | HttpRouter.HttpRouter.Provided // the context provider may require HttpRouter.Provided to run
408
- | Exclude<
409
- // it can also be removed from HandlerR
410
- Exclude<HandlerR, GetEffectContext<RequestContextMap, (T & S.Schema<Req, any, never>)["config"]>>,
411
- ContextProviderA
412
- >
413
- >
414
- ) => cb
415
- }