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