UNPKG

qcobjects

Version:

QCObjects is an Open-source framework that empowers full-stack developers to make micro-services and micro-frontends into an N-Tier architecture.

301 lines (263 loc) 9.38 kB
import { _QC_CLASSES } from "./PrimaryCollections"; import { _Cast, _CastProps } from "./Cast"; import { _DOMCreateElement } from "./DOMCreateElement"; import { __getType__ } from "./getType"; import { __instanceID, IncrementInstanceID } from "./IncrementInstanceID"; import { _methods_ } from "./introspection"; import { is_a } from "./is_a"; import { __is__forbidden_name__ } from "./is_forbidden_name"; import { _LegacyCopy } from "./LegacyCopy"; import { logger } from "./Logger"; import { isBrowser } from "./platform"; import { IQCObjectsElement, TBody, TClass } from "types"; import { InheritClass } from "./InheritClass"; import { _top } from "./top"; /** * Creates new object class of another object * * @param {String} name * @param {Object} type * @param {Object} definition * * @example * Class (name, type, definition) * Class (name, type) * Class (name, definition) * Class () * * * const MyClass = Class ("MyComponent", Component, { * name: "one_component", * method1 : () => {console.log ("done") } * }) * const myClassInstance = new MyClass ({name: "one_component"}) * * const MyClass = Class ("MyService",{ * name: "myservice", * }) * * const myClassInstance = new MyClass ({name: "myservice"}) */ export const Class: TClass = (name?: string, _type?: unknown, _definition?: unknown): InheritClass => { const _types_ = {}; let type: unknown, definition: unknown; switch (true) { case !name && !_type && !_definition: return class { } as unknown as InheritClass; case !!name && !_type && !_definition: type = class { }; definition = {}; break; case !!name && !_type && !!_definition: type = class { }; definition = _definition; break; case !!name && !!_type && !!_definition: type = _type; definition = _definition; break; default: return class { } as unknown as InheritClass; } if (typeof name !== "string") { throw new Error("Class name must be a string"); } if (typeof type !== "function") { throw new Error("Class type must be a function or class"); } if (__is__forbidden_name__(name)) { throw new Error(`${name} is not an allowed word in the name of a class`); } if (typeof (type as any).__definition === "object" && (type as any).__definition && Object.keys((type as any).__definition).length !== 0) { (definition as any).__definition = Object.assign(_LegacyCopy((type as any).__definition,["name"]), type); } (_types_ as any)[type.name] = type; if (typeof definition === "undefined" || definition === null) { definition = {}; } else { definition = { ...definition }; } /* hack to prevent duplicate __instanceID */ if (typeof (definition as any).__instanceID !== "undefined") { delete (definition as any).__instanceID; } _QC_CLASSES[name] = class extends (_types_ as any)[type.name] { __instanceID!: number; __namespace?: string | undefined; __definition: any = { ...(definition as any) }; childs: any; private _body: TBody; public get body(): TBody { return this._body; } public set body(value: TBody) { this._body = value; } static get __classType(): any { return (Object.getPrototypeOf(this.constructor) as Function).name; } get __classType(): string { return this.constructor.name; } static hierarchy(__class__: any): any[] { const __classType = function (o_c: any): any { return (Object.hasOwn(o_c, "__classType")) ? (o_c.__classType) : (__getType__.call(__class__, o_c)); }; const __hierarchy__proto__ = (c: any): any[] => { return (typeof c !== "undefined" && typeof c.__proto__ !== "undefined" && c.__proto__ !== null) ? (((__classType(c) !== "") ? ([__classType(c)]) : ([])).concat(__hierarchy__proto__(c.__proto__))) : ([]); }; if (typeof __class__ === "undefined" || __class__ === null) { __class__ = this; } let __hierarchy = []; __hierarchy.push(__classType(__class__)); __hierarchy = __hierarchy.concat(__hierarchy__proto__(__class__.__proto__)); return __hierarchy; } static getParentClass(): any { return Object.getPrototypeOf(this.prototype.constructor); } constructor(_o_?: any) { super(_o_ || {}); const self = this; IncrementInstanceID(); if (!(self as any).__instanceID) { Object.defineProperty(self, "__instanceID", { value: __instanceID, writable: false }); } if (typeof self.__definition !== "undefined") { Object.keys(self.__definition).filter(function (k) { return isNaN(k as any) && !["name", "__instanceID", "__classType", "__definition"].includes(k); }).forEach(function (key) { if (typeof self.__definition[key] === "function") { self[key] = self.__definition[key].bind(self); } else { self[key] = self.__definition[key]; } }); } _methods_(_QC_CLASSES[self.__classType]).map(function <T>(m: unknown): T { self[(m as Function).name] = (m as Function).bind(self); return m as T; }); _methods_(self.__definition).map(function (m): any { self[(m as Function).name] = (m as Function).bind(self); return m; }); if (self.body) { if (typeof self.__definition === "undefined" || (!Object.hasOwn(self.__definition, "body")) || typeof self.__definition.body === "undefined") { try { if (isBrowser) { self.body = _DOMCreateElement(self.__definition.__classType); } else { self.body = {}; } } catch (e: any) { logger.debug(`An error ocurred: ${e}.`); self.body = {}; } } else if (Object.hasOwn(self.__definition, "body")) { self.body = self.__definition.body; } } try { if (typeof self.__new__ === "function") { self.__new__.call(self, _o_); } else if (typeof super.__new__ === "function") { self.__new__ = super.__new__.bind(self); self.__new__.call(self, _o_); } if (typeof self === "object" && Object.hasOwn(self, "_new_") && typeof (self._new_ as any).isCalled === "undefined") { try { self._new_(_o_); (self._new_ as any).isCalled = true; } catch (e: any) { logger.warn(`${self.__classType}._new_() failed with error: ${e}`); } } } catch (e: any) { logger.warn(e); } } __new__(_o_: any) { _CastProps(_o_, this); } // eslint-disable-next-line no-unused-vars _new_(_o_?: any) { } getClass(): any { return Object.getPrototypeOf(this.constructor); } css(_css: any): any { if (typeof this.body !== "undefined" && typeof this?.body !== "string" && typeof (this?.body as HTMLElement)?.style !== "undefined") { logger.debug("body style"); if (this.body) { (this.body as any).style = _Cast(_css, (this?.body as HTMLElement)?.style); } } return (typeof this.body !== "string") ? (this?.body as HTMLElement)?.style : {}; } hierarchy(): any { const __instance__ = this; return this.getClass()?.hierarchy(__instance__); } append(_child?: any) { const child: any = _child || this.body; logger.debug("append: start"); if (is_a(child, "Component")) { logger.debug("append: child is a Component"); logger.debug(`appending the body of ${child.name}`); } if (typeof this.body !== "undefined") { logger.debug("append element"); if (arguments.length > 0) { logger.debug("append to element"); if (typeof this.body !== "string") { if (typeof (this.body as IQCObjectsElement)?.append !== "undefined") { (this?.body as IQCObjectsElement)?.append(child); } else { throw Error("body.append is undefined. That means the body is not well formed."); } } else { this.append(child); } if (typeof this.childs === "undefined") { this.childs = []; } this.childs.push(child); } else { if (isBrowser) { logger.debug("append to body"); document.body.append(child); } } } } attachIn(tag: any) { if (isBrowser) { const tags = (document as any).subelements(tag); for (let i = 0, j = tags.length; i < j; i++) { tags[i].append(this as any); } } else { throw new Error("attachIn not yet implemented for non browser platforms"); } } }; // remove the keys from definition that exist in the prototype _QC_CLASSES[name] = _CastProps(definition, _QC_CLASSES[name]); _QC_CLASSES[name].__definition = definition; _QC_CLASSES[name].__definition.__classType = name; (_top as any)[name] = _QC_CLASSES[name]; return _QC_CLASSES[name] as InheritClass; }; if (typeof Class.prototype !== "undefined") { Class.prototype.toString = function () { return "Class(name, type, definition) { [QCObjects native code] }"; }; }