UNPKG

@itrocks/reflect

Version:

Runtime introspection of TypeScript classes and their properties, including property type

110 lines 4.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReflectClass = void 0; require("reflect-metadata"); const class_file_1 = require("@itrocks/class-file"); const class_type_1 = require("@itrocks/class-type"); const class_type_2 = require("@itrocks/class-type"); const class_type_3 = require("@itrocks/class-type"); const property_default_1 = require("@itrocks/property-default"); const property_type_1 = require("@itrocks/property-type"); const sorted_array_1 = require("@itrocks/sorted-array"); const property_1 = require("./property"); const DEFAULTS = Symbol('defaults'); const TYPES = Symbol('types'); class Properties { *[Symbol.iterator]() { for (const value of Object.values(this)) { yield value; } } } class SortedPropertyNames extends sorted_array_1.SortedArray { static get [Symbol.species]() { return Array; } constructor(object) { super(...Object.getOwnPropertyNames(object).sort()); } } class ReflectClass { name; object; type; constructor(object) { this.object = (0, class_type_2.isObject)(object) ? object : undefined; this.type = (0, class_type_3.typeOf)(object); this.name = this.type.name; } inheritedPropertyDefaults(propertyDefaults) { const parent = this.parent; if (parent) { Object.assign(propertyDefaults, parent.propertyDefaults); } } inheritedPropertyTypes(propertyTypes) { const parent = this.parent; if (parent) { Object.assign(propertyTypes, parent.propertyTypes); } } get parent() { const parentType = Object.getPrototypeOf(this.type); const value = (parentType === Function.prototype) ? null : new ReflectClass(parentType); Object.defineProperty(this, 'parent', { configurable: true, enumerable: false, value, writable: true }); return value; } get properties() { const properties = new Properties; for (const name of this.propertyNames) { properties[name] = new property_1.ReflectProperty(this, name); } Object.defineProperty(this, 'properties', { configurable: true, enumerable: false, value: properties, writable: true }); return properties; } get propertyDefaults() { let value = Reflect.getOwnMetadata(DEFAULTS, this.type); if (!value) { value = {}; Reflect.defineMetadata(DEFAULTS, value, this.type); this.inheritedPropertyDefaults(value); if (this.type === (0, class_type_1.baseType)(this.type)) { Object.assign(value, (0, property_default_1.propertyDefaultsFromFile)((0, class_file_1.fileOf)(this.type))); } return value; } Object.defineProperty(this, 'propertyDefaults', { configurable: true, enumerable: false, value, writable: true }); return value; } get propertyNames() { let object = new this.type; const propertyNames = new SortedPropertyNames(object); propertyNames.distinct = true; while (object) { Object.entries(Object.getOwnPropertyDescriptors(object)).forEach(([name, descriptor]) => { if (!descriptor.get || (name[0] === '_')) return; propertyNames.push(name); }); object = Object.getPrototypeOf(object); } Object.defineProperty(this, 'propertyNames', { configurable: true, enumerable: false, value: propertyNames, writable: true }); return propertyNames; } get propertyTypes() { let value = Reflect.getOwnMetadata(TYPES, this.type); if (!value) { value = {}; Reflect.defineMetadata(TYPES, value, this.type); this.inheritedPropertyTypes(value); if (this.type === (0, class_type_1.baseType)(this.type)) { Object.assign(value, (0, property_type_1.propertyTypesFromFile)((0, class_file_1.fileOf)(this.type))); } return value; } Object.defineProperty(this, 'propertyTypes', { configurable: true, enumerable: false, value, writable: true }); return value; } } exports.ReflectClass = ReflectClass; //# sourceMappingURL=class.js.map