@effect-app/infra 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/_cjs/router.cjs +150 -0
- package/_cjs/router.cjs.map +1 -0
- package/dist/api/routing/match.d.ts +1 -1
- package/dist/router.d.ts +121 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +136 -0
- package/package.json +14 -4
- package/src/router.ts +547 -0
- 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 +37 -0
package/CHANGELOG.md
CHANGED
package/_cjs/router.cjs
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.makeRouter = void 0;
|
|
7
|
+
var _Effect = require("@effect-app/core/Effect");
|
|
8
|
+
var _utils = require("@effect-app/core/utils");
|
|
9
|
+
var _routing = require("@effect-app/infra/api/routing");
|
|
10
|
+
var _effectApp = require("effect-app");
|
|
11
|
+
var _http = require("effect-app/http");
|
|
12
|
+
var _schema = require("effect-app/schema");
|
|
13
|
+
// TODO: support FLIP
|
|
14
|
+
const makeRouter = (handleRequestEnv /* Middleware */) => {
|
|
15
|
+
function match(requestHandler, errorHandler, middleware) {
|
|
16
|
+
let middlewareLayer = undefined;
|
|
17
|
+
if (middleware) {
|
|
18
|
+
const {
|
|
19
|
+
handler,
|
|
20
|
+
makeRequestLayer
|
|
21
|
+
} = middleware(requestHandler);
|
|
22
|
+
requestHandler = handler; // todo
|
|
23
|
+
middlewareLayer = makeRequestLayer;
|
|
24
|
+
}
|
|
25
|
+
// const rdesc = yield* RouteDescriptors.flatMap((_) => _.get)
|
|
26
|
+
const handler = (0, _routing.makeRequestHandler)(requestHandler,
|
|
27
|
+
// one argument if no middleware, 2 if has middleware. TODO: clean this shit up
|
|
28
|
+
errorHandler, middlewareLayer);
|
|
29
|
+
const route = _http.HttpRouter.makeRoute(requestHandler.Request.method, requestHandler.Request.path, handler);
|
|
30
|
+
// TODO
|
|
31
|
+
// rdesc.push(makeRouteDescriptor(
|
|
32
|
+
// requestHandler.Request.path,
|
|
33
|
+
// requestHandler.Request.method,
|
|
34
|
+
// requestHandler
|
|
35
|
+
// ))
|
|
36
|
+
return route;
|
|
37
|
+
}
|
|
38
|
+
function handle(_, name, adaptResponse) {
|
|
39
|
+
const Request = _effectApp.S.REST.extractRequest(_);
|
|
40
|
+
const Response = _effectApp.S.REST.extractResponse(_);
|
|
41
|
+
return h => ({
|
|
42
|
+
adaptResponse,
|
|
43
|
+
h: h.handler,
|
|
44
|
+
name,
|
|
45
|
+
Request,
|
|
46
|
+
Response,
|
|
47
|
+
ResponseOpenApi: _.ResponseOpenApi ?? Response,
|
|
48
|
+
Context: null,
|
|
49
|
+
CTX: null,
|
|
50
|
+
rt: h._tag
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function matchFor(rsc) {
|
|
54
|
+
const filtered = (0, _utils.typedKeysOf)(rsc).reduce((acc, cur) => {
|
|
55
|
+
if (_effectApp.Predicate.isObject(rsc[cur]) && rsc[cur].Request) {
|
|
56
|
+
acc[cur] = rsc[cur];
|
|
57
|
+
}
|
|
58
|
+
return acc;
|
|
59
|
+
}, {});
|
|
60
|
+
const matchWithServices = action => {
|
|
61
|
+
return (services, f) => (req, ctx) => _effectApp.Effect.andThen((0, _Effect.allLower)(services), svc2 => f(req, {
|
|
62
|
+
...ctx,
|
|
63
|
+
...svc2,
|
|
64
|
+
Response: rsc[action].Response
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
const controllers = controllers => {
|
|
68
|
+
const handlers = (0, _utils.typedKeysOf)(filtered).reduce((acc, cur) => {
|
|
69
|
+
if (cur === "meta") return acc;
|
|
70
|
+
const m = rsc.meta;
|
|
71
|
+
if (!m) throw new Error("Resource has no meta specified");
|
|
72
|
+
acc[cur] = handle(rsc[cur], m.moduleName + "." + cur)(controllers[cur]);
|
|
73
|
+
return acc;
|
|
74
|
+
}, {});
|
|
75
|
+
const mapped = (0, _utils.typedKeysOf)(handlers).reduce((acc, cur) => {
|
|
76
|
+
const handler = handlers[cur];
|
|
77
|
+
const req = handler.Request;
|
|
78
|
+
class Request extends req {
|
|
79
|
+
static path = "/" + handler.name + (req.path === "/" ? "" : req.path);
|
|
80
|
+
static method = req.method === "AUTO" ? _schema.REST.determineMethod(handler.name.split(".")[1], req) : req.method;
|
|
81
|
+
}
|
|
82
|
+
if (req.method === "AUTO") {
|
|
83
|
+
Object.assign(Request, {
|
|
84
|
+
[Request.method === "GET" || Request.method === "DELETE" ? "Query" : "Body"]: req.Auto
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
Object.assign(handler, {
|
|
88
|
+
Request
|
|
89
|
+
});
|
|
90
|
+
acc[cur] = match(handler, errorHandler(req), handleRequestEnv // TODO
|
|
91
|
+
);
|
|
92
|
+
return acc;
|
|
93
|
+
}, {});
|
|
94
|
+
return _http.HttpRouter.fromIterable(Object.values(mapped));
|
|
95
|
+
};
|
|
96
|
+
const r = {
|
|
97
|
+
controllers,
|
|
98
|
+
...(0, _utils.typedKeysOf)(filtered).reduce((prev, cur) => {
|
|
99
|
+
;
|
|
100
|
+
prev[cur] = (svcOrFnOrEffect, fnOrNone) => _effectApp.Effect.isEffect(svcOrFnOrEffect) ? class {
|
|
101
|
+
static _tag = "d";
|
|
102
|
+
static handler = () => svcOrFnOrEffect;
|
|
103
|
+
} : typeof svcOrFnOrEffect === "function" ? class {
|
|
104
|
+
static _tag = "d";
|
|
105
|
+
static handler = (req, ctx) => svcOrFnOrEffect(req, {
|
|
106
|
+
...ctx,
|
|
107
|
+
Response: rsc[cur].Response
|
|
108
|
+
});
|
|
109
|
+
} : class {
|
|
110
|
+
static _tag = "d";
|
|
111
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone);
|
|
112
|
+
};
|
|
113
|
+
prev[cur + "Raw"] = (svcOrFnOrEffect, fnOrNone) => _effectApp.Effect.isEffect(svcOrFnOrEffect) ? class {
|
|
114
|
+
static _tag = "raw";
|
|
115
|
+
static handler = () => svcOrFnOrEffect;
|
|
116
|
+
} : typeof svcOrFnOrEffect === "function" ? class {
|
|
117
|
+
static _tag = "raw";
|
|
118
|
+
static handler = (req, ctx) => svcOrFnOrEffect(req, {
|
|
119
|
+
...ctx,
|
|
120
|
+
Response: rsc[cur].Response
|
|
121
|
+
});
|
|
122
|
+
} : class {
|
|
123
|
+
static _tag = "raw";
|
|
124
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone);
|
|
125
|
+
};
|
|
126
|
+
return prev;
|
|
127
|
+
}, {})
|
|
128
|
+
};
|
|
129
|
+
return r;
|
|
130
|
+
}
|
|
131
|
+
const errorHandler = resourceRequest => {
|
|
132
|
+
return (req, res, r2) => (0, _routing.defaultErrorHandler)(req, res, _effectApp.Effect.catchTag(r2, "ParseError", _ => _effectApp.Effect.die(_)), resourceRequest.failure);
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Gather all handlers of a module and attach them to the Server.
|
|
136
|
+
* If no `allowAnonymous` flag is on the Request, will require a valid authenticated user.
|
|
137
|
+
*/
|
|
138
|
+
function matchAll(handlers) {
|
|
139
|
+
const r = (0, _utils.typedKeysOf)(handlers).reduce((acc, cur) => {
|
|
140
|
+
return _http.HttpRouter.concat(acc, handlers[cur]);
|
|
141
|
+
}, _http.HttpRouter.empty);
|
|
142
|
+
return r;
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
matchFor,
|
|
146
|
+
matchAll
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
exports.makeRouter = makeRouter;
|
|
150
|
+
//# sourceMappingURL=router.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.cjs","names":["_Effect","require","_utils","_routing","_effectApp","_http","_schema","makeRouter","handleRequestEnv","match","requestHandler","errorHandler","middleware","middlewareLayer","undefined","handler","makeRequestLayer","makeRequestHandler","route","HttpRouter","makeRoute","Request","method","path","handle","_","name","adaptResponse","S","REST","extractRequest","Response","extractResponse","h","ResponseOpenApi","Context","CTX","rt","_tag","matchFor","rsc","filtered","typedKeysOf","reduce","acc","cur","Predicate","isObject","matchWithServices","action","services","f","req","ctx","Effect","andThen","allLower","svc2","controllers","handlers","m","meta","Error","moduleName","mapped","determineMethod","split","Object","assign","Auto","fromIterable","values","r","prev","svcOrFnOrEffect","fnOrNone","isEffect","resourceRequest","res","r2","defaultErrorHandler","catchTag","die","failure","matchAll","concat","empty","exports"],"sources":["../src/router.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -8,5 +8,5 @@ import type { HttpServerRequest, HttpServerResponse } from "effect-app/http";
|
|
|
8
8
|
import type { RequestHandler } from "./base.js";
|
|
9
9
|
import type { Middleware } from "./makeRequestHandler.js";
|
|
10
10
|
export declare const RouteDescriptors: Context.Tag<Ref<RouteDescriptorAny[]>, Ref<RouteDescriptorAny[]>>;
|
|
11
|
-
export declare function match<R, M, PathA extends Struct.Fields, CookieA extends Struct.Fields, QueryA extends Struct.Fields, BodyA extends Struct.Fields, HeaderA extends Struct.Fields, ReqA extends PathA & QueryA & BodyA, ResA extends Struct.Fields, ResE, MiddlewareE, PPath extends `/${string}`, R2, PR, RErr, CTX, Context, Config>(requestHandler: RequestHandler<R, M, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE, PPath, CTX, Context, Config>, errorHandler: <R>(req: HttpServerRequest.HttpServerRequest, res: HttpServerResponse.HttpServerResponse, r2: Effect<HttpServerResponse.HttpServerResponse, ValidationError | MiddlewareE | ResE, R>) => Effect<HttpServerResponse.HttpServerResponse, never, Exclude<RErr | R, HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext | Scope>>, middleware?: Middleware<R, M, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE, MiddlewareE, PPath, R2, PR, CTX, Context, Config>): Effect.Effect<HttpRouter.Route<import("@effect/platform/HttpServerError").RequestError, import("../../services/RequestContextContainer.js").RequestContextContainer | import("
|
|
11
|
+
export declare function match<R, M, PathA extends Struct.Fields, CookieA extends Struct.Fields, QueryA extends Struct.Fields, BodyA extends Struct.Fields, HeaderA extends Struct.Fields, ReqA extends PathA & QueryA & BodyA, ResA extends Struct.Fields, ResE, MiddlewareE, PPath extends `/${string}`, R2, PR, RErr, CTX, Context, Config>(requestHandler: RequestHandler<R, M, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE, PPath, CTX, Context, Config>, errorHandler: <R>(req: HttpServerRequest.HttpServerRequest, res: HttpServerResponse.HttpServerResponse, r2: Effect<HttpServerResponse.HttpServerResponse, ValidationError | MiddlewareE | ResE, R>) => Effect<HttpServerResponse.HttpServerResponse, never, Exclude<RErr | R, HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext | Scope>>, middleware?: Middleware<R, M, PathA, CookieA, QueryA, BodyA, HeaderA, ReqA, ResA, ResE, MiddlewareE, PPath, R2, PR, CTX, Context, Config>): Effect.Effect<HttpRouter.Route<import("@effect/platform/HttpServerError").RequestError, import("../../services/RequestContextContainer.js").RequestContextContainer | import("../../services/Store/ContextMapContainer.js").ContextMapContainer | import("@effect-app/infra-adapters/RequestFiberSet").RequestFiberSet | Exclude<R2, HttpRouter.HttpRouter.Provided> | Exclude<RErr, HttpRouter.HttpRouter.Provided> | Exclude<Exclude<Exclude<R, import("effect-app/utils").EnforceNonEmptyRecord<M>>, PR>, HttpRouter.HttpRouter.Provided>>, never, never>;
|
|
12
12
|
//# sourceMappingURL=match.d.ts.map
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { EffectUnunified, LowerServices } from "@effect-app/core/Effect";
|
|
2
|
+
import type { EnforceNonEmptyRecord } from "@effect-app/core/utils";
|
|
3
|
+
import type { _R, EffectDeps, Extr, ReqFromSchema } from "@effect-app/infra/api/routing";
|
|
4
|
+
import type { Types } from "effect-app";
|
|
5
|
+
import { Effect, S } from "effect-app";
|
|
6
|
+
import type { ValidationError } from "effect-app/client/errors";
|
|
7
|
+
import { HttpRouter } from "effect-app/http";
|
|
8
|
+
import { REST } from "effect-app/schema";
|
|
9
|
+
export type RouteMatch<R, M, PR = never> = HttpRouter.Route<never, Exclude<Exclude<R, EnforceNonEmptyRecord<M>>, PR>>;
|
|
10
|
+
export interface Hint<Err extends string> {
|
|
11
|
+
Err: Err;
|
|
12
|
+
}
|
|
13
|
+
export declare const makeRouter: <CTX, CTXMap extends Record<string, [string, any, boolean]>>(handleRequestEnv: any) => {
|
|
14
|
+
matchFor: <Rsc extends Record<string, any>>(rsc: Rsc) => {
|
|
15
|
+
controllers: <THandlers extends { [K in keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
16
|
+
Response: any;
|
|
17
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
18
|
+
Response: any;
|
|
19
|
+
} ? Rsc[K_1] : never; }]: {
|
|
20
|
+
new (): {};
|
|
21
|
+
_tag: "raw";
|
|
22
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[K]>>, ctx: CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }) => Effect<S.Schema.Encoded<Extr<REST.GetResponse<Rsc[K]>>>, import("effect-app/client/errors").OptimisticConcurrencyException | S.ParseResult.ParseError | ValidationError | import("effect-app/client/errors").InvalidStateError | import("effect-app/client/errors").NotFoundError<ItemType> | import("effect-app/client/errors").NotLoggedInError | import("effect-app/client/errors").LoginError | import("effect-app/client/errors").UnauthorizedError | import("effect-app/client/errors").ServiceUnavailableError | S.Schema.Type<REST.GetRequest<Rsc[K]>["failure"]>, any>;
|
|
23
|
+
} | {
|
|
24
|
+
new (): {};
|
|
25
|
+
_tag: "d";
|
|
26
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[K]>>, ctx: CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }) => Effect<S.Schema.Type<Extr<REST.GetResponse<Rsc[K]>>>, import("effect-app/client/errors").OptimisticConcurrencyException | S.ParseResult.ParseError | ValidationError | import("effect-app/client/errors").InvalidStateError | import("effect-app/client/errors").NotFoundError<ItemType> | import("effect-app/client/errors").NotLoggedInError | import("effect-app/client/errors").LoginError | import("effect-app/client/errors").UnauthorizedError | import("effect-app/client/errors").ServiceUnavailableError | S.Schema.Type<REST.GetRequest<Rsc[K]>["failure"]>, any>;
|
|
27
|
+
}; }>(controllers: THandlers) => HttpRouter.HttpRouter<[(keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
28
|
+
Response: any;
|
|
29
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
30
|
+
Response: any;
|
|
31
|
+
} ? Rsc[K_1] : never; } extends infer T extends keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
32
|
+
Response: any;
|
|
33
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
34
|
+
Response: any;
|
|
35
|
+
} ? Rsc[K_1] : never; } ? { [K in T]: RouteMatch<_R<ReturnType<THandlers[K]["handler"]>>, ReqFromSchema<REST.GetRequest<Rsc[K]>>, { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? never : CTXMap[key][0] : CTXMap[key][0]]: CTXMap[key][1]; }[keyof { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? never : CTXMap[key][0] : CTXMap[key][0]]: CTXMap[key][1]; }]>; } : never)[keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
36
|
+
Response: any;
|
|
37
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
38
|
+
Response: any;
|
|
39
|
+
} ? Rsc[K_1] : never; }]] extends [HttpRouter.Route<infer E, any>] ? E : never, [(keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
40
|
+
Response: any;
|
|
41
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
42
|
+
Response: any;
|
|
43
|
+
} ? Rsc[K_1] : never; } extends infer T extends keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
44
|
+
Response: any;
|
|
45
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
46
|
+
Response: any;
|
|
47
|
+
} ? Rsc[K_1] : never; } ? { [K in T]: RouteMatch<_R<ReturnType<THandlers[K]["handler"]>>, ReqFromSchema<REST.GetRequest<Rsc[K]>>, { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? never : CTXMap[key][0] : CTXMap[key][0]]: CTXMap[key][1]; }[keyof { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[K]> ? REST.GetRequest<Rsc[K]>[key] extends true ? never : CTXMap[key][0] : CTXMap[key][0]]: CTXMap[key][1]; }]>; } : never)[keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
48
|
+
Response: any;
|
|
49
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
50
|
+
Response: any;
|
|
51
|
+
} ? Rsc[K_1] : never; }]] extends [HttpRouter.Route<any, infer R>] ? R : never>;
|
|
52
|
+
} & { [Key in keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
53
|
+
Response: any;
|
|
54
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
55
|
+
Response: any;
|
|
56
|
+
} ? Rsc[K_1] : never; }]: {
|
|
57
|
+
<R2, E, A>(f: Effect<A, E, R2>): S.Schema.Type<REST.GetResponse<Rsc[Key]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key]>> ? T extends void ? A extends void ? {
|
|
58
|
+
new (): {};
|
|
59
|
+
_tag: "d";
|
|
60
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A, E, R2>;
|
|
61
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
62
|
+
new (): {};
|
|
63
|
+
_tag: "d";
|
|
64
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A, E, R2>;
|
|
65
|
+
} : never : never;
|
|
66
|
+
<R2, E_1, A_1>(f: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; } & Pick<Rsc[Key], "Response">) => Effect<A_1, E_1, R2>): S.Schema.Type<REST.GetResponse<Rsc[Key]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key]>> ? T extends void ? A_1 extends void ? {
|
|
67
|
+
new (): {};
|
|
68
|
+
_tag: "d";
|
|
69
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_1, E_1, R2>;
|
|
70
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
71
|
+
new (): {};
|
|
72
|
+
_tag: "d";
|
|
73
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_1, E_1, R2>;
|
|
74
|
+
} : never : never;
|
|
75
|
+
<SVC extends Record<string, EffectUnunified<any, any, any>>, R2, E_2, A_2>(services: SVC, f: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: import("@effect-app/core/utils").ComputeFlat<LowerServices<EffectDeps<SVC>> & CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; } & Pick<Rsc[Key], "Response">>) => Effect<A_2, E_2, R2>): S.Schema.Type<REST.GetResponse<Rsc[Key]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key]>> ? T extends void ? A_2 extends void ? {
|
|
76
|
+
new (): {};
|
|
77
|
+
_tag: "d";
|
|
78
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_2, E_2, R2>;
|
|
79
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
80
|
+
new (): {};
|
|
81
|
+
_tag: "d";
|
|
82
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key]> ? REST.GetRequest<Rsc[Key]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_2, E_2, R2>;
|
|
83
|
+
} : never : never;
|
|
84
|
+
}; } & { [Key_1 in keyof { [K_1 in keyof Rsc as Rsc[K_1] extends {
|
|
85
|
+
Response: any;
|
|
86
|
+
} ? K_1 : never]: Rsc[K_1] extends {
|
|
87
|
+
Response: any;
|
|
88
|
+
} ? Rsc[K_1] : never; } as Key_1 extends string ? `${Key_1}Raw` : never]: {
|
|
89
|
+
<R2_1, E, A>(f: Effect<A, E, R2_1>): S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> ? T extends void ? A extends void ? {
|
|
90
|
+
new (): {};
|
|
91
|
+
_tag: "raw";
|
|
92
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A, E, R2_1>;
|
|
93
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
94
|
+
new (): {};
|
|
95
|
+
_tag: "raw";
|
|
96
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A, E, R2_1>;
|
|
97
|
+
} : never : never;
|
|
98
|
+
<R2_1, E_1, A_1>(f: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; } & Pick<Rsc[Key_1], "Response">) => Effect<A_1, E_1, R2_1>): S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> ? T extends void ? A_1 extends void ? {
|
|
99
|
+
new (): {};
|
|
100
|
+
_tag: "raw";
|
|
101
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_1, E_1, R2_1>;
|
|
102
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
103
|
+
new (): {};
|
|
104
|
+
_tag: "raw";
|
|
105
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_1, E_1, R2_1>;
|
|
106
|
+
} : never : never;
|
|
107
|
+
<SVC extends Record<string, EffectUnunified<any, any, any>>, R2, E_2, A_2>(services: SVC, f: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: import("@effect-app/core/utils").ComputeFlat<LowerServices<EffectDeps<SVC>> & CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; } & Pick<Rsc[Key_1], "Response">>) => Effect<A_2, E_2, R2>): S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> extends infer T ? T extends S.Schema.Type<REST.GetResponse<Rsc[Key_1]>> ? T extends void ? A_2 extends void ? {
|
|
108
|
+
new (): {};
|
|
109
|
+
_tag: "raw";
|
|
110
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_2, E_2, R2>;
|
|
111
|
+
} : Hint<"You're returning non void for a void Response, please fix"> : {
|
|
112
|
+
new (): {};
|
|
113
|
+
_tag: "raw";
|
|
114
|
+
handler: (req: S.Schema.Type<REST.GetRequest<Rsc[Key_1]>>, ctx: Types.Simplify<CTX & { [key in keyof CTXMap as key extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key] extends true ? CTXMap[key][0] : never : never]?: CTXMap[key][1]; } & { [key_1 in keyof CTXMap as key_1 extends keyof REST.GetRequest<Rsc[Key_1]> ? REST.GetRequest<Rsc[Key_1]>[key_1] extends false ? CTXMap[key_1][0] : never : CTXMap[key_1][0]]: CTXMap[key_1][1]; }>) => Effect<A_2, E_2, R2>;
|
|
115
|
+
} : never : never;
|
|
116
|
+
}; };
|
|
117
|
+
matchAll: <T extends {
|
|
118
|
+
[key: string]: HttpRouter.HttpRouter<any, any>;
|
|
119
|
+
}>(handlers: T) => HttpRouter.HttpRouter<[T[keyof T]] extends [HttpRouter.HttpRouter<infer R, any>] ? R : never, [T[keyof T]] extends [HttpRouter.HttpRouter<any, infer E_3>] ? E_3 : never>;
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { allLower } from "@effect-app/core/Effect";
|
|
2
|
+
import { typedKeysOf } from "@effect-app/core/utils";
|
|
3
|
+
import { defaultErrorHandler, makeRequestHandler } from "@effect-app/infra/api/routing";
|
|
4
|
+
import { Effect, Predicate, S } from "effect-app";
|
|
5
|
+
import { HttpRouter } from "effect-app/http";
|
|
6
|
+
import { REST } from "effect-app/schema";
|
|
7
|
+
// TODO: support FLIP
|
|
8
|
+
export const makeRouter = (handleRequestEnv /* Middleware */) => {
|
|
9
|
+
function match(requestHandler, errorHandler, middleware) {
|
|
10
|
+
let middlewareLayer = undefined;
|
|
11
|
+
if (middleware) {
|
|
12
|
+
const { handler, makeRequestLayer } = middleware(requestHandler);
|
|
13
|
+
requestHandler = handler; // todo
|
|
14
|
+
middlewareLayer = makeRequestLayer;
|
|
15
|
+
}
|
|
16
|
+
// const rdesc = yield* RouteDescriptors.flatMap((_) => _.get)
|
|
17
|
+
const handler = makeRequestHandler(requestHandler, // one argument if no middleware, 2 if has middleware. TODO: clean this shit up
|
|
18
|
+
errorHandler, middlewareLayer);
|
|
19
|
+
const route = HttpRouter.makeRoute(requestHandler.Request.method, requestHandler.Request.path, handler);
|
|
20
|
+
// TODO
|
|
21
|
+
// rdesc.push(makeRouteDescriptor(
|
|
22
|
+
// requestHandler.Request.path,
|
|
23
|
+
// requestHandler.Request.method,
|
|
24
|
+
// requestHandler
|
|
25
|
+
// ))
|
|
26
|
+
return route;
|
|
27
|
+
}
|
|
28
|
+
function handle(_, name, adaptResponse) {
|
|
29
|
+
const Request = S.REST.extractRequest(_);
|
|
30
|
+
const Response = S.REST.extractResponse(_);
|
|
31
|
+
return (h) => ({
|
|
32
|
+
adaptResponse,
|
|
33
|
+
h: h.handler,
|
|
34
|
+
name,
|
|
35
|
+
Request,
|
|
36
|
+
Response,
|
|
37
|
+
ResponseOpenApi: _.ResponseOpenApi ?? Response,
|
|
38
|
+
Context: null,
|
|
39
|
+
CTX: null,
|
|
40
|
+
rt: h._tag
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function matchFor(rsc) {
|
|
44
|
+
const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
|
|
45
|
+
if (Predicate.isObject(rsc[cur]) && rsc[cur].Request) {
|
|
46
|
+
acc[cur] = rsc[cur];
|
|
47
|
+
}
|
|
48
|
+
return acc;
|
|
49
|
+
}, {});
|
|
50
|
+
const matchWithServices = (action) => {
|
|
51
|
+
return (services, f) => (req, ctx) => Effect.andThen(allLower(services), (svc2) => f(req, { ...ctx, ...svc2, Response: rsc[action].Response }));
|
|
52
|
+
};
|
|
53
|
+
const controllers = (controllers) => {
|
|
54
|
+
const handlers = typedKeysOf(filtered).reduce((acc, cur) => {
|
|
55
|
+
if (cur === "meta")
|
|
56
|
+
return acc;
|
|
57
|
+
const m = rsc.meta;
|
|
58
|
+
if (!m)
|
|
59
|
+
throw new Error("Resource has no meta specified");
|
|
60
|
+
acc[cur] = handle(rsc[cur], m.moduleName + "." + cur)(controllers[cur]);
|
|
61
|
+
return acc;
|
|
62
|
+
}, {});
|
|
63
|
+
const mapped = typedKeysOf(handlers).reduce((acc, cur) => {
|
|
64
|
+
const handler = handlers[cur];
|
|
65
|
+
const req = handler.Request;
|
|
66
|
+
class Request extends req {
|
|
67
|
+
static path = "/" + handler.name + (req.path === "/" ? "" : req.path);
|
|
68
|
+
static method = req.method === "AUTO"
|
|
69
|
+
? REST.determineMethod(handler.name.split(".")[1], req)
|
|
70
|
+
: req.method;
|
|
71
|
+
}
|
|
72
|
+
if (req.method === "AUTO") {
|
|
73
|
+
Object.assign(Request, {
|
|
74
|
+
[Request.method === "GET" || Request.method === "DELETE" ? "Query" : "Body"]: req.Auto
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
Object.assign(handler, { Request });
|
|
78
|
+
acc[cur] = match(handler, errorHandler(req), handleRequestEnv // TODO
|
|
79
|
+
);
|
|
80
|
+
return acc;
|
|
81
|
+
}, {});
|
|
82
|
+
return HttpRouter.fromIterable(Object.values(mapped));
|
|
83
|
+
};
|
|
84
|
+
const r = {
|
|
85
|
+
controllers,
|
|
86
|
+
...typedKeysOf(filtered).reduce((prev, cur) => {
|
|
87
|
+
;
|
|
88
|
+
prev[cur] = (svcOrFnOrEffect, fnOrNone) => Effect.isEffect(svcOrFnOrEffect)
|
|
89
|
+
? class {
|
|
90
|
+
static _tag = "d";
|
|
91
|
+
static handler = () => svcOrFnOrEffect;
|
|
92
|
+
}
|
|
93
|
+
: typeof svcOrFnOrEffect === "function"
|
|
94
|
+
? class {
|
|
95
|
+
static _tag = "d";
|
|
96
|
+
static handler = (req, ctx) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].Response });
|
|
97
|
+
}
|
|
98
|
+
: class {
|
|
99
|
+
static _tag = "d";
|
|
100
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone);
|
|
101
|
+
};
|
|
102
|
+
prev[cur + "Raw"] = (svcOrFnOrEffect, fnOrNone) => Effect.isEffect(svcOrFnOrEffect)
|
|
103
|
+
? class {
|
|
104
|
+
static _tag = "raw";
|
|
105
|
+
static handler = () => svcOrFnOrEffect;
|
|
106
|
+
}
|
|
107
|
+
: typeof svcOrFnOrEffect === "function"
|
|
108
|
+
? class {
|
|
109
|
+
static _tag = "raw";
|
|
110
|
+
static handler = (req, ctx) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].Response });
|
|
111
|
+
}
|
|
112
|
+
: class {
|
|
113
|
+
static _tag = "raw";
|
|
114
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone);
|
|
115
|
+
};
|
|
116
|
+
return prev;
|
|
117
|
+
}, {})
|
|
118
|
+
};
|
|
119
|
+
return r;
|
|
120
|
+
}
|
|
121
|
+
const errorHandler = (resourceRequest) => {
|
|
122
|
+
return (req, res, r2) => defaultErrorHandler(req, res, Effect.catchTag(r2, "ParseError", (_) => Effect.die(_)), resourceRequest.failure);
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Gather all handlers of a module and attach them to the Server.
|
|
126
|
+
* If no `allowAnonymous` flag is on the Request, will require a valid authenticated user.
|
|
127
|
+
*/
|
|
128
|
+
function matchAll(handlers) {
|
|
129
|
+
const r = typedKeysOf(handlers).reduce((acc, cur) => {
|
|
130
|
+
return HttpRouter.concat(acc, handlers[cur]);
|
|
131
|
+
}, HttpRouter.empty);
|
|
132
|
+
return r;
|
|
133
|
+
}
|
|
134
|
+
return { matchFor, matchAll };
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDbEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFBO0FBY3BELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLCtCQUErQixDQUFBO0FBRXZGLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUVqRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFHNUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBZ0J4QyxxQkFBcUI7QUFDckIsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLENBQ3hCLGdCQUFxQixDQUFDLGdCQUFnQixFQUN0QyxFQUFFO0lBb0JGLFNBQVMsS0FBSyxDQW9CWixjQWVDLEVBQ0QsWUFRQyxFQUNELFVBa0JDO1FBRUQsSUFBSSxlQUFlLEdBQTJDLFNBQVMsQ0FBQTtRQUN2RSxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsTUFBTSxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQTtZQUNoRSxjQUFjLEdBQUcsT0FBYyxDQUFBLENBQUMsT0FBTztZQUN2QyxlQUFlLEdBQUcsZ0JBQWdCLENBQUE7UUFDcEMsQ0FBQztRQUNELDhEQUE4RDtRQUU5RCxNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FrQmhDLGNBQXFCLEVBQUUsK0VBQStFO1FBQ3RHLFlBQVksRUFDWixlQUFlLENBQ2hCLENBQUE7UUFFRCxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsU0FBUyxDQUNoQyxjQUFjLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFDN0IsY0FBYyxDQUFDLE9B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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"pure-rand": "6.1.0",
|
|
20
20
|
"redlock": "^4.2.0",
|
|
21
21
|
"@effect-app/core": "1.9.0",
|
|
22
|
-
"
|
|
23
|
-
"effect-app": "1.
|
|
24
|
-
"@effect-app/
|
|
22
|
+
"effect-app": "1.15.0",
|
|
23
|
+
"@effect-app/schema": "1.11.0",
|
|
24
|
+
"@effect-app/infra-adapters": "1.10.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@babel/cli": "^7.25.6",
|
|
@@ -334,6 +334,16 @@
|
|
|
334
334
|
"default": "./_cjs/rateLimit.cjs"
|
|
335
335
|
}
|
|
336
336
|
},
|
|
337
|
+
"./router": {
|
|
338
|
+
"import": {
|
|
339
|
+
"types": "./dist/router.d.ts",
|
|
340
|
+
"default": "./dist/router.js"
|
|
341
|
+
},
|
|
342
|
+
"require": {
|
|
343
|
+
"types": "./dist/router.d.ts",
|
|
344
|
+
"default": "./_cjs/router.cjs"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
337
347
|
"./services/Emailer": {
|
|
338
348
|
"import": {
|
|
339
349
|
"types": "./dist/services/Emailer.d.ts",
|
package/src/router.ts
ADDED
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import type { EffectUnunified, LowerServices } from "@effect-app/core/Effect"
|
|
4
|
+
import { allLower } from "@effect-app/core/Effect"
|
|
5
|
+
import { typedKeysOf } from "@effect-app/core/utils"
|
|
6
|
+
import type { Compute, EnforceNonEmptyRecord } from "@effect-app/core/utils"
|
|
7
|
+
import type {
|
|
8
|
+
_E,
|
|
9
|
+
_R,
|
|
10
|
+
EffectDeps,
|
|
11
|
+
Extr,
|
|
12
|
+
JWTError,
|
|
13
|
+
Middleware,
|
|
14
|
+
ReqFromSchema,
|
|
15
|
+
ReqHandler,
|
|
16
|
+
RequestHandler,
|
|
17
|
+
ResFromSchema
|
|
18
|
+
} from "@effect-app/infra/api/routing"
|
|
19
|
+
import { defaultErrorHandler, makeRequestHandler } from "@effect-app/infra/api/routing"
|
|
20
|
+
import type { Layer, Scope, Types } from "effect-app"
|
|
21
|
+
import { Effect, Predicate, S } from "effect-app"
|
|
22
|
+
import type { SupportedErrors, ValidationError } from "effect-app/client/errors"
|
|
23
|
+
import { HttpRouter } from "effect-app/http"
|
|
24
|
+
import type { HttpServerRequest, HttpServerResponse } from "effect-app/http"
|
|
25
|
+
import type { Struct } from "effect-app/schema"
|
|
26
|
+
import { REST } from "effect-app/schema"
|
|
27
|
+
import type {} from "@effect/schema/ParseResult"
|
|
28
|
+
|
|
29
|
+
export type RouteMatch<
|
|
30
|
+
R,
|
|
31
|
+
M,
|
|
32
|
+
// TODO: specific errors
|
|
33
|
+
// Err extends SupportedErrors | S.ParseResult.ParseError,
|
|
34
|
+
PR = never
|
|
35
|
+
> // RErr = never,
|
|
36
|
+
= HttpRouter.Route<never, Exclude<Exclude<R, EnforceNonEmptyRecord<M>>, PR>>
|
|
37
|
+
|
|
38
|
+
export interface Hint<Err extends string> {
|
|
39
|
+
Err: Err
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// TODO: support FLIP
|
|
43
|
+
export const makeRouter = <CTX, CTXMap extends Record<string, [string, any, boolean]>>(
|
|
44
|
+
handleRequestEnv: any /* Middleware */
|
|
45
|
+
) => {
|
|
46
|
+
type GetCTX<T> =
|
|
47
|
+
& CTX
|
|
48
|
+
& {
|
|
49
|
+
[key in keyof CTXMap as key extends keyof T ? T[key] extends true ? CTXMap[key][0] : never : never]?:
|
|
50
|
+
CTXMap[key][1]
|
|
51
|
+
}
|
|
52
|
+
& {
|
|
53
|
+
[key in keyof CTXMap as key extends keyof T ? T[key] extends false ? CTXMap[key][0] : never : CTXMap[key][0]]:
|
|
54
|
+
CTXMap[key][1]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type Values<T extends Record<any, any>> = T[keyof T]
|
|
58
|
+
|
|
59
|
+
type GetContext<T> = Values<
|
|
60
|
+
{
|
|
61
|
+
[key in keyof CTXMap as key extends keyof T ? T[key] extends true ? never : CTXMap[key][0] : CTXMap[key][0]]: // TODO: or as an Optional available?
|
|
62
|
+
CTXMap[key][1]
|
|
63
|
+
}
|
|
64
|
+
>
|
|
65
|
+
function match<
|
|
66
|
+
R,
|
|
67
|
+
M,
|
|
68
|
+
PathA extends Struct.Fields,
|
|
69
|
+
CookieA extends Struct.Fields,
|
|
70
|
+
QueryA extends Struct.Fields,
|
|
71
|
+
BodyA extends Struct.Fields,
|
|
72
|
+
HeaderA extends Struct.Fields,
|
|
73
|
+
ReqA extends PathA & QueryA & BodyA,
|
|
74
|
+
ResA extends Struct.Fields,
|
|
75
|
+
ResE,
|
|
76
|
+
MiddlewareE,
|
|
77
|
+
PPath extends `/${string}`,
|
|
78
|
+
R2,
|
|
79
|
+
PR,
|
|
80
|
+
RErr,
|
|
81
|
+
CTX,
|
|
82
|
+
Context,
|
|
83
|
+
Config
|
|
84
|
+
>(
|
|
85
|
+
requestHandler: RequestHandler<
|
|
86
|
+
R,
|
|
87
|
+
M,
|
|
88
|
+
PathA,
|
|
89
|
+
CookieA,
|
|
90
|
+
QueryA,
|
|
91
|
+
BodyA,
|
|
92
|
+
HeaderA,
|
|
93
|
+
ReqA,
|
|
94
|
+
ResA,
|
|
95
|
+
ResE,
|
|
96
|
+
PPath,
|
|
97
|
+
CTX,
|
|
98
|
+
Context,
|
|
99
|
+
Config
|
|
100
|
+
>,
|
|
101
|
+
errorHandler: <R>(
|
|
102
|
+
req: HttpServerRequest.HttpServerRequest,
|
|
103
|
+
res: HttpServerResponse.HttpServerResponse,
|
|
104
|
+
r2: Effect<HttpServerResponse.HttpServerResponse, ValidationError | MiddlewareE | ResE, R>
|
|
105
|
+
) => Effect<
|
|
106
|
+
HttpServerResponse.HttpServerResponse,
|
|
107
|
+
never,
|
|
108
|
+
Exclude<RErr | R, HttpServerRequest.HttpServerRequest | HttpRouter.RouteContext | Scope>
|
|
109
|
+
>,
|
|
110
|
+
middleware?: Middleware<
|
|
111
|
+
R,
|
|
112
|
+
M,
|
|
113
|
+
PathA,
|
|
114
|
+
CookieA,
|
|
115
|
+
QueryA,
|
|
116
|
+
BodyA,
|
|
117
|
+
HeaderA,
|
|
118
|
+
ReqA,
|
|
119
|
+
ResA,
|
|
120
|
+
ResE,
|
|
121
|
+
MiddlewareE,
|
|
122
|
+
PPath,
|
|
123
|
+
R2,
|
|
124
|
+
PR,
|
|
125
|
+
CTX,
|
|
126
|
+
Context,
|
|
127
|
+
Config
|
|
128
|
+
>
|
|
129
|
+
) {
|
|
130
|
+
let middlewareLayer: Layer<PR, MiddlewareE, R2> | undefined = undefined
|
|
131
|
+
if (middleware) {
|
|
132
|
+
const { handler, makeRequestLayer } = middleware(requestHandler)
|
|
133
|
+
requestHandler = handler as any // todo
|
|
134
|
+
middlewareLayer = makeRequestLayer
|
|
135
|
+
}
|
|
136
|
+
// const rdesc = yield* RouteDescriptors.flatMap((_) => _.get)
|
|
137
|
+
|
|
138
|
+
const handler = makeRequestHandler<
|
|
139
|
+
R,
|
|
140
|
+
M,
|
|
141
|
+
PathA,
|
|
142
|
+
CookieA,
|
|
143
|
+
QueryA,
|
|
144
|
+
BodyA,
|
|
145
|
+
HeaderA,
|
|
146
|
+
ReqA,
|
|
147
|
+
ResA,
|
|
148
|
+
ResE,
|
|
149
|
+
MiddlewareE,
|
|
150
|
+
R2,
|
|
151
|
+
PR,
|
|
152
|
+
RErr,
|
|
153
|
+
PPath,
|
|
154
|
+
Config
|
|
155
|
+
>(
|
|
156
|
+
requestHandler as any, // one argument if no middleware, 2 if has middleware. TODO: clean this shit up
|
|
157
|
+
errorHandler,
|
|
158
|
+
middlewareLayer
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
const route = HttpRouter.makeRoute(
|
|
162
|
+
requestHandler.Request.method,
|
|
163
|
+
requestHandler.Request.path,
|
|
164
|
+
handler
|
|
165
|
+
)
|
|
166
|
+
// TODO
|
|
167
|
+
// rdesc.push(makeRouteDescriptor(
|
|
168
|
+
// requestHandler.Request.path,
|
|
169
|
+
// requestHandler.Request.method,
|
|
170
|
+
// requestHandler
|
|
171
|
+
// ))
|
|
172
|
+
return route
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function handle<
|
|
176
|
+
TModule extends Record<
|
|
177
|
+
string,
|
|
178
|
+
any
|
|
179
|
+
>
|
|
180
|
+
>(
|
|
181
|
+
_: TModule & { ResponseOpenApi?: any },
|
|
182
|
+
name: string,
|
|
183
|
+
adaptResponse?: any
|
|
184
|
+
) {
|
|
185
|
+
const Request = S.REST.extractRequest(_)
|
|
186
|
+
const Response = S.REST.extractResponse(_)
|
|
187
|
+
|
|
188
|
+
type ReqSchema = S.REST.GetRequest<TModule>
|
|
189
|
+
type ResSchema = S.REST.GetResponse<TModule>
|
|
190
|
+
type Req = InstanceType<
|
|
191
|
+
ReqSchema extends { new(...args: any[]): any } ? ReqSchema
|
|
192
|
+
: never
|
|
193
|
+
>
|
|
194
|
+
type Res = S.Schema.Type<Extr<ResSchema>>
|
|
195
|
+
|
|
196
|
+
return <R, E>(
|
|
197
|
+
h: { _tag: "raw" | "d"; handler: (r: Req) => Effect<Res, E, R> }
|
|
198
|
+
) => ({
|
|
199
|
+
adaptResponse,
|
|
200
|
+
h: h.handler,
|
|
201
|
+
name,
|
|
202
|
+
Request,
|
|
203
|
+
Response,
|
|
204
|
+
ResponseOpenApi: _.ResponseOpenApi ?? Response,
|
|
205
|
+
Context: null as any,
|
|
206
|
+
CTX: null as any,
|
|
207
|
+
rt: h._tag
|
|
208
|
+
} as ReqHandler<
|
|
209
|
+
Req,
|
|
210
|
+
R,
|
|
211
|
+
E,
|
|
212
|
+
Res,
|
|
213
|
+
ReqSchema,
|
|
214
|
+
ResSchema,
|
|
215
|
+
GetCTX<Req>,
|
|
216
|
+
GetContext<Req>
|
|
217
|
+
>)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
type HandleVoid<Expected, Actual, Result> = Expected extends void
|
|
221
|
+
? Actual extends void ? Result : Hint<"You're returning non void for a void Response, please fix">
|
|
222
|
+
: Result
|
|
223
|
+
|
|
224
|
+
function matchFor<Rsc extends Record<string, any>>(
|
|
225
|
+
rsc: Rsc
|
|
226
|
+
) {
|
|
227
|
+
type Filtered = {
|
|
228
|
+
[K in keyof Rsc as Rsc[K] extends { Response: any } ? K : never]: Rsc[K] extends { Response: any } ? Rsc[K]
|
|
229
|
+
: never
|
|
230
|
+
}
|
|
231
|
+
const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
|
|
232
|
+
if (Predicate.isObject(rsc[cur]) && rsc[cur].Request) {
|
|
233
|
+
acc[cur as keyof Filtered] = rsc[cur]
|
|
234
|
+
}
|
|
235
|
+
return acc
|
|
236
|
+
}, {} as Filtered)
|
|
237
|
+
|
|
238
|
+
const matchWithServices = <Key extends keyof Filtered>(action: Key) => {
|
|
239
|
+
type Req = ReqFromSchema<REST.GetRequest<Rsc[Key]>>
|
|
240
|
+
return <
|
|
241
|
+
SVC extends Record<
|
|
242
|
+
string,
|
|
243
|
+
Effect<any, any, any>
|
|
244
|
+
>,
|
|
245
|
+
R2,
|
|
246
|
+
E,
|
|
247
|
+
A
|
|
248
|
+
>(
|
|
249
|
+
services: SVC,
|
|
250
|
+
f: (
|
|
251
|
+
req: Req,
|
|
252
|
+
ctx: Compute<
|
|
253
|
+
LowerServices<EffectDeps<SVC>> & GetCTX<Req>,
|
|
254
|
+
"flat"
|
|
255
|
+
>
|
|
256
|
+
) => Effect<A, E, R2>
|
|
257
|
+
) =>
|
|
258
|
+
(req: any, ctx: any) =>
|
|
259
|
+
Effect.andThen(allLower(services), (svc2) => f(req, { ...ctx, ...svc2 as any, Response: rsc[action].Response }))
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
type MatchWithServicesNew<RT extends "raw" | "d", Key extends keyof Rsc> = {
|
|
263
|
+
<R2, E, A>(
|
|
264
|
+
f: Effect<A, E, R2>
|
|
265
|
+
): HandleVoid<
|
|
266
|
+
S.Schema.Type<REST.GetResponse<Rsc[Key]>>,
|
|
267
|
+
A,
|
|
268
|
+
Handler<
|
|
269
|
+
ReqFromSchema<REST.GetRequest<Rsc[Key]>>,
|
|
270
|
+
Types.Simplify<GetCTX<REST.GetRequest<Rsc[Key]>>>,
|
|
271
|
+
RT,
|
|
272
|
+
A,
|
|
273
|
+
E,
|
|
274
|
+
R2
|
|
275
|
+
>
|
|
276
|
+
>
|
|
277
|
+
<R2, E, A>(
|
|
278
|
+
f: (
|
|
279
|
+
req: ReqFromSchema<REST.GetRequest<Rsc[Key]>>,
|
|
280
|
+
ctx: GetCTX<REST.GetRequest<Rsc[Key]>> & Pick<Rsc[Key], "Response">
|
|
281
|
+
) => Effect<A, E, R2>
|
|
282
|
+
): HandleVoid<
|
|
283
|
+
S.Schema.Type<REST.GetResponse<Rsc[Key]>>,
|
|
284
|
+
A,
|
|
285
|
+
Handler<
|
|
286
|
+
ReqFromSchema<REST.GetRequest<Rsc[Key]>>,
|
|
287
|
+
Types.Simplify<GetCTX<REST.GetRequest<Rsc[Key]>>>,
|
|
288
|
+
RT,
|
|
289
|
+
A,
|
|
290
|
+
E,
|
|
291
|
+
R2
|
|
292
|
+
>
|
|
293
|
+
>
|
|
294
|
+
|
|
295
|
+
<
|
|
296
|
+
SVC extends Record<
|
|
297
|
+
string,
|
|
298
|
+
EffectUnunified<any, any, any>
|
|
299
|
+
>,
|
|
300
|
+
R2,
|
|
301
|
+
E,
|
|
302
|
+
A
|
|
303
|
+
>(
|
|
304
|
+
services: SVC,
|
|
305
|
+
f: (
|
|
306
|
+
req: ReqFromSchema<REST.GetRequest<Rsc[Key]>>,
|
|
307
|
+
ctx: Compute<
|
|
308
|
+
LowerServices<EffectDeps<SVC>> & GetCTX<REST.GetRequest<Rsc[Key]>> & Pick<Rsc[Key], "Response">,
|
|
309
|
+
"flat"
|
|
310
|
+
>
|
|
311
|
+
) => Effect<A, E, R2>
|
|
312
|
+
): HandleVoid<
|
|
313
|
+
S.Schema.Type<REST.GetResponse<Rsc[Key]>>,
|
|
314
|
+
A,
|
|
315
|
+
Handler<
|
|
316
|
+
ReqFromSchema<REST.GetRequest<Rsc[Key]>>,
|
|
317
|
+
Types.Simplify<GetCTX<REST.GetRequest<Rsc[Key]>>>,
|
|
318
|
+
RT,
|
|
319
|
+
A,
|
|
320
|
+
E,
|
|
321
|
+
R2
|
|
322
|
+
>
|
|
323
|
+
>
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
type Keys = keyof Filtered
|
|
327
|
+
type Handler<Req, Context, RT extends "raw" | "d", A, E, R> = {
|
|
328
|
+
new(): {}
|
|
329
|
+
_tag: RT
|
|
330
|
+
handler: (
|
|
331
|
+
req: Req,
|
|
332
|
+
ctx: Context
|
|
333
|
+
) => Effect<
|
|
334
|
+
A,
|
|
335
|
+
E,
|
|
336
|
+
R
|
|
337
|
+
>
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
type AHandler<Action extends Record<string, any>> =
|
|
341
|
+
| Handler<
|
|
342
|
+
ReqFromSchema<REST.GetRequest<Action>>,
|
|
343
|
+
GetCTX<REST.GetRequest<Action>>,
|
|
344
|
+
"raw",
|
|
345
|
+
ResRawFromSchema<REST.GetResponse<Action>>,
|
|
346
|
+
SupportedErrors | S.ParseResult.ParseError | S.Schema.Type<REST.GetRequest<Action>["failure"]>,
|
|
347
|
+
any
|
|
348
|
+
>
|
|
349
|
+
| Handler<
|
|
350
|
+
ReqFromSchema<REST.GetRequest<Action>>,
|
|
351
|
+
GetCTX<REST.GetRequest<Action>>,
|
|
352
|
+
"d",
|
|
353
|
+
ResFromSchema<REST.GetResponse<Action>>,
|
|
354
|
+
SupportedErrors | S.ParseResult.ParseError | S.Schema.Type<REST.GetRequest<Action>["failure"]>,
|
|
355
|
+
any
|
|
356
|
+
>
|
|
357
|
+
|
|
358
|
+
const controllers = <
|
|
359
|
+
THandlers extends {
|
|
360
|
+
// import to keep them separate via | for type checking!!
|
|
361
|
+
[K in Keys]: AHandler<Rsc[K]>
|
|
362
|
+
}
|
|
363
|
+
>(
|
|
364
|
+
controllers: THandlers
|
|
365
|
+
) => {
|
|
366
|
+
const handlers = typedKeysOf(filtered).reduce(
|
|
367
|
+
(acc, cur) => {
|
|
368
|
+
if (cur === "meta") return acc
|
|
369
|
+
const m = (rsc as any).meta as { moduleName: string }
|
|
370
|
+
if (!m) throw new Error("Resource has no meta specified")
|
|
371
|
+
;(acc as any)[cur] = handle(
|
|
372
|
+
rsc[cur],
|
|
373
|
+
m.moduleName + "." + (cur as string)
|
|
374
|
+
)(controllers[cur as keyof typeof controllers] as any)
|
|
375
|
+
return acc
|
|
376
|
+
},
|
|
377
|
+
{} as {
|
|
378
|
+
[K in Keys]: ReqHandler<
|
|
379
|
+
ReqFromSchema<REST.GetRequest<Rsc[K]>>,
|
|
380
|
+
_R<ReturnType<THandlers[K]["handler"]>>,
|
|
381
|
+
_E<ReturnType<THandlers[K]["handler"]>>,
|
|
382
|
+
ResFromSchema<REST.GetResponse<Rsc[K]>>,
|
|
383
|
+
REST.GetRequest<Rsc[K]>,
|
|
384
|
+
REST.GetResponse<Rsc[K]>,
|
|
385
|
+
GetCTX<REST.GetRequest<Rsc[K]>>,
|
|
386
|
+
GetContext<REST.GetRequest<Rsc[K]>>
|
|
387
|
+
>
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
const mapped = typedKeysOf(handlers).reduce((acc, cur) => {
|
|
392
|
+
const handler = handlers[cur]
|
|
393
|
+
const req = handler.Request
|
|
394
|
+
|
|
395
|
+
class Request extends (req as any) {
|
|
396
|
+
static path = "/" + handler.name + (req.path === "/" ? "" : req.path)
|
|
397
|
+
static method = req.method === "AUTO"
|
|
398
|
+
? REST.determineMethod(handler.name.split(".")[1]!, req)
|
|
399
|
+
: req.method
|
|
400
|
+
}
|
|
401
|
+
if (req.method === "AUTO") {
|
|
402
|
+
Object.assign(Request, {
|
|
403
|
+
[Request.method === "GET" || Request.method === "DELETE" ? "Query" : "Body"]: req.Auto
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
Object.assign(handler, { Request })
|
|
407
|
+
acc[cur] = match(
|
|
408
|
+
handler as any,
|
|
409
|
+
errorHandler(req),
|
|
410
|
+
handleRequestEnv // TODO
|
|
411
|
+
)
|
|
412
|
+
return acc
|
|
413
|
+
}, {} as any) as {
|
|
414
|
+
[K in Keys]: RouteMatch<
|
|
415
|
+
_R<ReturnType<THandlers[K]["handler"]>>,
|
|
416
|
+
ReqFromSchema<REST.GetRequest<Rsc[K]>>,
|
|
417
|
+
// _E<ReturnType<THandlers[K]["handler"]>>,
|
|
418
|
+
GetContext<REST.GetRequest<Rsc[K]>>
|
|
419
|
+
>
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
type _RRoute<T extends HttpRouter.Route<any, any>> = [T] extends [
|
|
423
|
+
HttpRouter.Route<any, infer R>
|
|
424
|
+
] ? R
|
|
425
|
+
: never
|
|
426
|
+
|
|
427
|
+
type _ERoute<T extends HttpRouter.Route<any, any>> = [T] extends [
|
|
428
|
+
HttpRouter.Route<infer E, any>
|
|
429
|
+
] ? E
|
|
430
|
+
: never
|
|
431
|
+
|
|
432
|
+
return HttpRouter.fromIterable(Object.values(mapped)) as HttpRouter.HttpRouter<
|
|
433
|
+
_ERoute<typeof mapped[keyof typeof mapped]>,
|
|
434
|
+
_RRoute<typeof mapped[keyof typeof mapped]>
|
|
435
|
+
>
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
type ResRawFromSchema<ResSchema> = S.Schema.Encoded<Extr<ResSchema>>
|
|
439
|
+
|
|
440
|
+
const r = {
|
|
441
|
+
controllers,
|
|
442
|
+
...typedKeysOf(filtered).reduce(
|
|
443
|
+
(prev, cur) => {
|
|
444
|
+
;(prev as any)[cur] = (svcOrFnOrEffect: any, fnOrNone: any) =>
|
|
445
|
+
Effect.isEffect(svcOrFnOrEffect)
|
|
446
|
+
? class {
|
|
447
|
+
static _tag = "d"
|
|
448
|
+
static handler = () => svcOrFnOrEffect
|
|
449
|
+
}
|
|
450
|
+
: typeof svcOrFnOrEffect === "function"
|
|
451
|
+
? class {
|
|
452
|
+
static _tag = "d"
|
|
453
|
+
static handler = (req: any, ctx: any) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].Response })
|
|
454
|
+
}
|
|
455
|
+
: class {
|
|
456
|
+
static _tag = "d"
|
|
457
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone)
|
|
458
|
+
}
|
|
459
|
+
;(prev as any)[(cur as any) + "Raw"] = (svcOrFnOrEffect: any, fnOrNone: any) =>
|
|
460
|
+
Effect.isEffect(svcOrFnOrEffect)
|
|
461
|
+
? class {
|
|
462
|
+
static _tag = "raw"
|
|
463
|
+
static handler = () => svcOrFnOrEffect
|
|
464
|
+
}
|
|
465
|
+
: typeof svcOrFnOrEffect === "function"
|
|
466
|
+
? class {
|
|
467
|
+
static _tag = "raw"
|
|
468
|
+
static handler = (req: any, ctx: any) => svcOrFnOrEffect(req, { ...ctx, Response: rsc[cur].Response })
|
|
469
|
+
}
|
|
470
|
+
: class {
|
|
471
|
+
static _tag = "raw"
|
|
472
|
+
static handler = matchWithServices(cur)(svcOrFnOrEffect, fnOrNone)
|
|
473
|
+
}
|
|
474
|
+
return prev
|
|
475
|
+
},
|
|
476
|
+
{} as
|
|
477
|
+
& {
|
|
478
|
+
// use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
|
|
479
|
+
[Key in keyof Filtered]: MatchWithServicesNew<"d", Key>
|
|
480
|
+
}
|
|
481
|
+
& {
|
|
482
|
+
// use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
|
|
483
|
+
[Key in keyof Filtered as Key extends string ? `${Key}Raw` : never]: MatchWithServicesNew<"raw", Key>
|
|
484
|
+
}
|
|
485
|
+
)
|
|
486
|
+
}
|
|
487
|
+
return r
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const errorHandler = (resourceRequest: { failure?: S.Schema.AnyNoContext }) => {
|
|
491
|
+
return <R>(
|
|
492
|
+
req: HttpServerRequest.HttpServerRequest,
|
|
493
|
+
res: HttpServerResponse.HttpServerResponse,
|
|
494
|
+
r2: Effect<HttpServerResponse.HttpServerResponse, SupportedErrors | JWTError | S.ParseResult.ParseError, R>
|
|
495
|
+
) => defaultErrorHandler(req, res, Effect.catchTag(r2, "ParseError", (_) => Effect.die(_)), resourceRequest.failure)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Gather all handlers of a module and attach them to the Server.
|
|
500
|
+
* If no `allowAnonymous` flag is on the Request, will require a valid authenticated user.
|
|
501
|
+
*/
|
|
502
|
+
|
|
503
|
+
function matchAll<T extends RequestHandlersTest>(handlers: T) {
|
|
504
|
+
const r = typedKeysOf(handlers).reduce((acc, cur) => {
|
|
505
|
+
return HttpRouter.concat(acc, handlers[cur] as any)
|
|
506
|
+
}, HttpRouter.empty)
|
|
507
|
+
|
|
508
|
+
type _RRouter<T extends HttpRouter.HttpRouter<any, any>> = [T] extends [
|
|
509
|
+
HttpRouter.HttpRouter<infer R, any>
|
|
510
|
+
] ? R
|
|
511
|
+
: never
|
|
512
|
+
|
|
513
|
+
type _ERouter<T extends HttpRouter.HttpRouter<any, any>> = [T] extends [
|
|
514
|
+
HttpRouter.HttpRouter<any, infer E>
|
|
515
|
+
] ? E
|
|
516
|
+
: never
|
|
517
|
+
|
|
518
|
+
return r as HttpRouter.HttpRouter<
|
|
519
|
+
_RRouter<typeof handlers[keyof typeof handlers]>,
|
|
520
|
+
_ERouter<typeof handlers[keyof typeof handlers]>
|
|
521
|
+
>
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// type SupportedRequestHandler = RequestHandler<
|
|
525
|
+
// any,
|
|
526
|
+
// any,
|
|
527
|
+
// any,
|
|
528
|
+
// any,
|
|
529
|
+
// any,
|
|
530
|
+
// any,
|
|
531
|
+
// any,
|
|
532
|
+
// any,
|
|
533
|
+
// any,
|
|
534
|
+
// SupportedErrors | S.ParseResult.ParseError,
|
|
535
|
+
// any,
|
|
536
|
+
// any,
|
|
537
|
+
// any,
|
|
538
|
+
// any
|
|
539
|
+
// >
|
|
540
|
+
|
|
541
|
+
// type RequestHandlers = { [key: string]: SupportedRequestHandler }
|
|
542
|
+
type RequestHandlersTest = {
|
|
543
|
+
[key: string]: HttpRouter.HttpRouter<any, any>
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return { matchFor, matchAll }
|
|
547
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// packages/infra/vitest.config.ts
|
|
2
|
+
import { defineConfig } from "file:///Users/patrickroza/pj/effect-app/libs/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30/node_modules/vite/dist/node/index.js";
|
|
3
|
+
|
|
4
|
+
// vite.config.base.ts
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
var __vite_injected_original_dirname = "/Users/patrickroza/pj/effect-app/libs";
|
|
8
|
+
function makeConfig(dirName) {
|
|
9
|
+
const prefix = path.resolve(__vite_injected_original_dirname, "packages");
|
|
10
|
+
const packages = fs.readdirSync(prefix).map((f) => prefix + "/" + f).filter((f) => fs.lstatSync(f).isDirectory());
|
|
11
|
+
const cfg = {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
13
|
+
//plugins: [autoImport],
|
|
14
|
+
test: {
|
|
15
|
+
include: ["./test/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
16
|
+
reporters: "verbose",
|
|
17
|
+
globals: true
|
|
18
|
+
},
|
|
19
|
+
resolve: {
|
|
20
|
+
alias: packages.reduce((acc, cur) => {
|
|
21
|
+
acc[JSON.parse(fs.readFileSync(cur + "/package.json", "utf-8")).name] = path.resolve(cur, cur.endsWith("core") ? "dist" : "src");
|
|
22
|
+
return acc;
|
|
23
|
+
}, {})
|
|
24
|
+
// "@effect-app/core/Prelude": path.join(__dirname, "packages/core/src/Prelude.code.ts")
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
console.log(cfg);
|
|
28
|
+
return cfg;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// packages/infra/vitest.config.ts
|
|
32
|
+
var __vite_injected_original_dirname2 = "/Users/patrickroza/pj/effect-app/libs/packages/infra";
|
|
33
|
+
var vitest_config_default = defineConfig(makeConfig(__vite_injected_original_dirname2));
|
|
34
|
+
export {
|
|
35
|
+
vitest_config_default as default
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50cyIsICJ2aXRlLmNvbmZpZy5iYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYS92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlXCJcbmltcG9ydCBtYWtlQ29uZmlnIGZyb20gXCIuLi8uLi92aXRlLmNvbmZpZy5iYXNlXCJcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKG1ha2VDb25maWcoX19kaXJuYW1lKSlcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlic1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy92aXRlLmNvbmZpZy5iYXNlLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCBmcyBmcm9tIFwiZnNcIlxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSBcInVucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGVcIlxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVzdC9jb25maWdcIlxuXG4vLyBjb25zdCBhdXRvSW1wb3J0ID0gQXV0b0ltcG9ydCh7XG4vLyAgIGR0czogXCIuL3Rlc3QvYXV0by1pbXBvcnRzLmQudHNcIixcbi8vICAgLy8gaW5jbHVkZTogW1xuLy8gICAvLyAgIC9cXC50ZXN0XFwuW3RqXXN4PyQvIC8vIC50cywgLnRzeCwgLmpzLCAuanN4XG4vLyAgIC8vIF0sXG4vLyAgIGltcG9ydHM6IFtcbi8vICAgICBcInZpdGVzdFwiXG4vLyAgIF1cbi8vIH0pXG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIG1ha2VDb25maWcoZGlyTmFtZT86IHN0cmluZykge1xuICBjb25zdCBwcmVmaXggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcInBhY2thZ2VzXCIpXG4gIGNvbnN0IHBhY2thZ2VzID0gZnMucmVhZGRpclN5bmMocHJlZml4KS5tYXAoZiA9PiBwcmVmaXggKyBcIi9cIiArIGYpLmZpbHRlcihmID0+IGZzLmxzdGF0U3luYyhmKS5pc0RpcmVjdG9yeSgpIClcbiAgY29uc3QgY2ZnID0ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgLy9wbHVnaW5zOiBbYXV0b0ltcG9ydF0sXG4gICAgdGVzdDoge1xuICAgICAgaW5jbHVkZTogIFtcIi4vdGVzdC8qKi8qLnRlc3Que2pzLG1qcyxjanMsdHMsbXRzLGN0cyxqc3gsdHN4fVwiXSxcbiAgICAgIHJlcG9ydGVyczogXCJ2ZXJib3NlXCIsXG4gICAgICBnbG9iYWxzOiB0cnVlXG4gICAgfSxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczogcGFja2FnZXMucmVkdWNlKChhY2MsIGN1cikgPT4geyAvLyB3b3JrYXJvdW5kIGZvciAvUHJlbHVkZSBpc3N1ZVxuICAgICAgYWNjW0pTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGN1ciArIFwiL3BhY2thZ2UuanNvblwiLCBcInV0Zi04XCIpKS5uYW1lXSA9IHBhdGgucmVzb2x2ZShjdXIsIGN1ci5lbmRzV2l0aChcImNvcmVcIikgPyBcImRpc3RcIiA6IFwic3JjXCIpXG4gICAgICByZXR1cm4gYWNjXG4gICAgfSwgeyB9KSAvLyBcIkBlZmZlY3QtYXBwL2NvcmUvUHJlbHVkZVwiOiBwYXRoLmpvaW4oX19kaXJuYW1lLCBcInBhY2thZ2VzL2NvcmUvc3JjL1ByZWx1ZGUuY29kZS50c1wiKVxuICB9XG4gIH1cbiAgY29uc29sZS5sb2coY2ZnKVxuICByZXR1cm4gY2ZnXG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUyxvQkFBb0I7OztBQ0E3QixPQUFPLFVBQVU7QUFDakIsT0FBTyxRQUFRO0FBRmYsSUFBTSxtQ0FBbUM7QUFnQjFCLFNBQVIsV0FBNEIsU0FBa0I7QUFDbkQsUUFBTSxTQUFTLEtBQUssUUFBUSxrQ0FBVyxVQUFVO0FBQ2pELFFBQU0sV0FBVyxHQUFHLFlBQVksTUFBTSxFQUFFLElBQUksT0FBSyxTQUFTLE1BQU0sQ0FBQyxFQUFFLE9BQU8sT0FBSyxHQUFHLFVBQVUsQ0FBQyxFQUFFLFlBQVksQ0FBRTtBQUM3RyxRQUFNLE1BQU07QUFBQTtBQUFBO0FBQUEsSUFHVixNQUFNO0FBQUEsTUFDSixTQUFVLENBQUMsa0RBQWtEO0FBQUEsTUFDN0QsV0FBVztBQUFBLE1BQ1gsU0FBUztBQUFBLElBQ1g7QUFBQSxJQUNBLFNBQVM7QUFBQSxNQUNQLE9BQU8sU0FBUyxPQUFPLENBQUMsS0FBSyxRQUFRO0FBQ3JDLFlBQUksS0FBSyxNQUFNLEdBQUcsYUFBYSxNQUFNLGlCQUFpQixPQUFPLENBQUMsRUFBRSxJQUFJLElBQUksS0FBSyxRQUFRLEtBQUssSUFBSSxTQUFTLE1BQU0sSUFBSSxTQUFTLEtBQUs7QUFDL0gsZUFBTztBQUFBLE1BQ1QsR0FBRyxDQUFFLENBQUM7QUFBQTtBQUFBLElBQ1I7QUFBQSxFQUNBO0FBQ0EsVUFBUSxJQUFJLEdBQUc7QUFDZixTQUFPO0FBQ1Q7OztBRHBDQSxJQUFNQSxvQ0FBbUM7QUFJekMsSUFBTyx3QkFBUSxhQUFhLFdBQVdDLGlDQUFTLENBQUM7IiwKICAibmFtZXMiOiBbIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIiwgIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIl0KfQo=
|