@effect-app/infra 1.28.3 → 1.29.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 (61) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/_cjs/api/{routing2 → routing}/DynamicMiddleware.cjs +1 -1
  3. package/_cjs/api/routing/DynamicMiddleware.cjs.map +1 -0
  4. package/_cjs/api/routing.cjs +135 -43
  5. package/_cjs/api/routing.cjs.map +1 -1
  6. package/dist/api/routing/DynamicMiddleware.d.ts.map +1 -0
  7. package/dist/api/routing/DynamicMiddleware.js +33 -0
  8. package/dist/api/routing.d.ts +100 -4
  9. package/dist/api/routing.d.ts.map +1 -1
  10. package/dist/api/routing.js +116 -9
  11. package/dist/services/Repository/ext.d.ts +4 -4
  12. package/package.json +9 -79
  13. package/src/api/{routing2 → routing}/DynamicMiddleware.ts +1 -1
  14. package/src/api/routing.ts +434 -8
  15. package/_cjs/api/routing/base.cjs +0 -135
  16. package/_cjs/api/routing/base.cjs.map +0 -1
  17. package/_cjs/api/routing/defaultErrorHandler.cjs +0 -62
  18. package/_cjs/api/routing/defaultErrorHandler.cjs.map +0 -1
  19. package/_cjs/api/routing/makeRequestHandler.cjs +0 -130
  20. package/_cjs/api/routing/makeRequestHandler.cjs.map +0 -1
  21. package/_cjs/api/routing/match.cjs +0 -40
  22. package/_cjs/api/routing/match.cjs.map +0 -1
  23. package/_cjs/api/routing/schema/routing.cjs +0 -136
  24. package/_cjs/api/routing/schema/routing.cjs.map +0 -1
  25. package/_cjs/api/routing2/DynamicMiddleware.cjs.map +0 -1
  26. package/_cjs/api/routing2.cjs +0 -142
  27. package/_cjs/api/routing2.cjs.map +0 -1
  28. package/_cjs/router.cjs +0 -170
  29. package/_cjs/router.cjs.map +0 -1
  30. package/dist/api/routing/base.d.ts +0 -97
  31. package/dist/api/routing/base.d.ts.map +0 -1
  32. package/dist/api/routing/base.js +0 -129
  33. package/dist/api/routing/defaultErrorHandler.d.ts +0 -19
  34. package/dist/api/routing/defaultErrorHandler.d.ts.map +0 -1
  35. package/dist/api/routing/defaultErrorHandler.js +0 -68
  36. package/dist/api/routing/makeRequestHandler.d.ts +0 -20
  37. package/dist/api/routing/makeRequestHandler.d.ts.map +0 -1
  38. package/dist/api/routing/makeRequestHandler.js +0 -151
  39. package/dist/api/routing/match.d.ts +0 -12
  40. package/dist/api/routing/match.d.ts.map +0 -1
  41. package/dist/api/routing/match.js +0 -27
  42. package/dist/api/routing/schema/routing.d.ts +0 -31
  43. package/dist/api/routing/schema/routing.d.ts.map +0 -1
  44. package/dist/api/routing/schema/routing.js +0 -123
  45. package/dist/api/routing2/DynamicMiddleware.d.ts.map +0 -1
  46. package/dist/api/routing2/DynamicMiddleware.js +0 -33
  47. package/dist/api/routing2.d.ts +0 -93
  48. package/dist/api/routing2.d.ts.map +0 -1
  49. package/dist/api/routing2.js +0 -117
  50. package/dist/router.d.ts +0 -91
  51. package/dist/router.d.ts.map +0 -1
  52. package/dist/router.js +0 -154
  53. package/src/api/routing/base.ts +0 -379
  54. package/src/api/routing/defaultErrorHandler.ts +0 -140
  55. package/src/api/routing/makeRequestHandler.ts +0 -343
  56. package/src/api/routing/match.ts +0 -128
  57. package/src/api/routing/schema/routing.ts +0 -237
  58. package/src/api/routing2.ts +0 -425
  59. package/src/api/writeDocs.ts.bak +0 -31
  60. package/src/router.ts +0 -619
  61. /package/dist/api/{routing2 → routing}/DynamicMiddleware.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "1.28.3",
3
+ "version": "1.29.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -20,10 +20,10 @@
20
20
  "proper-lockfile": "^4.1.2",
21
21
  "pure-rand": "6.1.0",
22
22
  "redlock": "^4.2.0",
23
+ "effect-app": "1.21.0",
24
+ "@effect-app/infra-adapters": "1.15.0",
23
25
  "@effect-app/core": "1.12.0",
24
- "@effect-app/infra-adapters": "1.14.0",
25
- "effect-app": "1.20.0",
26
- "@effect-app/schema": "1.14.0"
26
+ "@effect-app/schema": "1.15.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@babel/cli": "^7.25.7",
@@ -128,44 +128,14 @@
128
128
  "default": "./_cjs/api/routing.cjs"
129
129
  }
130
130
  },
131
- "./api/routing/base": {
131
+ "./api/routing/DynamicMiddleware": {
132
132
  "import": {
133
- "types": "./dist/api/routing/base.d.ts",
134
- "default": "./dist/api/routing/base.js"
133
+ "types": "./dist/api/routing/DynamicMiddleware.d.ts",
134
+ "default": "./dist/api/routing/DynamicMiddleware.js"
135
135
  },
136
136
  "require": {
137
- "types": "./dist/api/routing/base.d.ts",
138
- "default": "./_cjs/api/routing/base.cjs"
139
- }
140
- },
141
- "./api/routing/defaultErrorHandler": {
142
- "import": {
143
- "types": "./dist/api/routing/defaultErrorHandler.d.ts",
144
- "default": "./dist/api/routing/defaultErrorHandler.js"
145
- },
146
- "require": {
147
- "types": "./dist/api/routing/defaultErrorHandler.d.ts",
148
- "default": "./_cjs/api/routing/defaultErrorHandler.cjs"
149
- }
150
- },
151
- "./api/routing/makeRequestHandler": {
152
- "import": {
153
- "types": "./dist/api/routing/makeRequestHandler.d.ts",
154
- "default": "./dist/api/routing/makeRequestHandler.js"
155
- },
156
- "require": {
157
- "types": "./dist/api/routing/makeRequestHandler.d.ts",
158
- "default": "./_cjs/api/routing/makeRequestHandler.cjs"
159
- }
160
- },
161
- "./api/routing/match": {
162
- "import": {
163
- "types": "./dist/api/routing/match.d.ts",
164
- "default": "./dist/api/routing/match.js"
165
- },
166
- "require": {
167
- "types": "./dist/api/routing/match.d.ts",
168
- "default": "./_cjs/api/routing/match.cjs"
137
+ "types": "./dist/api/routing/DynamicMiddleware.d.ts",
138
+ "default": "./_cjs/api/routing/DynamicMiddleware.cjs"
169
139
  }
170
140
  },
171
141
  "./api/routing/schema/jwt": {
@@ -178,36 +148,6 @@
178
148
  "default": "./_cjs/api/routing/schema/jwt.cjs"
179
149
  }
180
150
  },
181
- "./api/routing/schema/routing": {
182
- "import": {
183
- "types": "./dist/api/routing/schema/routing.d.ts",
184
- "default": "./dist/api/routing/schema/routing.js"
185
- },
186
- "require": {
187
- "types": "./dist/api/routing/schema/routing.d.ts",
188
- "default": "./_cjs/api/routing/schema/routing.cjs"
189
- }
190
- },
191
- "./api/routing2": {
192
- "import": {
193
- "types": "./dist/api/routing2.d.ts",
194
- "default": "./dist/api/routing2.js"
195
- },
196
- "require": {
197
- "types": "./dist/api/routing2.d.ts",
198
- "default": "./_cjs/api/routing2.cjs"
199
- }
200
- },
201
- "./api/routing2/DynamicMiddleware": {
202
- "import": {
203
- "types": "./dist/api/routing2/DynamicMiddleware.d.ts",
204
- "default": "./dist/api/routing2/DynamicMiddleware.js"
205
- },
206
- "require": {
207
- "types": "./dist/api/routing2/DynamicMiddleware.d.ts",
208
- "default": "./_cjs/api/routing2/DynamicMiddleware.cjs"
209
- }
210
- },
211
151
  "./api/setupRequest": {
212
152
  "import": {
213
153
  "types": "./dist/api/setupRequest.d.ts",
@@ -378,16 +318,6 @@
378
318
  "default": "./_cjs/rateLimit.cjs"
379
319
  }
380
320
  },
381
- "./router": {
382
- "import": {
383
- "types": "./dist/router.d.ts",
384
- "default": "./dist/router.js"
385
- },
386
- "require": {
387
- "types": "./dist/router.d.ts",
388
- "default": "./_cjs/router.cjs"
389
- }
390
- },
391
321
  "./services/Emailer": {
392
322
  "import": {
393
323
  "types": "./dist/services/Emailer.d.ts",
@@ -163,7 +163,7 @@ export const makeRpcClient = <
163
163
  ) => {
164
164
  const req = S.TaggedRequest<Self>()(tag, {
165
165
  payload: fields,
166
- failure: merge(config?.failure, [...errorSchemas, generalErrors]),
166
+ failure: merge(config?.failure, [...errorSchemas, generalErrors].filter(Boolean)),
167
167
  success: config?.success ?? S.Void
168
168
  })
169
169
  return Object.assign(req, { config })
@@ -1,11 +1,437 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
1
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /* eslint-disable @typescript-eslint/ban-types */
4
+ /*
5
+ TODO: Effect.retry(r2, optimisticConcurrencySchedule) / was for PATCH only
6
+ TODO: uninteruptible commands! was for All except GET.
7
+ */
8
+ import { allLower, type EffectUnunified, type LowerServices } from "@effect-app/core/Effect"
9
+ import { typedKeysOf } from "@effect-app/core/utils"
10
+ import type { Compute } from "@effect-app/core/utils"
11
+ import type * as HttpApp from "@effect/platform/HttpApp"
12
+ import type { Rpc } from "@effect/rpc"
13
+ import { RpcRouter } from "@effect/rpc"
14
+ import type { S } from "effect-app"
15
+ import { Chunk, Context, Effect, FiberRef, Predicate, Stream } from "effect-app"
16
+ import type { HttpServerError } from "effect-app/http"
17
+ import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect-app/http"
18
+ import type { ContextMap, GetEffectContext, Middleware } from "./routing/DynamicMiddleware.js"
19
+ import { makeRpc } from "./routing/DynamicMiddleware.js"
3
20
 
4
- // codegen:start {preset: barrel, include: routing/*.ts }
5
- export * from "./routing/base.js"
6
- export * from "./routing/defaultErrorHandler.js"
7
- export * from "./routing/makeRequestHandler.js"
8
- export * from "./routing/match.js"
9
- // codegen:end
21
+ export type _R<T extends Effect<any, any, any>> = [T] extends [
22
+ Effect<any, any, infer R>
23
+ ] ? R
24
+ : never
10
25
 
11
- // export * from "@effect-app/infra/api/routing"
26
+ export type _E<T extends Effect<any, any, any>> = [T] extends [
27
+ Effect<any, infer E, any>
28
+ ] ? E
29
+ : never
30
+
31
+ export type EffectDeps<A> = {
32
+ [K in keyof A as A[K] extends Effect<any, any, any> ? K : never]: A[K] extends Effect<any, any, any> ? A[K] : never
33
+ }
34
+ /**
35
+ * Plain jane JSON version
36
+ */
37
+ export const toHttpApp = <R extends RpcRouter.RpcRouter<any, any>>(self: R, options?: {
38
+ readonly spanPrefix?: string
39
+ }): HttpApp.Default<
40
+ HttpServerError.RequestError,
41
+ RpcRouter.RpcRouter.Context<R>
42
+ > => {
43
+ const handler = RpcRouter.toHandler(self, options)
44
+ return Effect.withFiberRuntime((fiber) => {
45
+ const context = fiber.getFiberRef(FiberRef.currentContext)
46
+ const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest)
47
+ return Effect.flatMap(
48
+ request.json,
49
+ (_) =>
50
+ handler(_).pipe(
51
+ Stream.provideContext(context),
52
+ Stream.runCollect,
53
+ Effect.map((_) => Chunk.toReadonlyArray(_)),
54
+ Effect.andThen((_) => HttpServerResponse.json(_)),
55
+ Effect.orDie
56
+ )
57
+ )
58
+ })
59
+ }
60
+
61
+ type GetRouteContext<CTXMap extends Record<string, ContextMap.Any>, T> =
62
+ // & CTX
63
+ // inverted
64
+ & {
65
+ [
66
+ key in keyof CTXMap as CTXMap[key][3] extends true ? never
67
+ : key extends keyof T ? T[key] extends true ? CTXMap[key][0] : never
68
+ : never
69
+ ]?: CTXMap[key][1]
70
+ }
71
+ & {
72
+ [
73
+ key in keyof CTXMap as CTXMap[key][3] extends true ? never
74
+ : key extends keyof T ? T[key] extends false ? CTXMap[key][0] : never
75
+ : CTXMap[key][0]
76
+ ]: CTXMap[key][1]
77
+ }
78
+ // normal
79
+ & {
80
+ [
81
+ key in keyof CTXMap as CTXMap[key][3] extends false ? never
82
+ : key extends keyof T ? T[key] extends true ? CTXMap[key][0] : never
83
+ : never
84
+ ]: CTXMap[key][1]
85
+ }
86
+ & {
87
+ [
88
+ key in keyof CTXMap as CTXMap[key][3] extends false ? never
89
+ : key extends keyof T ? T[key] extends false ? CTXMap[key][0] : never
90
+ : CTXMap[key][0]
91
+ ]?: CTXMap[key][1]
92
+ }
93
+
94
+ export interface Hint<Err extends string> {
95
+ Err: Err
96
+ }
97
+
98
+ type HandleVoid<Expected, Actual, Result> = [Expected] extends [void]
99
+ ? [Actual] extends [void] ? Result : Hint<"You're returning non void for a void Response, please fix">
100
+ : Result
101
+
102
+ type AnyRequestModule = S.Schema.Any & { success?: S.Schema.Any; failure?: S.Schema.Any }
103
+
104
+ type GetSuccess<T> = T extends { success: S.Schema.Any } ? T["success"] : typeof S.Void
105
+
106
+ type GetSuccessShape<Action extends { success?: S.Schema.Any }, RT extends "d" | "raw"> = RT extends "raw"
107
+ ? S.Schema.Encoded<GetSuccess<Action>>
108
+ : S.Schema.Type<GetSuccess<Action>>
109
+ type GetFailure<T extends { failure?: S.Schema.Any }> = T["failure"] extends never ? typeof S.Never : T["failure"]
110
+
111
+ export interface Handler<Action extends AnyRequestModule, RT extends "raw" | "d", A, E, R, Context> {
112
+ new(): {}
113
+ _tag: RT
114
+ handler: (
115
+ req: S.Schema.Type<Action>,
116
+ ctx: Context
117
+ ) => Effect<
118
+ A,
119
+ E,
120
+ R
121
+ >
122
+ }
123
+
124
+ // Separate "raw" vs "d" to verify A (Encoded for "raw" vs Type for "d")
125
+ type AHandler<Action extends AnyRequestModule> =
126
+ | Handler<
127
+ Action,
128
+ "raw",
129
+ S.Schema.Encoded<GetSuccess<Action>>,
130
+ S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
131
+ any,
132
+ { Response: any }
133
+ >
134
+ | Handler<
135
+ Action,
136
+ "d",
137
+ S.Schema.Type<GetSuccess<Action>>,
138
+ S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
139
+ any,
140
+ { Response: any }
141
+ >
142
+
143
+ type Filter<T> = {
144
+ [K in keyof T as T[K] extends S.Schema.All & { success: S.Schema.Any; failure: S.Schema.Any } ? K : never]: T[K]
145
+ }
146
+
147
+ interface ExtendedMiddleware<Context, CTXMap extends Record<string, ContextMap.Any>>
148
+ extends Middleware<Context, CTXMap>
149
+ {
150
+ // TODO
151
+ makeContext: Effect<
152
+ { [K in keyof CTXMap as CTXMap[K][1] extends never ? never : CTXMap[K][0]]: CTXMap[K][1] },
153
+ never,
154
+ never
155
+ >
156
+ }
157
+
158
+ export const makeRouter = <Context, CTXMap extends Record<string, ContextMap.Any>>(
159
+ middleware: ExtendedMiddleware<Context, CTXMap>
160
+ ) => {
161
+ const rpc = makeRpc(middleware)
162
+ function matchFor<Rsc extends Record<string, any> & { meta: { moduleName: string } }>(
163
+ rsc: Rsc
164
+ ) {
165
+ const meta = (rsc as any).meta as { moduleName: string }
166
+ if (!meta) throw new Error("Resource has no meta specified") // TODO: do something with moduleName+cur etc.
167
+
168
+ type Filtered = Filter<Rsc>
169
+ const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
170
+ if (Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
171
+ acc[cur as keyof Filtered] = rsc[cur]
172
+ }
173
+ return acc
174
+ }, {} as Filtered)
175
+
176
+ const matchWithServices = <Key extends keyof Filtered>(action: Key) => {
177
+ return <
178
+ SVC extends Record<
179
+ string,
180
+ Effect<any, any, any>
181
+ >,
182
+ R2,
183
+ E,
184
+ A
185
+ >(
186
+ services: SVC,
187
+ f: (
188
+ req: S.Schema.Type<Rsc[Key]>,
189
+ ctx: Compute<
190
+ LowerServices<EffectDeps<SVC>> & GetRouteContext<CTXMap, Rsc[Key]["config"]> & {
191
+ Response: Rsc[Key]["success"]
192
+ },
193
+ "flat"
194
+ >
195
+ ) => Effect<A, E, R2>
196
+ ) =>
197
+ (req: any) =>
198
+ Effect.andThen(
199
+ Effect.all({ svc: allLower(services), ctx: middleware.makeContext }),
200
+ ({ ctx, svc }) => f(req, { ...svc, ...ctx, Response: rsc[action].success } as any)
201
+ )
202
+ }
203
+
204
+ type MatchWithServicesNew<RT extends "raw" | "d", Key extends keyof Rsc> = {
205
+ <R2, E, A>(
206
+ f: Effect<A, E, R2>
207
+ ): HandleVoid<
208
+ GetSuccessShape<Rsc[Key], RT>,
209
+ A,
210
+ Handler<
211
+ Rsc[Key],
212
+ RT,
213
+ A,
214
+ E,
215
+ Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
216
+ { Response: Rsc[Key]["success"] } //
217
+ >
218
+ >
219
+
220
+ <R2, E, A>(
221
+ f: (
222
+ req: S.Schema.Type<Rsc[Key]>,
223
+ ctx: GetRouteContext<CTXMap, Rsc[Key]["config"]> & { Response: Rsc[Key]["success"] }
224
+ ) => Effect<A, E, R2>
225
+ ): HandleVoid<
226
+ GetSuccessShape<Rsc[Key], RT>,
227
+ A,
228
+ Handler<
229
+ Rsc[Key],
230
+ RT,
231
+ A,
232
+ E,
233
+ Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
234
+ { Response: Rsc[Key]["success"] } //
235
+ >
236
+ >
237
+
238
+ <
239
+ SVC extends Record<
240
+ string,
241
+ EffectUnunified<any, any, any>
242
+ >,
243
+ R2,
244
+ E,
245
+ A
246
+ >(
247
+ services: SVC,
248
+ f: (
249
+ req: S.Schema.Type<Rsc[Key]>,
250
+ ctx: Compute<
251
+ LowerServices<EffectDeps<SVC>> & GetRouteContext<CTXMap, Rsc[Key]["config"]> & {
252
+ Response: Rsc[Key]["success"]
253
+ },
254
+ "flat"
255
+ >
256
+ ) => Effect<A, E, R2>
257
+ ): HandleVoid<
258
+ GetSuccessShape<Rsc[Key], RT>,
259
+ A,
260
+ Handler<
261
+ Rsc[Key],
262
+ RT,
263
+ A,
264
+ E,
265
+ Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
266
+ { Response: Rsc[Key]["success"] } //
267
+ >
268
+ >
269
+ }
270
+
271
+ type Keys = keyof Filtered
272
+
273
+ const controllers = <
274
+ THandlers extends {
275
+ // import to keep them separate via | for type checking!!
276
+ [K in Keys]: AHandler<Rsc[K]>
277
+ }
278
+ >(
279
+ controllers: THandlers
280
+ ) => {
281
+ const handlers = typedKeysOf(filtered).reduce(
282
+ (acc, cur) => {
283
+ ;(acc as any)[cur] = {
284
+ h: controllers[cur as keyof typeof controllers].handler,
285
+ Request: rsc[cur]
286
+ }
287
+
288
+ return acc
289
+ },
290
+ {} as {
291
+ [K in Keys]: {
292
+ h: (
293
+ r: S.Schema.Type<Rsc[K]>
294
+ ) => Effect<
295
+ S.Schema.Type<GetSuccess<Rsc[K]>>,
296
+ _E<ReturnType<THandlers[K]["handler"]>>,
297
+ _R<ReturnType<THandlers[K]["handler"]>>
298
+ >
299
+ Request: Rsc[K]
300
+ }
301
+ }
302
+ )
303
+
304
+ const mapped = typedKeysOf(handlers).reduce((acc, cur) => {
305
+ const handler = handlers[cur]
306
+ const req = handler.Request
307
+
308
+ acc[cur] = rpc.effect(req, handler.h as any, meta.moduleName) // TODO
309
+ return acc
310
+ }, {} as any) as {
311
+ [K in Keys]: Rpc.Rpc<
312
+ Rsc[K],
313
+ _R<ReturnType<THandlers[K]["handler"]>>
314
+ >
315
+ }
316
+
317
+ type RPCRouteR<T extends Rpc.Rpc<any, any>> = [T] extends [
318
+ Rpc.Rpc<any, infer R>
319
+ ] ? R
320
+ : never
321
+
322
+ type RPCRouteReq<T extends Rpc.Rpc<any, any>> = [T] extends [
323
+ Rpc.Rpc<infer Req, any>
324
+ ] ? Req
325
+ : never
326
+
327
+ const router = RpcRouter.make(...Object.values(mapped) as any) as RpcRouter.RpcRouter<
328
+ RPCRouteReq<typeof mapped[keyof typeof mapped]>,
329
+ RPCRouteR<typeof mapped[keyof typeof mapped]>
330
+ >
331
+
332
+ return HttpRouter.empty.pipe(
333
+ HttpRouter.all(
334
+ ("/rpc/" + rsc.meta.moduleName) as any,
335
+ toHttpApp(router),
336
+ // TODO: not queries.
337
+ { uninterruptible: true }
338
+ )
339
+ )
340
+ }
341
+
342
+ const r = {
343
+ controllers,
344
+ ...typedKeysOf(filtered).reduce(
345
+ (prev, cur) => {
346
+ ;(prev as any)[cur] = (svcOrFnOrEffect: any, fnOrNone: any) => {
347
+ const stack = new Error().stack?.split("\n").slice(2).join("\n")
348
+ return Effect.isEffect(svcOrFnOrEffect)
349
+ ? class {
350
+ static stack = stack
351
+ static _tag = "d"
352
+ static handler = () => svcOrFnOrEffect
353
+ }
354
+ : typeof svcOrFnOrEffect === "function"
355
+ ? class {
356
+ static stack = stack
357
+ static _tag = "d"
358
+ static handler = (req: any) =>
359
+ Effect.andThen(
360
+ Effect.all({ ctx: middleware.makeContext }),
361
+ ({ ctx }) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].success })
362
+ )
363
+ }
364
+ : class {
365
+ static stack = stack
366
+ static _tag = "d"
367
+ static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone)
368
+ }
369
+ }
370
+ ;(prev as any)[(cur as any) + "Raw"] = (svcOrFnOrEffect: any, fnOrNone: any) => {
371
+ const stack = new Error().stack?.split("\n").slice(2).join("\n")
372
+ return Effect.isEffect(svcOrFnOrEffect)
373
+ ? class {
374
+ static stack = stack
375
+ static _tag = "raw"
376
+ static handler = () => svcOrFnOrEffect
377
+ }
378
+ : typeof svcOrFnOrEffect === "function"
379
+ ? class {
380
+ static stack = stack
381
+ static _tag = "raw"
382
+ static handler = (req: any, ctx: any) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].success })
383
+ }
384
+ : class {
385
+ static stack = stack
386
+ static _tag = "raw"
387
+ static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone)
388
+ }
389
+ }
390
+ return prev
391
+ },
392
+ {} as
393
+ & {
394
+ // use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
395
+ /**
396
+ * Requires the Type shape
397
+ */
398
+ [Key in keyof Filtered]: MatchWithServicesNew<"d", Key>
399
+ }
400
+ & {
401
+ // use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
402
+ /**
403
+ * Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
404
+ */
405
+ [Key in keyof Filtered as Key extends string ? `${Key}Raw` : never]: MatchWithServicesNew<"raw", Key>
406
+ }
407
+ )
408
+ }
409
+ return r
410
+ }
411
+
412
+ type RequestHandlersTest = {
413
+ [key: string]: HttpRouter.HttpRouter<any, any>
414
+ }
415
+ function matchAll<T extends RequestHandlersTest>(handlers: T) {
416
+ const r = typedKeysOf(handlers).reduce((acc, cur) => {
417
+ return HttpRouter.concat(acc, handlers[cur] as any)
418
+ }, HttpRouter.empty)
419
+
420
+ type _RRouter<T extends HttpRouter.HttpRouter<any, any>> = [T] extends [
421
+ HttpRouter.HttpRouter<any, infer R>
422
+ ] ? R
423
+ : never
424
+
425
+ type _ERouter<T extends HttpRouter.HttpRouter<any, any>> = [T] extends [
426
+ HttpRouter.HttpRouter<infer E, any>
427
+ ] ? E
428
+ : never
429
+
430
+ return r as HttpRouter.HttpRouter<
431
+ _ERouter<typeof handlers[keyof typeof handlers]>,
432
+ _RRouter<typeof handlers[keyof typeof handlers]>
433
+ >
434
+ }
435
+
436
+ return { matchAll, matchFor }
437
+ }