UNPKG

@opra/common

Version:
204 lines (203 loc) 8.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ApiDocumentFactory = void 0; const index_js_1 = require("../../helpers/index.js"); const index_js_2 = require("../../schema/index.js"); const api_document_js_1 = require("../api-document.js"); const document_init_context_js_1 = require("../common/document-init-context.js"); const opra_document_error_js_1 = require("../common/opra-document-error.js"); const constants_js_1 = require("../constants.js"); const index_js_3 = require("../data-type/extended-types/index.js"); const index_js_4 = require("../data-type/primitive-types/index.js"); const data_type_factory_js_1 = require("./data-type.factory.js"); const http_api_factory_js_1 = require("./http-api.factory.js"); const rpc_api_factory_js_1 = require("./rpc-api.factory.js"); const OPRA_SPEC_URL = 'https://oprajs.com/spec/v' + index_js_2.OpraSchema.SpecVersion; /** * @class ApiDocumentFactory */ class ApiDocumentFactory { constructor() { this._allDocuments = {}; } /** * Creates ApiDocument instance from given schema object */ static async createDocument(schemaOrUrl, options) { const factory = new ApiDocumentFactory(); const context = options instanceof document_init_context_js_1.DocumentInitContext ? options : new document_init_context_js_1.DocumentInitContext(options); try { const document = new api_document_js_1.ApiDocument(); await factory.initDocument(document, context, schemaOrUrl); if (context.error.details.length) throw context.error; return document; } catch (e) { try { if (!(e instanceof opra_document_error_js_1.OpraDocumentError)) { context.addError(e); } } catch { // } if (!context.error.message) { const l = context.error.details.length; context.error.message = `(${l}) error${l > 1 ? 's' : ''} found in document schema.`; if (context.showErrorDetails) { context.error.message += context.error.details .map(d => `\n\n - ${d.message}` + (d.path ? `\n @${d.path}` : '')) .join(''); } } throw context.error; } } /** * Downloads schema from the given URL and creates the document instance * @param url */ async initDocument(document, context, schemaOrUrl) { let init; if (typeof schemaOrUrl === 'string') { const resp = await fetch(schemaOrUrl, { method: 'GET' }); init = await resp.json(); if (!init) return context.addError(`Invalid response returned from url: ${schemaOrUrl}`); init.url = schemaOrUrl; } else init = schemaOrUrl; // Add builtin data types if this document is the root let builtinDocument; if (!document[constants_js_1.BUILTIN]) { const t = document.node.findDataType('string'); builtinDocument = t?.node.getDocument(); if (!builtinDocument) { builtinDocument = await this.createBuiltinDocument(context); document.references.set('opra', builtinDocument); } } init.spec = init.spec || index_js_2.OpraSchema.SpecVersion; document.url = init.url; if (init.info) document.info = { ...init.info }; /** Add references */ if (init.references) { await context.enterAsync('.references', async () => { let ns; let r; for ([ns, r] of Object.entries(init.references)) { r = await (0, index_js_1.resolveThunk)(r); await context.enterAsync(`[${ns}]`, async () => { if (!constants_js_1.CLASS_NAME_PATTERN.test(ns)) throw new TypeError(`Invalid namespace (${ns})`); if (r instanceof api_document_js_1.ApiDocument) { document.references.set(ns, r); return; } const refDoc = new api_document_js_1.ApiDocument(); if (builtinDocument) refDoc.references.set('opra', builtinDocument); await this.initDocument(refDoc, context, r); document.references.set(ns, this._allDocuments[refDoc.id]); }); } }); } if (init.types) { await context.enterAsync('.types', async () => { await data_type_factory_js_1.DataTypeFactory.addDataTypes(context, document, init.types); }); } if (init.api) { await context.enterAsync(`.api`, async () => { if (init.api && init.api.transport === 'http') { const api = await http_api_factory_js_1.HttpApiFactory.createApi(context, { ...init.api, owner: document, }); if (api) document.api = api; } else if (init.api && init.api.transport === 'rpc') { const api = await rpc_api_factory_js_1.RpcApiFactory.createApi(context, { ...init.api, owner: document, }); if (api) document.api = api; } else context.addError(`Unknown service transport (${init.api.transport})`); }); } document.invalidate(); /** Add document to global registry */ if (!this._allDocuments[document.id]) this._allDocuments[document.id] = document; } /** * * @param context * @protected */ async createBuiltinDocument(context) { const init = { spec: index_js_2.OpraSchema.SpecVersion, url: OPRA_SPEC_URL, info: { version: index_js_2.OpraSchema.SpecVersion, title: 'Opra built-in types', license: { url: 'https://github.com/oprajs/opra/blob/main/LICENSE', name: 'MIT', }, }, types: [ // Primitive types index_js_4.AnyType, index_js_4.BigintType, index_js_4.BooleanType, index_js_4.IntegerType, index_js_4.NullType, index_js_4.NumberType, index_js_4.ObjectType, index_js_4.StringType, // Extended types index_js_3.Base64Type, index_js_3.DateType, index_js_3.DateStringType, index_js_3.DateTimeType, index_js_3.DateTimeStringType, index_js_3.EmailType, index_js_3.FieldPathType, index_js_3.FilterType, index_js_3.ObjectIdType, index_js_3.OperationResult, index_js_3.TimeType, index_js_3.UrlType, index_js_3.UuidType, ], }; const document = new api_document_js_1.ApiDocument(); document[constants_js_1.BUILTIN] = true; const BigIntConstructor = Object.getPrototypeOf(BigInt(0)).constructor; const BufferConstructor = Object.getPrototypeOf(Buffer.from([])); const _ctorTypeMap = document.types[constants_js_1.kCtorMap]; _ctorTypeMap.set(Object, 'object'); _ctorTypeMap.set(String, 'string'); _ctorTypeMap.set(Number, 'number'); _ctorTypeMap.set(Boolean, 'boolean'); _ctorTypeMap.set(Object, 'any'); _ctorTypeMap.set(Date, 'datetime'); _ctorTypeMap.set(BigIntConstructor, 'bigint'); _ctorTypeMap.set(ArrayBuffer, 'base64'); _ctorTypeMap.set(BufferConstructor, 'base64'); await this.initDocument(document, context, init); return document; } } exports.ApiDocumentFactory = ApiDocumentFactory;