UNPKG

@opra/common

Version:
204 lines (203 loc) 8.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RpcApiFactory = void 0; const objects_1 = require("@jsopen/objects"); const index_js_1 = require("../../helpers/index.js"); const constants_js_1 = require("../constants.js"); const rpc_api_js_1 = require("../rpc/rpc-api.js"); const rpc_controller_js_1 = require("../rpc/rpc-controller.js"); const rpc_header_js_1 = require("../rpc/rpc-header.js"); const rpc_operation_js_1 = require("../rpc/rpc-operation.js"); const rpc_operation_response_js_1 = require("../rpc/rpc-operation-response.js"); const data_type_factory_js_1 = require("./data-type.factory.js"); /** * @class RpcApiFactory */ class RpcApiFactory { /** * Generates RpcApi * @param context * @param init */ static async createApi(context, init) { const api = new rpc_api_js_1.RpcApi(init); if (init.controllers) { await context.enterAsync('.controllers', async () => { if (Array.isArray(init.controllers)) { for (const c of init.controllers) { const controller = await this._createController(context, api, c); if (controller) api.controllers.set(controller.name, controller); } } else { for (const [k, v] of Object.entries(init.controllers)) { const controller = await this._createController(context, api, v, k); if (controller) api.controllers.set(controller.name, controller); } } }); } return api; } static async _createController(context, parent, thunk, name) { if (typeof thunk === 'function' && !(0, objects_1.isConstructor)(thunk)) { thunk = thunk(); } thunk = await (0, index_js_1.resolveThunk)(thunk); let ctor; let metadata; let instance; // If thunk is a class if (typeof thunk === 'function') { metadata = Reflect.getMetadata(constants_js_1.RPC_CONTROLLER_METADATA, thunk); if (!metadata) return context.addError(`Class "${thunk.name}" doesn't have a valid RpcController metadata`); ctor = thunk; } else { // If thunk is an instance of a class decorated with RpcController() ctor = Object.getPrototypeOf(thunk).constructor; metadata = Reflect.getMetadata(constants_js_1.RPC_CONTROLLER_METADATA, ctor); if (metadata) instance = thunk; else { // If thunk is a DecoratorMetadata or InitArguments metadata = thunk; if (thunk.instance === 'object') { instance = thunk.instance; ctor = Object.getPrototypeOf(instance).constructor; } } } if (!metadata) return context.addError(`Class "${ctor.name}" is not decorated with RpcController()`); name = name || metadata.name; if (!name) throw new TypeError(`Controller name required`); const controller = new rpc_controller_js_1.RpcController(parent, { ...metadata, name, instance, ctor, }); if (metadata.types) { await context.enterAsync('.types', async () => { await data_type_factory_js_1.DataTypeFactory.addDataTypes(context, controller, metadata.types); }); } if (metadata.headers) { await context.enterAsync('.headers', async () => { let i = 0; for (const v of metadata.headers) { await context.enterAsync(`[${i++}]`, async () => { const prmArgs = { ...v }; await context.enterAsync('.type', async () => { if (v.type) prmArgs.type = controller.node.findDataType(v.type); if (!prmArgs.type && typeof v.type === 'object') { prmArgs.type = await data_type_factory_js_1.DataTypeFactory.createDataType(context, controller, v.type); } if (!prmArgs.type) prmArgs.type = controller.node.getDataType('any'); }); const prm = new rpc_header_js_1.RpcHeader(controller, prmArgs); controller.headers.push(prm); }); } }); } if (metadata.operations) { await context.enterAsync('.operations', async () => { for (const [operationName, operationMeta] of Object.entries(metadata.operations)) { await context.enterAsync(`[${operationName}]`, async () => { const operation = new rpc_operation_js_1.RpcOperation(controller, { ...operationMeta, name: operationName, types: undefined, payloadType: undefined, keyType: undefined, }); await this._initRpcOperation(context, operation, operationMeta); controller.operations.set(operation.name, operation); }); } }); } return controller; } /** * Initializes RpcOperation * @param context * @param operation * @param metadata * @protected */ static async _initRpcOperation(context, operation, metadata) { if (metadata.types) { await context.enterAsync('.types', async () => { await data_type_factory_js_1.DataTypeFactory.addDataTypes(context, operation, metadata.types); }); } operation.payloadType = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, operation, metadata.payloadType); if (metadata.keyType) { operation.keyType = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, operation, metadata.keyType); } if (metadata.headers) { await context.enterAsync('.headers', async () => { let i = 0; for (const v of metadata.headers) { await context.enterAsync(`[${i++}]`, async () => { const prmArgs = { ...v }; await context.enterAsync('.type', async () => { prmArgs.type = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, operation, v.type); }); const prm = new rpc_header_js_1.RpcHeader(operation, prmArgs); operation.headers.push(prm); }); } }); } if (metadata.response) { await context.enterAsync('.response', async () => { const response = new rpc_operation_response_js_1.RpcOperationResponse(operation, { ...metadata.response, payloadType: undefined, keyType: undefined, }); await this._initRpcOperationResponse(context, response, metadata.response); operation.response = response; }); } } /** * Initializes RpcOperationResponse * @param context * @param response * @param metadata * @protected */ static async _initRpcOperationResponse(context, response, metadata) { response.payloadType = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, response, metadata.payloadType); if (metadata.keyType) { response.keyType = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, response, metadata.keyType); } if (metadata.headers) { await context.enterAsync('.headers', async () => { let i = 0; for (const v of metadata.headers) { await context.enterAsync(`[${i++}]`, async () => { const prmArgs = { ...v }; await context.enterAsync('.type', async () => { prmArgs.type = await data_type_factory_js_1.DataTypeFactory.resolveDataType(context, response, v.type); }); const prm = new rpc_header_js_1.RpcHeader(response, prmArgs); response.headers.push(prm); }); } }); } } } exports.RpcApiFactory = RpcApiFactory;