UNPKG

@opra/common

Version:
125 lines (124 loc) 4.55 kB
import 'reflect-metadata'; import { omitUndefined } from '@jsopen/objects'; import { asMutable } from 'ts-gems'; import { OpraSchema } from '../../schema/index.js'; import { DocumentInitContext } from '../common/document-init-context.js'; import { DECORATOR } from '../constants.js'; import { ComplexTypeDecorator } from '../decorators/complex-type.decorator.js'; import { ApiField } from './api-field.js'; import { ComplexTypeBase } from './complex-type-base.js'; import { DataType } from './data-type.js'; /** * ComplexType constructor */ export const ComplexType = function (...args) { // Decorator if (!this) return ComplexType[DECORATOR].apply(undefined, args); // Constructor const [owner, initArgs] = args; const context = args[2] || new DocumentInitContext({ maxErrors: 0 }); ComplexTypeBase.call(this, owner, initArgs, context); const _this = asMutable(this); _this.kind = OpraSchema.ComplexType.Kind; _this.discriminatorField = initArgs.discriminatorField; _this.discriminatorValue = initArgs.discriminatorValue; if (initArgs.base) { context.enter('.base', () => { // noinspection SuspiciousTypeOfGuard if (!(initArgs.base instanceof ComplexTypeBase)) { throw new TypeError(`"${initArgs.base.kind}" can't be set as base for a "${this.kind}"`); } _this.base = initArgs.base; _this.additionalFields = _this.base.additionalFields; _this.keyField = _this.base.keyField; /** Copy fields from base */ for (const v of _this.base.fields('*')) { _this._fields.set(v.name, new ApiField(this, v)); } }); } if (initArgs.additionalFields !== undefined) _this.additionalFields = initArgs.additionalFields; if (initArgs.keyField !== undefined) _this.keyField = initArgs.keyField; _this.ctor = initArgs.ctor || _this.base?.ctor; /** Add own fields */ if (initArgs.fields) { context.enter('.fields', () => { for (const [k, v] of Object.entries(initArgs.fields)) { const field = new ApiField(this, { ...v, name: k, }); this._fields.set(field.name, field); } }); } }; /** * * @class ComplexType */ class ComplexTypeClass extends ComplexTypeBase { extendsFrom(baseType) { if (!(baseType instanceof DataType)) baseType = this.node.getDataType(baseType); if (!(baseType instanceof ComplexTypeBase)) return false; if (baseType === this) return true; return !!this.base?.extendsFrom(baseType); } toJSON(options) { const superJson = super.toJSON(options); const baseName = this.base ? this.node.getDataTypeNameWithNs(this.base) : undefined; const out = { ...superJson, kind: this.kind, base: this.base ? baseName ? baseName : this.base.toJSON(options) : undefined, discriminatorField: this.discriminatorField, discriminatorValue: this.discriminatorValue, }; if (this.additionalFields) { if (this.additionalFields instanceof DataType) { const typeName = this.node.getDataTypeNameWithNs(this.additionalFields); out.additionalFields = typeName ? typeName : this.additionalFields.toJSON(options); } else out.additionalFields = this.additionalFields; } if (this._fields.size) { const fields = {}; let i = 0; for (const field of this._fields.values()) { if (field.origin === this && field.inScope(options?.scope)) { fields[field.name] = field.toJSON(options); i++; } } if (i) out.fields = fields; } return omitUndefined(out); } _locateBase(callback) { if (!this.base) return; if (callback(this.base)) return this.base; if (this.base._locateBase) return this.base._locateBase(callback); } } ComplexType.prototype = ComplexTypeClass.prototype; Object.assign(ComplexType, ComplexTypeDecorator); ComplexType[DECORATOR] = ComplexTypeDecorator;