@effect-app/infra 2.35.3 → 2.36.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.
@@ -1,802 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
- /* eslint-disable @typescript-eslint/no-empty-object-type */
4
- /* eslint-disable @typescript-eslint/no-explicit-any */
5
- /*
6
- TODO: Effect.retry(r2, optimisticConcurrencySchedule) / was for PATCH only
7
- TODO: uninteruptible commands! was for All except GET.
8
- */
9
- import type * as HttpApp from "@effect/platform/HttpApp"
10
- import { Rpc, RpcRouter } from "@effect/rpc"
11
- import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
12
- import { Array, Cause, Chunk, Context, Effect, FiberRef, flow, Layer, Predicate, S, Schema, Stream } from "effect-app"
13
- import type { GetEffectContext, RPCContextMap } from "effect-app/client/req"
14
- import type { HttpServerError } from "effect-app/http"
15
- import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect-app/http"
16
- import { pretty, typedKeysOf, typedValuesOf } from "effect-app/utils"
17
- import type { Contravariant } from "effect/Types"
18
- import { logError, reportError } from "../errorReporter.js"
19
- import { InfraLogger } from "../logger.js"
20
- import type { Middleware } from "./routing/DynamicMiddleware.js"
21
- import { makeRpc } from "./routing/DynamicMiddleware.js"
22
-
23
- const logRequestError = logError("Request")
24
- const reportRequestError = reportError("Request")
25
-
26
- export type _R<T extends Effect<any, any, any>> = [T] extends [
27
- Effect<any, any, infer R>
28
- ] ? R
29
- : never
30
-
31
- export type _E<T extends Effect<any, any, any>> = [T] extends [
32
- Effect<any, infer E, any>
33
- ] ? E
34
- : never
35
-
36
- export type EffectDeps<A> = {
37
- [K in keyof A as A[K] extends Effect<any, any, any> ? K : never]: A[K] extends Effect<any, any, any> ? A[K] : never
38
- }
39
- /**
40
- * Plain jane JSON version
41
- * @deprecated use HttpRpcRouterNoStream.toHttpApp once support options
42
- */
43
- export const toHttpApp = <R extends RpcRouter.RpcRouter<any, any>>(self: R, options?: {
44
- readonly spanPrefix?: string
45
- }): HttpApp.Default<
46
- HttpServerError.RequestError,
47
- RpcRouter.RpcRouter.Context<R>
48
- > => {
49
- const handler = RpcRouter.toHandler(self, options)
50
- return Effect.withFiberRuntime((fiber) => {
51
- const context = fiber.getFiberRef(FiberRef.currentContext)
52
- const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest)
53
- return Effect.flatMap(
54
- request.json,
55
- (_) =>
56
- handler(_).pipe(
57
- Stream.provideContext(context),
58
- Stream.runCollect,
59
- Effect.map((_) => Chunk.toReadonlyArray(_)),
60
- Effect.andThen((_) => {
61
- let status = 200
62
- for (const r of _.flat()) {
63
- if (typeof r === "number") continue
64
- const results = Array.isArray(r) ? r : [r]
65
- if (results.some((_: S.ExitEncoded<any, any, any>) => _._tag === "Failure" && _.cause._tag === "Die")) {
66
- status = 500
67
- break
68
- }
69
- if (results.some((_: S.ExitEncoded<any, any, any>) => _._tag === "Failure" && _.cause._tag === "Fail")) {
70
- status = 422 // 418
71
- break
72
- }
73
- }
74
- return HttpServerResponse.json(_, { status })
75
- }),
76
- Effect.orDie,
77
- Effect.tapDefect(reportError("RPCHttpApp"))
78
- )
79
- )
80
- })
81
- }
82
-
83
- export interface Hint<Err extends string> {
84
- Err: Err
85
- }
86
-
87
- type HandleVoid<Expected, Actual, Result> = [Expected] extends [void]
88
- ? [Actual] extends [void] ? Result : Hint<"You're returning non void for a void Response, please fix">
89
- : Result
90
-
91
- type AnyRequestModule = S.Schema.Any & { _tag: string; success?: S.Schema.Any; failure?: S.Schema.Any }
92
- export interface AddAction<Actions extends AnyRequestModule, Accum extends Record<string, any> = {}> {
93
- accum: Accum
94
- add<A extends Handler<Actions, any, any>>(
95
- a: A
96
- ): Exclude<Actions, A extends Handler<infer M, any, any> ? M : never> extends never ?
97
- & Accum
98
- & { [K in A extends Handler<infer M, any, any> ? M extends AnyRequestModule ? M["_tag"] : never : never]: A }
99
- :
100
- & AddAction<
101
- Exclude<Actions, A extends Handler<infer M, any, any> ? M : never>,
102
- & Accum
103
- & { [K in A extends Handler<infer M, any, any> ? M extends AnyRequestModule ? M["_tag"] : never : never]: A }
104
- >
105
- & Accum
106
- & { [K in A extends Handler<infer M, any, any> ? M extends AnyRequestModule ? M["_tag"] : never : never]: A }
107
- }
108
-
109
- type GetSuccess<T> = T extends { success: S.Schema.Any } ? T["success"] : typeof S.Void
110
-
111
- type GetSuccessShape<Action extends { success?: S.Schema.Any }, RT extends "d" | "raw"> = RT extends "raw"
112
- ? S.Schema.Encoded<GetSuccess<Action>>
113
- : S.Schema.Type<GetSuccess<Action>>
114
- type GetFailure<T extends { failure?: S.Schema.Any }> = T["failure"] extends never ? typeof S.Never : T["failure"]
115
-
116
- type HandlerFull<Action extends AnyRequestModule, RT extends "raw" | "d", A, E, R> = {
117
- new(): {}
118
- _tag: RT
119
- stack: string
120
- handler: (
121
- req: S.Schema.Type<Action>
122
- ) => Effect<
123
- A,
124
- E,
125
- R
126
- >
127
- }
128
-
129
- export interface Handler<Action extends AnyRequestModule, RT extends "raw" | "d", R> extends
130
- HandlerFull<
131
- Action,
132
- RT,
133
- GetSuccessShape<Action, RT>,
134
- S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
135
- R
136
- >
137
- {
138
- }
139
-
140
- type AHandler<Action extends AnyRequestModule> = Handler<
141
- Action,
142
- any,
143
- any
144
- >
145
-
146
- type Filter<T> = {
147
- [K in keyof T as T[K] extends AnyRequestModule ? K : never]: T[K]
148
- }
149
-
150
- export const RouterSymbol = Symbol()
151
- export interface RouterShape<Rsc> {
152
- [RouterSymbol]: Rsc
153
- }
154
-
155
- type RPCRouteR<T extends Rpc.Rpc<any, any>> = [T] extends [
156
- Rpc.Rpc<any, infer R>
157
- ] ? R
158
- : never
159
-
160
- type RPCRouteReq<T extends Rpc.Rpc<any, any>> = [T] extends [
161
- Rpc.Rpc<infer Req, any>
162
- ] ? Req
163
- : never
164
-
165
- type Match<
166
- Rsc extends Record<string, any>,
167
- CTXMap extends Record<string, any>,
168
- RT extends "raw" | "d",
169
- Key extends keyof Rsc,
170
- Context
171
- > = {
172
- // TODO: deal with HandleVoid and ability to extends from GetSuccessShape...
173
- // aka we want to make sure that the return type is void if the success is void,
174
- // and make sure A is the actual expected type
175
-
176
- // note: the defaults of = never prevent the whole router to error
177
- <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(
178
- f: Effect<A, E, R2>
179
- ): HandleVoid<
180
- GetSuccessShape<Rsc[Key], RT>,
181
- A,
182
- Handler<
183
- Rsc[Key],
184
- RT,
185
- Exclude<
186
- Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
187
- HttpRouter.HttpRouter.Provided
188
- >
189
- >
190
- >
191
-
192
- <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(
193
- f: (req: S.Schema.Type<Rsc[Key]>) => Effect<A, E, R2>
194
- ): HandleVoid<
195
- GetSuccessShape<Rsc[Key], RT>,
196
- A,
197
- Handler<
198
- Rsc[Key],
199
- RT,
200
- Exclude<
201
- Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
202
- HttpRouter.HttpRouter.Provided
203
- >
204
- >
205
- >
206
- }
207
-
208
- export type RouteMatcher<
209
- CTXMap extends Record<string, any>,
210
- Rsc extends Record<string, any>,
211
- Context
212
- > = {
213
- // use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
214
- /**
215
- * Requires the Type shape
216
- */
217
- [Key in keyof Filter<Rsc>]: Match<Rsc, CTXMap, "d", Key, Context> & {
218
- success: Rsc[Key]["success"]
219
- successRaw: S.SchemaClass<S.Schema.Encoded<Rsc[Key]["success"]>>
220
- failure: Rsc[Key]["failure"]
221
- /**
222
- * Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
223
- */
224
- raw: Match<Rsc, CTXMap, "raw", Key, Context>
225
- }
226
- }
227
- // export interface RouteMatcher<
228
- // Filtered extends Record<string, any>,
229
- // CTXMap extends Record<string, any>,
230
- // Rsc extends Filtered
231
- // > extends RouteMatcherInt<Filtered, CTXMap, Rsc> {}
232
-
233
- export const makeMiddleware = <
234
- Context,
235
- CTXMap extends Record<string, RPCContextMap.Any>,
236
- RMW,
237
- Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
238
- >(content: Middleware<Context, CTXMap, RMW, Layers>): Middleware<Context, CTXMap, RMW, Layers> => content
239
-
240
- export const makeRouter = <
241
- Context,
242
- CTXMap extends Record<string, RPCContextMap.Any>,
243
- RMW,
244
- Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
245
- >(
246
- middleware: Middleware<Context, CTXMap, RMW, Layers>,
247
- devMode: boolean
248
- ) => {
249
- function matchFor<
250
- const ModuleName extends string,
251
- const Rsc extends Record<string, any>
252
- >(
253
- rsc: Rsc & { meta: { moduleName: ModuleName } }
254
- ) {
255
- const meta = rsc.meta
256
- type Filtered = Filter<Rsc>
257
- const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
258
- if (Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
259
- acc[cur as keyof Filtered] = rsc[cur]
260
- }
261
- return acc
262
- }, {} as Filtered)
263
-
264
- const items = typedKeysOf(filtered).reduce(
265
- (prev, cur) => {
266
- ;(prev as any)[cur] = Object.assign((fnOrEffect: any) => {
267
- const stack = new Error().stack?.split("\n").slice(2).join("\n")
268
- return Effect.isEffect(fnOrEffect)
269
- ? class {
270
- static request = rsc[cur]
271
- static stack = stack
272
- static _tag = "d"
273
- static handler = () => fnOrEffect
274
- }
275
- : class {
276
- static request = rsc[cur]
277
- static stack = stack
278
- static _tag = "d"
279
- static handler = fnOrEffect
280
- }
281
- }, {
282
- success: rsc[cur].success,
283
- successRaw: S.encodedSchema(rsc[cur].success),
284
- failure: rsc[cur].failure,
285
- raw: // "Raw" variations are for when you don't want to decode just to encode it again on the response
286
- // e.g for direct projection from DB
287
- // but more importantly, to skip Effectful decoders, like to resolve relationships from the database or remote client.
288
- (fnOrEffect: any) => {
289
- const stack = new Error().stack?.split("\n").slice(2).join("\n")
290
- return Effect.isEffect(fnOrEffect)
291
- ? class {
292
- static request = rsc[cur]
293
- static stack = stack
294
- static _tag = "raw"
295
- static handler = () => fnOrEffect
296
- }
297
- : class {
298
- static request = rsc[cur]
299
- static stack = stack
300
- static _tag = "raw"
301
- static handler = (req: any, ctx: any) => fnOrEffect(req, { ...ctx, Response: rsc[cur].success })
302
- }
303
- }
304
- })
305
- return prev
306
- },
307
- {} as RouteMatcher<CTXMap, Rsc, Context>
308
- )
309
-
310
- type Keys = keyof Filtered
311
-
312
- type GetSuccess<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
313
- NonEmptyReadonlyArray<Layer.Layer.Any> ? {
314
- [k in keyof Layers]: Layer.Layer.Success<Layers[k]>
315
- }[number]
316
- : never
317
-
318
- type GetContext<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
319
- NonEmptyReadonlyArray<Layer.Layer.Any> ? {
320
- [k in keyof Layers]: Layer.Layer.Context<Layers[k]>
321
- }[number]
322
- : never
323
-
324
- type GetError<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends NonEmptyReadonlyArray<Layer.Layer.Any>
325
- ? { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number]
326
- : never
327
-
328
- const f = <
329
- E,
330
- R,
331
- THandlers extends {
332
- // import to keep them separate via | for type checking!!
333
- [K in Keys]: AHandler<Rsc[K]>
334
- },
335
- TLayers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
336
- >(
337
- layers: TLayers,
338
- make: Effect<THandlers, E, R>
339
- ) => {
340
- type ProvidedLayers =
341
- | { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
342
- | { [k in keyof TLayers]: Layer.Layer.Success<TLayers[k]> }[number]
343
- type Router = RouterShape<Rsc>
344
- const r: HttpRouter.HttpRouter.TagClass<
345
- Router,
346
- `${typeof meta.moduleName}Router`,
347
- never,
348
- Exclude<
349
- | Context
350
- | RPCRouteR<
351
- { [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Rsc>]
352
- >,
353
- HttpRouter.HttpRouter.Provided
354
- >
355
- > = (class Router extends HttpRouter.Tag(`${meta.moduleName}Router`)<Router>() {}) as any
356
-
357
- const layer = r.use((router) =>
358
- Effect.gen(function*() {
359
- const controllers = yield* make
360
- const rpc = yield* makeRpc(middleware)
361
-
362
- // return make.pipe(Effect.map((c) => controllers(c, layers)))
363
- const mapped = typedKeysOf(filtered).reduce((acc, cur) => {
364
- const handler = controllers[cur as keyof typeof controllers]
365
- const req = rsc[cur]
366
-
367
- acc[cur] = rpc.effect(
368
- handler._tag === "raw"
369
- ? class extends (req as any) {
370
- static success = S.encodedSchema(req.success)
371
- get [Schema.symbolSerializable]() {
372
- return this.constructor
373
- }
374
- get [Schema.symbolWithResult]() {
375
- return {
376
- failure: req.failure,
377
- success: S.encodedSchema(req.success)
378
- }
379
- }
380
- } as any
381
- : req,
382
- (req) =>
383
- // TODO: render more data... similar to console?
384
- Effect
385
- .annotateCurrentSpan(
386
- "requestInput",
387
- Object.entries(req).reduce((prev, [key, value]: [string, unknown]) => {
388
- prev[key] = key === "password"
389
- ? "<redacted>"
390
- : typeof value === "string" || typeof value === "number" || typeof value === "boolean"
391
- ? typeof value === "string" && value.length > 256
392
- ? (value.substring(0, 253) + "...")
393
- : value
394
- : Array.isArray(value)
395
- ? `Array[${value.length}]`
396
- : value === null || value === undefined
397
- ? `${value}`
398
- : typeof value === "object" && value
399
- ? `Object[${Object.keys(value).length}]`
400
- : typeof value
401
- return prev
402
- }, {} as Record<string, string | number | boolean>)
403
- )
404
- .pipe(
405
- // can't use andThen due to some being a function and effect
406
- Effect.zipRight(handler.handler(req as any) as any),
407
- Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
408
- Effect.tapDefect((cause) =>
409
- Effect
410
- .all([
411
- reportRequestError(cause, {
412
- action: `${meta.moduleName}.${req._tag}`
413
- }),
414
- Rpc.currentHeaders.pipe(Effect.andThen((headers) => {
415
- return InfraLogger
416
- .logError("Finished request", cause)
417
- .pipe(Effect.annotateLogs({
418
- action: `${meta.moduleName}.${req._tag}`,
419
- req: pretty(req),
420
- headers: pretty(headers)
421
- // resHeaders: pretty(
422
- // Object
423
- // .entries(headers)
424
- // .reduce((prev, [key, value]) => {
425
- // prev[key] = value && typeof value === "string" ? snipString(value) : value
426
- // return prev
427
- // }, {} as Record<string, any>)
428
- // )
429
- }))
430
- }))
431
- ])
432
- ),
433
- devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")),
434
- Effect.withSpan("Request." + meta.moduleName + "." + req._tag, {
435
- captureStackTrace: () => handler.stack
436
- })
437
- ),
438
- meta.moduleName
439
- ) // TODO
440
- return acc
441
- }, {} as any) as {
442
- [K in Keys]: Rpc.Rpc<
443
- Rsc[K],
444
- Context | _R<ReturnType<THandlers[K]["handler"]>>
445
- >
446
- }
447
-
448
- const rpcRouter = RpcRouter.make(...Object.values(mapped) as any) as RpcRouter.RpcRouter<
449
- RPCRouteReq<typeof mapped[keyof typeof mapped]>,
450
- RPCRouteR<typeof mapped[keyof typeof mapped]>
451
- >
452
- const httpApp = toHttpApp(rpcRouter, {
453
- spanPrefix: rsc
454
- .meta
455
- .moduleName + "."
456
- })
457
- yield* router
458
- .post(
459
- "/",
460
- httpApp as any,
461
- // TODO: not queries.
462
- { uninterruptible: true }
463
- )
464
- })
465
- )
466
-
467
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
468
- const routes = layer.pipe(
469
- Layer.provideMerge(r.Live),
470
- layers && Array.isNonEmptyReadonlyArray(layers) ? Layer.provide(layers as any) as any : (_) => _,
471
- // TODO: only provide to the middleware?
472
- middleware.dependencies ? Layer.provide(middleware.dependencies as any) : (_) => _
473
- ) as Layer.Layer<
474
- Router,
475
- GetError<TLayers> | E,
476
- | GetContext<TLayers>
477
- | Exclude<
478
- RMW | R,
479
- ProvidedLayers
480
- >
481
- >
482
-
483
- // Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
484
-
485
- return {
486
- moduleName: meta.moduleName,
487
- Router: r,
488
- routes
489
- }
490
- }
491
-
492
- const effect: {
493
- // Multiple times duplicated the "good" overload, so that errors will only mention the last overload when failing
494
- <
495
- const Make extends {
496
- dependencies: Array<Layer.Layer.Any>
497
- effect: Effect<
498
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
499
- any,
500
- Make["strict"] extends false ? any : GetSuccess<Make["dependencies"]>
501
- >
502
- strict?: boolean
503
- /** @deprecated */
504
- readonly ಠ_ಠ: never
505
- }
506
- >(
507
- make: Make
508
- ): {
509
- moduleName: ModuleName
510
- Router: HttpRouter.HttpRouter.TagClass<
511
- RouterShape<Rsc>,
512
- `${ModuleName}Router`,
513
- never,
514
- | Exclude<Context, HttpRouter.HttpRouter.Provided>
515
- | Exclude<
516
- RPCRouteR<
517
- {
518
- [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<MakeHandlers<Make, Filter<Rsc>>[K]["handler"]>>>
519
- }[keyof Filter<Rsc>]
520
- >,
521
- HttpRouter.HttpRouter.Provided
522
- >
523
- >
524
- routes: Layer.Layer<
525
- RouterShape<Rsc>,
526
- MakeErrors<Make> | GetError<Make["dependencies"]>,
527
- | GetContext<Make["dependencies"]>
528
- // | GetContext<Layers> // elsewhere provided
529
- | Exclude<MakeContext<Make> | RMW, GetSuccess<Make["dependencies"]> | GetSuccess<Layers>>
530
- >
531
- }
532
- <
533
- const Make extends {
534
- dependencies: Array<Layer.Layer.Any>
535
- effect: Effect<
536
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
537
- any,
538
- Make["strict"] extends false ? any : GetSuccess<Make["dependencies"]>
539
- >
540
- strict?: boolean
541
- /** @deprecated */
542
- readonly ಠ_ಠ: never
543
- }
544
- >(
545
- make: Make
546
- ): {
547
- moduleName: ModuleName
548
- Router: HttpRouter.HttpRouter.TagClass<
549
- RouterShape<Rsc>,
550
- `${ModuleName}Router`,
551
- never,
552
- | Exclude<Context, HttpRouter.HttpRouter.Provided>
553
- | Exclude<
554
- RPCRouteR<
555
- {
556
- [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<MakeHandlers<Make, Filter<Rsc>>[K]["handler"]>>>
557
- }[keyof Filter<Rsc>]
558
- >,
559
- HttpRouter.HttpRouter.Provided
560
- >
561
- >
562
- routes: Layer.Layer<
563
- RouterShape<Rsc>,
564
- MakeErrors<Make> | GetError<Make["dependencies"]>,
565
- | GetContext<Make["dependencies"]>
566
- // | GetContext<Layers> // elsewhere provided
567
- | Exclude<MakeContext<Make> | RMW, GetSuccess<Make["dependencies"]> | GetSuccess<Layers>>
568
- >
569
- }
570
- <
571
- const Make extends {
572
- dependencies: Array<Layer.Layer.Any>
573
- effect: Effect<
574
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
575
- any,
576
- Make["strict"] extends false ? any : GetSuccess<Make["dependencies"]>
577
- >
578
- strict?: boolean
579
- /** @deprecated */
580
- readonly ಠ_ಠ: never
581
- }
582
- >(
583
- make: Make
584
- ): {
585
- moduleName: ModuleName
586
- Router: HttpRouter.HttpRouter.TagClass<
587
- RouterShape<Rsc>,
588
- `${ModuleName}Router`,
589
- never,
590
- | Exclude<Context, HttpRouter.HttpRouter.Provided>
591
- | Exclude<
592
- RPCRouteR<
593
- {
594
- [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<MakeHandlers<Make, Filter<Rsc>>[K]["handler"]>>>
595
- }[keyof Filter<Rsc>]
596
- >,
597
- HttpRouter.HttpRouter.Provided
598
- >
599
- >
600
- routes: Layer.Layer<
601
- RouterShape<Rsc>,
602
- MakeErrors<Make> | GetError<Make["dependencies"]>,
603
- | GetContext<Make["dependencies"]>
604
- // | GetContext<Layers> // elsewhere provided
605
- | Exclude<MakeContext<Make> | RMW, GetSuccess<Make["dependencies"]> | GetSuccess<Layers>>
606
- >
607
- }
608
- <
609
- const Make extends {
610
- dependencies: Array<Layer.Layer.Any>
611
- effect: Effect<
612
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
613
- any,
614
- GetSuccess<Make["dependencies"]>
615
- >
616
- strict?: boolean
617
- /** @deprecated */
618
- readonly ಠ_ಠ: never
619
- }
620
- >(
621
- make: Make
622
- ): {
623
- moduleName: ModuleName
624
- Router: HttpRouter.HttpRouter.TagClass<
625
- RouterShape<Rsc>,
626
- `${ModuleName}Router`,
627
- never,
628
- | Exclude<Context, HttpRouter.HttpRouter.Provided>
629
- | Exclude<
630
- RPCRouteR<
631
- {
632
- [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<MakeHandlers<Make, Filter<Rsc>>[K]["handler"]>>>
633
- }[keyof Filter<Rsc>]
634
- >,
635
- HttpRouter.HttpRouter.Provided
636
- >
637
- >
638
- routes: Layer.Layer<
639
- RouterShape<Rsc>,
640
- MakeErrors<Make> | GetError<Make["dependencies"]>,
641
- | GetContext<Make["dependencies"]>
642
- // | GetContext<Layers> // elsewhere provided
643
- | Exclude<MakeContext<Make> | RMW, GetSuccess<Make["dependencies"]> | GetSuccess<Layers>>
644
- >
645
- }
646
- <
647
- const Make extends {
648
- dependencies: Array<Layer.Layer.Any>
649
- effect: Effect<
650
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
651
- any,
652
- GetSuccess<Make["dependencies"]>
653
- >
654
- strict?: boolean
655
- }
656
- >(
657
- make: Make
658
- ): {
659
- moduleName: ModuleName
660
- Router: HttpRouter.HttpRouter.TagClass<
661
- RouterShape<Rsc>,
662
- `${ModuleName}Router`,
663
- never,
664
- | Exclude<Context, HttpRouter.HttpRouter.Provided>
665
- | Exclude<
666
- RPCRouteR<
667
- {
668
- [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<MakeHandlers<Make, Filter<Rsc>>[K]["handler"]>>>
669
- }[keyof Filter<Rsc>]
670
- >,
671
- HttpRouter.HttpRouter.Provided
672
- >
673
- >
674
- routes: Layer.Layer<
675
- RouterShape<Rsc>,
676
- MakeErrors<Make> | GetError<Make["dependencies"]>,
677
- | GetContext<Make["dependencies"]>
678
- // | GetContext<Layers> // elsewhere provided
679
- | Exclude<MakeContext<Make> | RMW, GetSuccess<Make["dependencies"]> | GetSuccess<Layers>>
680
- >
681
- }
682
- <
683
- const Make extends {
684
- dependencies: [
685
- ...Make["dependencies"],
686
- ...Exclude<Effect.Context<Make["effect"]>, MakeDepsOut<Make>> extends never ? []
687
- : [Layer.Layer<Exclude<Effect.Context<Make["effect"]>, MakeDepsOut<Make>>, never, never>]
688
- ]
689
- effect: Effect<
690
- { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]> },
691
- any,
692
- any
693
- >
694
- strict?: boolean
695
- }
696
- >(
697
- make: Make
698
- ): {
699
- moduleName: ModuleName
700
- Router: HttpRouter.HttpRouter.TagClass<
701
- RouterShape<Rsc>,
702
- `${ModuleName}Router`,
703
- never,
704
- Exclude<Context, HttpRouter.HttpRouter.Provided>
705
- > // | Exclude<
706
- // RPCRouteR<
707
- // { [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Rsc>]
708
- // >,
709
- // HttpRouter.HttpRouter.Provided
710
- // >
711
- routes: any
712
- }
713
- } = ((m: { dependencies: any; effect: any; strict?: any }) => f(m.dependencies, m.effect)) as any
714
-
715
- const total = Object.keys(filtered).length
716
- const router: AddAction<Filtered[keyof Filtered]> = {
717
- accum: {},
718
- add(a: any) {
719
- ;(this.accum as any)[a.request._tag] = a
720
- ;(this as any)[a.request._tag] = a
721
- if (Object.keys(this.accum).length === total) return this.accum as any
722
- return this as any
723
- }
724
- }
725
- return Object.assign(effect, items, { router })
726
- }
727
-
728
- type HR<T> = T extends HttpRouter.HttpRouter<any, infer R> ? R : never
729
- type HE<T> = T extends HttpRouter.HttpRouter<infer E, any> ? E : never
730
-
731
- type RequestHandlersTest = {
732
- [key: string]: {
733
- Router: { router: Effect<HttpRouter.HttpRouter<any, any>, any, any> }
734
- routes: Layer.Layer<any, any, any>
735
- moduleName: string
736
- }
737
- }
738
- function matchAll<T extends RequestHandlersTest, A, E, R>(
739
- handlers: T,
740
- requestLayer: Layer.Layer<A, E, R>
741
- ) {
742
- const routers = typedValuesOf(handlers)
743
-
744
- const rootRouter = class extends HttpRouter.Tag("RootRouter")<
745
- "RootRouter",
746
- HR<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>,
747
- HE<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>
748
- >() {}
749
-
750
- const r = rootRouter
751
- .use((router) =>
752
- Effect.gen(function*() {
753
- for (const route of routers) {
754
- yield* router.mount(
755
- ("/rpc/" + route.moduleName) as any,
756
- yield* route
757
- .Router
758
- .router
759
- .pipe(Effect.map(HttpRouter.use(flow(Effect.provide(requestLayer))))) as any
760
- )
761
- }
762
- })
763
- )
764
- .pipe(Layer.provide(routers.map((r) => r.routes).flat() as unknown as NonEmptyArray<Layer.Layer.Any>))
765
-
766
- return {
767
- layer: r as Layer.Layer<
768
- never,
769
- Layer.Layer.Error<typeof handlers[keyof typeof handlers]["routes"]>,
770
- Layer.Layer.Context<typeof handlers[keyof typeof handlers]["routes"]>
771
- >,
772
- Router: rootRouter as any as HttpRouter.HttpRouter.TagClass<
773
- "RootRouter",
774
- "RootRouter",
775
- HE<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>,
776
- R | Exclude<HR<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>, A>
777
- >
778
- }
779
- }
780
-
781
- return { matchAll, matchFor }
782
- }
783
-
784
- export type MakeDeps<Make> = Make extends { readonly dependencies: ReadonlyArray<Layer.Layer.Any> }
785
- ? Make["dependencies"][number]
786
- : never
787
-
788
- export type MakeErrors<Make> = Make extends { readonly effect: Effect<any, infer E, any> } ? E
789
- : never
790
-
791
- export type MakeContext<Make> = Make extends { readonly effect: Effect<any, any, infer R> } ? R
792
- : never
793
-
794
- export type MakeHandlers<Make, Handlers extends Record<string, any>> = Make extends
795
- { readonly effect: Effect<{ [K in keyof Handlers]: AHandler<Handlers[K]> }, any, any> }
796
- ? Effect.Success<Make["effect"]>
797
- : never
798
-
799
- /**
800
- * @since 3.9.0
801
- */
802
- export type MakeDepsOut<Make> = Contravariant.Type<MakeDeps<Make>[Layer.LayerTypeId]["_ROut"]>