UNPKG

@opra/common

Version:
131 lines (130 loc) 4.74 kB
import { OpraSchema } from '../../schema/index.js'; import { DATATYPE_METADATA, kDataTypeMap, kTypeNSMap } from '../constants.js'; /** * @class DocumentNode */ export class DocumentNode { constructor(element, parent) { this.element = element; this.parent = parent; } getDocument() { if (this._document) return this._document; if (this.element[kTypeNSMap]) return this.element; if (this.parent) return (this._document = this.parent.getDocument()); // istanbul ignore next throw new Error('ApiDocument not found in document tree'); } hasDataType(nameOrCtor, scope) { return !!this.findDataType(nameOrCtor, scope); } findDataType(nameOrCtor, scope) { const dt = this[kDataTypeMap]?.get(nameOrCtor); if (dt && dt.inScope(scope)) return dt; return this.parent ? this.parent.findDataType(nameOrCtor, scope) : undefined; } /** * Returns DataType instance by name or Constructor. Returns undefined if not found */ getDataType(nameOrCtor, scope) { const dt = this.findDataType(nameOrCtor, scope); if (dt) return dt; let name = ''; if (typeof nameOrCtor === 'function') { const metadata = Reflect.getMetadata(DATATYPE_METADATA, nameOrCtor); name = metadata.name; } else if (typeof nameOrCtor === 'object') { const metadata = nameOrCtor[DATATYPE_METADATA]; name = metadata?.name; } if (!name) { if (nameOrCtor && typeof nameOrCtor === 'string') name = nameOrCtor; else if (typeof nameOrCtor === 'function') name = nameOrCtor.name; } if (dt) throw new TypeError(`Data type${name ? ' (' + name + ')' : ''} is not in requested scope (${scope})`); throw new TypeError(`Unknown data type${name ? ' (' + name + ')' : ''}`); } getDataTypeNameWithNs(dataType) { if (!dataType.name) return; const ns = this.getDocument().getDataTypeNs(dataType); return ns ? ns + ':' + dataType.name : dataType.name; } /** * Returns ComplexType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a ComplexType */ getComplexType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.ComplexType.Kind) return t; throw new TypeError(`Data type "${t.name}" is not a ComplexType`); } /** * Returns SimpleType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a SimpleType */ getSimpleType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.SimpleType.Kind) return t; throw new TypeError(`Data type "${t.name || t}" is not a SimpleType`); } /** * Returns EnumType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a EnumType */ getEnumType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.EnumType.Kind) return t; throw new TypeError(`Data type "${t.name || t}" is not a EnumType`); } /** * Returns EnumType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a MappedType */ getMappedType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.MappedType.Kind) return t; throw new TypeError(`Data type "${t.name || t}" is not a MappedType`); } /** * Returns EnumType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a MixinType */ getMixinType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.MixinType.Kind) return t; throw new TypeError(`Data type "${t.name || t}" is not a MixinType`); } /** * Returns EnumType instance by name or Constructor. * Returns undefined if not found * Throws error if data type is not a UnionType */ getUnionType(nameOrCtor, scope) { const t = this.getDataType(nameOrCtor, scope); if (t.kind === OpraSchema.UnionType.Kind) return t; throw new TypeError(`Data type "${t.name || t}" is not a MixinType`); } }