UNPKG

@opra/common

Version:
164 lines (163 loc) 5.85 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.ApiDocument = void 0; const objects_1 = require("@jsopen/objects"); const super_fast_md5_1 = require("super-fast-md5"); const index_js_1 = require("../helpers/index.js"); const index_js_2 = require("../schema/index.js"); const data_type_map_js_1 = require("./common/data-type-map.js"); const document_element_js_1 = require("./common/document-element.js"); const constants_js_1 = require("./constants.js"); const data_type_js_1 = require("./data-type/data-type.js"); const http_api_js_1 = require("./http/http-api.js"); const rpc_api_js_1 = require("./rpc/rpc-api.js"); /** * * @class ApiDocument */ class ApiDocument extends document_element_js_1.DocumentElement { constructor() { super(null); this[_a] = new WeakMap(); this.id = ''; this.info = {}; this.references = new index_js_1.ResponsiveMap(); this.types = new data_type_map_js_1.DataTypeMap(); this.node[constants_js_1.kDataTypeMap] = this.types; this.node.findDataType = this._findDataType.bind(this); } /** * Returns NS of datatype. Returns undefined if not found * @param nameOrCtor */ getDataTypeNs(nameOrCtor) { const dt = nameOrCtor instanceof data_type_js_1.DataType ? this._findDataType(nameOrCtor.name || '') : this._findDataType(nameOrCtor); if (dt) return this[constants_js_1.kTypeNSMap].get(dt); } findDocument(id) { if (this.id === id) return this; for (const doc of this.references.values()) { if (doc.id === id) return doc; const d = doc.findDocument(id); if (d) return d; } } get httpApi() { if (!(this.api && this.api instanceof http_api_js_1.HttpApi)) { throw new TypeError('The document do not contains HttpApi instance'); } return this.api; } get rpcApi() { if (!(this.api && this.api instanceof rpc_api_js_1.RpcApi)) { throw new TypeError('The document do not contains RpcApi instance'); } return this.api; } toJSON() { return this.export(); } /** * Export as Opra schema definition object */ export(options) { const out = (0, objects_1.omitUndefined)({ spec: index_js_2.OpraSchema.SpecVersion, id: this.id, url: this.url, info: (0, index_js_1.cloneObject)(this.info, true), }); if (this.references.size) { let i = 0; const references = {}; for (const [ns, doc] of this.references.entries()) { if (doc[constants_js_1.BUILTIN]) continue; references[ns] = { id: doc.id, url: doc.url, info: (0, index_js_1.cloneObject)(doc.info, true), }; i++; } if (i) out.references = references; } if (this.types.size) { out.types = {}; for (const v of this.types.values()) { if (!v.inScope(options?.scope)) continue; out.types[v.name] = v.toJSON(options); } } if (this.api) out.api = this.api.toJSON(options); return out; } invalidate() { /** Generate id */ const x = this.export({}); delete x.id; this.id = (0, super_fast_md5_1.md5)(JSON.stringify(x)); /** Clear [kTypeNSMap] */ this[constants_js_1.kTypeNSMap] = new WeakMap(); } _findDataType(nameOrCtor, scope, visitedRefs) { let result = this.types.get(nameOrCtor); if (result && result.inScope(scope)) return result; if (!this.references.size) return; // Lookup for references if (typeof nameOrCtor === 'string') { // If given string has namespace pattern (ns:type_name) const m = constants_js_1.NAMESPACE_PATTERN.exec(nameOrCtor); if (m) { const ns = m[1]; if (ns) { const ref = this.references.get(ns); if (!ref) return; visitedRefs = visitedRefs || new WeakMap(); visitedRefs.set(this, true); visitedRefs.set(ref, true); return ref._findDataType(m[2], scope, visitedRefs); } nameOrCtor = m[2]; } } // if not found, search in references (from last to first) visitedRefs = visitedRefs || new WeakMap(); visitedRefs.set(this, true); const references = Array.from(this.references.keys()).reverse(); /** First step, lookup for own types */ for (const refNs of references) { const ref = this.references.get(refNs); result = ref?.types.get(nameOrCtor); if (result) { this[constants_js_1.kTypeNSMap].set(result, ref?.[constants_js_1.BUILTIN] ? '' : refNs); return result; } } /** If not found lookup for child references */ for (const refNs of references) { const ref = this.references.get(refNs); visitedRefs.set(ref, true); result = ref._findDataType(nameOrCtor, scope, visitedRefs); if (result) { this[constants_js_1.kTypeNSMap].set(result, ref?.[constants_js_1.BUILTIN] ? '' : refNs); return result; } } } } exports.ApiDocument = ApiDocument; _a = constants_js_1.kTypeNSMap;