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