UNPKG

moost

Version:
1,353 lines (1,325 loc) 44.7 kB
//#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 = `infact`; 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 = `${targetClass.name}`; switch (event) { case "new-instance": { const params = args?.map((a) => { switch (typeof a) { case "number": case "boolean": return `${a}`; case "string": return `"${a.slice(0, 1)}..."`; 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) => `${a}`).join(", ") || ""; logger.info(`new ${instance}(${params})`); break; } case "warn": { const hier = `⋱ ${args?.map(String).join(" → ") || ""}`; logger.warn(`${instance} - ${message} ${hier}`); break; } case "error": { const hier = `⋱ ${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}()${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(`moost`); 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; } });