@effect-app/infra 2.70.2 → 2.71.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.
- package/CHANGELOG.md +12 -0
- package/dist/Store/ContextMapContainer.d.ts +1 -1
- package/dist/api/internal/middlewares.js +1 -1
- package/dist/api/routing/DynamicMiddleware.d.ts +29 -19
- package/dist/api/routing/DynamicMiddleware.d.ts.map +1 -1
- package/dist/api/routing/DynamicMiddleware.js +37 -13
- package/dist/api/routing/utils.d.ts +7 -0
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing/utils.js +2 -1
- package/dist/api/routing.d.ts +47 -48
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +54 -67
- package/package.json +2 -2
- package/src/api/internal/middlewares.ts +1 -1
- package/src/api/routing/DynamicMiddleware.ts +178 -62
- package/src/api/routing/utils.ts +2 -0
- package/src/api/routing.ts +208 -169
- package/test/controller.test.ts +63 -108
- package/test/dist/controller.test.d.ts.map +1 -1
package/src/api/routing.ts
CHANGED
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
import { determineMethod } from "@effect-app/infra/api/routing/utils"
|
|
5
|
+
import { determineMethod, isCommand } from "@effect-app/infra/api/routing/utils"
|
|
6
6
|
import { logError, reportError } from "@effect-app/infra/errorReporter"
|
|
7
7
|
import { InfraLogger } from "@effect-app/infra/logger"
|
|
8
8
|
import { Rpc, RpcGroup, RpcServer } from "@effect/rpc"
|
|
9
|
-
import { Array, Cause, Context, Duration, Effect, Layer, type NonEmptyReadonlyArray, ParseResult, Predicate, Request, S, Schedule, Schema } from "effect-app"
|
|
10
|
-
import type { GetEffectContext, RPCContextMap } from "effect-app/client/req"
|
|
9
|
+
import { Array, Cause, Context, Duration, Effect, Layer, type NonEmptyArray, type NonEmptyReadonlyArray, ParseResult, Predicate, Request, S, Schedule, Schema } from "effect-app"
|
|
10
|
+
import type { GetEffectContext, GetEffectError, RPCContextMap } from "effect-app/client/req"
|
|
11
11
|
import { type HttpHeaders, HttpRouter } from "effect-app/http"
|
|
12
12
|
import { pretty, typedKeysOf, typedValuesOf } from "effect-app/utils"
|
|
13
13
|
import type { Contravariant } from "effect/Types"
|
|
14
14
|
import { type YieldWrap } from "effect/Utils"
|
|
15
|
-
import { type ContextProviderShape, makeRpc, type Middleware } from "./routing/DynamicMiddleware.js"
|
|
15
|
+
import { type ContextProviderShape, makeMiddlewareLayer, makeRpc, type Middleware } from "./routing/DynamicMiddleware.js"
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
export * from "./routing/DynamicMiddleware.js"
|
|
18
|
+
|
|
19
|
+
export namespace LayersUtils {
|
|
18
20
|
export type GetLayersSuccess<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
19
21
|
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
20
22
|
[k in keyof Layers]: Layer.Layer.Success<Layers[k]>
|
|
@@ -133,10 +135,10 @@ type RPCRouteR<
|
|
|
133
135
|
|
|
134
136
|
type Match<
|
|
135
137
|
Resource extends Record<string, any>,
|
|
136
|
-
|
|
138
|
+
RequestContextMap extends Record<string, any>,
|
|
137
139
|
RT extends RequestType,
|
|
138
140
|
Key extends keyof Resource,
|
|
139
|
-
|
|
141
|
+
MiddlewareR
|
|
140
142
|
> = {
|
|
141
143
|
// note: the defaults of = never prevent the whole router to error (??)
|
|
142
144
|
<A extends GetSuccessShape<Resource[Key], RT>, R2 = never, E = never>(
|
|
@@ -145,7 +147,7 @@ type Match<
|
|
|
145
147
|
Resource[Key],
|
|
146
148
|
RT,
|
|
147
149
|
Exclude<
|
|
148
|
-
|
|
150
|
+
MiddlewareR | Exclude<R2, GetEffectContext<RequestContextMap, Resource[Key]["config"]>>,
|
|
149
151
|
HttpRouter.HttpRouter.Provided
|
|
150
152
|
>
|
|
151
153
|
>
|
|
@@ -156,23 +158,23 @@ type Match<
|
|
|
156
158
|
Resource[Key],
|
|
157
159
|
RT,
|
|
158
160
|
Exclude<
|
|
159
|
-
|
|
161
|
+
MiddlewareR | Exclude<R2, GetEffectContext<RequestContextMap, Resource[Key]["config"]>>,
|
|
160
162
|
HttpRouter.HttpRouter.Provided
|
|
161
163
|
>
|
|
162
164
|
>
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
export type RouteMatcher<
|
|
166
|
-
|
|
168
|
+
RequestContextMap extends Record<string, any>,
|
|
167
169
|
Resource extends Record<string, any>,
|
|
168
|
-
|
|
170
|
+
MiddlewareR
|
|
169
171
|
> = {
|
|
170
172
|
// use Resource as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
|
|
171
173
|
/**
|
|
172
174
|
* Requires the Type shape
|
|
173
175
|
*/
|
|
174
176
|
[Key in keyof FilterRequestModules<Resource>]:
|
|
175
|
-
& Match<Resource,
|
|
177
|
+
& Match<Resource, RequestContextMap, RequestTypes.DECODED, Key, MiddlewareR>
|
|
176
178
|
& {
|
|
177
179
|
success: Resource[Key]["success"]
|
|
178
180
|
successRaw: S.SchemaClass<S.Schema.Encoded<Resource[Key]["success"]>>
|
|
@@ -180,41 +182,37 @@ export type RouteMatcher<
|
|
|
180
182
|
/**
|
|
181
183
|
* Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
|
|
182
184
|
*/
|
|
183
|
-
raw: Match<Resource,
|
|
185
|
+
raw: Match<Resource, RequestContextMap, RequestTypes.TYPE, Key, MiddlewareR>
|
|
184
186
|
}
|
|
185
187
|
}
|
|
186
188
|
|
|
187
|
-
// identity factory for Middleware
|
|
188
|
-
export const makeMiddleware = <
|
|
189
|
-
MiddlewareContext,
|
|
190
|
-
CTXMap extends Record<string, RPCContextMap.Any>,
|
|
191
|
-
MiddlewareR,
|
|
192
|
-
Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[],
|
|
193
|
-
CtxId,
|
|
194
|
-
CtxTag extends string,
|
|
195
|
-
RRet,
|
|
196
|
-
RErr,
|
|
197
|
-
RCtx
|
|
198
|
-
>(
|
|
199
|
-
content: Middleware<MiddlewareContext, CTXMap, MiddlewareR, Layers, CtxId, CtxTag, RRet, RErr, RCtx>
|
|
200
|
-
): Middleware<MiddlewareContext, CTXMap, MiddlewareR, Layers, CtxId, CtxTag, RRet, RErr, RCtx> => content
|
|
201
|
-
|
|
202
189
|
export class Router extends HttpRouter.Tag("@effect-app/Rpc")<Router>() {}
|
|
203
190
|
|
|
204
191
|
export const makeRouter = <
|
|
205
|
-
MiddlewareContext,
|
|
206
|
-
CTXMap extends Record<string, RPCContextMap.Any>,
|
|
207
192
|
MiddlewareR,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
193
|
+
RequestContextMap extends Record<string, RPCContextMap.Any>,
|
|
194
|
+
MakeMiddlewareR,
|
|
195
|
+
MiddlewareDependencies extends NonEmptyArray<Layer.Layer.Any>,
|
|
196
|
+
ContextProviderId,
|
|
197
|
+
ContextProviderKey extends string,
|
|
198
|
+
ContextProviderA,
|
|
199
|
+
MakeContextProviderE,
|
|
200
|
+
MakeContextProviderR
|
|
214
201
|
>(
|
|
215
|
-
middleware: Middleware<
|
|
202
|
+
middleware: Middleware<
|
|
203
|
+
MiddlewareR,
|
|
204
|
+
RequestContextMap,
|
|
205
|
+
MakeMiddlewareR,
|
|
206
|
+
MiddlewareDependencies,
|
|
207
|
+
ContextProviderId,
|
|
208
|
+
ContextProviderKey,
|
|
209
|
+
ContextProviderA,
|
|
210
|
+
MakeContextProviderE,
|
|
211
|
+
MakeContextProviderR
|
|
212
|
+
>,
|
|
216
213
|
devMode: boolean
|
|
217
214
|
) => {
|
|
215
|
+
const middlewareLayer = makeMiddlewareLayer(middleware)
|
|
218
216
|
function matchFor<
|
|
219
217
|
const ModuleName extends string,
|
|
220
218
|
const Resource extends Record<string, any>
|
|
@@ -231,7 +229,9 @@ export const makeRouter = <
|
|
|
231
229
|
Effect<
|
|
232
230
|
any,
|
|
233
231
|
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
234
|
-
|
|
232
|
+
// the actual implementation of the handler may just require the dynamic context provided by the middleware
|
|
233
|
+
// and the per request context provided by the context provider
|
|
234
|
+
GetEffectContext<RequestContextMap, Action["config"]> | ContextProviderA
|
|
235
235
|
>
|
|
236
236
|
>,
|
|
237
237
|
GetSuccessShape<Action, RT>,
|
|
@@ -246,7 +246,9 @@ export const makeRouter = <
|
|
|
246
246
|
) => Effect<
|
|
247
247
|
GetSuccessShape<Action, RT>,
|
|
248
248
|
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
249
|
-
|
|
249
|
+
// the actual implementation of the handler may just require the dynamic context provided by the middleware
|
|
250
|
+
// and the per request context provided by the context provider
|
|
251
|
+
GetEffectContext<RequestContextMap, Action["config"]> | ContextProviderA
|
|
250
252
|
>
|
|
251
253
|
|
|
252
254
|
type HandlerEff<
|
|
@@ -255,7 +257,9 @@ export const makeRouter = <
|
|
|
255
257
|
> = Effect<
|
|
256
258
|
GetSuccessShape<Action, RT>,
|
|
257
259
|
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
258
|
-
|
|
260
|
+
// the actual implementation of the handler may just require the dynamic context provided by the middleware
|
|
261
|
+
// and the per request context provided by the context provider
|
|
262
|
+
GetEffectContext<RequestContextMap, Action["config"]> | ContextProviderA
|
|
259
263
|
>
|
|
260
264
|
|
|
261
265
|
type Handlers<Action extends AnyRequestModule, RT extends RequestType> =
|
|
@@ -282,24 +286,24 @@ export const makeRouter = <
|
|
|
282
286
|
return acc
|
|
283
287
|
}, {} as RequestModules)
|
|
284
288
|
|
|
285
|
-
const
|
|
289
|
+
const routeMatcher = typedKeysOf(requestModules).reduce(
|
|
286
290
|
(prev, cur) => {
|
|
287
|
-
;(prev as any)[cur] = Object.assign((
|
|
288
|
-
//
|
|
289
|
-
if (
|
|
291
|
+
;(prev as any)[cur] = Object.assign((handlerImpl: any) => {
|
|
292
|
+
// handlerImpl is the actual handler implementation
|
|
293
|
+
if (handlerImpl[Symbol.toStringTag] === "GeneratorFunction") handlerImpl = Effect.fnUntraced(handlerImpl)
|
|
290
294
|
const stack = new Error().stack?.split("\n").slice(2).join("\n")
|
|
291
|
-
return Effect.isEffect(
|
|
295
|
+
return Effect.isEffect(handlerImpl)
|
|
292
296
|
? class {
|
|
293
297
|
static request = rsc[cur]
|
|
294
298
|
static stack = stack
|
|
295
299
|
static _tag = RequestTypes.DECODED
|
|
296
|
-
static handler = () =>
|
|
300
|
+
static handler = () => handlerImpl
|
|
297
301
|
}
|
|
298
302
|
: class {
|
|
299
303
|
static request = rsc[cur]
|
|
300
304
|
static stack = stack
|
|
301
305
|
static _tag = RequestTypes.DECODED
|
|
302
|
-
static handler =
|
|
306
|
+
static handler = handlerImpl
|
|
303
307
|
}
|
|
304
308
|
}, {
|
|
305
309
|
success: rsc[cur].success,
|
|
@@ -308,36 +312,35 @@ export const makeRouter = <
|
|
|
308
312
|
raw: // "Raw" variations are for when you don't want to decode just to encode it again on the response
|
|
309
313
|
// e.g for direct projection from DB
|
|
310
314
|
// but more importantly, to skip Effectful decoders, like to resolve relationships from the database or remote client.
|
|
311
|
-
(
|
|
312
|
-
if (
|
|
315
|
+
(handlerImpl: any) => {
|
|
316
|
+
if (handlerImpl[Symbol.toStringTag] === "GeneratorFunction") handlerImpl = Effect.fnUntraced(handlerImpl)
|
|
313
317
|
const stack = new Error().stack?.split("\n").slice(2).join("\n")
|
|
314
|
-
return Effect.isEffect(
|
|
318
|
+
return Effect.isEffect(handlerImpl)
|
|
315
319
|
? class {
|
|
316
320
|
static request = rsc[cur]
|
|
317
321
|
static stack = stack
|
|
318
322
|
static _tag = RequestTypes.TYPE
|
|
319
|
-
static handler = () =>
|
|
323
|
+
static handler = () => handlerImpl
|
|
320
324
|
}
|
|
321
325
|
: class {
|
|
322
326
|
static request = rsc[cur]
|
|
323
327
|
static stack = stack
|
|
324
328
|
static _tag = RequestTypes.TYPE
|
|
325
|
-
static handler =
|
|
329
|
+
static handler = handlerImpl
|
|
326
330
|
}
|
|
327
331
|
}
|
|
328
332
|
})
|
|
329
333
|
return prev
|
|
330
334
|
},
|
|
331
|
-
{} as RouteMatcher<
|
|
335
|
+
{} as RouteMatcher<RequestContextMap, Resource, MiddlewareR>
|
|
332
336
|
)
|
|
333
337
|
|
|
334
|
-
const total = Object.keys(requestModules).length
|
|
335
338
|
const router: AddAction<RequestModules[keyof RequestModules]> = {
|
|
336
339
|
accum: {},
|
|
337
340
|
add(a: any) {
|
|
338
341
|
;(this.accum as any)[a.request._tag] = a
|
|
339
342
|
;(this as any)[a.request._tag] = a
|
|
340
|
-
if (Object.keys(this.accum).length ===
|
|
343
|
+
if (Object.keys(this.accum).length === Object.keys(requestModules).length) return this.accum as any
|
|
341
344
|
return this as any
|
|
342
345
|
}
|
|
343
346
|
}
|
|
@@ -353,8 +356,9 @@ export const makeRouter = <
|
|
|
353
356
|
FilterRequestModules<Resource>[K],
|
|
354
357
|
Impl[K] extends { raw: any } ? RequestTypes.TYPE : RequestTypes.DECODED,
|
|
355
358
|
Exclude<
|
|
356
|
-
|
|
|
359
|
+
| MiddlewareR
|
|
357
360
|
| Exclude<
|
|
361
|
+
// retrieves context R from the actual implementation of the handler
|
|
358
362
|
Impl[K] extends { raw: any } ? Impl[K]["raw"] extends (...args: any[]) => Effect<any, any, infer R> ? R
|
|
359
363
|
: Impl[K]["raw"] extends Effect<any, any, infer R> ? R
|
|
360
364
|
: Impl[K]["raw"] extends (...args: any[]) => Generator<
|
|
@@ -371,34 +375,30 @@ export const makeRouter = <
|
|
|
371
375
|
any
|
|
372
376
|
> ? R
|
|
373
377
|
: never,
|
|
374
|
-
GetEffectContext<
|
|
378
|
+
GetEffectContext<RequestContextMap, Resource[K]["config"]>
|
|
375
379
|
>,
|
|
376
380
|
HttpRouter.HttpRouter.Provided
|
|
377
381
|
>
|
|
378
382
|
>
|
|
379
|
-
} = (
|
|
380
|
-
typedKeysOf(
|
|
381
|
-
acc[cur] = "raw" in
|
|
383
|
+
} = (impl: Record<keyof RequestModules, any>) =>
|
|
384
|
+
typedKeysOf(impl).reduce((acc, cur) => {
|
|
385
|
+
acc[cur] = "raw" in impl[cur] ? routeMatcher[cur].raw(impl[cur].raw) : routeMatcher[cur](impl[cur])
|
|
382
386
|
return acc
|
|
383
387
|
}, {} as any)
|
|
384
388
|
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
389
|
+
const makeRoutes = <
|
|
390
|
+
MakeE,
|
|
391
|
+
MakeR,
|
|
388
392
|
THandlers extends {
|
|
389
393
|
// import to keep them separate via | for type checking!!
|
|
390
394
|
[K in keyof RequestModules]: AnyHandler<Resource[K]>
|
|
391
395
|
},
|
|
392
|
-
|
|
396
|
+
MakeDependencies extends NonEmptyArray<Layer.Layer.Any> | never[]
|
|
393
397
|
>(
|
|
394
|
-
|
|
395
|
-
make: Effect<THandlers,
|
|
398
|
+
dependencies: MakeDependencies,
|
|
399
|
+
make: Effect<THandlers, MakeE, MakeR> | Generator<YieldWrap<Effect<any, MakeE, MakeR>>, THandlers, any>
|
|
396
400
|
) => {
|
|
397
|
-
type ProvidedLayers =
|
|
398
|
-
| { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
|
|
399
|
-
| { [k in keyof TLayers]: Layer.Layer.Success<TLayers[k]> }[number]
|
|
400
401
|
type Router = RouterShape<Resource>
|
|
401
|
-
|
|
402
402
|
const layer = Effect
|
|
403
403
|
.gen(function*() {
|
|
404
404
|
make = (make as any)[Symbol.toStringTag] === "GeneratorFunction"
|
|
@@ -408,35 +408,35 @@ export const makeRouter = <
|
|
|
408
408
|
const controllers = yield* make
|
|
409
409
|
const rpc = yield* makeRpc(middleware)
|
|
410
410
|
|
|
411
|
-
// return make.pipe(Effect.map((c) => controllers(c,
|
|
411
|
+
// return make.pipe(Effect.map((c) => controllers(c, dependencies)))
|
|
412
412
|
const mapped = typedKeysOf(requestModules).reduce((acc, cur) => {
|
|
413
413
|
const handler = controllers[cur as keyof typeof controllers]
|
|
414
|
-
const
|
|
414
|
+
const resource = rsc[cur]
|
|
415
415
|
|
|
416
|
-
const method = determineMethod(String(cur),
|
|
417
|
-
const isCommand = method._tag === "command"
|
|
416
|
+
const method = determineMethod(String(cur), resource)
|
|
418
417
|
|
|
419
|
-
const handle = isCommand
|
|
420
|
-
? (req:
|
|
418
|
+
const handle = isCommand(method)
|
|
419
|
+
? (req: S.Schema.Type<AnyRequestModule>, headers: HttpHeaders.Headers) =>
|
|
421
420
|
Effect.retry(handler.handler(req, headers) as any, optimisticConcurrencySchedule)
|
|
422
|
-
: (req:
|
|
421
|
+
: (req: S.Schema.Type<AnyRequestModule>, headers: HttpHeaders.Headers) =>
|
|
422
|
+
Effect.interruptible(handler.handler(req, headers) as any)
|
|
423
423
|
|
|
424
424
|
acc[cur] = [
|
|
425
425
|
handler._tag === RequestTypes.TYPE
|
|
426
|
-
? class extends (
|
|
427
|
-
static success = S.encodedSchema(
|
|
426
|
+
? class extends (resource as any) {
|
|
427
|
+
static success = S.encodedSchema(resource.success)
|
|
428
428
|
get [Schema.symbolSerializable]() {
|
|
429
429
|
return this.constructor
|
|
430
430
|
}
|
|
431
431
|
get [Schema.symbolWithResult]() {
|
|
432
432
|
return {
|
|
433
|
-
failure:
|
|
434
|
-
success: S.encodedSchema(
|
|
433
|
+
failure: resource.failure,
|
|
434
|
+
success: S.encodedSchema(resource.success)
|
|
435
435
|
}
|
|
436
436
|
}
|
|
437
437
|
} as any
|
|
438
|
-
:
|
|
439
|
-
rpc.effect(
|
|
438
|
+
: resource,
|
|
439
|
+
rpc.effect(resource, (input: any, headers: HttpHeaders.Headers) =>
|
|
440
440
|
// TODO: render more data... similar to console?
|
|
441
441
|
Effect
|
|
442
442
|
.annotateCurrentSpan(
|
|
@@ -468,13 +468,13 @@ export const makeRouter = <
|
|
|
468
468
|
Effect
|
|
469
469
|
.all([
|
|
470
470
|
reportRequestError(cause, {
|
|
471
|
-
action: `${meta.moduleName}.${
|
|
471
|
+
action: `${meta.moduleName}.${resource._tag}`
|
|
472
472
|
}),
|
|
473
473
|
InfraLogger
|
|
474
474
|
.logError("Finished request", cause)
|
|
475
475
|
.pipe(Effect.annotateLogs({
|
|
476
|
-
action: `${meta.moduleName}.${
|
|
477
|
-
req: pretty(
|
|
476
|
+
action: `${meta.moduleName}.${resource._tag}`,
|
|
477
|
+
req: pretty(resource),
|
|
478
478
|
headers: pretty(headers)
|
|
479
479
|
// resHeaders: pretty(
|
|
480
480
|
// Object
|
|
@@ -490,7 +490,7 @@ export const makeRouter = <
|
|
|
490
490
|
// NOTE: this does not catch errors from the middlewares..
|
|
491
491
|
// we should re-evalute this in any case..
|
|
492
492
|
devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")),
|
|
493
|
-
Effect.withSpan("Request." + meta.moduleName + "." +
|
|
493
|
+
Effect.withSpan("Request." + meta.moduleName + "." + resource._tag, {
|
|
494
494
|
captureStackTrace: () => handler.stack
|
|
495
495
|
})
|
|
496
496
|
), meta.moduleName),
|
|
@@ -504,73 +504,73 @@ export const makeRouter = <
|
|
|
504
504
|
req: any,
|
|
505
505
|
headers: HttpHeaders.Headers
|
|
506
506
|
) => Effect.Effect<
|
|
507
|
-
|
|
508
|
-
Effect.Error<ReturnType<THandlers[K]["handler"]
|
|
509
|
-
|
|
507
|
+
Effect.Success<ReturnType<THandlers[K]["handler"]>>,
|
|
508
|
+
| Effect.Error<ReturnType<THandlers[K]["handler"]>>
|
|
509
|
+
| GetEffectError<RequestContextMap, Resource[K]["config"]>,
|
|
510
|
+
| MiddlewareR
|
|
511
|
+
| Exclude<
|
|
512
|
+
Effect.Context<ReturnType<THandlers[K]["handler"]>>,
|
|
513
|
+
ContextProviderA | GetEffectContext<RequestContextMap, Resource[K]["config"]>
|
|
514
|
+
>
|
|
510
515
|
>
|
|
511
516
|
]
|
|
512
517
|
}
|
|
513
518
|
|
|
514
519
|
const rpcs = RpcGroup.make(
|
|
515
|
-
...typedValuesOf(mapped).map((
|
|
516
|
-
return Rpc.fromTaggedRequest(
|
|
520
|
+
...typedValuesOf(mapped).map(([resource]) => {
|
|
521
|
+
return Rpc.fromTaggedRequest(resource)
|
|
517
522
|
})
|
|
518
523
|
)
|
|
519
524
|
const rpcLayer = rpcs.toLayer(Effect.gen(function*() {
|
|
520
|
-
return typedValuesOf(mapped).reduce((acc, [
|
|
521
|
-
acc[
|
|
525
|
+
return typedValuesOf(mapped).reduce((acc, [resource, handler]) => {
|
|
526
|
+
acc[resource._tag] = handler
|
|
522
527
|
return acc
|
|
523
528
|
}, {} as Record<string, any>)
|
|
524
529
|
})) as unknown as Layer<
|
|
525
530
|
{ [K in keyof RequestModules]: Rpc.Handler<K> },
|
|
526
|
-
|
|
527
|
-
|
|
531
|
+
| MakeContextProviderE
|
|
532
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
533
|
+
| LayersUtils.GetLayersError<MakeDependencies>,
|
|
534
|
+
| RPCRouteR<typeof mapped[keyof typeof mapped]>
|
|
535
|
+
| MakeContextProviderR
|
|
536
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
537
|
+
| LayersUtils.GetLayersSuccess<MiddlewareDependencies>
|
|
538
|
+
| LayersUtils.GetLayersContext<MakeDependencies>
|
|
528
539
|
>
|
|
529
540
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
541
|
+
return RpcServer
|
|
542
|
+
.layer(rpcs, { spanPrefix: "RpcServer." + meta.moduleName })
|
|
543
|
+
.pipe(Layer.provide(rpcLayer))
|
|
544
|
+
.pipe(
|
|
545
|
+
Layer.provideMerge(
|
|
546
|
+
RpcServer.layerProtocolHttp(
|
|
547
|
+
{ path: ("/" + meta.moduleName) as `/${typeof meta.moduleName}`, routerTag: Router }
|
|
548
|
+
)
|
|
536
549
|
)
|
|
537
550
|
)
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
// const rpcRouter = RpcRouter.make(...typedValuesOf(mapped).map(_ => _[0]) as any) as RpcRouter.RpcRouter<
|
|
541
|
-
// RPCRouteReq<typeof mapped[keyof typeof mapped]>,
|
|
542
|
-
// RPCRouteR<typeof mapped[keyof typeof mapped]>
|
|
543
|
-
// >
|
|
544
|
-
// const httpApp = toHttpApp(rpcRouter, {
|
|
545
|
-
// spanPrefix: rsc
|
|
546
|
-
// .meta
|
|
547
|
-
// .moduleName + "."
|
|
548
|
-
// })
|
|
549
|
-
// yield* router
|
|
550
|
-
// .post(
|
|
551
|
-
// "/",
|
|
552
|
-
// httpApp as any,
|
|
553
|
-
// { uninterruptible: true }
|
|
554
|
-
// )
|
|
555
551
|
})
|
|
556
552
|
.pipe(Layer.unwrapEffect)
|
|
557
553
|
|
|
558
554
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
559
555
|
const routes = (
|
|
560
556
|
layer.pipe(
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
557
|
+
Layer.provide([
|
|
558
|
+
...dependencies ?? [],
|
|
559
|
+
middleware.contextProvider.Default,
|
|
560
|
+
middlewareLayer
|
|
561
|
+
] as any) as any
|
|
565
562
|
)
|
|
566
563
|
) as (Layer.Layer<
|
|
567
564
|
Router,
|
|
568
|
-
LayersUtils.GetLayersError<
|
|
569
|
-
|
|
|
570
|
-
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
565
|
+
| LayersUtils.GetLayersError<MakeDependencies>
|
|
566
|
+
| MakeE
|
|
567
|
+
| MakeContextProviderE
|
|
568
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>,
|
|
569
|
+
| LayersUtils.GetLayersContext<MakeDependencies>
|
|
570
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
571
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
572
|
+
| MakeContextProviderR
|
|
573
|
+
| Exclude<MakeR, LayersUtils.GetLayersSuccess<MakeDependencies>>
|
|
574
574
|
>)
|
|
575
575
|
|
|
576
576
|
// Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
|
|
@@ -605,12 +605,17 @@ export const makeRouter = <
|
|
|
605
605
|
|
|
606
606
|
routes: Layer.Layer<
|
|
607
607
|
RouterShape<Resource>,
|
|
608
|
-
MakeErrors<Make>
|
|
608
|
+
| MakeErrors<Make>
|
|
609
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
610
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
611
|
+
| MakeContextProviderE,
|
|
609
612
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
610
|
-
|
|
613
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
614
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
615
|
+
| MakeContextProviderR
|
|
611
616
|
| Exclude<
|
|
612
|
-
MakeContext<Make
|
|
613
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
617
|
+
MakeContext<Make>,
|
|
618
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
614
619
|
>
|
|
615
620
|
>
|
|
616
621
|
|
|
@@ -636,12 +641,17 @@ export const makeRouter = <
|
|
|
636
641
|
|
|
637
642
|
routes: Layer.Layer<
|
|
638
643
|
RouterShape<Resource>,
|
|
639
|
-
MakeErrors<Make>
|
|
644
|
+
| MakeErrors<Make>
|
|
645
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
646
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
647
|
+
| MakeContextProviderE,
|
|
640
648
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
641
|
-
|
|
649
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
650
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
651
|
+
| MakeContextProviderR
|
|
642
652
|
| Exclude<
|
|
643
|
-
MakeContext<Make
|
|
644
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
653
|
+
MakeContext<Make>,
|
|
654
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
645
655
|
>
|
|
646
656
|
>
|
|
647
657
|
|
|
@@ -667,12 +677,17 @@ export const makeRouter = <
|
|
|
667
677
|
|
|
668
678
|
routes: Layer.Layer<
|
|
669
679
|
RouterShape<Resource>,
|
|
670
|
-
MakeErrors<Make>
|
|
680
|
+
| MakeErrors<Make>
|
|
681
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
682
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
683
|
+
| MakeContextProviderE,
|
|
671
684
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
672
|
-
|
|
685
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
686
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
687
|
+
| MakeContextProviderR
|
|
673
688
|
| Exclude<
|
|
674
|
-
MakeContext<Make
|
|
675
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
689
|
+
MakeContext<Make>,
|
|
690
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
676
691
|
>
|
|
677
692
|
>
|
|
678
693
|
|
|
@@ -698,12 +713,17 @@ export const makeRouter = <
|
|
|
698
713
|
|
|
699
714
|
routes: Layer.Layer<
|
|
700
715
|
RouterShape<Resource>,
|
|
701
|
-
MakeErrors<Make>
|
|
716
|
+
| MakeErrors<Make>
|
|
717
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
718
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
719
|
+
| MakeContextProviderE,
|
|
702
720
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
703
|
-
|
|
721
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
722
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
723
|
+
| MakeContextProviderR
|
|
704
724
|
| Exclude<
|
|
705
|
-
MakeContext<Make
|
|
706
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
725
|
+
MakeContext<Make>,
|
|
726
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
707
727
|
>
|
|
708
728
|
>
|
|
709
729
|
|
|
@@ -729,12 +749,17 @@ export const makeRouter = <
|
|
|
729
749
|
|
|
730
750
|
routes: Layer.Layer<
|
|
731
751
|
RouterShape<Resource>,
|
|
732
|
-
MakeErrors<Make>
|
|
752
|
+
| MakeErrors<Make>
|
|
753
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
754
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
755
|
+
| MakeContextProviderE,
|
|
733
756
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
734
|
-
|
|
757
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
758
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
759
|
+
| MakeContextProviderR
|
|
735
760
|
| Exclude<
|
|
736
|
-
MakeContext<Make
|
|
737
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
761
|
+
MakeContext<Make>,
|
|
762
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
738
763
|
>
|
|
739
764
|
>
|
|
740
765
|
|
|
@@ -758,12 +783,17 @@ export const makeRouter = <
|
|
|
758
783
|
|
|
759
784
|
routes: Layer.Layer<
|
|
760
785
|
RouterShape<Resource>,
|
|
761
|
-
MakeErrors<Make>
|
|
786
|
+
| MakeErrors<Make>
|
|
787
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
788
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
789
|
+
| MakeContextProviderE,
|
|
762
790
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
763
|
-
|
|
791
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
792
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
793
|
+
| MakeContextProviderR
|
|
764
794
|
| Exclude<
|
|
765
|
-
MakeContext<Make
|
|
766
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
795
|
+
MakeContext<Make>,
|
|
796
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
767
797
|
>
|
|
768
798
|
>
|
|
769
799
|
|
|
@@ -790,12 +820,17 @@ export const makeRouter = <
|
|
|
790
820
|
|
|
791
821
|
routes: Layer.Layer<
|
|
792
822
|
RouterShape<Resource>,
|
|
793
|
-
MakeErrors<Make>
|
|
823
|
+
| MakeErrors<Make>
|
|
824
|
+
| LayersUtils.GetLayersError<Make["dependencies"]>
|
|
825
|
+
| LayersUtils.GetLayersError<MiddlewareDependencies>
|
|
826
|
+
| MakeContextProviderE,
|
|
794
827
|
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
795
|
-
|
|
828
|
+
| Exclude<MakeMiddlewareR, LayersUtils.GetLayersSuccess<MiddlewareDependencies>>
|
|
829
|
+
| LayersUtils.GetLayersContext<MiddlewareDependencies>
|
|
830
|
+
| MakeContextProviderR
|
|
796
831
|
| Exclude<
|
|
797
|
-
MakeContext<Make
|
|
798
|
-
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
832
|
+
MakeContext<Make>,
|
|
833
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
799
834
|
>
|
|
800
835
|
>
|
|
801
836
|
|
|
@@ -824,7 +859,7 @@ export const makeRouter = <
|
|
|
824
859
|
RouterShape<Resource>,
|
|
825
860
|
`${ModuleName}Router`,
|
|
826
861
|
never,
|
|
827
|
-
Exclude<
|
|
862
|
+
Exclude<MiddlewareR, HttpRouter.HttpRouter.Provided>
|
|
828
863
|
> // | Exclude<
|
|
829
864
|
// RPCRouteR<
|
|
830
865
|
// { [K in keyof Filter<Resource>]: Rpc.Rpc<Resource[K], Effect.Context<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Resource>]
|
|
@@ -837,20 +872,21 @@ export const makeRouter = <
|
|
|
837
872
|
make: Make
|
|
838
873
|
}
|
|
839
874
|
} =
|
|
840
|
-
((
|
|
841
|
-
Object.assign(
|
|
875
|
+
((make: { dependencies: any; effect: any; strict?: any }) =>
|
|
876
|
+
Object.assign(makeRoutes(make.dependencies, make.effect), { make })) as any
|
|
842
877
|
|
|
843
|
-
return Object.assign(effect,
|
|
878
|
+
return Object.assign(effect, routeMatcher, { router, router3 })
|
|
844
879
|
}
|
|
845
880
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
881
|
+
function matchAll<
|
|
882
|
+
T extends {
|
|
883
|
+
[key: string]: {
|
|
884
|
+
// Router: { router: Effect<HttpRouter.HttpRouter<any, any>, any, any> }
|
|
885
|
+
routes: Layer.Layer<any, any, any>
|
|
886
|
+
moduleName: string
|
|
887
|
+
}
|
|
851
888
|
}
|
|
852
|
-
|
|
853
|
-
function matchAll<T extends RequestHandlersTest>(
|
|
889
|
+
>(
|
|
854
890
|
handlers: T
|
|
855
891
|
) {
|
|
856
892
|
const routers = typedValuesOf(handlers)
|
|
@@ -908,6 +944,8 @@ export const RequestCacheLayers = Layer.mergeAll(
|
|
|
908
944
|
type GetContext<T> = T extends Context.Context<infer Y> ? Y : never
|
|
909
945
|
|
|
910
946
|
export const contextMaker = <
|
|
947
|
+
// TDeps is an array of services whit Default implementation
|
|
948
|
+
// each service is an effect which builds some context for each request
|
|
911
949
|
TDeps extends Array.NonEmptyReadonlyArray<
|
|
912
950
|
& (
|
|
913
951
|
| Context.Tag<any, Effect<Context.Context<any>, any, any> & { _tag: any }>
|
|
@@ -933,12 +971,13 @@ export const contextMaker = <
|
|
|
933
971
|
dependencies: deps.map((_) => _.Default) as any,
|
|
934
972
|
effect: Effect.gen(function*() {
|
|
935
973
|
const services = yield* Effect.all(deps)
|
|
974
|
+
// services are effects which return some Context.Context<...>
|
|
936
975
|
return Effect.all(services as any[]).pipe(
|
|
937
976
|
Effect.map((_) => Context.mergeAll(..._ as any))
|
|
938
977
|
)
|
|
939
978
|
}) as any
|
|
940
979
|
})
|
|
941
980
|
|
|
942
|
-
export class
|
|
981
|
+
export class EmptyContextMaker extends Effect.Service<EmptyContextMaker>()("EmptyContextMaker", {
|
|
943
982
|
succeed: Effect.succeed(Context.empty()) satisfies ContextProviderShape<never>
|
|
944
983
|
}) {}
|