@effect-app/infra 2.64.6 → 2.65.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 +11 -0
- package/dist/api/internal/auth.js +2 -2
- package/dist/api/internal/middlewares.d.ts +0 -1
- package/dist/api/internal/middlewares.d.ts.map +1 -1
- package/dist/api/internal/middlewares.js +26 -27
- package/dist/api/routing/DynamicMiddleware.d.ts +17 -12
- package/dist/api/routing/DynamicMiddleware.d.ts.map +1 -1
- package/dist/api/routing/DynamicMiddleware.js +12 -4
- package/dist/api/routing.d.ts +144 -102
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +38 -27
- package/package.json +2 -2
- package/src/api/internal/auth.ts +1 -1
- package/src/api/internal/middlewares.ts +29 -37
- package/src/api/routing/DynamicMiddleware.ts +72 -47
- package/src/api/routing.ts +447 -400
- package/test/controller.test.ts +55 -146
- package/test/dist/controller.legacy2.test.d.ts.map +1 -0
- package/test/dist/controller.legacy3.test.d.ts.map +1 -0
- package/test/dist/controller.test copy.d.ts +169 -0
- package/test/dist/controller.test copy.d.ts.map +1 -0
- package/test/dist/controller.test copy.js +152 -0
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/controller6.test.d.ts.map +1 -0
- package/test/dist/controller7.test.d.ts.map +1 -0
- package/test/dist/filterApi.test.d.ts.map +1 -0
package/src/api/routing.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { determineMethod } 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, Duration, Effect, Layer, type NonEmptyReadonlyArray, ParseResult, Predicate, Request, S, Schedule, Schema } from "effect-app"
|
|
9
|
+
import { Array, Cause, Context, Duration, Effect, Layer, type NonEmptyReadonlyArray, ParseResult, Predicate, Request, S, Schedule, Schema } from "effect-app"
|
|
10
10
|
import type { GetEffectContext, 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"
|
|
@@ -14,131 +14,149 @@ import type { Contravariant } from "effect/Types"
|
|
|
14
14
|
import { type YieldWrap } from "effect/Utils"
|
|
15
15
|
import { makeRpc, type Middleware } from "./routing/DynamicMiddleware.js"
|
|
16
16
|
|
|
17
|
+
namespace LayersUtils {
|
|
18
|
+
export type GetLayersSuccess<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
19
|
+
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
20
|
+
[k in keyof Layers]: Layer.Layer.Success<Layers[k]>
|
|
21
|
+
}[number]
|
|
22
|
+
: never
|
|
23
|
+
|
|
24
|
+
export type GetLayersContext<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
25
|
+
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
26
|
+
[k in keyof Layers]: Layer.Layer.Context<Layers[k]>
|
|
27
|
+
}[number]
|
|
28
|
+
: never
|
|
29
|
+
|
|
30
|
+
export type GetLayersError<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
31
|
+
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
32
|
+
[k in keyof Layers]: Layer.Layer.Error<Layers[k]>
|
|
33
|
+
}[number]
|
|
34
|
+
: never
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
const logRequestError = logError("Request")
|
|
18
38
|
const reportRequestError = reportError("Request")
|
|
19
39
|
|
|
40
|
+
// retry just once on optimistic concurrency exceptions
|
|
20
41
|
const optimisticConcurrencySchedule = Schedule.once.pipe(
|
|
21
42
|
Schedule.intersect(Schedule.recurWhile<any>((a) => a?._tag === "OptimisticConcurrencyException"))
|
|
22
43
|
)
|
|
23
44
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
] ? R
|
|
27
|
-
: never
|
|
28
|
-
|
|
29
|
-
export type _E<T extends Effect<any, any, any>> = [T] extends [
|
|
30
|
-
Effect<any, infer E, any>
|
|
31
|
-
] ? E
|
|
32
|
-
: never
|
|
33
|
-
|
|
34
|
-
export type EffectDeps<A> = {
|
|
35
|
-
[K in keyof A as A[K] extends Effect<any, any, any> ? K : never]: A[K] extends Effect<any, any, any> ? A[K] : never
|
|
36
|
-
}
|
|
37
|
-
|
|
45
|
+
// it's the result of extending S.Req setting success, config
|
|
46
|
+
// it's a schema plus some metadata
|
|
38
47
|
export type AnyRequestModule = S.Schema.Any & {
|
|
39
|
-
_tag: string
|
|
40
|
-
config: any
|
|
41
|
-
success: S.Schema.Any
|
|
42
|
-
failure: S.Schema.Any
|
|
48
|
+
_tag: string // unique identifier for the request module
|
|
49
|
+
config: any // ?
|
|
50
|
+
success: S.Schema.Any // validates the success response
|
|
51
|
+
failure: S.Schema.Any // validates the failure response
|
|
43
52
|
}
|
|
53
|
+
|
|
54
|
+
// builder pattern for adding actions to a router until all actions are added
|
|
44
55
|
export interface AddAction<Actions extends AnyRequestModule, Accum extends Record<string, any> = {}> {
|
|
45
56
|
accum: Accum
|
|
46
57
|
add<A extends Handler<Actions, any, any>>(
|
|
47
58
|
a: A
|
|
48
|
-
):
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
): A extends Handler<infer M extends AnyRequestModule, any, any> ? Exclude<Actions, M> extends never ?
|
|
60
|
+
& Accum
|
|
61
|
+
& { [K in M["_tag"]]: A }
|
|
51
62
|
:
|
|
52
63
|
& AddAction<
|
|
53
|
-
Exclude<Actions,
|
|
64
|
+
Exclude<Actions, M>,
|
|
54
65
|
& Accum
|
|
55
|
-
& { [K in
|
|
66
|
+
& { [K in M["_tag"]]: A }
|
|
56
67
|
>
|
|
57
68
|
& Accum
|
|
58
|
-
& { [K in
|
|
69
|
+
& { [K in M["_tag"]]: A }
|
|
70
|
+
: never
|
|
59
71
|
}
|
|
60
72
|
|
|
61
|
-
|
|
73
|
+
// note:
|
|
74
|
+
// "d" stands for decoded i.e. the Type
|
|
75
|
+
// "raw" stands for encoded i.e. the Encoded
|
|
76
|
+
namespace RequestTypes {
|
|
77
|
+
export const DECODED = "d" as const
|
|
78
|
+
export type DECODED = typeof DECODED
|
|
79
|
+
export const TYPE = "raw" as const
|
|
80
|
+
export type TYPE = typeof TYPE
|
|
81
|
+
}
|
|
82
|
+
type RequestType = typeof RequestTypes[keyof typeof RequestTypes]
|
|
62
83
|
|
|
63
|
-
type
|
|
64
|
-
? S.Schema.Encoded<GetSuccess<Action>>
|
|
65
|
-
: S.Schema.Type<GetSuccess<Action>>
|
|
84
|
+
type GetSuccess<T> = T extends { success: S.Schema.Any } ? T["success"] : typeof S.Void
|
|
66
85
|
type GetFailure<T extends { failure?: S.Schema.Any }> = T["failure"] extends never ? typeof S.Never : T["failure"]
|
|
67
86
|
|
|
68
|
-
type
|
|
87
|
+
type GetSuccessShape<Action extends { success?: S.Schema.Any }, RT extends RequestType> = {
|
|
88
|
+
d: S.Schema.Type<GetSuccess<Action>>
|
|
89
|
+
raw: S.Schema.Encoded<GetSuccess<Action>>
|
|
90
|
+
}[RT]
|
|
91
|
+
|
|
92
|
+
interface HandlerBase<Action extends AnyRequestModule, RT extends RequestType, A, E, R> {
|
|
69
93
|
new(): {}
|
|
70
94
|
_tag: RT
|
|
71
95
|
stack: string
|
|
72
|
-
handler: (
|
|
73
|
-
req: S.Schema.Type<Action>,
|
|
74
|
-
headers: HttpHeaders.Headers
|
|
75
|
-
) => Effect<
|
|
76
|
-
A,
|
|
77
|
-
E,
|
|
78
|
-
R
|
|
79
|
-
>
|
|
96
|
+
handler: (req: S.Schema.Type<Action>, headers: HttpHeaders.Headers) => Effect<A, E, R>
|
|
80
97
|
}
|
|
81
98
|
|
|
82
|
-
export interface Handler<Action extends AnyRequestModule, RT extends
|
|
83
|
-
|
|
99
|
+
export interface Handler<Action extends AnyRequestModule, RT extends RequestType, R> extends
|
|
100
|
+
HandlerBase<
|
|
84
101
|
Action,
|
|
85
102
|
RT,
|
|
86
103
|
GetSuccessShape<Action, RT>,
|
|
87
104
|
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
88
105
|
R
|
|
89
106
|
>
|
|
90
|
-
{
|
|
91
|
-
}
|
|
107
|
+
{}
|
|
92
108
|
|
|
93
|
-
type
|
|
109
|
+
type AnyHandler<Action extends AnyRequestModule> = Handler<
|
|
94
110
|
Action,
|
|
95
|
-
|
|
96
|
-
any
|
|
111
|
+
RequestType,
|
|
112
|
+
any // R
|
|
97
113
|
>
|
|
98
114
|
|
|
99
|
-
|
|
115
|
+
// a Resource is typically the whole module with all the exported sh*t
|
|
116
|
+
// this helper retrieves only the entities (classes) which are built by extending S.Req
|
|
117
|
+
type FilterRequestModules<T> = {
|
|
100
118
|
[K in keyof T as T[K] extends AnyRequestModule ? K : never]: T[K]
|
|
101
119
|
}
|
|
102
120
|
|
|
103
121
|
export const RouterSymbol = Symbol()
|
|
104
|
-
export interface RouterShape<
|
|
105
|
-
[RouterSymbol]:
|
|
122
|
+
export interface RouterShape<Resource> {
|
|
123
|
+
[RouterSymbol]: Resource
|
|
106
124
|
}
|
|
107
125
|
|
|
108
126
|
type RPCRouteR<
|
|
109
|
-
T extends [any, (
|
|
127
|
+
T extends [any, (req: any, headers: HttpHeaders.Headers) => Effect<any, any, any>]
|
|
110
128
|
> = T extends [
|
|
111
129
|
any,
|
|
112
|
-
(
|
|
130
|
+
(...args: any[]) => Effect<any, any, infer R>
|
|
113
131
|
] ? R
|
|
114
132
|
: never
|
|
115
133
|
|
|
116
134
|
type Match<
|
|
117
|
-
|
|
135
|
+
Resource extends Record<string, any>,
|
|
118
136
|
CTXMap extends Record<string, any>,
|
|
119
|
-
RT extends
|
|
120
|
-
Key extends keyof
|
|
121
|
-
|
|
137
|
+
RT extends RequestType,
|
|
138
|
+
Key extends keyof Resource,
|
|
139
|
+
MiddlewareContext
|
|
122
140
|
> = {
|
|
123
|
-
// note: the defaults of = never prevent the whole router to error
|
|
124
|
-
<A extends GetSuccessShape<
|
|
141
|
+
// note: the defaults of = never prevent the whole router to error (??)
|
|
142
|
+
<A extends GetSuccessShape<Resource[Key], RT>, R2 = never, E = never>(
|
|
125
143
|
f: Effect<A, E, R2>
|
|
126
144
|
): Handler<
|
|
127
|
-
|
|
145
|
+
Resource[Key],
|
|
128
146
|
RT,
|
|
129
147
|
Exclude<
|
|
130
|
-
|
|
148
|
+
MiddlewareContext | Exclude<R2, GetEffectContext<CTXMap, Resource[Key]["config"]>>,
|
|
131
149
|
HttpRouter.HttpRouter.Provided
|
|
132
150
|
>
|
|
133
151
|
>
|
|
134
152
|
|
|
135
|
-
<A extends GetSuccessShape<
|
|
136
|
-
f: (req: S.Schema.Type<
|
|
153
|
+
<A extends GetSuccessShape<Resource[Key], RT>, R2 = never, E = never>(
|
|
154
|
+
f: (req: S.Schema.Type<Resource[Key]>) => Effect<A, E, R2>
|
|
137
155
|
): Handler<
|
|
138
|
-
|
|
156
|
+
Resource[Key],
|
|
139
157
|
RT,
|
|
140
158
|
Exclude<
|
|
141
|
-
|
|
159
|
+
MiddlewareContext | Exclude<R2, GetEffectContext<CTXMap, Resource[Key]["config"]>>,
|
|
142
160
|
HttpRouter.HttpRouter.Provided
|
|
143
161
|
>
|
|
144
162
|
>
|
|
@@ -146,78 +164,139 @@ type Match<
|
|
|
146
164
|
|
|
147
165
|
export type RouteMatcher<
|
|
148
166
|
CTXMap extends Record<string, any>,
|
|
149
|
-
|
|
150
|
-
|
|
167
|
+
Resource extends Record<string, any>,
|
|
168
|
+
MiddlewareContext
|
|
151
169
|
> = {
|
|
152
|
-
// use
|
|
170
|
+
// use Resource as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
|
|
153
171
|
/**
|
|
154
172
|
* Requires the Type shape
|
|
155
173
|
*/
|
|
156
|
-
[Key in keyof
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
174
|
+
[Key in keyof FilterRequestModules<Resource>]:
|
|
175
|
+
& Match<Resource, CTXMap, RequestTypes.DECODED, Key, MiddlewareContext>
|
|
176
|
+
& {
|
|
177
|
+
success: Resource[Key]["success"]
|
|
178
|
+
successRaw: S.SchemaClass<S.Schema.Encoded<Resource[Key]["success"]>>
|
|
179
|
+
failure: Resource[Key]["failure"]
|
|
180
|
+
/**
|
|
181
|
+
* Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
|
|
182
|
+
*/
|
|
183
|
+
raw: Match<Resource, CTXMap, RequestTypes.TYPE, Key, MiddlewareContext>
|
|
184
|
+
}
|
|
165
185
|
}
|
|
166
|
-
// export interface RouteMatcher<
|
|
167
|
-
// Filtered extends Record<string, any>,
|
|
168
|
-
// CTXMap extends Record<string, any>,
|
|
169
|
-
// Rsc extends Filtered
|
|
170
|
-
// > extends RouteMatcherInt<Filtered, CTXMap, Rsc> {}
|
|
171
186
|
|
|
187
|
+
// identity factory for Middleware
|
|
172
188
|
export const makeMiddleware = <
|
|
173
|
-
|
|
189
|
+
MiddlewareContext,
|
|
174
190
|
CTXMap extends Record<string, RPCContextMap.Any>,
|
|
175
|
-
|
|
176
|
-
Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
|
|
177
|
-
|
|
191
|
+
MiddlewareR,
|
|
192
|
+
Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[],
|
|
193
|
+
CtxId,
|
|
194
|
+
RRet,
|
|
195
|
+
RErr,
|
|
196
|
+
RCtx
|
|
197
|
+
>(
|
|
198
|
+
content: Middleware<MiddlewareContext, CTXMap, MiddlewareR, Layers, CtxId, RRet, RErr, RCtx>
|
|
199
|
+
): Middleware<MiddlewareContext, CTXMap, MiddlewareR, Layers, CtxId, RRet, RErr, RCtx> => content
|
|
178
200
|
|
|
179
201
|
export class Router extends HttpRouter.Tag("@effect-app/Rpc")<Router>() {}
|
|
180
202
|
|
|
181
203
|
export const makeRouter = <
|
|
182
|
-
|
|
204
|
+
MiddlewareContext,
|
|
183
205
|
CTXMap extends Record<string, RPCContextMap.Any>,
|
|
184
|
-
|
|
185
|
-
Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
|
|
206
|
+
MiddlewareR,
|
|
207
|
+
Layers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[],
|
|
208
|
+
CtxId,
|
|
209
|
+
RRet,
|
|
210
|
+
RErr,
|
|
211
|
+
RCtx
|
|
186
212
|
>(
|
|
187
|
-
middleware: Middleware<
|
|
213
|
+
middleware: Middleware<MiddlewareContext, CTXMap, MiddlewareR, Layers, CtxId, RRet, RErr, RCtx>,
|
|
188
214
|
devMode: boolean
|
|
189
215
|
) => {
|
|
190
216
|
function matchFor<
|
|
191
217
|
const ModuleName extends string,
|
|
192
|
-
const
|
|
218
|
+
const Resource extends Record<string, any>
|
|
193
219
|
>(
|
|
194
|
-
rsc:
|
|
220
|
+
rsc: Resource & { meta: { moduleName: ModuleName } }
|
|
195
221
|
) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
222
|
+
type HandlerWithInputGen<
|
|
223
|
+
Action extends AnyRequestModule,
|
|
224
|
+
RT extends RequestType
|
|
225
|
+
> = (
|
|
226
|
+
req: S.Schema.Type<Action>
|
|
227
|
+
) => Generator<
|
|
228
|
+
YieldWrap<
|
|
229
|
+
Effect<
|
|
230
|
+
any,
|
|
231
|
+
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
232
|
+
GetEffectContext<CTXMap, Action["config"]> | RRet
|
|
233
|
+
>
|
|
234
|
+
>,
|
|
235
|
+
GetSuccessShape<Action, RT>,
|
|
236
|
+
never
|
|
237
|
+
>
|
|
238
|
+
|
|
239
|
+
type HandlerWithInputEff<
|
|
240
|
+
Action extends AnyRequestModule,
|
|
241
|
+
RT extends RequestType
|
|
242
|
+
> = (
|
|
243
|
+
req: S.Schema.Type<Action>
|
|
244
|
+
) => Effect<
|
|
245
|
+
GetSuccessShape<Action, RT>,
|
|
246
|
+
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
247
|
+
GetEffectContext<CTXMap, Action["config"]> | RRet
|
|
248
|
+
>
|
|
249
|
+
|
|
250
|
+
type HandlerEff<
|
|
251
|
+
Action extends AnyRequestModule,
|
|
252
|
+
RT extends RequestType
|
|
253
|
+
> = Effect<
|
|
254
|
+
GetSuccessShape<Action, RT>,
|
|
255
|
+
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
256
|
+
GetEffectContext<CTXMap, Action["config"]> | RRet
|
|
257
|
+
>
|
|
258
|
+
|
|
259
|
+
type Handlers<Action extends AnyRequestModule, RT extends RequestType> =
|
|
260
|
+
| HandlerWithInputGen<Action, RT>
|
|
261
|
+
| HandlerWithInputEff<Action, RT>
|
|
262
|
+
| HandlerEff<Action, RT>
|
|
263
|
+
|
|
264
|
+
type HandlersDecoded<Action extends AnyRequestModule> = Handlers<Action, RequestTypes.DECODED>
|
|
265
|
+
|
|
266
|
+
type HandlersRaw<Action extends AnyRequestModule> =
|
|
267
|
+
| { raw: HandlerWithInputGen<Action, RequestTypes.TYPE> }
|
|
268
|
+
| { raw: HandlerWithInputEff<Action, RequestTypes.TYPE> }
|
|
269
|
+
| { raw: HandlerEff<Action, RequestTypes.TYPE> }
|
|
270
|
+
|
|
271
|
+
type AnyHandlers<Action extends AnyRequestModule> = HandlersRaw<Action> | HandlersDecoded<Action>
|
|
272
|
+
|
|
273
|
+
const { meta } = rsc
|
|
274
|
+
|
|
275
|
+
type RequestModules = FilterRequestModules<Resource>
|
|
276
|
+
const requestModules = typedKeysOf(rsc).reduce((acc, cur) => {
|
|
199
277
|
if (Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
|
|
200
|
-
acc[cur as keyof
|
|
278
|
+
acc[cur as keyof RequestModules] = rsc[cur]
|
|
201
279
|
}
|
|
202
280
|
return acc
|
|
203
|
-
}, {} as
|
|
281
|
+
}, {} as RequestModules)
|
|
204
282
|
|
|
205
|
-
const items = typedKeysOf(
|
|
283
|
+
const items = typedKeysOf(requestModules).reduce(
|
|
206
284
|
(prev, cur) => {
|
|
207
285
|
;(prev as any)[cur] = Object.assign((fnOrEffect: any) => {
|
|
286
|
+
// fnOrEffect is the actual handler implementation
|
|
208
287
|
if (fnOrEffect[Symbol.toStringTag] === "GeneratorFunction") fnOrEffect = Effect.fnUntraced(fnOrEffect)
|
|
209
288
|
const stack = new Error().stack?.split("\n").slice(2).join("\n")
|
|
210
289
|
return Effect.isEffect(fnOrEffect)
|
|
211
290
|
? class {
|
|
212
291
|
static request = rsc[cur]
|
|
213
292
|
static stack = stack
|
|
214
|
-
static _tag =
|
|
293
|
+
static _tag = RequestTypes.DECODED
|
|
215
294
|
static handler = () => fnOrEffect
|
|
216
295
|
}
|
|
217
296
|
: class {
|
|
218
297
|
static request = rsc[cur]
|
|
219
298
|
static stack = stack
|
|
220
|
-
static _tag =
|
|
299
|
+
static _tag = RequestTypes.DECODED
|
|
221
300
|
static handler = fnOrEffect
|
|
222
301
|
}
|
|
223
302
|
}, {
|
|
@@ -234,42 +313,24 @@ export const makeRouter = <
|
|
|
234
313
|
? class {
|
|
235
314
|
static request = rsc[cur]
|
|
236
315
|
static stack = stack
|
|
237
|
-
static _tag =
|
|
316
|
+
static _tag = RequestTypes.TYPE
|
|
238
317
|
static handler = () => fnOrEffect
|
|
239
318
|
}
|
|
240
319
|
: class {
|
|
241
320
|
static request = rsc[cur]
|
|
242
321
|
static stack = stack
|
|
243
|
-
static _tag =
|
|
244
|
-
static handler =
|
|
322
|
+
static _tag = RequestTypes.TYPE
|
|
323
|
+
static handler = fnOrEffect
|
|
245
324
|
}
|
|
246
325
|
}
|
|
247
326
|
})
|
|
248
327
|
return prev
|
|
249
328
|
},
|
|
250
|
-
{} as RouteMatcher<CTXMap,
|
|
329
|
+
{} as RouteMatcher<CTXMap, Resource, MiddlewareContext>
|
|
251
330
|
)
|
|
252
331
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
type GetSuccess<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
256
|
-
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
257
|
-
[k in keyof Layers]: Layer.Layer.Success<Layers[k]>
|
|
258
|
-
}[number]
|
|
259
|
-
: never
|
|
260
|
-
|
|
261
|
-
type GetContext<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends
|
|
262
|
-
NonEmptyReadonlyArray<Layer.Layer.Any> ? {
|
|
263
|
-
[k in keyof Layers]: Layer.Layer.Context<Layers[k]>
|
|
264
|
-
}[number]
|
|
265
|
-
: never
|
|
266
|
-
|
|
267
|
-
type GetError<Layers extends ReadonlyArray<Layer.Layer.Any>> = Layers extends NonEmptyReadonlyArray<Layer.Layer.Any>
|
|
268
|
-
? { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number]
|
|
269
|
-
: never
|
|
270
|
-
|
|
271
|
-
const total = Object.keys(filtered).length
|
|
272
|
-
const router: AddAction<Filtered[keyof Filtered]> = {
|
|
332
|
+
const total = Object.keys(requestModules).length
|
|
333
|
+
const router: AddAction<RequestModules[keyof RequestModules]> = {
|
|
273
334
|
accum: {},
|
|
274
335
|
add(a: any) {
|
|
275
336
|
;(this.accum as any)[a.request._tag] = a
|
|
@@ -279,57 +340,18 @@ export const makeRouter = <
|
|
|
279
340
|
}
|
|
280
341
|
}
|
|
281
342
|
|
|
282
|
-
type HndlrWithInputG<
|
|
283
|
-
Action extends AnyRequestModule,
|
|
284
|
-
Mode extends "d" | "raw"
|
|
285
|
-
> = (
|
|
286
|
-
req: S.Schema.Type<Action>
|
|
287
|
-
) => Generator<
|
|
288
|
-
YieldWrap<Effect<any, S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError, any>>,
|
|
289
|
-
GetSuccessShape<Action, Mode>,
|
|
290
|
-
never
|
|
291
|
-
>
|
|
292
|
-
|
|
293
|
-
type HndlrWithInput<Action extends AnyRequestModule, Mode extends "d" | "raw"> = (
|
|
294
|
-
req: S.Schema.Type<Action>
|
|
295
|
-
) => Effect<
|
|
296
|
-
GetSuccessShape<Action, Mode>,
|
|
297
|
-
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
298
|
-
any
|
|
299
|
-
>
|
|
300
|
-
|
|
301
|
-
type Hndlr<Action extends AnyRequestModule, Mode extends "d" | "raw"> = Effect<
|
|
302
|
-
GetSuccessShape<Action, Mode>,
|
|
303
|
-
S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
|
|
304
|
-
any
|
|
305
|
-
>
|
|
306
|
-
|
|
307
|
-
type Hndlrs<Action extends AnyRequestModule, Mode extends "d" | "raw"> =
|
|
308
|
-
| HndlrWithInputG<Action, Mode>
|
|
309
|
-
| HndlrWithInput<Action, Mode>
|
|
310
|
-
| Hndlr<Action, Mode>
|
|
311
|
-
|
|
312
|
-
type DHndlrs<Action extends AnyRequestModule> = Hndlrs<Action, "d">
|
|
313
|
-
|
|
314
|
-
type RawHndlrs<Action extends AnyRequestModule> =
|
|
315
|
-
| { raw: HndlrWithInputG<Action, "raw"> }
|
|
316
|
-
| { raw: HndlrWithInput<Action, "raw"> }
|
|
317
|
-
| { raw: Hndlr<Action, "raw"> }
|
|
318
|
-
|
|
319
|
-
type AnyHndlrs<Action extends AnyRequestModule> = RawHndlrs<Action> | DHndlrs<Action>
|
|
320
|
-
|
|
321
343
|
const router3: <
|
|
322
344
|
const Impl extends {
|
|
323
|
-
[K in keyof
|
|
345
|
+
[K in keyof FilterRequestModules<Resource>]: AnyHandlers<Resource[K]>
|
|
324
346
|
}
|
|
325
347
|
>(
|
|
326
348
|
impl: Impl
|
|
327
349
|
) => {
|
|
328
|
-
[K in keyof Impl & keyof
|
|
329
|
-
|
|
330
|
-
Impl[K] extends { raw: any } ?
|
|
350
|
+
[K in keyof Impl & keyof FilterRequestModules<Resource>]: Handler<
|
|
351
|
+
FilterRequestModules<Resource>[K],
|
|
352
|
+
Impl[K] extends { raw: any } ? RequestTypes.TYPE : RequestTypes.DECODED,
|
|
331
353
|
Exclude<
|
|
332
|
-
|
|
|
354
|
+
| MiddlewareContext
|
|
333
355
|
| Exclude<
|
|
334
356
|
Impl[K] extends { raw: any } ? Impl[K]["raw"] extends (...args: any[]) => Effect<any, any, infer R> ? R
|
|
335
357
|
: Impl[K]["raw"] extends Effect<any, any, infer R> ? R
|
|
@@ -347,12 +369,12 @@ export const makeRouter = <
|
|
|
347
369
|
any
|
|
348
370
|
> ? R
|
|
349
371
|
: never,
|
|
350
|
-
GetEffectContext<CTXMap,
|
|
372
|
+
GetEffectContext<CTXMap, Resource[K]["config"]>
|
|
351
373
|
>,
|
|
352
374
|
HttpRouter.HttpRouter.Provided
|
|
353
375
|
>
|
|
354
376
|
>
|
|
355
|
-
} = (obj: Record<keyof
|
|
377
|
+
} = (obj: Record<keyof RequestModules, any>) =>
|
|
356
378
|
typedKeysOf(obj).reduce((acc, cur) => {
|
|
357
379
|
acc[cur] = "raw" in obj[cur] ? items[cur].raw(obj[cur].raw) : items[cur](obj[cur])
|
|
358
380
|
return acc
|
|
@@ -363,7 +385,7 @@ export const makeRouter = <
|
|
|
363
385
|
R,
|
|
364
386
|
THandlers extends {
|
|
365
387
|
// import to keep them separate via | for type checking!!
|
|
366
|
-
[K in
|
|
388
|
+
[K in keyof RequestModules]: AnyHandler<Resource[K]>
|
|
367
389
|
},
|
|
368
390
|
TLayers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
|
|
369
391
|
>(
|
|
@@ -373,185 +395,181 @@ export const makeRouter = <
|
|
|
373
395
|
type ProvidedLayers =
|
|
374
396
|
| { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
|
|
375
397
|
| { [k in keyof TLayers]: Layer.Layer.Success<TLayers[k]> }[number]
|
|
376
|
-
type Router = RouterShape<
|
|
377
|
-
|
|
378
|
-
const layer =
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
success: S.encodedSchema(req.success)
|
|
412
|
-
}
|
|
398
|
+
type Router = RouterShape<Resource>
|
|
399
|
+
|
|
400
|
+
const layer = Effect
|
|
401
|
+
.gen(function*() {
|
|
402
|
+
make = (make as any)[Symbol.toStringTag] === "GeneratorFunction"
|
|
403
|
+
? Effect.fnUntraced(make as any)(router3) as any
|
|
404
|
+
: make
|
|
405
|
+
|
|
406
|
+
const controllers = yield* make
|
|
407
|
+
const rpc = yield* makeRpc(middleware)
|
|
408
|
+
|
|
409
|
+
// return make.pipe(Effect.map((c) => controllers(c, layers)))
|
|
410
|
+
const mapped = typedKeysOf(requestModules).reduce((acc, cur) => {
|
|
411
|
+
const handler = controllers[cur as keyof typeof controllers]
|
|
412
|
+
const req = rsc[cur]
|
|
413
|
+
|
|
414
|
+
const method = determineMethod(String(cur), req)
|
|
415
|
+
const isCommand = method._tag === "command"
|
|
416
|
+
|
|
417
|
+
const handle = isCommand
|
|
418
|
+
? (req: any, headers: HttpHeaders.Headers) =>
|
|
419
|
+
Effect.retry(handler.handler(req, headers) as any, optimisticConcurrencySchedule)
|
|
420
|
+
: (req: any, headers: HttpHeaders.Headers) => Effect.interruptible(handler.handler(req, headers) as any)
|
|
421
|
+
|
|
422
|
+
acc[cur] = [
|
|
423
|
+
handler._tag === RequestTypes.TYPE
|
|
424
|
+
? class extends (req as any) {
|
|
425
|
+
static success = S.encodedSchema(req.success)
|
|
426
|
+
get [Schema.symbolSerializable]() {
|
|
427
|
+
return this.constructor
|
|
428
|
+
}
|
|
429
|
+
get [Schema.symbolWithResult]() {
|
|
430
|
+
return {
|
|
431
|
+
failure: req.failure,
|
|
432
|
+
success: S.encodedSchema(req.success)
|
|
413
433
|
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
[K
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
any,
|
|
489
|
-
_E<ReturnType<THandlers[K]["handler"]>>,
|
|
490
|
-
Context | _R<ReturnType<THandlers[K]["handler"]>>
|
|
491
|
-
> // Context | _R<ReturnType<THandlers[K]["handler"]>>
|
|
492
|
-
]
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
const rpcs = RpcGroup.make(
|
|
496
|
-
...typedValuesOf(mapped).map((_) => {
|
|
497
|
-
return Rpc.fromTaggedRequest(_[0])
|
|
498
|
-
})
|
|
499
|
-
)
|
|
500
|
-
const rpcLayer = (requestLayers: any) =>
|
|
501
|
-
rpcs.toLayer(Effect.gen(function*() {
|
|
502
|
-
return typedValuesOf(mapped).reduce((acc, [req, handler]) => {
|
|
503
|
-
acc[req._tag] = handler(requestLayers)
|
|
504
|
-
return acc
|
|
505
|
-
}, {} as Record<string, any>)
|
|
506
|
-
})) as unknown as Layer<
|
|
507
|
-
{ [K in keyof Filtered]: Rpc.Handler<K> },
|
|
508
|
-
never,
|
|
509
|
-
RPCRouteR<typeof mapped[keyof typeof mapped]>
|
|
434
|
+
}
|
|
435
|
+
} as any
|
|
436
|
+
: req,
|
|
437
|
+
rpc.effect(req, (input: any, headers: HttpHeaders.Headers) =>
|
|
438
|
+
// TODO: render more data... similar to console?
|
|
439
|
+
Effect
|
|
440
|
+
.annotateCurrentSpan(
|
|
441
|
+
"requestInput",
|
|
442
|
+
Object.entries(input).reduce((prev, [key, value]: [string, unknown]) => {
|
|
443
|
+
prev[key] = key === "password"
|
|
444
|
+
? "<redacted>"
|
|
445
|
+
: typeof value === "string" || typeof value === "number" || typeof value === "boolean"
|
|
446
|
+
? typeof value === "string" && value.length > 256
|
|
447
|
+
? (value.substring(0, 253) + "...")
|
|
448
|
+
: value
|
|
449
|
+
: Array.isArray(value)
|
|
450
|
+
? `Array[${value.length}]`
|
|
451
|
+
: value === null || value === undefined
|
|
452
|
+
? `${value}`
|
|
453
|
+
: typeof value === "object" && value
|
|
454
|
+
? `Object[${Object.keys(value).length}]`
|
|
455
|
+
: typeof value
|
|
456
|
+
return prev
|
|
457
|
+
}, {} as Record<string, string | number | boolean>)
|
|
458
|
+
)
|
|
459
|
+
.pipe(
|
|
460
|
+
// can't use andThen due to some being a function and effect
|
|
461
|
+
Effect.zipRight(handle(input, headers)),
|
|
462
|
+
// TODO: support ParseResult if the error channel of the request allows it.. but who would want that?
|
|
463
|
+
Effect.catchAll((_) => ParseResult.isParseError(_) ? Effect.die(_) : Effect.fail(_)),
|
|
464
|
+
Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
|
|
465
|
+
Effect.tapDefect((cause) =>
|
|
466
|
+
Effect
|
|
467
|
+
.all([
|
|
468
|
+
reportRequestError(cause, {
|
|
469
|
+
action: `${meta.moduleName}.${req._tag}`
|
|
470
|
+
}),
|
|
471
|
+
InfraLogger
|
|
472
|
+
.logError("Finished request", cause)
|
|
473
|
+
.pipe(Effect.annotateLogs({
|
|
474
|
+
action: `${meta.moduleName}.${req._tag}`,
|
|
475
|
+
req: pretty(req),
|
|
476
|
+
headers: pretty(headers)
|
|
477
|
+
// resHeaders: pretty(
|
|
478
|
+
// Object
|
|
479
|
+
// .entries(headers)
|
|
480
|
+
// .reduce((prev, [key, value]) => {
|
|
481
|
+
// prev[key] = value && typeof value === "string" ? snipString(value) : value
|
|
482
|
+
// return prev
|
|
483
|
+
// }, {} as Record<string, any>)
|
|
484
|
+
// )
|
|
485
|
+
}))
|
|
486
|
+
])
|
|
487
|
+
),
|
|
488
|
+
// NOTE: this does not catch errors from the middlewares..
|
|
489
|
+
// we should re-evalute this in any case..
|
|
490
|
+
devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")),
|
|
491
|
+
Effect.withSpan("Request." + meta.moduleName + "." + req._tag, {
|
|
492
|
+
captureStackTrace: () => handler.stack
|
|
493
|
+
})
|
|
494
|
+
), meta.moduleName),
|
|
495
|
+
meta.moduleName
|
|
496
|
+
] as const
|
|
497
|
+
return acc
|
|
498
|
+
}, {} as any) as {
|
|
499
|
+
[K in keyof RequestModules]: [
|
|
500
|
+
Resource[K],
|
|
501
|
+
(
|
|
502
|
+
req: any,
|
|
503
|
+
headers: HttpHeaders.Headers
|
|
504
|
+
) => Effect.Effect<
|
|
505
|
+
any,
|
|
506
|
+
Effect.Error<ReturnType<THandlers[K]["handler"]>>,
|
|
507
|
+
MiddlewareContext | Effect.Context<ReturnType<THandlers[K]["handler"]>>
|
|
510
508
|
>
|
|
509
|
+
]
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const rpcs = RpcGroup.make(
|
|
513
|
+
...typedValuesOf(mapped).map((_) => {
|
|
514
|
+
return Rpc.fromTaggedRequest(_[0])
|
|
515
|
+
})
|
|
516
|
+
)
|
|
517
|
+
const rpcLayer = rpcs.toLayer(Effect.gen(function*() {
|
|
518
|
+
return typedValuesOf(mapped).reduce((acc, [req, handler]) => {
|
|
519
|
+
acc[req._tag] = handler
|
|
520
|
+
return acc
|
|
521
|
+
}, {} as Record<string, any>)
|
|
522
|
+
})) as unknown as Layer<
|
|
523
|
+
{ [K in keyof RequestModules]: Rpc.Handler<K> },
|
|
524
|
+
never,
|
|
525
|
+
RPCRouteR<typeof mapped[keyof typeof mapped]> | RCtx
|
|
526
|
+
>
|
|
511
527
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
)
|
|
528
|
+
const impl = rpcLayer
|
|
529
|
+
const l = RpcServer.layer(rpcs, { spanPrefix: "RpcServer." + meta.moduleName }).pipe(Layer.provide(impl))
|
|
530
|
+
return l.pipe(
|
|
531
|
+
Layer.provideMerge(
|
|
532
|
+
RpcServer.layerProtocolHttp(
|
|
533
|
+
{ path: ("/" + meta.moduleName) as `/${typeof meta.moduleName}`, routerTag: Router }
|
|
519
534
|
)
|
|
520
535
|
)
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
// const rpcRouter = RpcRouter.make(...typedValuesOf(mapped).map(_ => _[0]) as any) as RpcRouter.RpcRouter<
|
|
539
|
+
// RPCRouteReq<typeof mapped[keyof typeof mapped]>,
|
|
540
|
+
// RPCRouteR<typeof mapped[keyof typeof mapped]>
|
|
541
|
+
// >
|
|
542
|
+
// const httpApp = toHttpApp(rpcRouter, {
|
|
543
|
+
// spanPrefix: rsc
|
|
544
|
+
// .meta
|
|
545
|
+
// .moduleName + "."
|
|
546
|
+
// })
|
|
547
|
+
// yield* router
|
|
548
|
+
// .post(
|
|
549
|
+
// "/",
|
|
550
|
+
// httpApp as any,
|
|
551
|
+
// { uninterruptible: true }
|
|
552
|
+
// )
|
|
553
|
+
})
|
|
554
|
+
.pipe(Layer.unwrapEffect)
|
|
539
555
|
|
|
540
556
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
541
|
-
const routes = (
|
|
542
|
-
layer
|
|
557
|
+
const routes = (
|
|
558
|
+
layer.pipe(
|
|
543
559
|
layers && Array.isNonEmptyReadonlyArray(layers) ? Layer.provide(layers as any) as any : (_) => _,
|
|
560
|
+
Layer.provide(middleware.contextProvider.Default),
|
|
544
561
|
// TODO: only provide to the middleware?
|
|
545
562
|
middleware.dependencies ? Layer.provide(middleware.dependencies as any) : (_) => _
|
|
546
|
-
)
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
>
|
|
563
|
+
)
|
|
564
|
+
) as (Layer.Layer<
|
|
565
|
+
Router,
|
|
566
|
+
LayersUtils.GetLayersError<TLayers> | E | RErr,
|
|
567
|
+
| LayersUtils.GetLayersContext<TLayers>
|
|
568
|
+
| Exclude<
|
|
569
|
+
MiddlewareR | R | RCtx,
|
|
570
|
+
ProvidedLayers
|
|
571
|
+
>
|
|
572
|
+
>)
|
|
555
573
|
|
|
556
574
|
// Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
|
|
557
575
|
|
|
@@ -567,8 +585,10 @@ export const makeRouter = <
|
|
|
567
585
|
const Make extends {
|
|
568
586
|
dependencies: Array<Layer.Layer.Any>
|
|
569
587
|
effect: (match: typeof router3) => Generator<
|
|
570
|
-
YieldWrap<
|
|
571
|
-
|
|
588
|
+
YieldWrap<
|
|
589
|
+
Effect<any, any, Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>>
|
|
590
|
+
>,
|
|
591
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
572
592
|
any
|
|
573
593
|
>
|
|
574
594
|
|
|
@@ -581,12 +601,15 @@ export const makeRouter = <
|
|
|
581
601
|
): {
|
|
582
602
|
moduleName: ModuleName
|
|
583
603
|
|
|
584
|
-
routes:
|
|
585
|
-
RouterShape<
|
|
586
|
-
MakeErrors<Make> |
|
|
587
|
-
|
|
|
604
|
+
routes: Layer.Layer<
|
|
605
|
+
RouterShape<Resource>,
|
|
606
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
607
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
588
608
|
// | GetContext<Layers> // elsewhere provided
|
|
589
|
-
| Exclude<
|
|
609
|
+
| Exclude<
|
|
610
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
611
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
612
|
+
>
|
|
590
613
|
>
|
|
591
614
|
|
|
592
615
|
// just for type testing purposes
|
|
@@ -596,9 +619,9 @@ export const makeRouter = <
|
|
|
596
619
|
const Make extends {
|
|
597
620
|
dependencies: Array<Layer.Layer.Any>
|
|
598
621
|
effect: Effect<
|
|
599
|
-
{ [K in keyof
|
|
622
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
600
623
|
any,
|
|
601
|
-
Make["strict"] extends false ? any :
|
|
624
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
602
625
|
>
|
|
603
626
|
strict?: boolean
|
|
604
627
|
/** @deprecated */
|
|
@@ -609,12 +632,15 @@ export const makeRouter = <
|
|
|
609
632
|
): {
|
|
610
633
|
moduleName: ModuleName
|
|
611
634
|
|
|
612
|
-
routes:
|
|
613
|
-
RouterShape<
|
|
614
|
-
MakeErrors<Make> |
|
|
615
|
-
|
|
|
635
|
+
routes: Layer.Layer<
|
|
636
|
+
RouterShape<Resource>,
|
|
637
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
638
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
616
639
|
// | GetContext<Layers> // elsewhere provided
|
|
617
|
-
| Exclude<
|
|
640
|
+
| Exclude<
|
|
641
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
642
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
643
|
+
>
|
|
618
644
|
>
|
|
619
645
|
|
|
620
646
|
// just for type testing purposes
|
|
@@ -624,9 +650,9 @@ export const makeRouter = <
|
|
|
624
650
|
const Make extends {
|
|
625
651
|
dependencies: Array<Layer.Layer.Any>
|
|
626
652
|
effect: Effect<
|
|
627
|
-
{ [K in keyof
|
|
653
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
628
654
|
any,
|
|
629
|
-
Make["strict"] extends false ? any :
|
|
655
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
630
656
|
>
|
|
631
657
|
strict?: boolean
|
|
632
658
|
/** @deprecated */
|
|
@@ -637,12 +663,15 @@ export const makeRouter = <
|
|
|
637
663
|
): {
|
|
638
664
|
moduleName: ModuleName
|
|
639
665
|
|
|
640
|
-
routes:
|
|
641
|
-
RouterShape<
|
|
642
|
-
MakeErrors<Make> |
|
|
643
|
-
|
|
|
666
|
+
routes: Layer.Layer<
|
|
667
|
+
RouterShape<Resource>,
|
|
668
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
669
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
644
670
|
// | GetContext<Layers> // elsewhere provided
|
|
645
|
-
| Exclude<
|
|
671
|
+
| Exclude<
|
|
672
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
673
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
674
|
+
>
|
|
646
675
|
>
|
|
647
676
|
|
|
648
677
|
// just for type testing purposes
|
|
@@ -652,9 +681,9 @@ export const makeRouter = <
|
|
|
652
681
|
const Make extends {
|
|
653
682
|
dependencies: Array<Layer.Layer.Any>
|
|
654
683
|
effect: Effect<
|
|
655
|
-
{ [K in keyof
|
|
684
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
656
685
|
any,
|
|
657
|
-
Make["strict"] extends false ? any :
|
|
686
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
658
687
|
>
|
|
659
688
|
strict?: boolean
|
|
660
689
|
/** @deprecated */
|
|
@@ -665,12 +694,15 @@ export const makeRouter = <
|
|
|
665
694
|
): {
|
|
666
695
|
moduleName: ModuleName
|
|
667
696
|
|
|
668
|
-
routes:
|
|
669
|
-
RouterShape<
|
|
670
|
-
MakeErrors<Make> |
|
|
671
|
-
|
|
|
697
|
+
routes: Layer.Layer<
|
|
698
|
+
RouterShape<Resource>,
|
|
699
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
700
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
672
701
|
// | GetContext<Layers> // elsewhere provided
|
|
673
|
-
| Exclude<
|
|
702
|
+
| Exclude<
|
|
703
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
704
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
705
|
+
>
|
|
674
706
|
>
|
|
675
707
|
|
|
676
708
|
// just for type testing purposes
|
|
@@ -680,9 +712,9 @@ export const makeRouter = <
|
|
|
680
712
|
const Make extends {
|
|
681
713
|
dependencies: Array<Layer.Layer.Any>
|
|
682
714
|
effect: Effect<
|
|
683
|
-
{ [K in keyof
|
|
715
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
684
716
|
any,
|
|
685
|
-
|
|
717
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
686
718
|
>
|
|
687
719
|
strict?: boolean
|
|
688
720
|
/** @deprecated */
|
|
@@ -693,12 +725,15 @@ export const makeRouter = <
|
|
|
693
725
|
): {
|
|
694
726
|
moduleName: ModuleName
|
|
695
727
|
|
|
696
|
-
routes:
|
|
697
|
-
RouterShape<
|
|
698
|
-
MakeErrors<Make> |
|
|
699
|
-
|
|
|
728
|
+
routes: Layer.Layer<
|
|
729
|
+
RouterShape<Resource>,
|
|
730
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
731
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
700
732
|
// | GetContext<Layers> // elsewhere provided
|
|
701
|
-
| Exclude<
|
|
733
|
+
| Exclude<
|
|
734
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
735
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
736
|
+
>
|
|
702
737
|
>
|
|
703
738
|
|
|
704
739
|
// just for type testing purposes
|
|
@@ -708,9 +743,9 @@ export const makeRouter = <
|
|
|
708
743
|
const Make extends {
|
|
709
744
|
dependencies: Array<Layer.Layer.Any>
|
|
710
745
|
effect: Effect<
|
|
711
|
-
{ [K in keyof
|
|
746
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
712
747
|
any,
|
|
713
|
-
|
|
748
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
714
749
|
>
|
|
715
750
|
strict?: boolean
|
|
716
751
|
}
|
|
@@ -719,12 +754,15 @@ export const makeRouter = <
|
|
|
719
754
|
): {
|
|
720
755
|
moduleName: ModuleName
|
|
721
756
|
|
|
722
|
-
routes:
|
|
723
|
-
RouterShape<
|
|
724
|
-
MakeErrors<Make> |
|
|
725
|
-
|
|
|
757
|
+
routes: Layer.Layer<
|
|
758
|
+
RouterShape<Resource>,
|
|
759
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
760
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
726
761
|
// | GetContext<Layers> // elsewhere provided
|
|
727
|
-
| Exclude<
|
|
762
|
+
| Exclude<
|
|
763
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
764
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
765
|
+
>
|
|
728
766
|
>
|
|
729
767
|
|
|
730
768
|
// just for type testing purposes
|
|
@@ -734,8 +772,10 @@ export const makeRouter = <
|
|
|
734
772
|
const Make extends {
|
|
735
773
|
dependencies: Array<Layer.Layer.Any>
|
|
736
774
|
effect: (match: typeof router3) => Generator<
|
|
737
|
-
YieldWrap<
|
|
738
|
-
|
|
775
|
+
YieldWrap<
|
|
776
|
+
Effect<any, any, Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>>
|
|
777
|
+
>,
|
|
778
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
739
779
|
any
|
|
740
780
|
>
|
|
741
781
|
|
|
@@ -746,12 +786,15 @@ export const makeRouter = <
|
|
|
746
786
|
): {
|
|
747
787
|
moduleName: ModuleName
|
|
748
788
|
|
|
749
|
-
routes:
|
|
750
|
-
RouterShape<
|
|
751
|
-
MakeErrors<Make> |
|
|
752
|
-
|
|
|
789
|
+
routes: Layer.Layer<
|
|
790
|
+
RouterShape<Resource>,
|
|
791
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
792
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
753
793
|
// | GetContext<Layers> // elsewhere provided
|
|
754
|
-
| Exclude<
|
|
794
|
+
| Exclude<
|
|
795
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
796
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
797
|
+
>
|
|
755
798
|
>
|
|
756
799
|
|
|
757
800
|
// just for type testing purposes
|
|
@@ -765,7 +808,7 @@ export const makeRouter = <
|
|
|
765
808
|
: [Layer.Layer<Exclude<Effect.Context<Make["effect"]>, MakeDepsOut<Make>>, never, never>]
|
|
766
809
|
]
|
|
767
810
|
effect: Effect<
|
|
768
|
-
{ [K in keyof
|
|
811
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
769
812
|
any,
|
|
770
813
|
any
|
|
771
814
|
>
|
|
@@ -776,13 +819,13 @@ export const makeRouter = <
|
|
|
776
819
|
): {
|
|
777
820
|
moduleName: ModuleName
|
|
778
821
|
Router: HttpRouter.HttpRouter.TagClass<
|
|
779
|
-
RouterShape<
|
|
822
|
+
RouterShape<Resource>,
|
|
780
823
|
`${ModuleName}Router`,
|
|
781
824
|
never,
|
|
782
|
-
Exclude<
|
|
825
|
+
Exclude<MiddlewareContext, HttpRouter.HttpRouter.Provided>
|
|
783
826
|
> // | Exclude<
|
|
784
827
|
// RPCRouteR<
|
|
785
|
-
// { [K in keyof Filter<
|
|
828
|
+
// { [K in keyof Filter<Resource>]: Rpc.Rpc<Resource[K], Effect.Context<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Resource>]
|
|
786
829
|
// >,
|
|
787
830
|
// HttpRouter.HttpRouter.Provided
|
|
788
831
|
// >
|
|
@@ -801,20 +844,19 @@ export const makeRouter = <
|
|
|
801
844
|
type RequestHandlersTest = {
|
|
802
845
|
[key: string]: {
|
|
803
846
|
// Router: { router: Effect<HttpRouter.HttpRouter<any, any>, any, any> }
|
|
804
|
-
routes:
|
|
847
|
+
routes: Layer.Layer<any, any, any>
|
|
805
848
|
moduleName: string
|
|
806
849
|
}
|
|
807
850
|
}
|
|
808
|
-
function matchAll<T extends RequestHandlersTest
|
|
809
|
-
handlers: T
|
|
810
|
-
requestLayer: Layer.Layer<A, E, R>
|
|
851
|
+
function matchAll<T extends RequestHandlersTest>(
|
|
852
|
+
handlers: T
|
|
811
853
|
) {
|
|
812
854
|
const routers = typedValuesOf(handlers)
|
|
813
855
|
|
|
814
|
-
return Layer.mergeAll(...routers.map((_) => _.routes
|
|
856
|
+
return Layer.mergeAll(...routers.map((_) => _.routes) as [any]) as unknown as Layer.Layer<
|
|
815
857
|
never,
|
|
816
|
-
Layer.Layer.Error<
|
|
817
|
-
Layer.Layer.Context<
|
|
858
|
+
Layer.Layer.Error<typeof handlers[keyof typeof handlers]["routes"]>,
|
|
859
|
+
Layer.Layer.Context<typeof handlers[keyof typeof handlers]["routes"]>
|
|
818
860
|
> // TODO
|
|
819
861
|
}
|
|
820
862
|
|
|
@@ -822,9 +864,9 @@ export const makeRouter = <
|
|
|
822
864
|
matchAll,
|
|
823
865
|
matchFor: <
|
|
824
866
|
const ModuleName extends string,
|
|
825
|
-
const
|
|
867
|
+
const Resource extends Record<string, any>
|
|
826
868
|
>(
|
|
827
|
-
rsc:
|
|
869
|
+
rsc: Resource & { meta: { moduleName: ModuleName } }
|
|
828
870
|
) => matchFor(rsc).router3,
|
|
829
871
|
Router: matchFor
|
|
830
872
|
}
|
|
@@ -843,7 +885,7 @@ export type MakeContext<Make> = Make extends { readonly effect: Effect<any, any,
|
|
|
843
885
|
: never
|
|
844
886
|
|
|
845
887
|
export type MakeHandlers<Make, Handlers extends Record<string, any>> = Make extends
|
|
846
|
-
{ readonly effect: Effect<{ [K in keyof Handlers]:
|
|
888
|
+
{ readonly effect: Effect<{ [K in keyof Handlers]: AnyHandler<Handlers[K]> }, any, any> }
|
|
847
889
|
? Effect.Success<Make["effect"]>
|
|
848
890
|
: Make extends { readonly effect: (_: any) => Generator<YieldWrap<any>, infer S, any> } ? S
|
|
849
891
|
: never
|
|
@@ -860,3 +902,8 @@ export const RequestCacheLayers = Layer.mergeAll(
|
|
|
860
902
|
Layer.setRequestCaching(true),
|
|
861
903
|
Layer.setRequestBatching(true)
|
|
862
904
|
)
|
|
905
|
+
|
|
906
|
+
export class DefaultContextMaker extends Effect.Service<DefaultContextMaker>()("ContextMaker", {
|
|
907
|
+
strict: false,
|
|
908
|
+
succeed: Effect.succeed(Context.empty())
|
|
909
|
+
}) {}
|