@effect-app/infra 2.9.1 → 2.9.2

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @effect-app/infra
2
2
 
3
+ ## 2.9.2
4
+
5
+ ### Patch Changes
6
+
7
+ - experiment
8
+
3
9
  ## 2.9.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toHttpApp = exports.makeRouter = exports.makeMiddleware = exports.RouterSymbol = void 0;
7
+ var _rpc = require("@effect/rpc");
8
+ var _effectApp = require("effect-app");
9
+ var _http = require("effect-app/http");
10
+ var _utils = require("effect-app/utils");
11
+ var _errorReporter = require("../errorReporter.cjs");
12
+ var _logger = require("../logger.cjs");
13
+ var _DynamicMiddleware = require("./routing/DynamicMiddleware.cjs");
14
+ const logRequestError = (0, _errorReporter.logError)("Request");
15
+ const reportRequestError = (0, _errorReporter.reportError)("Request");
16
+ /**
17
+ * Plain jane JSON version
18
+ * @deprecated use HttpRpcRouterNoStream.toHttpApp once support options
19
+ */
20
+ const toHttpApp = (self, options) => {
21
+ const handler = _rpc.RpcRouter.toHandler(self, options);
22
+ return _effectApp.Effect.withFiberRuntime(fiber => {
23
+ const context = fiber.getFiberRef(_effectApp.FiberRef.currentContext);
24
+ const request = _effectApp.Context.unsafeGet(context, _http.HttpServerRequest.HttpServerRequest);
25
+ return _effectApp.Effect.flatMap(request.json, _ => handler(_).pipe(_effectApp.Stream.provideContext(context), _effectApp.Stream.runCollect, _effectApp.Effect.map(_ => _effectApp.Chunk.toReadonlyArray(_)), _effectApp.Effect.andThen(_ => {
26
+ let status = 200;
27
+ for (const r of _.flat()) {
28
+ if (typeof r === "number") continue;
29
+ const results = Array.isArray(r) ? r : [r];
30
+ if (results.some(_ => _._tag === "Failure" && _.cause._tag === "Die")) {
31
+ status = 500;
32
+ break;
33
+ }
34
+ if (results.some(_ => _._tag === "Failure" && _.cause._tag === "Fail")) {
35
+ status = 422; // 418
36
+ break;
37
+ }
38
+ }
39
+ return _http.HttpServerResponse.json(_, {
40
+ status
41
+ });
42
+ }), _effectApp.Effect.orDie, _effectApp.Effect.tapDefect((0, _errorReporter.reportError)("RPCHttpApp"))));
43
+ });
44
+ };
45
+ exports.toHttpApp = toHttpApp;
46
+ const RouterSymbol = exports.RouterSymbol = Symbol();
47
+ // export interface RouteMatcher<
48
+ // Filtered extends Record<string, any>,
49
+ // CTXMap extends Record<string, any>,
50
+ // Rsc extends Filtered
51
+ // > extends RouteMatcherInt<Filtered, CTXMap, Rsc> {}
52
+ const makeMiddleware = content => content;
53
+ exports.makeMiddleware = makeMiddleware;
54
+ const makeRouter = (middleware, devMode) => {
55
+ function matchFor(rsc) {
56
+ const meta = rsc.meta;
57
+ const filtered = (0, _utils.typedKeysOf)(rsc).reduce((acc, cur) => {
58
+ if (_effectApp.Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
59
+ acc[cur] = rsc[cur];
60
+ }
61
+ return acc;
62
+ }, {});
63
+ const items = (0, _utils.typedKeysOf)(filtered).reduce((prev, cur) => {
64
+ ;
65
+ prev[cur] = Object.assign(fnOrEffect => {
66
+ const stack = new Error().stack?.split("\n").slice(2).join("\n");
67
+ return _effectApp.Effect.isEffect(fnOrEffect) ? class {
68
+ static stack = stack;
69
+ static _tag = "d";
70
+ static handler = () => fnOrEffect;
71
+ } : class {
72
+ static stack = stack;
73
+ static _tag = "d";
74
+ static handler = fnOrEffect;
75
+ };
76
+ }, {
77
+ success: rsc[cur].success,
78
+ successRaw: _effectApp.S.encodedSchema(rsc[cur].success),
79
+ failure: rsc[cur].failure,
80
+ raw:
81
+ // "Raw" variations are for when you don't want to decode just to encode it again on the response
82
+ // e.g for direct projection from DB
83
+ // but more importantly, to skip Effectful decoders, like to resolve relationships from the database or remote client.
84
+ fnOrEffect => {
85
+ const stack = new Error().stack?.split("\n").slice(2).join("\n");
86
+ return _effectApp.Effect.isEffect(fnOrEffect) ? class {
87
+ static stack = stack;
88
+ static _tag = "raw";
89
+ static handler = () => fnOrEffect;
90
+ } : class {
91
+ static stack = stack;
92
+ static _tag = "raw";
93
+ static handler = (req, ctx) => fnOrEffect(req, {
94
+ ...ctx,
95
+ Response: rsc[cur].success
96
+ });
97
+ };
98
+ }
99
+ });
100
+ return prev;
101
+ }, {});
102
+ const effect = (layers, make) => {
103
+ const r = class Router extends _http.HttpRouter.Tag(`${meta.moduleName}Router`)() {};
104
+ const layer = r.use(router => _effectApp.Effect.gen(function* () {
105
+ const controllers = yield* make(items);
106
+ const rpc = yield* (0, _DynamicMiddleware.makeRpc)(middleware);
107
+ // return make.pipe(Effect.map((c) => controllers(c, layers)))
108
+ const mapped = (0, _utils.typedKeysOf)(filtered).reduce((acc, cur) => {
109
+ const handler = controllers[cur];
110
+ const req = rsc[cur];
111
+ acc[cur] = rpc.effect(handler._tag === "raw" ? class extends req {
112
+ static success = _effectApp.S.encodedSchema(req.success);
113
+ get [_effectApp.Schema.symbolSerializable]() {
114
+ return this.constructor;
115
+ }
116
+ get [_effectApp.Schema.symbolWithResult]() {
117
+ return {
118
+ failure: req.failure,
119
+ success: _effectApp.S.encodedSchema(req.success)
120
+ };
121
+ }
122
+ } : req, req => _effectApp.Effect.annotateCurrentSpan("requestInput", Object.entries(req).reduce((prev, [key, value]) => {
123
+ prev[key] = key === "password" ? "<redacted>" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? typeof value === "string" && value.length > 256 ? value.substring(0, 253) + "..." : value : Array.isArray(value) ? `Array[${value.length}]` : value === null || value === undefined ? `${value}` : typeof value === "object" && value ? `Object[${Object.keys(value).length}]` : typeof value;
124
+ return prev;
125
+ }, {})).pipe(
126
+ // can't use andThen due to some being a function and effect
127
+ _effectApp.Effect.zipRight(handler.handler(req)), _effectApp.Effect.tapErrorCause(cause => _effectApp.Cause.isFailure(cause) ? logRequestError(cause) : _effectApp.Effect.void), _effectApp.Effect.tapDefect(cause => _effectApp.Effect.all([reportRequestError(cause, {
128
+ action: `${meta.moduleName}.${req._tag}`
129
+ }), _rpc.Rpc.currentHeaders.pipe(_effectApp.Effect.andThen(headers => {
130
+ return _logger.InfraLogger.logError("Finished request", cause).pipe(_effectApp.Effect.annotateLogs({
131
+ action: `${meta.moduleName}.${req._tag}`,
132
+ req: (0, _utils.pretty)(req),
133
+ headers: (0, _utils.pretty)(headers)
134
+ // resHeaders: pretty(
135
+ // Object
136
+ // .entries(headers)
137
+ // .reduce((prev, [key, value]) => {
138
+ // prev[key] = value && typeof value === "string" ? snipString(value) : value
139
+ // return prev
140
+ // }, {} as Record<string, any>)
141
+ // )
142
+ }));
143
+ }))])), devMode ? _ => _ : _effectApp.Effect.catchAllDefect(() => _effectApp.Effect.die("Internal Server Error")), _effectApp.Effect.withSpan("Request." + meta.moduleName + "." + req._tag, {
144
+ captureStackTrace: () => handler.stack
145
+ })), meta.moduleName); // TODO
146
+ return acc;
147
+ }, {});
148
+ const rpcRouter = _rpc.RpcRouter.make(...Object.values(mapped));
149
+ const httpApp = toHttpApp(rpcRouter, {
150
+ spanPrefix: rsc.meta.moduleName + "."
151
+ });
152
+ yield* router.all("/", httpApp,
153
+ // TODO: not queries.
154
+ {
155
+ uninterruptible: true
156
+ });
157
+ }));
158
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
159
+ const routes = layer.pipe(_effectApp.Layer.provideMerge(r.Live), layers ? _effectApp.Layer.provide(layers) : _ => _,
160
+ // TODO: only provide to the middleware?
161
+ middleware.dependencies ? _effectApp.Layer.provide(middleware.dependencies) : _ => _);
162
+ // Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
163
+ return {
164
+ moduleName: meta.moduleName,
165
+ Router: r,
166
+ routes
167
+ };
168
+ };
169
+ return effect;
170
+ }
171
+ function matchAll(handlers, requestLayer) {
172
+ const routers = (0, _utils.typedValuesOf)(handlers);
173
+ const rootRouter = class extends _http.HttpRouter.Tag("RootRouter")() {};
174
+ const r = rootRouter.use(router => _effectApp.Effect.gen(function* () {
175
+ for (const route of routers) {
176
+ yield* router.mount("/rpc/" + route.moduleName, yield* route.Router.router.pipe(_effectApp.Effect.map(_http.HttpRouter.use((0, _effectApp.flow)(_effectApp.Effect.provide(requestLayer))))));
177
+ }
178
+ })).pipe(_effectApp.Layer.provide(routers.map(r => r.routes).flat()));
179
+ return {
180
+ layer: r,
181
+ Router: rootRouter
182
+ };
183
+ }
184
+ return {
185
+ matchAll,
186
+ matchFor
187
+ };
188
+ };
189
+ exports.makeRouter = makeRouter;
190
+ //# sourceMappingURL=routing4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing4.cjs","names":["_rpc","require","_effectApp","_http","_utils","_errorReporter","_logger","_DynamicMiddleware","logRequestError","logError","reportRequestError","reportError","toHttpApp","self","options","handler","RpcRouter","toHandler","Effect","withFiberRuntime","fiber","context","getFiberRef","FiberRef","currentContext","request","Context","unsafeGet","HttpServerRequest","flatMap","json","_","pipe","Stream","provideContext","runCollect","map","Chunk","toReadonlyArray","andThen","status","r","flat","results","Array","isArray","some","_tag","cause","HttpServerResponse","orDie","tapDefect","exports","RouterSymbol","Symbol","makeMiddleware","content","makeRouter","middleware","devMode","matchFor","rsc","meta","filtered","typedKeysOf","reduce","acc","cur","Predicate","isObject","items","prev","Object","assign","fnOrEffect","stack","Error","split","slice","join","isEffect","success","successRaw","S","encodedSchema","failure","raw","req","ctx","Response","effect","layers","make","Router","HttpRouter","Tag","moduleName","layer","use","router","gen","controllers","rpc","makeRpc","mapped","Schema","symbolSerializable","constructor","symbolWithResult","annotateCurrentSpan","entries","key","value","length","substring","undefined","keys","zipRight","tapErrorCause","Cause","isFailure","void","all","action","Rpc","currentHeaders","headers","InfraLogger","annotateLogs","pretty","catchAllDefect","die","withSpan","captureStackTrace","rpcRouter","values","httpApp","spanPrefix","uninterruptible","routes","Layer","provideMerge","Live","provide","dependencies","matchAll","handlers","requestLayer","routers","typedValuesOf","rootRouter","route","mount","flow"],"sources":["../../src/api/routing4.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,104 @@
1
+ import type * as HttpApp from "@effect/platform/HttpApp";
2
+ import { Rpc, RpcRouter } from "@effect/rpc";
3
+ import type { NonEmptyArray } from "effect-app";
4
+ import { Effect, Layer, S } from "effect-app";
5
+ import type { GetEffectContext, RPCContextMap } from "effect-app/client/req";
6
+ import type { HttpServerError } from "effect-app/http";
7
+ import { HttpRouter } from "effect-app/http";
8
+ import type { Middleware } from "./routing/DynamicMiddleware.js";
9
+ export type _R<T extends Effect<any, any, any>> = [T] extends [
10
+ Effect<any, any, infer R>
11
+ ] ? R : never;
12
+ export type _E<T extends Effect<any, any, any>> = [T] extends [
13
+ Effect<any, infer E, any>
14
+ ] ? E : never;
15
+ export type EffectDeps<A> = {
16
+ [K in keyof A as A[K] extends Effect<any, any, any> ? K : never]: A[K] extends Effect<any, any, any> ? A[K] : never;
17
+ };
18
+ /**
19
+ * Plain jane JSON version
20
+ * @deprecated use HttpRpcRouterNoStream.toHttpApp once support options
21
+ */
22
+ export declare const toHttpApp: <R extends RpcRouter.RpcRouter<any, any>>(self: R, options?: {
23
+ readonly spanPrefix?: string;
24
+ }) => HttpApp.Default<HttpServerError.RequestError, RpcRouter.RpcRouter.Context<R>>;
25
+ export interface Hint<Err extends string> {
26
+ Err: Err;
27
+ }
28
+ type HandleVoid<Expected, Actual, Result> = [Expected] extends [void] ? [Actual] extends [void] ? Result : Hint<"You're returning non void for a void Response, please fix"> : Result;
29
+ type AnyRequestModule = S.Schema.Any & {
30
+ success?: S.Schema.Any;
31
+ failure?: S.Schema.Any;
32
+ };
33
+ type GetSuccess<T> = T extends {
34
+ success: S.Schema.Any;
35
+ } ? T["success"] : typeof S.Void;
36
+ type GetSuccessShape<Action extends {
37
+ success?: S.Schema.Any;
38
+ }, RT extends "d" | "raw"> = RT extends "raw" ? S.Schema.Encoded<GetSuccess<Action>> : S.Schema.Type<GetSuccess<Action>>;
39
+ type GetFailure<T extends {
40
+ failure?: S.Schema.Any;
41
+ }> = T["failure"] extends never ? typeof S.Never : T["failure"];
42
+ type HandlerFull<Action extends AnyRequestModule, RT extends "raw" | "d", A, E, R> = {
43
+ new (): {};
44
+ _tag: RT;
45
+ stack: string;
46
+ handler: (req: S.Schema.Type<Action>) => Effect<A, E, R>;
47
+ };
48
+ export interface Handler<Action extends AnyRequestModule, RT extends "raw" | "d", R> extends HandlerFull<Action, RT, GetSuccessShape<Action, RT>, S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError, R> {
49
+ }
50
+ type AHandler<Action extends AnyRequestModule> = Handler<Action, any, any>;
51
+ type Filter<T> = {
52
+ [K in keyof T as T[K] extends S.Schema.All & {
53
+ success: S.Schema.Any;
54
+ failure: S.Schema.Any;
55
+ } ? K : never]: T[K];
56
+ };
57
+ export declare const RouterSymbol: unique symbol;
58
+ export interface RouterShape<Rsc> {
59
+ [RouterSymbol]: Rsc;
60
+ }
61
+ type RPCRouteR<T extends Rpc.Rpc<any, any>> = [T] extends [
62
+ Rpc.Rpc<any, infer R>
63
+ ] ? R : never;
64
+ type Match<Rsc extends Record<string, any>, CTXMap extends Record<string, any>, RT extends "raw" | "d", Key extends keyof Rsc, Context> = {
65
+ <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(f: Effect<A, E, R2>): HandleVoid<GetSuccessShape<Rsc[Key], RT>, A, Handler<Rsc[Key], RT, Exclude<Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>, HttpRouter.HttpRouter.Provided>>>;
66
+ <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(f: (req: S.Schema.Type<Rsc[Key]>) => Effect<A, E, R2>): HandleVoid<GetSuccessShape<Rsc[Key], RT>, A, Handler<Rsc[Key], RT, Exclude<Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>, HttpRouter.HttpRouter.Provided>>>;
67
+ };
68
+ export type RouteMatcher<CTXMap extends Record<string, any>, Rsc extends Record<string, any>, Context> = {
69
+ [Key in keyof Filter<Rsc>]: Match<Rsc, CTXMap, "d", Key, Context> & {
70
+ success: Rsc[Key]["success"];
71
+ successRaw: S.SchemaClass<S.Schema.Encoded<Rsc[Key]["success"]>>;
72
+ failure: Rsc[Key]["failure"];
73
+ /**
74
+ * Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
75
+ */
76
+ raw: Match<Rsc, CTXMap, "raw", Key, Context>;
77
+ };
78
+ };
79
+ export declare const makeMiddleware: <Context, CTXMap extends Record<string, RPCContextMap.Any>, RMW, Layers extends Array<Layer.Layer.Any>>(content: Middleware<Context, CTXMap, RMW, Layers>) => Middleware<Context, CTXMap, RMW, Layers>;
80
+ export declare const makeRouter: <Context, CTXMap extends Record<string, RPCContextMap.Any>, RMW, Layers extends Array<Layer.Layer.Any>>(middleware: Middleware<Context, CTXMap, RMW, Layers>, devMode: boolean) => {
81
+ matchAll: <T extends {
82
+ [key: string]: {
83
+ Router: {
84
+ router: Effect<HttpRouter.HttpRouter<any, any>, any, any>;
85
+ };
86
+ routes: Layer.Layer<any, any, any>;
87
+ moduleName: string;
88
+ };
89
+ }, A, E, R>(handlers: T, requestLayer: Layer.Layer<A, E, R>) => {
90
+ layer: Layer.Layer<never, Layer.Layer.Error<(typeof handlers)[keyof typeof handlers]["routes"]>, Layer.Layer.Context<(typeof handlers)[keyof typeof handlers]["routes"]>>;
91
+ Router: HttpRouter.HttpRouter.TagClass<"RootRouter", "RootRouter", Effect.Effect.Success<T[keyof T]["Router"]["router"]> extends infer T_1 ? T_1 extends Effect.Effect.Success<T[keyof T]["Router"]["router"]> ? T_1 extends HttpRouter.HttpRouter<infer E_1, any> ? E_1 : never : never : never, R | Exclude<Effect.Effect.Success<T[keyof T]["Router"]["router"]> extends infer T_2 ? T_2 extends Effect.Effect.Success<T[keyof T]["Router"]["router"]> ? T_2 extends HttpRouter.HttpRouter<any, infer R_1> ? R_1 : never : never : never, A>>;
92
+ };
93
+ matchFor: <const ModuleName extends string, const Rsc extends Record<string, any>>(rsc: Rsc & {
94
+ meta: {
95
+ moduleName: ModuleName;
96
+ };
97
+ }) => <E_1, R_1, THandlers extends { [K in keyof Filter<Rsc>]: AHandler<Rsc[K]>; }, TLayers extends NonEmptyArray<Layer.Layer.Any>>(layers: TLayers, make: (requests: RouteMatcher<CTXMap, Rsc, Context>) => Effect<THandlers, E_1, R_1>) => {
98
+ moduleName: ModuleName;
99
+ Router: HttpRouter.HttpRouter.TagClass<RouterShape<Rsc>, `${ModuleName}Router`, never, Exclude<Context, HttpRouter.HttpRouter.Provided> | Exclude<RPCRouteR<{ [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<THandlers[K]["handler"]>>>; }[keyof Filter<Rsc>]>, HttpRouter.HttpRouter.Provided>>;
100
+ routes: Layer.Layer<RouterShape<Rsc>, E_1 | { [k in keyof TLayers]: Layer.Layer.Error<TLayers[k]>; }[number], { [k_1 in keyof TLayers]: Layer.Layer.Context<TLayers[k_1]>; }[number] | Exclude<RMW, { [k_2 in keyof Layers]: Layer.Layer.Success<Layers[k_2]>; }[number] | { [k_3 in keyof TLayers]: Layer.Layer.Success<TLayers[k_3]>; }[number]> | Exclude<R_1, { [k_2 in keyof Layers]: Layer.Layer.Success<Layers[k_2]>; }[number] | { [k_3 in keyof TLayers]: Layer.Layer.Success<TLayers[k_3]>; }[number]>>;
101
+ };
102
+ };
103
+ export {};
104
+ //# sourceMappingURL=routing4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing4.d.ts","sourceRoot":"","sources":["../../src/api/routing4.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ import { Rpc, RpcRouter } from "@effect/rpc";
2
+ import { Cause, Chunk, Context, Effect, FiberRef, flow, Layer, Predicate, S, Schema, Stream } from "effect-app";
3
+ import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect-app/http";
4
+ import { pretty, typedKeysOf, typedValuesOf } from "effect-app/utils";
5
+ import { logError, reportError } from "../errorReporter.js";
6
+ import { InfraLogger } from "../logger.js";
7
+ import { makeRpc } from "./routing/DynamicMiddleware.js";
8
+ const logRequestError = logError("Request");
9
+ const reportRequestError = reportError("Request");
10
+ /**
11
+ * Plain jane JSON version
12
+ * @deprecated use HttpRpcRouterNoStream.toHttpApp once support options
13
+ */
14
+ export const toHttpApp = (self, options) => {
15
+ const handler = RpcRouter.toHandler(self, options);
16
+ return Effect.withFiberRuntime((fiber) => {
17
+ const context = fiber.getFiberRef(FiberRef.currentContext);
18
+ const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest);
19
+ return Effect.flatMap(request.json, (_) => handler(_).pipe(Stream.provideContext(context), Stream.runCollect, Effect.map((_) => Chunk.toReadonlyArray(_)), Effect.andThen((_) => {
20
+ let status = 200;
21
+ for (const r of _.flat()) {
22
+ if (typeof r === "number")
23
+ continue;
24
+ const results = Array.isArray(r) ? r : [r];
25
+ if (results.some((_) => _._tag === "Failure" && _.cause._tag === "Die")) {
26
+ status = 500;
27
+ break;
28
+ }
29
+ if (results.some((_) => _._tag === "Failure" && _.cause._tag === "Fail")) {
30
+ status = 422; // 418
31
+ break;
32
+ }
33
+ }
34
+ return HttpServerResponse.json(_, { status });
35
+ }), Effect.orDie, Effect.tapDefect(reportError("RPCHttpApp"))));
36
+ });
37
+ };
38
+ export const RouterSymbol = Symbol();
39
+ // export interface RouteMatcher<
40
+ // Filtered extends Record<string, any>,
41
+ // CTXMap extends Record<string, any>,
42
+ // Rsc extends Filtered
43
+ // > extends RouteMatcherInt<Filtered, CTXMap, Rsc> {}
44
+ export const makeMiddleware = (content) => content;
45
+ export const makeRouter = (middleware, devMode) => {
46
+ function matchFor(rsc) {
47
+ const meta = rsc.meta;
48
+ const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
49
+ if (Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
50
+ acc[cur] = rsc[cur];
51
+ }
52
+ return acc;
53
+ }, {});
54
+ const items = typedKeysOf(filtered).reduce((prev, cur) => {
55
+ ;
56
+ prev[cur] = Object.assign((fnOrEffect) => {
57
+ const stack = new Error().stack?.split("\n").slice(2).join("\n");
58
+ return Effect.isEffect(fnOrEffect)
59
+ ? class {
60
+ static stack = stack;
61
+ static _tag = "d";
62
+ static handler = () => fnOrEffect;
63
+ }
64
+ : class {
65
+ static stack = stack;
66
+ static _tag = "d";
67
+ static handler = fnOrEffect;
68
+ };
69
+ }, {
70
+ success: rsc[cur].success,
71
+ successRaw: S.encodedSchema(rsc[cur].success),
72
+ failure: rsc[cur].failure,
73
+ raw: // "Raw" variations are for when you don't want to decode just to encode it again on the response
74
+ // e.g for direct projection from DB
75
+ // but more importantly, to skip Effectful decoders, like to resolve relationships from the database or remote client.
76
+ (fnOrEffect) => {
77
+ const stack = new Error().stack?.split("\n").slice(2).join("\n");
78
+ return Effect.isEffect(fnOrEffect)
79
+ ? class {
80
+ static stack = stack;
81
+ static _tag = "raw";
82
+ static handler = () => fnOrEffect;
83
+ }
84
+ : class {
85
+ static stack = stack;
86
+ static _tag = "raw";
87
+ static handler = (req, ctx) => fnOrEffect(req, { ...ctx, Response: rsc[cur].success });
88
+ };
89
+ }
90
+ });
91
+ return prev;
92
+ }, {});
93
+ const effect = (layers, make) => {
94
+ const r = (class Router extends HttpRouter.Tag(`${meta.moduleName}Router`)() {
95
+ });
96
+ const layer = r.use((router) => Effect.gen(function* () {
97
+ const controllers = yield* make(items);
98
+ const rpc = yield* makeRpc(middleware);
99
+ // return make.pipe(Effect.map((c) => controllers(c, layers)))
100
+ const mapped = typedKeysOf(filtered).reduce((acc, cur) => {
101
+ const handler = controllers[cur];
102
+ const req = rsc[cur];
103
+ acc[cur] = rpc.effect(handler._tag === "raw"
104
+ ? class extends req {
105
+ static success = S.encodedSchema(req.success);
106
+ get [Schema.symbolSerializable]() {
107
+ return this.constructor;
108
+ }
109
+ get [Schema.symbolWithResult]() {
110
+ return {
111
+ failure: req.failure,
112
+ success: S.encodedSchema(req.success)
113
+ };
114
+ }
115
+ }
116
+ : req, (req) => Effect
117
+ .annotateCurrentSpan("requestInput", Object.entries(req).reduce((prev, [key, value]) => {
118
+ prev[key] = key === "password"
119
+ ? "<redacted>"
120
+ : typeof value === "string" || typeof value === "number" || typeof value === "boolean"
121
+ ? typeof value === "string" && value.length > 256
122
+ ? (value.substring(0, 253) + "...")
123
+ : value
124
+ : Array.isArray(value)
125
+ ? `Array[${value.length}]`
126
+ : value === null || value === undefined
127
+ ? `${value}`
128
+ : typeof value === "object" && value
129
+ ? `Object[${Object.keys(value).length}]`
130
+ : typeof value;
131
+ return prev;
132
+ }, {}))
133
+ .pipe(
134
+ // can't use andThen due to some being a function and effect
135
+ Effect.zipRight(handler.handler(req)), Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void), Effect.tapDefect((cause) => Effect
136
+ .all([
137
+ reportRequestError(cause, {
138
+ action: `${meta.moduleName}.${req._tag}`
139
+ }),
140
+ Rpc.currentHeaders.pipe(Effect.andThen((headers) => {
141
+ return InfraLogger
142
+ .logError("Finished request", cause)
143
+ .pipe(Effect.annotateLogs({
144
+ action: `${meta.moduleName}.${req._tag}`,
145
+ req: pretty(req),
146
+ headers: pretty(headers)
147
+ // resHeaders: pretty(
148
+ // Object
149
+ // .entries(headers)
150
+ // .reduce((prev, [key, value]) => {
151
+ // prev[key] = value && typeof value === "string" ? snipString(value) : value
152
+ // return prev
153
+ // }, {} as Record<string, any>)
154
+ // )
155
+ }));
156
+ }))
157
+ ])), devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")), Effect.withSpan("Request." + meta.moduleName + "." + req._tag, {
158
+ captureStackTrace: () => handler.stack
159
+ })), meta.moduleName); // TODO
160
+ return acc;
161
+ }, {});
162
+ const rpcRouter = RpcRouter.make(...Object.values(mapped));
163
+ const httpApp = toHttpApp(rpcRouter, {
164
+ spanPrefix: rsc
165
+ .meta
166
+ .moduleName + "."
167
+ });
168
+ yield* router
169
+ .all("/", httpApp,
170
+ // TODO: not queries.
171
+ { uninterruptible: true });
172
+ }));
173
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
174
+ const routes = layer.pipe(Layer.provideMerge(r.Live), layers ? Layer.provide(layers) : (_) => _,
175
+ // TODO: only provide to the middleware?
176
+ middleware.dependencies ? Layer.provide(middleware.dependencies) : (_) => _);
177
+ // Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
178
+ return {
179
+ moduleName: meta.moduleName,
180
+ Router: r,
181
+ routes
182
+ };
183
+ };
184
+ return effect;
185
+ }
186
+ function matchAll(handlers, requestLayer) {
187
+ const routers = typedValuesOf(handlers);
188
+ const rootRouter = class extends HttpRouter.Tag("RootRouter")() {
189
+ };
190
+ const r = rootRouter
191
+ .use((router) => Effect.gen(function* () {
192
+ for (const route of routers) {
193
+ yield* router.mount(("/rpc/" + route.moduleName), yield* route
194
+ .Router
195
+ .router
196
+ .pipe(Effect.map(HttpRouter.use(flow(Effect.provide(requestLayer))))));
197
+ }
198
+ }))
199
+ .pipe(Layer.provide(routers.map((r) => r.routes).flat()));
200
+ return {
201
+ layer: r,
202
+ Router: rootRouter
203
+ };
204
+ }
205
+ return { matchAll, matchFor };
206
+ };
207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGluZzQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3JvdXRpbmc0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBRTVDLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBRy9HLE9BQU8sRUFBRSxVQUFVLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUNuRixPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNyRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFFMUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGdDQUFnQyxDQUFBO0FBRXhELE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUMzQyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQWVqRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxTQUFTLEdBQUcsQ0FBMEMsSUFBTyxFQUFFLE9BRTNFLEVBR0MsRUFBRTtJQUNGLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ2xELE9BQU8sTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDdkMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxR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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "2.9.1",
3
+ "version": "2.9.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -659,6 +659,16 @@
659
659
  "default": "./_cjs/api/routing/schema/jwt.cjs"
660
660
  }
661
661
  },
662
+ "./api/routing4": {
663
+ "import": {
664
+ "types": "./dist/api/routing4.d.ts",
665
+ "default": "./dist/api/routing4.js"
666
+ },
667
+ "require": {
668
+ "types": "./dist/api/routing4.d.ts",
669
+ "default": "./_cjs/api/routing4.cjs"
670
+ }
671
+ },
662
672
  "./api/setupRequest": {
663
673
  "import": {
664
674
  "types": "./dist/api/setupRequest.d.ts",
@@ -0,0 +1,510 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ /*
5
+ TODO: Effect.retry(r2, optimisticConcurrencySchedule) / was for PATCH only
6
+ TODO: uninteruptible commands! was for All except GET.
7
+ */
8
+ import type * as HttpApp from "@effect/platform/HttpApp"
9
+ import { Rpc, RpcRouter } from "@effect/rpc"
10
+ import type { NonEmptyArray } from "effect-app"
11
+ import { Cause, Chunk, Context, Effect, FiberRef, flow, Layer, Predicate, S, Schema, Stream } from "effect-app"
12
+ import type { GetEffectContext, RPCContextMap } from "effect-app/client/req"
13
+ import type { HttpServerError } from "effect-app/http"
14
+ import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect-app/http"
15
+ import { pretty, typedKeysOf, typedValuesOf } from "effect-app/utils"
16
+ import { logError, reportError } from "../errorReporter.js"
17
+ import { InfraLogger } from "../logger.js"
18
+ import type { Middleware } from "./routing/DynamicMiddleware.js"
19
+ import { makeRpc } from "./routing/DynamicMiddleware.js"
20
+
21
+ const logRequestError = logError("Request")
22
+ const reportRequestError = reportError("Request")
23
+
24
+ export type _R<T extends Effect<any, any, any>> = [T] extends [
25
+ Effect<any, any, infer R>
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
+ /**
38
+ * Plain jane JSON version
39
+ * @deprecated use HttpRpcRouterNoStream.toHttpApp once support options
40
+ */
41
+ export const toHttpApp = <R extends RpcRouter.RpcRouter<any, any>>(self: R, options?: {
42
+ readonly spanPrefix?: string
43
+ }): HttpApp.Default<
44
+ HttpServerError.RequestError,
45
+ RpcRouter.RpcRouter.Context<R>
46
+ > => {
47
+ const handler = RpcRouter.toHandler(self, options)
48
+ return Effect.withFiberRuntime((fiber) => {
49
+ const context = fiber.getFiberRef(FiberRef.currentContext)
50
+ const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest)
51
+ return Effect.flatMap(
52
+ request.json,
53
+ (_) =>
54
+ handler(_).pipe(
55
+ Stream.provideContext(context),
56
+ Stream.runCollect,
57
+ Effect.map((_) => Chunk.toReadonlyArray(_)),
58
+ Effect.andThen((_) => {
59
+ let status = 200
60
+ for (const r of _.flat()) {
61
+ if (typeof r === "number") continue
62
+ const results = Array.isArray(r) ? r : [r]
63
+ if (results.some((_: S.ExitEncoded<any, any, any>) => _._tag === "Failure" && _.cause._tag === "Die")) {
64
+ status = 500
65
+ break
66
+ }
67
+ if (results.some((_: S.ExitEncoded<any, any, any>) => _._tag === "Failure" && _.cause._tag === "Fail")) {
68
+ status = 422 // 418
69
+ break
70
+ }
71
+ }
72
+ return HttpServerResponse.json(_, { status })
73
+ }),
74
+ Effect.orDie,
75
+ Effect.tapDefect(reportError("RPCHttpApp"))
76
+ )
77
+ )
78
+ })
79
+ }
80
+
81
+ export interface Hint<Err extends string> {
82
+ Err: Err
83
+ }
84
+
85
+ type HandleVoid<Expected, Actual, Result> = [Expected] extends [void]
86
+ ? [Actual] extends [void] ? Result : Hint<"You're returning non void for a void Response, please fix">
87
+ : Result
88
+
89
+ type AnyRequestModule = S.Schema.Any & { success?: S.Schema.Any; failure?: S.Schema.Any }
90
+
91
+ type GetSuccess<T> = T extends { success: S.Schema.Any } ? T["success"] : typeof S.Void
92
+
93
+ type GetSuccessShape<Action extends { success?: S.Schema.Any }, RT extends "d" | "raw"> = RT extends "raw"
94
+ ? S.Schema.Encoded<GetSuccess<Action>>
95
+ : S.Schema.Type<GetSuccess<Action>>
96
+ type GetFailure<T extends { failure?: S.Schema.Any }> = T["failure"] extends never ? typeof S.Never : T["failure"]
97
+
98
+ type HandlerFull<Action extends AnyRequestModule, RT extends "raw" | "d", A, E, R> = {
99
+ new(): {}
100
+ _tag: RT
101
+ stack: string
102
+ handler: (
103
+ req: S.Schema.Type<Action>
104
+ ) => Effect<
105
+ A,
106
+ E,
107
+ R
108
+ >
109
+ }
110
+
111
+ export interface Handler<Action extends AnyRequestModule, RT extends "raw" | "d", R> extends
112
+ HandlerFull<
113
+ Action,
114
+ RT,
115
+ GetSuccessShape<Action, RT>,
116
+ S.Schema.Type<GetFailure<Action>> | S.ParseResult.ParseError,
117
+ R
118
+ >
119
+ {
120
+ }
121
+
122
+ type AHandler<Action extends AnyRequestModule> = Handler<
123
+ Action,
124
+ any,
125
+ any
126
+ >
127
+
128
+ type Filter<T> = {
129
+ [K in keyof T as T[K] extends S.Schema.All & { success: S.Schema.Any; failure: S.Schema.Any } ? K : never]: T[K]
130
+ }
131
+
132
+ export const RouterSymbol = Symbol()
133
+ export interface RouterShape<Rsc> {
134
+ [RouterSymbol]: Rsc
135
+ }
136
+
137
+ type RPCRouteR<T extends Rpc.Rpc<any, any>> = [T] extends [
138
+ Rpc.Rpc<any, infer R>
139
+ ] ? R
140
+ : never
141
+
142
+ type RPCRouteReq<T extends Rpc.Rpc<any, any>> = [T] extends [
143
+ Rpc.Rpc<infer Req, any>
144
+ ] ? Req
145
+ : never
146
+
147
+ type Match<
148
+ Rsc extends Record<string, any>,
149
+ CTXMap extends Record<string, any>,
150
+ RT extends "raw" | "d",
151
+ Key extends keyof Rsc,
152
+ Context
153
+ > = {
154
+ // TODO: deal with HandleVoid and ability to extends from GetSuccessShape...
155
+ // aka we want to make sure that the return type is void if the success is void,
156
+ // and make sure A is the actual expected type
157
+
158
+ // note: the defaults of = never prevent the whole router to error
159
+ <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(
160
+ f: Effect<A, E, R2>
161
+ ): HandleVoid<
162
+ GetSuccessShape<Rsc[Key], RT>,
163
+ A,
164
+ Handler<
165
+ Rsc[Key],
166
+ RT,
167
+ Exclude<
168
+ Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
169
+ HttpRouter.HttpRouter.Provided
170
+ >
171
+ >
172
+ >
173
+
174
+ <A extends GetSuccessShape<Rsc[Key], RT>, R2 = never, E = never>(
175
+ f: (req: S.Schema.Type<Rsc[Key]>) => Effect<A, E, R2>
176
+ ): HandleVoid<
177
+ GetSuccessShape<Rsc[Key], RT>,
178
+ A,
179
+ Handler<
180
+ Rsc[Key],
181
+ RT,
182
+ Exclude<
183
+ Context | Exclude<R2, GetEffectContext<CTXMap, Rsc[Key]["config"]>>,
184
+ HttpRouter.HttpRouter.Provided
185
+ >
186
+ >
187
+ >
188
+ }
189
+
190
+ export type RouteMatcher<
191
+ CTXMap extends Record<string, any>,
192
+ Rsc extends Record<string, any>,
193
+ Context
194
+ > = {
195
+ // use Rsc as Key over using Keys, so that the Go To on X.Action remain in tact in Controllers files
196
+ /**
197
+ * Requires the Type shape
198
+ */
199
+ [Key in keyof Filter<Rsc>]: Match<Rsc, CTXMap, "d", Key, Context> & {
200
+ success: Rsc[Key]["success"]
201
+ successRaw: S.SchemaClass<S.Schema.Encoded<Rsc[Key]["success"]>>
202
+ failure: Rsc[Key]["failure"]
203
+ /**
204
+ * Requires the Encoded shape (e.g directly undecoded from DB, so that we don't do multiple Decode/Encode)
205
+ */
206
+ raw: Match<Rsc, CTXMap, "raw", Key, Context>
207
+ }
208
+ }
209
+ // export interface RouteMatcher<
210
+ // Filtered extends Record<string, any>,
211
+ // CTXMap extends Record<string, any>,
212
+ // Rsc extends Filtered
213
+ // > extends RouteMatcherInt<Filtered, CTXMap, Rsc> {}
214
+
215
+ export const makeMiddleware = <
216
+ Context,
217
+ CTXMap extends Record<string, RPCContextMap.Any>,
218
+ RMW,
219
+ Layers extends Array<Layer.Layer.Any>
220
+ >(content: Middleware<Context, CTXMap, RMW, Layers>): Middleware<Context, CTXMap, RMW, Layers> => content
221
+
222
+ export const makeRouter = <
223
+ Context,
224
+ CTXMap extends Record<string, RPCContextMap.Any>,
225
+ RMW,
226
+ Layers extends Array<Layer.Layer.Any>
227
+ >(
228
+ middleware: Middleware<Context, CTXMap, RMW, Layers>,
229
+ devMode: boolean
230
+ ) => {
231
+ function matchFor<
232
+ const ModuleName extends string,
233
+ const Rsc extends Record<string, any>
234
+ >(
235
+ rsc: Rsc & { meta: { moduleName: ModuleName } }
236
+ ) {
237
+ const meta = rsc.meta
238
+ type Filtered = Filter<Rsc>
239
+ const filtered = typedKeysOf(rsc).reduce((acc, cur) => {
240
+ if (Predicate.isObject(rsc[cur]) && rsc[cur]["success"]) {
241
+ acc[cur as keyof Filtered] = rsc[cur]
242
+ }
243
+ return acc
244
+ }, {} as Filtered)
245
+
246
+ const items = typedKeysOf(filtered).reduce(
247
+ (prev, cur) => {
248
+ ;(prev as any)[cur] = Object.assign((fnOrEffect: any) => {
249
+ const stack = new Error().stack?.split("\n").slice(2).join("\n")
250
+ return Effect.isEffect(fnOrEffect)
251
+ ? class {
252
+ static stack = stack
253
+ static _tag = "d"
254
+ static handler = () => fnOrEffect
255
+ }
256
+ : class {
257
+ static stack = stack
258
+ static _tag = "d"
259
+ static handler = fnOrEffect
260
+ }
261
+ }, {
262
+ success: rsc[cur].success,
263
+ successRaw: S.encodedSchema(rsc[cur].success),
264
+ failure: rsc[cur].failure,
265
+ raw: // "Raw" variations are for when you don't want to decode just to encode it again on the response
266
+ // e.g for direct projection from DB
267
+ // but more importantly, to skip Effectful decoders, like to resolve relationships from the database or remote client.
268
+ (fnOrEffect: any) => {
269
+ const stack = new Error().stack?.split("\n").slice(2).join("\n")
270
+ return Effect.isEffect(fnOrEffect)
271
+ ? class {
272
+ static stack = stack
273
+ static _tag = "raw"
274
+ static handler = () => fnOrEffect
275
+ }
276
+ : class {
277
+ static stack = stack
278
+ static _tag = "raw"
279
+ static handler = (req: any, ctx: any) => fnOrEffect(req, { ...ctx, Response: rsc[cur].success })
280
+ }
281
+ }
282
+ })
283
+ return prev
284
+ },
285
+ {} as RouteMatcher<CTXMap, Rsc, Context>
286
+ )
287
+
288
+ type Keys = keyof Filtered
289
+
290
+ const effect = <
291
+ E,
292
+ R,
293
+ THandlers extends {
294
+ // import to keep them separate via | for type checking!!
295
+ [K in Keys]: AHandler<Rsc[K]>
296
+ },
297
+ TLayers extends NonEmptyArray<Layer.Layer.Any>
298
+ >(
299
+ layers: TLayers,
300
+ make: (requests: typeof items) => Effect<THandlers, E, R>
301
+ ) => {
302
+ type ProvidedLayers =
303
+ | { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
304
+ | { [k in keyof TLayers]: Layer.Layer.Success<TLayers[k]> }[number]
305
+ type Router = RouterShape<Rsc>
306
+ const r: HttpRouter.HttpRouter.TagClass<
307
+ Router,
308
+ `${typeof meta.moduleName}Router`,
309
+ never,
310
+ Exclude<
311
+ | Context
312
+ | RPCRouteR<
313
+ { [K in keyof Filter<Rsc>]: Rpc.Rpc<Rsc[K], _R<ReturnType<THandlers[K]["handler"]>>> }[keyof Filter<Rsc>]
314
+ >,
315
+ HttpRouter.HttpRouter.Provided
316
+ >
317
+ > = (class Router extends HttpRouter.Tag(`${meta.moduleName}Router`)<Router>() {}) as any
318
+
319
+ const layer = r.use((router) =>
320
+ Effect.gen(function*() {
321
+ const controllers = yield* make(items)
322
+ const rpc = yield* makeRpc(middleware)
323
+
324
+ // return make.pipe(Effect.map((c) => controllers(c, layers)))
325
+ const mapped = typedKeysOf(filtered).reduce((acc, cur) => {
326
+ const handler = controllers[cur as keyof typeof controllers]
327
+ const req = rsc[cur]
328
+
329
+ acc[cur] = rpc.effect(
330
+ handler._tag === "raw"
331
+ ? class extends (req as any) {
332
+ static success = S.encodedSchema(req.success)
333
+ get [Schema.symbolSerializable]() {
334
+ return this.constructor
335
+ }
336
+ get [Schema.symbolWithResult]() {
337
+ return {
338
+ failure: req.failure,
339
+ success: S.encodedSchema(req.success)
340
+ }
341
+ }
342
+ } as any
343
+ : req,
344
+ (req) =>
345
+ Effect
346
+ .annotateCurrentSpan(
347
+ "requestInput",
348
+ Object.entries(req).reduce((prev, [key, value]: [string, unknown]) => {
349
+ prev[key] = key === "password"
350
+ ? "<redacted>"
351
+ : typeof value === "string" || typeof value === "number" || typeof value === "boolean"
352
+ ? typeof value === "string" && value.length > 256
353
+ ? (value.substring(0, 253) + "...")
354
+ : value
355
+ : Array.isArray(value)
356
+ ? `Array[${value.length}]`
357
+ : value === null || value === undefined
358
+ ? `${value}`
359
+ : typeof value === "object" && value
360
+ ? `Object[${Object.keys(value).length}]`
361
+ : typeof value
362
+ return prev
363
+ }, {} as Record<string, string | number | boolean>)
364
+ )
365
+ .pipe(
366
+ // can't use andThen due to some being a function and effect
367
+ Effect.zipRight(handler.handler(req as any) as any),
368
+ Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
369
+ Effect.tapDefect((cause) =>
370
+ Effect
371
+ .all([
372
+ reportRequestError(cause, {
373
+ action: `${meta.moduleName}.${req._tag}`
374
+ }),
375
+ Rpc.currentHeaders.pipe(Effect.andThen((headers) => {
376
+ return InfraLogger
377
+ .logError("Finished request", cause)
378
+ .pipe(Effect.annotateLogs({
379
+ action: `${meta.moduleName}.${req._tag}`,
380
+ req: pretty(req),
381
+ headers: pretty(headers)
382
+ // resHeaders: pretty(
383
+ // Object
384
+ // .entries(headers)
385
+ // .reduce((prev, [key, value]) => {
386
+ // prev[key] = value && typeof value === "string" ? snipString(value) : value
387
+ // return prev
388
+ // }, {} as Record<string, any>)
389
+ // )
390
+ }))
391
+ }))
392
+ ])
393
+ ),
394
+ devMode ? (_) => _ : Effect.catchAllDefect(() => Effect.die("Internal Server Error")),
395
+ Effect.withSpan("Request." + meta.moduleName + "." + req._tag, {
396
+ captureStackTrace: () => handler.stack
397
+ })
398
+ ),
399
+ meta.moduleName
400
+ ) // TODO
401
+ return acc
402
+ }, {} as any) as {
403
+ [K in Keys]: Rpc.Rpc<
404
+ Rsc[K],
405
+ Context | _R<ReturnType<THandlers[K]["handler"]>>
406
+ >
407
+ }
408
+
409
+ const rpcRouter = RpcRouter.make(...Object.values(mapped) as any) as RpcRouter.RpcRouter<
410
+ RPCRouteReq<typeof mapped[keyof typeof mapped]>,
411
+ RPCRouteR<typeof mapped[keyof typeof mapped]>
412
+ >
413
+ const httpApp = toHttpApp(rpcRouter, {
414
+ spanPrefix: rsc
415
+ .meta
416
+ .moduleName + "."
417
+ })
418
+ yield* router
419
+ .all(
420
+ "/",
421
+ httpApp as any,
422
+ // TODO: not queries.
423
+ { uninterruptible: true }
424
+ )
425
+ })
426
+ )
427
+
428
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
429
+ const routes = layer.pipe(
430
+ Layer.provideMerge(r.Live),
431
+ layers ? Layer.provide(layers) as any : (_) => _,
432
+ // TODO: only provide to the middleware?
433
+ middleware.dependencies ? Layer.provide(middleware.dependencies as any) : (_) => _
434
+ ) as Layer.Layer<
435
+ Router,
436
+ { [k in keyof TLayers]: Layer.Layer.Error<TLayers[k]> }[number] | E,
437
+ | { [k in keyof TLayers]: Layer.Layer.Context<TLayers[k]> }[number]
438
+ | Exclude<
439
+ RMW | R,
440
+ ProvidedLayers
441
+ >
442
+ >
443
+
444
+ // Effect.Effect<HttpRouter.HttpRouter<unknown, HttpRouter.HttpRouter.DefaultServices>, never, UserRouter>
445
+
446
+ return {
447
+ moduleName: meta.moduleName,
448
+ Router: r,
449
+ routes
450
+ }
451
+ }
452
+
453
+ return effect
454
+ }
455
+
456
+ type HR<T> = T extends HttpRouter.HttpRouter<any, infer R> ? R : never
457
+ type HE<T> = T extends HttpRouter.HttpRouter<infer E, any> ? E : never
458
+
459
+ type RequestHandlersTest = {
460
+ [key: string]: {
461
+ Router: { router: Effect<HttpRouter.HttpRouter<any, any>, any, any> }
462
+ routes: Layer.Layer<any, any, any>
463
+ moduleName: string
464
+ }
465
+ }
466
+ function matchAll<T extends RequestHandlersTest, A, E, R>(
467
+ handlers: T,
468
+ requestLayer: Layer.Layer<A, E, R>
469
+ ) {
470
+ const routers = typedValuesOf(handlers)
471
+
472
+ const rootRouter = class extends HttpRouter.Tag("RootRouter")<
473
+ "RootRouter",
474
+ HR<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>,
475
+ HE<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>
476
+ >() {}
477
+
478
+ const r = rootRouter
479
+ .use((router) =>
480
+ Effect.gen(function*() {
481
+ for (const route of routers) {
482
+ yield* router.mount(
483
+ ("/rpc/" + route.moduleName) as any,
484
+ yield* route
485
+ .Router
486
+ .router
487
+ .pipe(Effect.map(HttpRouter.use(flow(Effect.provide(requestLayer))))) as any
488
+ )
489
+ }
490
+ })
491
+ )
492
+ .pipe(Layer.provide(routers.map((r) => r.routes).flat() as unknown as NonEmptyArray<Layer.Layer.Any>))
493
+
494
+ return {
495
+ layer: r as Layer.Layer<
496
+ never,
497
+ Layer.Layer.Error<typeof handlers[keyof typeof handlers]["routes"]>,
498
+ Layer.Layer.Context<typeof handlers[keyof typeof handlers]["routes"]>
499
+ >,
500
+ Router: rootRouter as any as HttpRouter.HttpRouter.TagClass<
501
+ "RootRouter",
502
+ "RootRouter",
503
+ HE<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>,
504
+ R | Exclude<HR<Effect.Success<typeof handlers[keyof typeof handlers]["Router"]["router"]>>, A>
505
+ >
506
+ }
507
+ }
508
+
509
+ return { matchAll, matchFor }
510
+ }