moost
Version:
1,353 lines (1,325 loc) • 44.7 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const __prostojs_mate = __toESM(require("@prostojs/mate"));
const __wooksjs_event_core = __toESM(require("@wooksjs/event-core"));
const __prostojs_infact = __toESM(require("@prostojs/infact"));
const __prostojs_logger = __toESM(require("@prostojs/logger"));
const hookable = __toESM(require("hookable"));
const wooks = __toESM(require("wooks"));
//#region packages/moost/src/logger.ts
let defaultLogger;
function setDefaultLogger(logger) {
defaultLogger = logger;
}
function getDefaultLogger(topic) {
if (!defaultLogger) defaultLogger = new __prostojs_logger.ProstoLogger({
level: 4,
transports: [loggerConsoleTransport]
});
return topic && defaultLogger instanceof __prostojs_logger.ProstoLogger ? defaultLogger.createTopic(topic) : defaultLogger;
}
function createLogger(opts) {
return new __prostojs_logger.ProstoLogger({
...opts,
level: opts?.level ?? 4,
transports: opts?.transports ?? [loggerConsoleTransport]
});
}
const loggerConsoleTransport = (0, __prostojs_logger.createConsoleTransort)({ format: __prostojs_logger.coloredConsole });
//#endregion
//#region packages/moost/src/pipes/run-pipes.ts
async function runPipes(pipes, initialValue, metas, level) {
let v = initialValue;
for (const pipe of pipes) v = await pipe.handler(v, metas, level);
return v;
}
//#endregion
//#region packages/moost/src/metadata/moost-metadata.ts
const METADATA_WORKSPACE = "moost";
const moostMate = new __prostojs_mate.Mate(METADATA_WORKSPACE, {
readType: true,
readReturnType: true,
collectPropKeys: true,
inherit(classMeta, targetMeta, level) {
if (level === "CLASS") return !!classMeta?.inherit;
if (level === "PROP") return !!targetMeta?.inherit || !!(classMeta?.inherit && !targetMeta);
return !!targetMeta?.inherit;
}
});
function getMoostMate() {
return moostMate;
}
//#endregion
//#region packages/moost/src/metadata/infact.ts
const sharedMoostInfact = getNewMoostInfact();
const INFACT_BANNER = `[2m[35minfact`;
let loggingOptions = {
newInstance: "SINGLETON",
warn: true,
error: true
};
function setInfactLoggingOptions(options) {
loggingOptions = {
...loggingOptions,
...options
};
}
function getMoostInfact() {
return sharedMoostInfact;
}
const scopeVarsMap = /* @__PURE__ */ new Map();
/**
* Define global scope name to be used with `@InjectFromScope` and `@InjectScopeVars` decorators
*
* You can read scoped vars with `getInfactScopeVars`
* @param name scope name
* @param scopeVars key-value object as scoped vars
*/ function defineInfactScope(name, scopeVars) {
scopeVarsMap.set(name, scopeVars);
getMoostInfact().registerScope(name);
}
/**
* Read scoped vars defined with `defineInfactScope`
* @param name scope name
* @returns key-value object as scoped vars
*/ function getInfactScopeVars(name) {
return scopeVarsMap.get(name);
}
/**
* Get Infact instance (used for Dependency Injections)
*/ function getNewMoostInfact() {
const infactInstance = new __prostojs_infact.Infact({
describeClass(classConstructor) {
const meta = getMoostMate().read(classConstructor);
return {
injectable: !!meta?.injectable,
global: false,
constructorParams: meta?.params || [],
provide: meta?.provide,
properties: meta?.properties || [],
scopeId: meta?.injectable === "FOR_EVENT" ? (0, __wooksjs_event_core.useEventId)().getId() : void 0
};
},
resolveParam({ paramMeta, customData, classConstructor, index, scopeId, instantiate }) {
if (paramMeta && customData?.pipes) return runPipes(customData.pipes, void 0, {
paramMeta,
type: classConstructor,
key: "constructor",
scopeId,
classMeta: getMoostMate().read(classConstructor),
index,
targetMeta: paramMeta,
instantiate
}, "PARAM");
},
describeProp(classConstructor, key) {
const meta = getMoostMate().read(classConstructor, key);
return meta;
},
resolveProp({ instance, key, initialValue, propMeta, scopeId, classMeta, customData, classConstructor, instantiate }) {
if (propMeta && customData?.pipes) return runPipes(customData.pipes, initialValue, {
instance,
type: classConstructor,
key,
scopeId,
propMeta,
targetMeta: propMeta,
classMeta,
instantiate
}, "PROP");
},
storeProvideRegByInstance: true,
on: (event, targetClass, message, args) => {
switch (event) {
case "new-instance": {
const scope = getMoostMate().read(targetClass)?.injectable || "SINGLETON";
if (loggingOptions.newInstance === false || !(loggingOptions.newInstance === scope || loggingOptions.newInstance === "SINGLETON" && scope === true)) return;
break;
}
case "warn": {
if (!loggingOptions.warn) return;
break;
}
case "error": {
if (!loggingOptions.error) return;
break;
}
default:
}
let logger;
try {
logger = event === "error" ? getDefaultLogger(INFACT_BANNER) : (0, __wooksjs_event_core.useEventLogger)(INFACT_BANNER);
} catch (error) {
logger = getDefaultLogger(INFACT_BANNER);
}
const instance = `[4m${targetClass.name}[24m`;
switch (event) {
case "new-instance": {
const params = args?.map((a) => {
switch (typeof a) {
case "number":
case "boolean": return `[33m${a}[2m[34m`;
case "string": return `[92m"${a.slice(0, 1)}..."[2m[34m`;
case "object": {
if (Array.isArray(a)) return `[${a.length}]`;
if ((0, __prostojs_mate.getConstructor)(a)) return (0, __prostojs_mate.getConstructor)(a).name;
return "{}";
}
default: return "*";
}
}).map((a) => `[2m[1m${a}[22m[2m`).join(", ") || "";
logger.info(`new ${instance}[2m[34m(${params})`);
break;
}
case "warn": {
const hier = `[2m[34m⋱ ${args?.map(String).join(" → ") || ""}`;
logger.warn(`${instance} - ${message} ${hier}`);
break;
}
case "error": {
const hier = `[2m[34m⋱ ${args?.map(String).join(" → ") || ""}`;
logger.error(`Failed to instantiate ${instance}. ${message} ${hier}`);
break;
}
default: break;
}
}
});
return infactInstance;
}
//#endregion
//#region packages/moost/src/composables/controller.composable.ts
function setControllerContext(controller, method, route) {
const { store } = (0, __wooksjs_event_core.useAsyncEventContext)();
const { set } = store("controller");
set("instance", controller);
set("method", method);
set("route", route);
}
function useControllerContext() {
const { store } = (0, __wooksjs_event_core.useAsyncEventContext)();
const { get } = store("controller");
const getController = () => get("instance");
const getMethod = () => get("method");
const getRoute = () => get("route");
const getControllerMeta = () => getMoostMate().read(getController());
const getMethodMeta = (name) => getMoostMate().read(getController(), name || getMethod());
function instantiate(c) {
return getMoostInfact().getForInstance(getController(), c);
}
return {
instantiate,
getRoute,
getController,
getMethod,
getControllerMeta,
getMethodMeta,
getPropertiesList: () => getControllerMeta()?.properties || [],
getScope: () => getControllerMeta()?.injectable || "SINGLETON",
getParamsMeta: () => getMethodMeta()?.params || [],
getPropMeta: (name) => getMethodMeta(name)
};
}
//#endregion
//#region packages/moost/src/adapter-utils.ts
const infact = getMoostInfact();
function registerEventScope(scopeId) {
infact.registerScope(scopeId);
return () => {
infact.unregisterScope(scopeId);
};
}
function defineMoostEventHandler(options) {
const ci = (0, __wooksjs_event_core.getContextInjector)();
return async () => {
const scopeId = (0, __wooksjs_event_core.useEventId)().getId();
const logger = (0, __wooksjs_event_core.useEventLogger)(options.loggerTitle);
const unscope = registerEventScope(scopeId);
let response;
const hookOptions = {
scopeId,
logger,
unscope,
method: options.controllerMethod,
getResponse: () => response,
reply: (r) => response = r
};
if (options.hooks?.init) await options.hooks.init(hookOptions);
const instance = await options.getControllerInstance();
if (instance) {
setControllerContext(instance, options.controllerMethod || "", options.targetPath);
ci.hook(options.handlerType, "Controller:registered");
}
const interceptorHandler = await options.getIterceptorHandler();
if (interceptorHandler?.count) try {
response = await ci.with("Interceptors:init", () => interceptorHandler.init());
if (response !== void 0) return await endWithResponse();
} catch (error) {
options.logErrors && logger.error(error);
response = error;
return endWithResponse(true);
}
let args = [];
if (options.resolveArgs) try {
args = await ci.with("Arguments:resolve", () => options.resolveArgs());
} catch (error) {
options.logErrors && logger.error(error);
response = error;
return endWithResponse(true);
}
if (interceptorHandler?.countBefore) {
response = await ci.with("Interceptors:before", () => interceptorHandler.fireBefore(response));
if (response !== void 0) return endWithResponse();
}
const callControllerMethod = () => {
if (options.callControllerMethod) return options.callControllerMethod(args);
else if (instance && options.controllerMethod && typeof instance[options.controllerMethod] === "function") return instance[options.controllerMethod](...args);
};
try {
response = await ci.with(`Handler:${options.targetPath}`, {
"moost.handler": options.controllerMethod || "",
"moost.controller": (0, __prostojs_mate.getConstructor)(instance).name
}, () => callControllerMethod());
} catch (error) {
options.logErrors && logger.error(error);
response = error;
return endWithResponse(true);
}
async function endWithResponse(raise = false) {
if (interceptorHandler?.countAfter || interceptorHandler?.countOnError) try {
response = await ci.with("Interceptors:after", () => interceptorHandler.fireAfter(response));
} catch (error) {
options.logErrors && logger.error(error);
if (!options.manualUnscope) unscope();
throw error;
}
if (!options.manualUnscope) unscope();
if (options.hooks?.end) await options.hooks.end(hookOptions);
if (raise) throw response;
return response;
}
return endWithResponse();
};
}
//#endregion
//#region packages/moost/src/binding/utils.ts
function getInstanceOwnMethods(instance) {
const proto = Object.getPrototypeOf(instance);
return [
...getParentProps((0, __prostojs_mate.getConstructor)(instance)),
...Object.getOwnPropertyNames(proto),
...Object.getOwnPropertyNames(instance)
].filter((m) => typeof instance[m] === "function");
}
function getInstanceOwnProps(instance) {
const proto = Object.getPrototypeOf(instance);
return [
...getParentProps((0, __prostojs_mate.getConstructor)(instance)),
...Object.getOwnPropertyNames(proto),
...Object.getOwnPropertyNames(instance)
].filter((m) => typeof instance[m] !== "function");
}
const fnProto = Object.getPrototypeOf(Function);
function getParentProps(constructor) {
const parent = Object.getPrototypeOf(constructor);
if (typeof parent === "function" && parent !== fnProto && parent !== constructor && parent.prototype) return [...getParentProps(parent), ...Object.getOwnPropertyNames(parent.prototype)];
return [];
}
//#endregion
//#region packages/moost/src/class-function/class-function.ts
async function getCallableFn(targetInstance, fn, pipes, logger) {
const mate$1 = getMoostMate();
const meta = mate$1.read(fn);
if (meta?.injectable) {
const infact$1 = getMoostInfact();
const instance = await infact$1.getForInstance(targetInstance, fn, { customData: { pipes: [...pipes || [], ...meta.pipes || []].sort((a, b) => a.priority - b.priority) } });
return (...args) => instance.handler(...args);
}
if (typeof fn === "function") return fn;
const e = /* @__PURE__ */ new Error(`getCallableFn failed for "${(0, __prostojs_mate.getConstructor)(targetInstance).name}" because the passed arg is not a Function nor TClassFunction`);
logger.error(e);
throw e;
}
//#endregion
//#region packages/moost/src/interceptor-handler.ts
function _define_property$1(obj, key, value) {
if (key in obj) Object.defineProperty(obj, key, {
value,
enumerable: true,
configurable: true,
writable: true
});
else obj[key] = value;
return obj;
}
var InterceptorHandler = class {
get count() {
return this.handlers.length;
}
get countBefore() {
return this.before.length;
}
get countAfter() {
return this.after.length;
}
get countOnError() {
return this.onError.length;
}
replyFn(reply) {
this.response = reply;
this.responseOverwritten = true;
}
async init() {
const ci = (0, __wooksjs_event_core.getContextInjector)();
for (const { handler, name } of this.handlers) {
const response = await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "init" }, () => handler((fn) => {
this.before.push({
name,
fn
});
}, (fn) => {
this.after.unshift({
name,
fn
});
}, (fn) => {
this.onError.unshift({
name,
fn
});
}));
if (response !== void 0) return response;
}
}
async fireBefore(response) {
const ci = (0, __wooksjs_event_core.getContextInjector)();
this.response = response;
for (const { name, fn } of this.before) {
await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "before" }, () => fn(this.replyFn.bind(this)));
if (this.responseOverwritten) break;
}
return this.response;
}
async fireAfter(response) {
const ci = (0, __wooksjs_event_core.getContextInjector)();
this.response = response;
if (response instanceof Error) for (const { name, fn } of this.onError) await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "after" }, () => fn(response, this.replyFn.bind(this)));
else for (const { name, fn } of this.after) await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "onError" }, () => fn(response, this.replyFn.bind(this)));
return this.response;
}
constructor(handlers) {
_define_property$1(this, "handlers", void 0);
_define_property$1(this, "before", void 0);
_define_property$1(this, "after", void 0);
_define_property$1(this, "onError", void 0);
_define_property$1(this, "response", void 0);
_define_property$1(this, "responseOverwritten", void 0);
this.handlers = handlers;
this.before = [];
this.after = [];
this.onError = [];
this.responseOverwritten = false;
}
};
//#endregion
//#region packages/moost/src/utils.ts
const mate = getMoostMate();
function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes, logger) {
return () => {
const interceptorHandlers = [];
for (const { handler, name } of interceptors) {
const interceptorMeta = mate.read(handler);
if (interceptorMeta?.injectable) interceptorHandlers.push({
handler: async (...args) => {
const targetInstance = await getTargetInstance();
return (await getCallableFn(targetInstance, handler, pipes, logger))(...args);
},
name
});
else interceptorHandlers.push({
handler,
name
});
}
return Promise.resolve(new InterceptorHandler(interceptorHandlers));
};
}
//#endregion
//#region packages/moost/src/binding/bind-controller.ts
async function bindControllerMethods(options) {
const opts = options || {};
const { getInstance } = opts;
const { classConstructor } = opts;
const { adapters } = opts;
opts.globalPrefix = opts.globalPrefix || "";
opts.provide = opts.provide || {};
const fakeInstance = Object.create(classConstructor.prototype);
const methods = getInstanceOwnMethods(fakeInstance);
const mate$1 = getMoostMate();
const meta = mate$1.read(classConstructor) || {};
const ownPrefix = typeof opts.replaceOwnPrefix === "string" ? opts.replaceOwnPrefix : meta.controller?.prefix || "";
const prefix = `${opts.globalPrefix}/${ownPrefix}`;
const controllerOverview = {
meta,
computedPrefix: prefix,
type: classConstructor,
handlers: []
};
for (const method of methods) {
const methodMeta = getMoostMate().read(fakeInstance, method) || {};
if (!methodMeta.handlers?.length) continue;
const pipes = [...opts.pipes || [], ...methodMeta.pipes || []].sort((a, b) => a.priority - b.priority);
const interceptors = [
...opts.interceptors || [],
...meta.interceptors || [],
...methodMeta.interceptors || []
].sort((a, b) => a.priority - b.priority);
const getIterceptorHandler = getIterceptorHandlerFactory(interceptors, getInstance, pipes, options.logger);
const argsPipes = [];
for (const p of methodMeta.params || []) argsPipes.push({
meta: p,
pipes: [...pipes, ...p.pipes || []].sort((a, b) => a.priority - b.priority)
});
const resolveArgs = async () => {
const args = [];
for (const [i, { pipes: pipes$1, meta: paramMeta }] of argsPipes.entries()) args[i] = await runPipes(pipes$1, void 0, {
classMeta: meta,
methodMeta,
paramMeta,
type: classConstructor,
key: method,
index: i,
targetMeta: paramMeta,
instantiate: (t) => useControllerContext().instantiate(t)
}, "PARAM");
return args;
};
const wm = /* @__PURE__ */ new WeakMap();
controllerOverview.handlers.push(...methodMeta.handlers.map((h) => {
const data = {
meta: methodMeta,
path: h.path,
type: h.type,
method,
handler: h,
registeredAs: []
};
wm.set(h, data);
return data;
}));
for (const adapter of adapters) await adapter.bindHandler({
prefix,
fakeInstance,
getInstance,
method,
handlers: methodMeta.handlers,
getIterceptorHandler,
resolveArgs,
logHandler: (eventName) => {
options.moostInstance.logMappedHandler(eventName, classConstructor, method);
},
register(h, path, args) {
const data = wm.get(h);
if (data) data.registeredAs.push({
path,
args
});
}
});
}
return controllerOverview;
}
//#endregion
//#region packages/moost/src/decorators/circular.decorator.ts
function Circular(resolver) {
return getMoostMate().decorate("circular", resolver);
}
//#endregion
//#region packages/moost/src/decorators/common.decorator.ts
/**
* Apply Multiple Decorators
*
* @param decorators - array of decorators
* @returns
*/ function ApplyDecorators(...decorators) {
const mate$1 = getMoostMate();
return mate$1.apply(...decorators);
}
/**
* ## Label
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Label metadata
*/ function Label(value) {
return getMoostMate().decorate("label", value);
}
/**
* ## Description
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Description metadata
*/ function Description(value) {
return getMoostMate().decorate("description", value);
}
/**
* ## Value
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Value metadata
*/ function Value(value) {
return getMoostMate().decorate("value", value);
}
/**
* ## Id
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Id metadata
*/ function Id(value) {
return getMoostMate().decorate("id", value);
}
/**
* ## Optional
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Optional metadata
*/ function Optional() {
return getMoostMate().decorate("optional", true);
}
/**
* ## Required
* ### @Decorator
* _Common purpose decorator that may be used by various adapters for various purposes_
*
* Stores Required metadata
*/ function Required() {
const mate$1 = getMoostMate();
return mate$1.apply(mate$1.decorate("required", true), mate$1.decorateClass((meta, level, key, index) => {
if (typeof index !== "number" && meta && ["string", "symbol"].includes(typeof key)) {
meta.requiredProps = meta.requiredProps || [];
meta.requiredProps.push(key);
}
return meta;
}));
}
//#endregion
//#region packages/moost/src/decorators/injectable.decorator.ts
/**
* ## Injectable
* ### @Decorator
* Mark the Class as Injectable to enable it to be used in dependency injection
* @param scope - Scope for injection ("FOR_EVENT" | "SINGLETON" | true)
* FOR_EVENT - will create a new instance for each incoming request
* SINGLETON | true - will create a new instance only once
* @param label - field label
*/ function Injectable(scope = true) {
return getMoostMate().decorate("injectable", scope);
}
const insureInjectable = getMoostMate().decorate((meta) => {
if (!meta.injectable) meta.injectable = true;
return meta;
});
//#endregion
//#region packages/moost/src/decorators/controller.decorator.ts
/**
* ## Controller
* ### @Decorator
* Set Class as a Controller
* @param prefix - define the prefix for all the paths of this controller
*/ function Controller(prefix) {
const mate$1 = getMoostMate();
return mate$1.apply(insureInjectable, mate$1.decorate("controller", { prefix: prefix || "" }));
}
function ImportController(prefix, controller, provide) {
return getMoostMate().decorate("importController", {
prefix: typeof prefix === "string" ? prefix : void 0,
typeResolver: typeof prefix === "string" ? controller : prefix,
provide: typeof prefix === "string" ? provide || void 0 : controller || void 0
}, true);
}
//#endregion
//#region packages/moost/src/decorators/inherit.decorator.ts
/**
* ## Inherit
* ### @Decorator
* Inherit metadata from super class
* @returns
*/ const Inherit = () => getMoostMate().decorate("inherit", true);
//#endregion
//#region packages/moost/src/decorators/intercept.decorator.ts
var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
TInterceptorPriority$1[TInterceptorPriority$1["BEFORE_ALL"] = 0] = "BEFORE_ALL";
TInterceptorPriority$1[TInterceptorPriority$1["BEFORE_GUARD"] = 1] = "BEFORE_GUARD";
TInterceptorPriority$1[TInterceptorPriority$1["GUARD"] = 2] = "GUARD";
TInterceptorPriority$1[TInterceptorPriority$1["AFTER_GUARD"] = 3] = "AFTER_GUARD";
TInterceptorPriority$1[TInterceptorPriority$1["INTERCEPTOR"] = 4] = "INTERCEPTOR";
TInterceptorPriority$1[TInterceptorPriority$1["CATCH_ERROR"] = 5] = "CATCH_ERROR";
TInterceptorPriority$1[TInterceptorPriority$1["AFTER_ALL"] = 6] = "AFTER_ALL";
return TInterceptorPriority$1;
}({});
/**
* ## Intercept
* ### @Decorator
* Set interceptor
* @param handler interceptor fn (use defineInterceptorFn)
* @param priority interceptor priority
* @returns
*/ function Intercept(handler, priority, name) {
return getMoostMate().decorate("interceptors", {
handler,
priority: priority || handler.priority || 4,
name: name || handler._name || handler.name
}, true);
}
//#endregion
//#region packages/moost/src/decorators/resolve.decorator.ts
/**
* Hook to the Response Status
* @decorator
* @param resolver - resolver function
* @param label - field label
* @paramType unknown
*/ function Resolve(resolver, label) {
return (target, key, index) => {
const i = typeof index === "number" ? index : void 0;
getMoostMate().decorate("resolver", (metas, level) => {
let newLabel = label;
if (!newLabel && level === "PROP" && typeof metas.key === "string") newLabel = metas.key;
fillLabel(target, key || "", i, newLabel);
return resolver(metas, level);
})(target, key, i);
};
}
/**
* Get Param Value from url parh
* @decorator
* @param name - param name
* @paramType string
*/ function Param(name) {
return getMoostMate().apply(getMoostMate().decorate("paramSource", "ROUTE"), getMoostMate().decorate("paramName", name), Resolve(() => (0, __wooksjs_event_core.useRouteParams)().get(name), name));
}
/**
* Get Parsed Params from url parh
* @decorator
* @paramType object
*/ function Params() {
return Resolve(() => (0, __wooksjs_event_core.useRouteParams)().params, "params");
}
/**
* Provide Const Value
* @decorator
* @param value - provided value
* @param label - label of the field
* @paramType unknown
*/ function Const(value, label) {
return Resolve(() => value, label);
}
/**
* Provide Const Value from Factory fn
* @decorator
* @param factory - value Factory fn
* @param label - label of the field
* @paramType unknown
*/ function ConstFactory(factory, label) {
return Resolve(async () => factory(), label);
}
function fillLabel(target, key, index, name) {
if (name) {
const meta = getMoostMate().read(target, key);
if (typeof index === "number") {
if (!meta?.params?.[index]?.label) Label(name)(target, key, index);
} else if (!meta?.label) Label(name)(target, key);
}
}
//#endregion
//#region packages/moost/src/decorators/logger.decorator.ts
/**
* Resolves event logger from event context
* @param topic
* @returns Resolver to '@wooksjs/event-core' (EventLogger)
*/ function InjectEventLogger(topic) {
return Resolve(() => (0, __wooksjs_event_core.useEventLogger)(topic));
}
/**
* Resolves app-level logger
* @param topic - logger topic (can be overrided by @LoggerTopic)
* @returns
*/ function InjectMoostLogger(topic) {
return Resolve(async (metas) => {
const { instantiate, getController } = useControllerContext();
const controller = getController();
const moostApp = controller instanceof Moost ? controller : await instantiate(Moost);
const meta = metas.classMeta;
return moostApp.getLogger(meta?.loggerTopic || topic || meta?.id);
});
}
/**
* Sets logger topic (used in @InjectMoostLogger)
* @param topic - logger topic (banner)
* @returns
*/ function LoggerTopic(topic) {
return getMoostMate().decorate("loggerTopic", topic);
}
//#endregion
//#region packages/moost/src/pipes/types.ts
var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
TPipePriority$1[TPipePriority$1["BEFORE_RESOLVE"] = 0] = "BEFORE_RESOLVE";
TPipePriority$1[TPipePriority$1["RESOLVE"] = 1] = "RESOLVE";
TPipePriority$1[TPipePriority$1["AFTER_RESOLVE"] = 2] = "AFTER_RESOLVE";
TPipePriority$1[TPipePriority$1["BEFORE_TRANSFORM"] = 3] = "BEFORE_TRANSFORM";
TPipePriority$1[TPipePriority$1["TRANSFORM"] = 4] = "TRANSFORM";
TPipePriority$1[TPipePriority$1["AFTER_TRANSFORM"] = 5] = "AFTER_TRANSFORM";
TPipePriority$1[TPipePriority$1["BEFORE_VALIDATE"] = 6] = "BEFORE_VALIDATE";
TPipePriority$1[TPipePriority$1["VALIDATE"] = 7] = "VALIDATE";
TPipePriority$1[TPipePriority$1["AFTER_VALIDATE"] = 8] = "AFTER_VALIDATE";
return TPipePriority$1;
}({});
//#endregion
//#region packages/moost/src/decorators/pipe.decorator.ts
/**
* ## Pipe
* ### @Decorator
* Attach pipe
* @param handler pipe handler
* @param priority pipe priority
* @returns
*/ function Pipe(handler, priority) {
if (typeof priority !== "number") priority = typeof handler.priority === "number" ? handler.priority : TPipePriority.TRANSFORM;
return getMoostMate().decorate("pipes", {
handler,
priority
}, true);
}
//#endregion
//#region packages/moost/src/decorators/provide.decorator.ts
/**
* ## Provide
* ### @Decorator
* Defines provide registry for class (and all the children)
* @param type - string or class constructor
* @param fn - factory function for provided value
*/ function Provide(type, fn) {
return getMoostMate().decorate((meta) => {
meta.provide = meta.provide || {};
Object.assign(meta.provide, (0, __prostojs_infact.createProvideRegistry)([type, fn]));
return meta;
});
}
/**
* ## Replace
* ### @Decorator
* Defines class to replace in DI
* @param type - class to replace
* @param newType - new class
*/ function Replace(type, newType) {
return getMoostMate().decorate((meta) => {
meta.replace = meta.replace || {};
Object.assign(meta.replace, (0, __prostojs_infact.createReplaceRegistry)([type, newType]));
return meta;
});
}
/**
* ## Inject
* ### @Decorator
* Defines a key from provide registry to inject value
* (For optional values use with @Optional())
* @param type - string or class constructor
*/ function Inject(type) {
return getMoostMate().decorate("inject", type);
}
/**
* Injects instance from scope
*
* (scope must be defined by `defineInfactScope` fn)
* @param name scope name
*/ function InjectFromScope(name) {
return getMoostMate().decorate("fromScope", name);
}
/**
* Inject vars from scope for instances
* instantiated with `@InjectFromScope` decorator
*/ function InjectScopeVars(name) {
return Resolve(({ scopeId }) => {
if (scopeId) return name ? getInfactScopeVars(scopeId)?.[name] : getInfactScopeVars(scopeId);
return void 0;
});
}
//#endregion
//#region packages/moost/src/define.ts
/**
* ### Define Interceptor Function
*
* ```ts
* defineInterceptorFn((before, after, onError) => {
* //init
* before(() => {
* // before handler
* })
* after((response, reply) => {
* // after handler
* })
* onError((error, reply) => {
* // when error occured
* })
* },
* TInterceptorPriority.INTERCEPTOR,
* )
* ```
*
* @param fn interceptor function
* @param priority priority of the interceptor where BEFORE_ALL = 0, BEFORE_GUARD = 1, GUARD = 2, AFTER_GUARD = 3, INTERCEPTOR = 4, CATCH_ERROR = 5, AFTER_ALL = 6
* @returns
*/ function defineInterceptorFn(fn, priority = TInterceptorPriority.INTERCEPTOR) {
fn.priority = priority;
return fn;
}
/**
* ### Define Pipe Function
*
* ```ts
* // example of a transform pipe
* const uppercaseTransformPipe = definePipeFn((value, metas, level) => {
* return typeof value === 'string' ? value.toUpperCase() : value
* },
* TPipePriority.TRANSFORM,
* )
* ```
*
* @param fn interceptor function
* @param priority priority of the pipe where BEFORE_RESOLVE = 0, RESOLVE = 1, AFTER_RESOLVE = 2, BEFORE_TRANSFORM = 3, TRANSFORM = 4, AFTER_TRANSFORM = 5, BEFORE_VALIDATE = 6, VALIDATE = 7, AFTER_VALIDATE = 8
* @returns
*/ function definePipeFn(fn, priority = TPipePriority.TRANSFORM) {
fn.priority = priority;
return fn;
}
//#endregion
//#region packages/moost/src/pipes/resolve.pipe.ts
const resolvePipe = definePipeFn((_value, metas, level) => {
const resolver = metas.targetMeta?.resolver;
if (resolver) return resolver(metas, level);
return void 0;
}, TPipePriority.RESOLVE);
//#endregion
//#region packages/moost/src/pipes/shared-pipes.ts
const sharedPipes = [{
handler: resolvePipe,
priority: TPipePriority.RESOLVE
}];
//#endregion
//#region packages/moost/src/moost.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;
}
/**
* ## Moost
* Main moostjs class that serves as a shell for Moost Adapters
*
* ### Usage with HTTP Adapter
* ```ts
* │ // HTTP server example
* │ import { MoostHttp, Get } from '@moostjs/event-http'
* │ import { Moost, Param } from 'moost'
* │
* │ class MyServer extends Moost {
* │ @Get('test/:name')
* │ test(@Param('name') name: string) {
* │ return { message: `Hello ${name}!` }
* │ }
* │ }
* │
* │ const app = new MyServer()
* │ const http = new MoostHttp()
* │ app.adapter(http).listen(3000, () => {
* │ app.getLogger('MyApp').log('Up on port 3000')
* │ })
* │ app.init()
* ```
* ### Usage with CLI Adapter
* ```ts
* │ // CLI example
* │ import { MoostCli, Cli, CliOption, cliHelpInterceptor } from '@moostjs/event-cli'
* │ import { Moost, Param } from 'moost'
* │
* │ class MyApp extends Moost {
* │ @Cli('command/:arg')
* │ command(
* │ @Param('arg')
* │ arg: string,
* │ @CliOption('test', 't')
* │ test: boolean,
* │ ) {
* │ return `command run with flag arg=${ arg }, test=${ test }`
* │ }
* │ }
* │
* │ const app = new MyApp()
* │ app.applyGlobalInterceptors(cliHelpInterceptor())
* │
* │ const cli = new MoostCli()
* │ app.adapter(cli)
* │ app.init()
* ```
*/ var Moost = class Moost extends hookable.Hookable {
_fireEventStart(source) {
this.callHook("event-start", source);
}
_fireEventEnd(source) {
this.callHook("event-end", source);
}
/**
* ### getLogger
* Provides application logger
* ```js
* // get logger with topic = "App"
* const logger = app.getLogger('App')
* logger.log('...')
* ```
* @param topic
* @returns
*/ getLogger(topic) {
if (topic && this.logger instanceof __prostojs_logger.ProstoLogger) return this.logger.createTopic(topic);
return this.logger;
}
adapter(a) {
this.adapters.push(a);
return a;
}
getControllersOverview() {
return this.controllersOverview;
}
/**
* ### init
* Ititializes adapter. Must be called after adapters are attached.
*/ async init() {
this.setProvideRegistry((0, __prostojs_infact.createProvideRegistry)([Moost, () => this], [__prostojs_logger.ProstoLogger, () => this.logger], ["MOOST_LOGGER", () => this.logger]));
for (const a of this.adapters) {
const constructor = (0, __prostojs_mate.getConstructor)(a);
if (constructor) this.setProvideRegistry((0, __prostojs_infact.createProvideRegistry)([constructor, () => a]));
if (typeof a.getProvideRegistry === "function") this.setProvideRegistry(a.getProvideRegistry());
}
this.unregisteredControllers.unshift(this);
await this.bindControllers();
for (const a of this.adapters) await (a.onInit && a.onInit(this));
}
async bindControllers() {
const meta = getMoostMate();
const thisMeta = meta.read(this);
const provide = {
...thisMeta?.provide,
...this.provide
};
const replace = {
...thisMeta?.replace,
...this.replace
};
for (const _controller of this.unregisteredControllers) {
let newPrefix;
let controller = _controller;
if (Array.isArray(_controller) && typeof _controller[0] === "string") {
newPrefix = _controller[0];
controller = _controller[1];
}
await this.bindController(controller, provide, replace, this.options?.globalPrefix || "", newPrefix);
}
this.unregisteredControllers = [];
}
async bindController(controller, provide, replace, globalPrefix, replaceOwnPrefix) {
const mate$1 = getMoostMate();
const classMeta = mate$1.read(controller);
const infact$1 = getMoostInfact();
const isControllerConsructor = (0, __prostojs_mate.isConstructor)(controller);
const pipes = [...this.pipes, ...classMeta?.pipes || []].sort((a, b) => a.priority - b.priority);
let instance;
const infactOpts = {
provide,
replace,
customData: { pipes }
};
if (isControllerConsructor && (classMeta?.injectable === "SINGLETON" || classMeta?.injectable === true)) await (0, __wooksjs_event_core.createAsyncEventContext)({
event: { type: "init" },
options: {}
})(async () => {
setControllerContext(this, "bindController", "");
instance = await infact$1.get(controller, infactOpts);
});
else if (!isControllerConsructor) {
instance = controller;
infact$1.setInstanceRegistries(instance, provide, replace, { pipes });
}
const getInstance = instance ? () => Promise.resolve(instance) : async () => await infact$1.get(controller, { ...infactOpts });
const classConstructor = (0, __prostojs_mate.isConstructor)(controller) ? controller : (0, __prostojs_mate.getConstructor)(controller);
this.controllersOverview.push(await bindControllerMethods({
getInstance,
classConstructor,
adapters: this.adapters,
globalPrefix,
replaceOwnPrefix,
interceptors: Array.from(this.interceptors),
pipes,
provide: classMeta?.provide,
replace: classMeta?.replace,
logger: this.logger,
moostInstance: this
}));
if (classMeta?.importController) {
const prefix = typeof replaceOwnPrefix === "string" ? replaceOwnPrefix : classMeta.controller?.prefix;
const mergedProvide = {
...provide,
...classMeta.provide
};
const mergedReplace = {
...this.replace,
...classMeta.replace
};
for (const ic of classMeta.importController) if (ic.typeResolver) {
const isConstr = (0, __prostojs_mate.isConstructor)(ic.typeResolver);
const isFunc = typeof ic.typeResolver === "function";
await this.bindController(isConstr ? ic.typeResolver : isFunc ? await ic.typeResolver() : ic.typeResolver, ic.provide ? {
...mergedProvide,
...ic.provide
} : mergedProvide, mergedReplace, `${globalPrefix}/${prefix || ""}`, ic.prefix);
}
}
}
applyGlobalPipes(...items) {
for (const item of items) if (typeof item === "function") this.pipes.push({
handler: item,
priority: typeof item.priority === "number" ? item.priority : TPipePriority.TRANSFORM
});
else this.pipes.push({
handler: item.handler,
priority: item.priority
});
this.globalInterceptorHandler = void 0;
return this;
}
/**
* Provides InterceptorHandler with global interceptors and pipes.
* Used to process interceptors when event handler was not found.
*
* @returns IterceptorHandler
*/ getGlobalInterceptorHandler() {
if (!this.globalInterceptorHandler) {
const mate$1 = getMoostMate();
const thisMeta = mate$1.read(this);
const pipes = [...this.pipes || [], ...thisMeta?.pipes || []].sort((a, b) => a.priority - b.priority);
const interceptors = [...this.interceptors, ...thisMeta?.interceptors || []].sort((a, b) => a.priority - b.priority);
this.globalInterceptorHandler = getIterceptorHandlerFactory(interceptors, () => Promise.resolve(this), pipes, this.logger);
}
return this.globalInterceptorHandler();
}
applyGlobalInterceptors(...items) {
for (const item of items) if (typeof item === "function") this.interceptors.push({
handler: item,
priority: typeof item.priority === "number" ? item.priority : TInterceptorPriority.INTERCEPTOR,
name: item._name || item.name || "<anonymous>"
});
else this.interceptors.push({
handler: item.handler,
priority: item.priority,
name: item.name || item.handler._name || item.handler.name || "<anonymous>"
});
this.globalInterceptorHandler = void 0;
return this;
}
/**
* Register new entries to provide as dependency injections
* @param provide - Provide Registry (use createProvideRegistry from '\@prostojs/infact')
* @returns
*/ setProvideRegistry(provide) {
this.provide = {
...this.provide,
...provide
};
return this;
}
/**
* Register replace classes to provide as dependency injections
* @param replace - Replace Registry (use createReplaceRegistry from '\@prostojs/infact')
* @returns
*/ setReplaceRegistry(replace) {
this.replace = {
...this.replace,
...replace
};
return this;
}
/**
* Register controllers (similar to @ImportController decorator)
* @param controllers - list of target controllers (instances)
* @returns
*/ registerControllers(...controllers) {
this.unregisteredControllers.push(...controllers);
return this;
}
logMappedHandler(eventName, classConstructor, method, stroke, prefix) {
const c = stroke ? "\x1B[9m" : "";
const coff = stroke ? "\x1B[29m" : "";
this.logger.info(`${prefix || ""}${c}${eventName} ${"\x1B[0m\x1B[2m\x1B[32m" + c}→ ${classConstructor.name}.${"\x1B[36m" + c}${method}[32m()${coff}`);
}
constructor(options) {
super(), _define_property(this, "options", void 0), _define_property(this, "logger", void 0), _define_property(this, "pipes", void 0), _define_property(this, "interceptors", void 0), _define_property(this, "adapters", void 0), _define_property(this, "controllersOverview", void 0), _define_property(this, "provide", void 0), _define_property(this, "replace", void 0), _define_property(this, "unregisteredControllers", void 0), _define_property(this, "globalInterceptorHandler", void 0), this.options = options, this.pipes = Array.from(sharedPipes), this.interceptors = [], this.adapters = [], this.controllersOverview = [], this.provide = (0, __prostojs_infact.createProvideRegistry)([__prostojs_infact.Infact, getMoostInfact], [__prostojs_mate.Mate, getMoostMate]), this.replace = {}, this.unregisteredControllers = [];
this.logger = options?.logger || getDefaultLogger(`[2m[35mmoost`);
setDefaultLogger(this.logger);
const mate$1 = getMoostMate();
Object.assign(mate$1, { logger: this.getLogger("mate") });
}
};
//#endregion
exports.ApplyDecorators = ApplyDecorators;
exports.Circular = Circular;
exports.Const = Const;
exports.ConstFactory = ConstFactory;
Object.defineProperty(exports, 'ContextInjector', {
enumerable: true,
get: function () {
return __wooksjs_event_core.ContextInjector;
}
});
exports.Controller = Controller;
exports.Description = Description;
Object.defineProperty(exports, 'EventLogger', {
enumerable: true,
get: function () {
return __wooksjs_event_core.EventLogger;
}
});
exports.Id = Id;
exports.ImportController = ImportController;
exports.Inherit = Inherit;
exports.Inject = Inject;
exports.InjectEventLogger = InjectEventLogger;
exports.InjectFromScope = InjectFromScope;
exports.InjectMoostLogger = InjectMoostLogger;
exports.InjectScopeVars = InjectScopeVars;
exports.Injectable = Injectable;
exports.Intercept = Intercept;
exports.InterceptorHandler = InterceptorHandler;
exports.Label = Label;
exports.LoggerTopic = LoggerTopic;
exports.Moost = Moost;
exports.Optional = Optional;
exports.Param = Param;
exports.Params = Params;
exports.Pipe = Pipe;
Object.defineProperty(exports, 'ProstoLogger', {
enumerable: true,
get: function () {
return __prostojs_logger.ProstoLogger;
}
});
exports.Provide = Provide;
exports.Replace = Replace;
exports.Required = Required;
exports.Resolve = Resolve;
exports.TInterceptorPriority = TInterceptorPriority;
exports.TPipePriority = TPipePriority;
exports.Value = Value;
Object.defineProperty(exports, 'clearGlobalWooks', {
enumerable: true,
get: function () {
return wooks.clearGlobalWooks;
}
});
exports.createLogger = createLogger;
Object.defineProperty(exports, 'createProvideRegistry', {
enumerable: true,
get: function () {
return __prostojs_infact.createProvideRegistry;
}
});
Object.defineProperty(exports, 'createReplaceRegistry', {
enumerable: true,
get: function () {
return __prostojs_infact.createReplaceRegistry;
}
});
exports.defineInfactScope = defineInfactScope;
exports.defineInterceptorFn = defineInterceptorFn;
exports.defineMoostEventHandler = defineMoostEventHandler;
exports.definePipeFn = definePipeFn;
Object.defineProperty(exports, 'getConstructor', {
enumerable: true,
get: function () {
return __prostojs_mate.getConstructor;
}
});
Object.defineProperty(exports, 'getContextInjector', {
enumerable: true,
get: function () {
return __wooksjs_event_core.getContextInjector;
}
});
Object.defineProperty(exports, 'getGlobalWooks', {
enumerable: true,
get: function () {
return wooks.getGlobalWooks;
}
});
exports.getInfactScopeVars = getInfactScopeVars;
exports.getInstanceOwnMethods = getInstanceOwnMethods;
exports.getInstanceOwnProps = getInstanceOwnProps;
exports.getMoostInfact = getMoostInfact;
exports.getMoostMate = getMoostMate;
exports.getNewMoostInfact = getNewMoostInfact;
Object.defineProperty(exports, 'isConstructor', {
enumerable: true,
get: function () {
return __prostojs_mate.isConstructor;
}
});
exports.loggerConsoleTransport = loggerConsoleTransport;
exports.registerEventScope = registerEventScope;
Object.defineProperty(exports, 'replaceContextInjector', {
enumerable: true,
get: function () {
return __wooksjs_event_core.replaceContextInjector;
}
});
exports.resolvePipe = resolvePipe;
exports.setControllerContext = setControllerContext;
exports.setInfactLoggingOptions = setInfactLoggingOptions;
Object.defineProperty(exports, 'useAsyncEventContext', {
enumerable: true,
get: function () {
return __wooksjs_event_core.useAsyncEventContext;
}
});
exports.useControllerContext = useControllerContext;
Object.defineProperty(exports, 'useEventLogger', {
enumerable: true,
get: function () {
return __wooksjs_event_core.useEventLogger;
}
});