@effect-app/infra 2.64.5 → 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 +17 -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 +458 -401
- package/test/controller.test.ts +65 -128
- 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 +46 -23
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/controller6.test.d.ts.map +1 -1
- package/test/dist/controller7.test.d.ts.map +1 -1
- package/test/dist/controller5.test.d.ts.map +0 -1
- package/vitest.config.ts.timestamp-1711656440838-19c636fe320df.mjs +0 -0
- package/vitest.config.ts.timestamp-1711724061890-6ecedb0a07fdd.mjs +0 -0
- package/vitest.config.ts.timestamp-1711743489537-da8d9e5f66c9f.mjs +0 -0
- package/vitest.config.ts.timestamp-1711744615239-dcf257a844e01.mjs +0 -37
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,70 +340,41 @@ 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
|
|
358
|
+
: Impl[K]["raw"] extends (...args: any[]) => Generator<
|
|
359
|
+
YieldWrap<Effect<any, any, infer R>>,
|
|
360
|
+
any,
|
|
361
|
+
any
|
|
362
|
+
> ? R
|
|
336
363
|
: never
|
|
337
364
|
: Impl[K] extends (...args: any[]) => Effect<any, any, infer R> ? R
|
|
338
365
|
: Impl[K] extends Effect<any, any, infer R> ? R
|
|
366
|
+
: Impl[K] extends (...args: any[]) => Generator<
|
|
367
|
+
YieldWrap<Effect<any, any, infer R>>,
|
|
368
|
+
any,
|
|
369
|
+
any
|
|
370
|
+
> ? R
|
|
339
371
|
: never,
|
|
340
|
-
GetEffectContext<CTXMap,
|
|
372
|
+
GetEffectContext<CTXMap, Resource[K]["config"]>
|
|
341
373
|
>,
|
|
342
374
|
HttpRouter.HttpRouter.Provided
|
|
343
375
|
>
|
|
344
376
|
>
|
|
345
|
-
} = (obj: Record<keyof
|
|
377
|
+
} = (obj: Record<keyof RequestModules, any>) =>
|
|
346
378
|
typedKeysOf(obj).reduce((acc, cur) => {
|
|
347
379
|
acc[cur] = "raw" in obj[cur] ? items[cur].raw(obj[cur].raw) : items[cur](obj[cur])
|
|
348
380
|
return acc
|
|
@@ -353,195 +385,191 @@ export const makeRouter = <
|
|
|
353
385
|
R,
|
|
354
386
|
THandlers extends {
|
|
355
387
|
// import to keep them separate via | for type checking!!
|
|
356
|
-
[K in
|
|
388
|
+
[K in keyof RequestModules]: AnyHandler<Resource[K]>
|
|
357
389
|
},
|
|
358
390
|
TLayers extends NonEmptyReadonlyArray<Layer.Layer.Any> | never[]
|
|
359
391
|
>(
|
|
360
392
|
layers: TLayers,
|
|
361
|
-
make: Effect<THandlers, E, R> | Generator<YieldWrap<Effect<any, any,
|
|
393
|
+
make: Effect<THandlers, E, R> | Generator<YieldWrap<Effect<any, any, R>>, THandlers, E>
|
|
362
394
|
) => {
|
|
363
395
|
type ProvidedLayers =
|
|
364
396
|
| { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
|
|
365
397
|
| { [k in keyof TLayers]: Layer.Layer.Success<TLayers[k]> }[number]
|
|
366
|
-
type Router = RouterShape<
|
|
367
|
-
|
|
368
|
-
const layer =
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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)
|
|
397
433
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
requestLayers: any
|
|
474
|
-
) => (
|
|
475
|
-
req: any,
|
|
476
|
-
headers: HttpHeaders.Headers
|
|
477
|
-
) => Effect.Effect<
|
|
478
|
-
any,
|
|
479
|
-
_E<ReturnType<THandlers[K]["handler"]>>,
|
|
480
|
-
Context | _R<ReturnType<THandlers[K]["handler"]>>
|
|
481
|
-
> // Context | _R<ReturnType<THandlers[K]["handler"]>>
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
const rpcs = RpcGroup.make(
|
|
486
|
-
...typedValuesOf(mapped).map((_) => {
|
|
487
|
-
return Rpc.fromTaggedRequest(_[0])
|
|
488
|
-
})
|
|
489
|
-
)
|
|
490
|
-
const rpcLayer = (requestLayers: any) =>
|
|
491
|
-
rpcs.toLayer(Effect.gen(function*() {
|
|
492
|
-
return typedValuesOf(mapped).reduce((acc, [req, handler]) => {
|
|
493
|
-
acc[req._tag] = handler(requestLayers)
|
|
494
|
-
return acc
|
|
495
|
-
}, {} as Record<string, any>)
|
|
496
|
-
})) as unknown as Layer<
|
|
497
|
-
{ [K in keyof Filtered]: Rpc.Handler<K> },
|
|
498
|
-
never,
|
|
499
|
-
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"]>>
|
|
500
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
|
+
>
|
|
501
527
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
)
|
|
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 }
|
|
509
534
|
)
|
|
510
535
|
)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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)
|
|
529
555
|
|
|
530
556
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
531
|
-
const routes = (
|
|
532
|
-
layer
|
|
557
|
+
const routes = (
|
|
558
|
+
layer.pipe(
|
|
533
559
|
layers && Array.isNonEmptyReadonlyArray(layers) ? Layer.provide(layers as any) as any : (_) => _,
|
|
560
|
+
Layer.provide(middleware.contextProvider.Default),
|
|
534
561
|
// TODO: only provide to the middleware?
|
|
535
562
|
middleware.dependencies ? Layer.provide(middleware.dependencies as any) : (_) => _
|
|
536
|
-
)
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
>
|
|
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
|
+
>)
|
|
545
573
|
|
|
546
574
|
// Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
|
|
547
575
|
|
|
@@ -557,8 +585,10 @@ export const makeRouter = <
|
|
|
557
585
|
const Make extends {
|
|
558
586
|
dependencies: Array<Layer.Layer.Any>
|
|
559
587
|
effect: (match: typeof router3) => Generator<
|
|
560
|
-
YieldWrap<
|
|
561
|
-
|
|
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]> },
|
|
562
592
|
any
|
|
563
593
|
>
|
|
564
594
|
|
|
@@ -571,12 +601,15 @@ export const makeRouter = <
|
|
|
571
601
|
): {
|
|
572
602
|
moduleName: ModuleName
|
|
573
603
|
|
|
574
|
-
routes:
|
|
575
|
-
RouterShape<
|
|
576
|
-
MakeErrors<Make> |
|
|
577
|
-
|
|
|
604
|
+
routes: Layer.Layer<
|
|
605
|
+
RouterShape<Resource>,
|
|
606
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
607
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
578
608
|
// | GetContext<Layers> // elsewhere provided
|
|
579
|
-
| Exclude<
|
|
609
|
+
| Exclude<
|
|
610
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
611
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
612
|
+
>
|
|
580
613
|
>
|
|
581
614
|
|
|
582
615
|
// just for type testing purposes
|
|
@@ -586,9 +619,9 @@ export const makeRouter = <
|
|
|
586
619
|
const Make extends {
|
|
587
620
|
dependencies: Array<Layer.Layer.Any>
|
|
588
621
|
effect: Effect<
|
|
589
|
-
{ [K in keyof
|
|
622
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
590
623
|
any,
|
|
591
|
-
Make["strict"] extends false ? any :
|
|
624
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
592
625
|
>
|
|
593
626
|
strict?: boolean
|
|
594
627
|
/** @deprecated */
|
|
@@ -599,12 +632,15 @@ export const makeRouter = <
|
|
|
599
632
|
): {
|
|
600
633
|
moduleName: ModuleName
|
|
601
634
|
|
|
602
|
-
routes:
|
|
603
|
-
RouterShape<
|
|
604
|
-
MakeErrors<Make> |
|
|
605
|
-
|
|
|
635
|
+
routes: Layer.Layer<
|
|
636
|
+
RouterShape<Resource>,
|
|
637
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
638
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
606
639
|
// | GetContext<Layers> // elsewhere provided
|
|
607
|
-
| Exclude<
|
|
640
|
+
| Exclude<
|
|
641
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
642
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
643
|
+
>
|
|
608
644
|
>
|
|
609
645
|
|
|
610
646
|
// just for type testing purposes
|
|
@@ -614,9 +650,9 @@ export const makeRouter = <
|
|
|
614
650
|
const Make extends {
|
|
615
651
|
dependencies: Array<Layer.Layer.Any>
|
|
616
652
|
effect: Effect<
|
|
617
|
-
{ [K in keyof
|
|
653
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
618
654
|
any,
|
|
619
|
-
Make["strict"] extends false ? any :
|
|
655
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
620
656
|
>
|
|
621
657
|
strict?: boolean
|
|
622
658
|
/** @deprecated */
|
|
@@ -627,12 +663,15 @@ export const makeRouter = <
|
|
|
627
663
|
): {
|
|
628
664
|
moduleName: ModuleName
|
|
629
665
|
|
|
630
|
-
routes:
|
|
631
|
-
RouterShape<
|
|
632
|
-
MakeErrors<Make> |
|
|
633
|
-
|
|
|
666
|
+
routes: Layer.Layer<
|
|
667
|
+
RouterShape<Resource>,
|
|
668
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
669
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
634
670
|
// | GetContext<Layers> // elsewhere provided
|
|
635
|
-
| Exclude<
|
|
671
|
+
| Exclude<
|
|
672
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
673
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
674
|
+
>
|
|
636
675
|
>
|
|
637
676
|
|
|
638
677
|
// just for type testing purposes
|
|
@@ -642,9 +681,9 @@ export const makeRouter = <
|
|
|
642
681
|
const Make extends {
|
|
643
682
|
dependencies: Array<Layer.Layer.Any>
|
|
644
683
|
effect: Effect<
|
|
645
|
-
{ [K in keyof
|
|
684
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
646
685
|
any,
|
|
647
|
-
Make["strict"] extends false ? any :
|
|
686
|
+
Make["strict"] extends false ? any : LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
648
687
|
>
|
|
649
688
|
strict?: boolean
|
|
650
689
|
/** @deprecated */
|
|
@@ -655,12 +694,15 @@ export const makeRouter = <
|
|
|
655
694
|
): {
|
|
656
695
|
moduleName: ModuleName
|
|
657
696
|
|
|
658
|
-
routes:
|
|
659
|
-
RouterShape<
|
|
660
|
-
MakeErrors<Make> |
|
|
661
|
-
|
|
|
697
|
+
routes: Layer.Layer<
|
|
698
|
+
RouterShape<Resource>,
|
|
699
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
700
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
662
701
|
// | GetContext<Layers> // elsewhere provided
|
|
663
|
-
| Exclude<
|
|
702
|
+
| Exclude<
|
|
703
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
704
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
705
|
+
>
|
|
664
706
|
>
|
|
665
707
|
|
|
666
708
|
// just for type testing purposes
|
|
@@ -670,9 +712,9 @@ export const makeRouter = <
|
|
|
670
712
|
const Make extends {
|
|
671
713
|
dependencies: Array<Layer.Layer.Any>
|
|
672
714
|
effect: Effect<
|
|
673
|
-
{ [K in keyof
|
|
715
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
674
716
|
any,
|
|
675
|
-
|
|
717
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
676
718
|
>
|
|
677
719
|
strict?: boolean
|
|
678
720
|
/** @deprecated */
|
|
@@ -683,12 +725,15 @@ export const makeRouter = <
|
|
|
683
725
|
): {
|
|
684
726
|
moduleName: ModuleName
|
|
685
727
|
|
|
686
|
-
routes:
|
|
687
|
-
RouterShape<
|
|
688
|
-
MakeErrors<Make> |
|
|
689
|
-
|
|
|
728
|
+
routes: Layer.Layer<
|
|
729
|
+
RouterShape<Resource>,
|
|
730
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
731
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
690
732
|
// | GetContext<Layers> // elsewhere provided
|
|
691
|
-
| Exclude<
|
|
733
|
+
| Exclude<
|
|
734
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
735
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
736
|
+
>
|
|
692
737
|
>
|
|
693
738
|
|
|
694
739
|
// just for type testing purposes
|
|
@@ -698,9 +743,9 @@ export const makeRouter = <
|
|
|
698
743
|
const Make extends {
|
|
699
744
|
dependencies: Array<Layer.Layer.Any>
|
|
700
745
|
effect: Effect<
|
|
701
|
-
{ [K in keyof
|
|
746
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
702
747
|
any,
|
|
703
|
-
|
|
748
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]>
|
|
704
749
|
>
|
|
705
750
|
strict?: boolean
|
|
706
751
|
}
|
|
@@ -709,12 +754,15 @@ export const makeRouter = <
|
|
|
709
754
|
): {
|
|
710
755
|
moduleName: ModuleName
|
|
711
756
|
|
|
712
|
-
routes:
|
|
713
|
-
RouterShape<
|
|
714
|
-
MakeErrors<Make> |
|
|
715
|
-
|
|
|
757
|
+
routes: Layer.Layer<
|
|
758
|
+
RouterShape<Resource>,
|
|
759
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
760
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
716
761
|
// | GetContext<Layers> // elsewhere provided
|
|
717
|
-
| Exclude<
|
|
762
|
+
| Exclude<
|
|
763
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
764
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
765
|
+
>
|
|
718
766
|
>
|
|
719
767
|
|
|
720
768
|
// just for type testing purposes
|
|
@@ -724,8 +772,10 @@ export const makeRouter = <
|
|
|
724
772
|
const Make extends {
|
|
725
773
|
dependencies: Array<Layer.Layer.Any>
|
|
726
774
|
effect: (match: typeof router3) => Generator<
|
|
727
|
-
YieldWrap<
|
|
728
|
-
|
|
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]> },
|
|
729
779
|
any
|
|
730
780
|
>
|
|
731
781
|
|
|
@@ -736,12 +786,15 @@ export const makeRouter = <
|
|
|
736
786
|
): {
|
|
737
787
|
moduleName: ModuleName
|
|
738
788
|
|
|
739
|
-
routes:
|
|
740
|
-
RouterShape<
|
|
741
|
-
MakeErrors<Make> |
|
|
742
|
-
|
|
|
789
|
+
routes: Layer.Layer<
|
|
790
|
+
RouterShape<Resource>,
|
|
791
|
+
MakeErrors<Make> | LayersUtils.GetLayersError<Make["dependencies"]>,
|
|
792
|
+
| LayersUtils.GetLayersContext<Make["dependencies"]>
|
|
743
793
|
// | GetContext<Layers> // elsewhere provided
|
|
744
|
-
| Exclude<
|
|
794
|
+
| Exclude<
|
|
795
|
+
MakeContext<Make> | MiddlewareR | RCtx,
|
|
796
|
+
LayersUtils.GetLayersSuccess<Make["dependencies"]> | LayersUtils.GetLayersSuccess<Layers>
|
|
797
|
+
>
|
|
745
798
|
>
|
|
746
799
|
|
|
747
800
|
// just for type testing purposes
|
|
@@ -755,7 +808,7 @@ export const makeRouter = <
|
|
|
755
808
|
: [Layer.Layer<Exclude<Effect.Context<Make["effect"]>, MakeDepsOut<Make>>, never, never>]
|
|
756
809
|
]
|
|
757
810
|
effect: Effect<
|
|
758
|
-
{ [K in keyof
|
|
811
|
+
{ [K in keyof FilterRequestModules<Resource>]: AnyHandler<Resource[K]> },
|
|
759
812
|
any,
|
|
760
813
|
any
|
|
761
814
|
>
|
|
@@ -766,13 +819,13 @@ export const makeRouter = <
|
|
|
766
819
|
): {
|
|
767
820
|
moduleName: ModuleName
|
|
768
821
|
Router: HttpRouter.HttpRouter.TagClass<
|
|
769
|
-
RouterShape<
|
|
822
|
+
RouterShape<Resource>,
|
|
770
823
|
`${ModuleName}Router`,
|
|
771
824
|
never,
|
|
772
|
-
Exclude<
|
|
825
|
+
Exclude<MiddlewareContext, HttpRouter.HttpRouter.Provided>
|
|
773
826
|
> // | Exclude<
|
|
774
827
|
// RPCRouteR<
|
|
775
|
-
// { [K in keyof Filter<
|
|
828
|
+
// { [K in keyof Filter<Resource>]: Rpc.Rpc<Resource[K], Effect.Context<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Resource>]
|
|
776
829
|
// >,
|
|
777
830
|
// HttpRouter.HttpRouter.Provided
|
|
778
831
|
// >
|
|
@@ -791,20 +844,19 @@ export const makeRouter = <
|
|
|
791
844
|
type RequestHandlersTest = {
|
|
792
845
|
[key: string]: {
|
|
793
846
|
// Router: { router: Effect<HttpRouter.HttpRouter<any, any>, any, any> }
|
|
794
|
-
routes:
|
|
847
|
+
routes: Layer.Layer<any, any, any>
|
|
795
848
|
moduleName: string
|
|
796
849
|
}
|
|
797
850
|
}
|
|
798
|
-
function matchAll<T extends RequestHandlersTest
|
|
799
|
-
handlers: T
|
|
800
|
-
requestLayer: Layer.Layer<A, E, R>
|
|
851
|
+
function matchAll<T extends RequestHandlersTest>(
|
|
852
|
+
handlers: T
|
|
801
853
|
) {
|
|
802
854
|
const routers = typedValuesOf(handlers)
|
|
803
855
|
|
|
804
|
-
return Layer.mergeAll(...routers.map((_) => _.routes
|
|
856
|
+
return Layer.mergeAll(...routers.map((_) => _.routes) as [any]) as unknown as Layer.Layer<
|
|
805
857
|
never,
|
|
806
|
-
Layer.Layer.Error<
|
|
807
|
-
Layer.Layer.Context<
|
|
858
|
+
Layer.Layer.Error<typeof handlers[keyof typeof handlers]["routes"]>,
|
|
859
|
+
Layer.Layer.Context<typeof handlers[keyof typeof handlers]["routes"]>
|
|
808
860
|
> // TODO
|
|
809
861
|
}
|
|
810
862
|
|
|
@@ -812,9 +864,9 @@ export const makeRouter = <
|
|
|
812
864
|
matchAll,
|
|
813
865
|
matchFor: <
|
|
814
866
|
const ModuleName extends string,
|
|
815
|
-
const
|
|
867
|
+
const Resource extends Record<string, any>
|
|
816
868
|
>(
|
|
817
|
-
rsc:
|
|
869
|
+
rsc: Resource & { meta: { moduleName: ModuleName } }
|
|
818
870
|
) => matchFor(rsc).router3,
|
|
819
871
|
Router: matchFor
|
|
820
872
|
}
|
|
@@ -833,7 +885,7 @@ export type MakeContext<Make> = Make extends { readonly effect: Effect<any, any,
|
|
|
833
885
|
: never
|
|
834
886
|
|
|
835
887
|
export type MakeHandlers<Make, Handlers extends Record<string, any>> = Make extends
|
|
836
|
-
{ readonly effect: Effect<{ [K in keyof Handlers]:
|
|
888
|
+
{ readonly effect: Effect<{ [K in keyof Handlers]: AnyHandler<Handlers[K]> }, any, any> }
|
|
837
889
|
? Effect.Success<Make["effect"]>
|
|
838
890
|
: Make extends { readonly effect: (_: any) => Generator<YieldWrap<any>, infer S, any> } ? S
|
|
839
891
|
: never
|
|
@@ -850,3 +902,8 @@ export const RequestCacheLayers = Layer.mergeAll(
|
|
|
850
902
|
Layer.setRequestCaching(true),
|
|
851
903
|
Layer.setRequestBatching(true)
|
|
852
904
|
)
|
|
905
|
+
|
|
906
|
+
export class DefaultContextMaker extends Effect.Service<DefaultContextMaker>()("ContextMaker", {
|
|
907
|
+
strict: false,
|
|
908
|
+
succeed: Effect.succeed(Context.empty())
|
|
909
|
+
}) {}
|