@opra/common
Version:
Opra common package
164 lines (163 loc) • 5.85 kB
JavaScript
"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;