@moostjs/event-http
Version:
@moostjs/event-http
297 lines (291 loc) • 10.8 kB
JavaScript
import { Intercept, Resolve, TInterceptorPriority, defineInterceptorFn, defineMoostEventHandler, getMoostMate } from "moost";
import { attachHook } from "@wooksjs/event-core";
import { HttpError, WooksHttp, createHttpApp, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useSearchParams, useSetCookie, useSetCookies, useSetHeader, useStatus } from "@wooksjs/event-http";
import { useBody } from "@wooksjs/http-body";
import { createProvideRegistry } from "@prostojs/infact";
import { Server } from "http";
import { Server as Server$1 } from "https";
//#region packages/event-http/src/decorators/http-method.decorator.ts
function HttpMethod(method, path) {
return getMoostMate().decorate("handlers", {
method,
path,
type: "HTTP"
}, true);
}
const All = (path) => HttpMethod("*", path);
const Get = (path) => HttpMethod("GET", path);
const Post = (path) => HttpMethod("POST", path);
const Put = (path) => HttpMethod("PUT", path);
const Delete = (path) => HttpMethod("DELETE", path);
const Patch = (path) => HttpMethod("PATCH", path);
//#endregion
//#region packages/event-http/src/decorators/resolve.decorator.ts
const StatusHook = () => Resolve((metas, level) => {
const hook = useStatus();
if (level === "PARAM") return hook;
if (level === "PROP" && metas.instance && metas.key) {
const initialValue = metas.instance[metas.key];
attachHook(metas.instance, {
get: () => hook.value,
set: (v) => hook.value = v
}, metas.key);
return typeof initialValue === "number" ? initialValue : 200;
}
}, "statusCode");
const HeaderHook = (name) => Resolve((metas, level) => {
const hook = useSetHeader(name);
if (level === "PARAM") return hook;
if (level === "PROP" && metas.instance && metas.key) {
const initialValue = metas.instance[metas.key];
attachHook(metas.instance, {
get: () => hook.value,
set: (v) => hook.value = v
}, metas.key);
return typeof initialValue === "string" ? initialValue : "";
}
}, name);
const CookieHook = (name) => Resolve((metas, level) => {
const hook = useSetCookie(name);
if (level === "PARAM") return hook;
if (level === "PROP" && metas.instance && metas.key) {
const initialValue = metas.instance[metas.key];
attachHook(metas.instance, {
get: () => hook.value,
set: (v) => hook.value = v
}, metas.key);
return typeof initialValue === "string" ? initialValue : "";
}
}, name);
const CookieAttrsHook = (name) => Resolve((metas, level) => {
const hook = useSetCookie(name);
if (level === "PARAM") return attachHook({}, {
get: () => hook.attrs,
set: (v) => hook.attrs = v
});
if (level === "PROP" && metas.instance && metas.key) {
const initialValue = metas.instance[metas.key];
attachHook(metas.instance, {
get: () => hook.attrs,
set: (v) => hook.attrs = v
}, metas.key);
return typeof initialValue === "object" ? initialValue : {};
}
}, name);
function Authorization(name) {
return Resolve(() => {
const auth = useAuthorization();
switch (name) {
case "username": return auth.isBasic() ? auth.basicCredentials()?.username : undefined;
case "password": return auth.isBasic() ? auth.basicCredentials()?.password : undefined;
case "bearer": return auth.isBearer() ? auth.authorization : undefined;
case "raw": return auth.authRawCredentials();
case "type": return auth.authType();
}
}, "authorization");
}
function Header(name) {
return Resolve(() => {
const headers = useHeaders();
return headers[name];
}, `header: ${name}`);
}
function Cookie(name) {
return Resolve(() => useCookies().getCookie(name), `cookie: ${name}`);
}
function Query(name) {
const isItem = !!name;
const _name = isItem ? name : "Query";
return getMoostMate().apply(getMoostMate().decorate("paramSource", isItem ? "QUERY_ITEM" : "QUERY"), getMoostMate().decorate("paramName", _name), Resolve(() => {
const { jsonSearchParams, urlSearchParams } = useSearchParams();
if (isItem) {
const p = urlSearchParams();
const value = p.get(name);
return value === null ? undefined : value;
}
const json = jsonSearchParams();
return Object.keys(json).length > 0 ? json : undefined;
}, _name));
}
function Url() {
return Resolve(() => useRequest().url || "", "url");
}
function Method() {
return Resolve(() => useRequest().method, "http_method");
}
function Req() {
return Resolve(() => useRequest().rawRequest, "request");
}
function Res(opts) {
return Resolve(() => useResponse().rawResponse(opts), "response");
}
function ReqId() {
return Resolve(() => useRequest().reqId(), "reqId");
}
function Ip(opts) {
return Resolve(() => useRequest().getIp(opts), "ip");
}
function IpList() {
return Resolve(() => useRequest().getIpList(), "ipList");
}
function Body() {
return getMoostMate().apply(getMoostMate().decorate("paramSource", "BODY"), Resolve(() => useBody().parseBody(), "body"));
}
function RawBody() {
return Resolve(() => useBody().rawBody(), "body");
}
//#endregion
//#region packages/event-http/src/decorators/set.decorator.ts
const setHeaderInterceptor = (name, value, opts) => {
const fn = (_before, after, onError) => {
const h = useSetHeader(name);
const status = useStatus();
const cb = () => {
if ((!h.value || opts?.force) && (!opts?.status || opts.status === status.value)) h.value = value;
};
if (opts?.when !== "error") after(cb);
if (opts?.when === "always" || opts?.when === "error") onError(cb);
};
fn.priority = TInterceptorPriority.AFTER_ALL;
return fn;
};
function SetHeader(...args) {
return Intercept(setHeaderInterceptor(...args));
}
const setCookieInterceptor = (name, value, attrs) => {
const fn = (before, after) => {
const { setCookie, getCookie } = useSetCookies();
after(() => {
if (!getCookie(name)) setCookie(name, value, attrs);
});
};
fn.priority = TInterceptorPriority.AFTER_ALL;
return fn;
};
function SetCookie(...args) {
return Intercept(setCookieInterceptor(...args));
}
const setStatusInterceptor = (code, opts) => defineInterceptorFn((before, after) => {
const status = useStatus();
after(() => {
if (!status.isDefined || opts?.force) status.value = code;
});
});
function SetStatus(...args) {
return Intercept(setStatusInterceptor(...args));
}
//#endregion
//#region packages/event-http/src/decorators/limits.decorator.ts
const globalBodySizeLimit = (n) => defineInterceptorFn(() => {
useRequest().setMaxInflated(n);
}, TInterceptorPriority.BEFORE_ALL);
const globalCompressedBodySizeLimit = (n) => defineInterceptorFn(() => {
useRequest().setMaxCompressed(n);
}, TInterceptorPriority.BEFORE_ALL);
const globalBodyReadTimeoutMs = (n) => defineInterceptorFn(() => {
useRequest().setReadTimeoutMs(n);
}, TInterceptorPriority.BEFORE_ALL);
const BodySizeLimit = (n) => Intercept(globalBodySizeLimit(n));
const CompressedBodySizeLimit = (n) => Intercept(globalCompressedBodySizeLimit(n));
const BodyReadTimeoutMs = (n) => Intercept(globalBodyReadTimeoutMs(n));
//#endregion
//#region packages/event-http/src/event-http.ts
function _define_property(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
const LOGGER_TITLE = "moost-http";
const CONTEXT_TYPE = "HTTP";
var MoostHttp = class {
getHttpApp() {
return this.httpApp;
}
getServerCb() {
return this.httpApp.getServerCb();
}
listen(port, hostname, backlog, listeningListener) {
return this.httpApp.listen(port, hostname, backlog, listeningListener);
}
async onNotFound() {
return defineMoostEventHandler({
loggerTitle: LOGGER_TITLE,
getIterceptorHandler: () => this.moost?.getGlobalInterceptorHandler(),
getControllerInstance: () => this.moost,
callControllerMethod: () => new HttpError(404, "Resource Not Found"),
targetPath: "",
handlerType: "__SYSTEM__"
})();
}
onInit(moost) {
this.moost = moost;
}
getProvideRegistry() {
return createProvideRegistry([WooksHttp, () => this.getHttpApp()], ["WooksHttp", () => this.getHttpApp()], [Server, () => this.getHttpApp().getServer()], [Server$1, () => this.getHttpApp().getServer()]);
}
getLogger() {
return this.getHttpApp().getLogger("[moost-http]");
}
bindHandler(opts) {
let fn;
for (const handler of opts.handlers) {
if (handler.type !== "HTTP") continue;
const httpPath = handler.path;
const path = typeof httpPath === "string" ? httpPath : typeof opts.method === "string" ? opts.method : "";
const targetPath = `${`${opts.prefix || ""}/${path}`.replace(/\/\/+/g, "/")}${path.endsWith("//") ? "/" : ""}`;
fn = defineMoostEventHandler({
contextType: CONTEXT_TYPE,
loggerTitle: LOGGER_TITLE,
getIterceptorHandler: opts.getIterceptorHandler,
getControllerInstance: opts.getInstance,
controllerMethod: opts.method,
resolveArgs: opts.resolveArgs,
manualUnscope: true,
hooks: { init: ({ unscope }) => {
const { rawRequest } = useRequest();
rawRequest.on("end", unscope);
} },
targetPath,
handlerType: handler.type
});
const routerBinding = this.httpApp.on(handler.method, targetPath, fn);
const { getPath: pathBuilder } = routerBinding;
const methodMeta = getMoostMate().read(opts.fakeInstance, opts.method) || {};
const id = methodMeta.id || opts.method;
if (id) {
const methods = this.pathBuilders[id] = this.pathBuilders[id] || {};
if (handler.method === "*") {
methods.GET = pathBuilder;
methods.PUT = pathBuilder;
methods.PATCH = pathBuilder;
methods.POST = pathBuilder;
methods.DELETE = pathBuilder;
} else methods[handler.method] = pathBuilder;
}
opts.logHandler(`${"\x1B[36m"}(${handler.method})${"\x1B[32m"}${targetPath}`);
const args = routerBinding.getArgs();
const params = {};
args.forEach((a) => params[a] = `{${a}}`);
opts.register(handler, routerBinding.getPath(params), args);
}
}
constructor(httpApp) {
_define_property(this, "name", "http");
_define_property(this, "httpApp", void 0);
_define_property(this, "pathBuilders", {});
_define_property(this, "moost", void 0);
if (httpApp && httpApp instanceof WooksHttp) this.httpApp = httpApp;
else if (httpApp) this.httpApp = createHttpApp({
...httpApp,
onNotFound: this.onNotFound.bind(this)
});
else this.httpApp = createHttpApp({ onNotFound: this.onNotFound.bind(this) });
}
};
//#endregion
export { All, Authorization, Body, BodyReadTimeoutMs, BodySizeLimit, CompressedBodySizeLimit, Cookie, CookieAttrsHook, CookieHook, Delete, Get, Header, HeaderHook, HttpError, HttpMethod, Ip, IpList, Method, MoostHttp, Patch, Post, Put, Query, RawBody, Req, ReqId, Res, SetCookie, SetHeader, SetStatus, StatusHook, Url, globalBodyReadTimeoutMs, globalBodySizeLimit, globalCompressedBodySizeLimit, useHttpContext };