@opra/common
Version:
Opra common package
204 lines (203 loc) • 8.97 kB
JavaScript
;
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;