UNPKG

json-api-nestjs

Version:
231 lines 9.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExecuteService = void 0; exports.isZodError = isZodError; const tslib_1 = require("tslib"); const common_1 = require("@nestjs/common"); const constants_1 = require("@nestjs/common/constants"); const core_1 = require("@nestjs/core"); const nestjs_shared_1 = require("../../../utils/nestjs-shared"); const interceptors_1 = require("@nestjs/core/interceptors"); const rxjs_1 = require("rxjs"); const async_hooks_1 = require("async_hooks"); const constants_2 = require("../constants"); const constants_3 = require("../../../constants"); function isZodError(param) { return (param instanceof Object && 'message' in param && Array.isArray(param.message) && 'path' in param.message[0]); } let ExecuteService = class ExecuteService { // @Inject(CURRENT_DATA_SOURCE_TOKEN) private readonly dataSource!: DataSource; moduleRef; asyncIteratorFactory; runInTransaction; mapControllerInterceptor; asyncLocalStorage; _interceptorsContextCreator; get interceptorsContextCreator() { if (!this._interceptorsContextCreator) { this._interceptorsContextCreator = new interceptors_1.InterceptorsContextCreator(this.moduleRef.container, this.moduleRef.applicationConfig); } return this._interceptorsContextCreator; } interceptorsConsumer = new interceptors_1.InterceptorsConsumer(); async run(params, tmpIds) { return this.runInTransaction(() => this.executeOperations(params, tmpIds)); } async executeOperations(params, tmpIds = []) { const iterateParams = this.asyncIteratorFactory.createIterator(params, this.runOneOperation.bind(this)); const resultArray = []; let i = 0; const tmpIdsMap = {}; try { for await (const item of iterateParams) { const currentParams = params[i]; const controller = this.getControllerInstance(currentParams); const methodName = currentParams.methodName; const paramsForExecute = item; const itemReplace = this.replaceTmpIds(paramsForExecute, tmpIdsMap); const body = itemReplace.at(-1); const currentTmpId = tmpIds[i]; if (methodName === 'postOne' && currentTmpId && body) { if (typeof body === 'object' && 'attributes' in body) { body['id'] = `${currentTmpId}`; itemReplace[itemReplace.length - 1]; } } const interceptors = this.getInterceptorsArray(controller, controller[methodName], currentParams.module); const result$ = await this.interceptorsConsumer.intercept(interceptors, [ ...Object.values(this.asyncLocalStorage.getStore() || {}), itemReplace, ], controller, // @ts-ignore controller[methodName], // @ts-ignore async () => controller[methodName](...itemReplace)); const result = interceptors.length === 0 ? await result$ : await (0, rxjs_1.lastValueFrom)(result$); if (tmpIds[i] && result && !Array.isArray(result.data) && result.data) { tmpIdsMap[tmpIds[i]] = result.data.id; } if (result instanceof Object) { resultArray.push(result); } i++; } } catch (e) { this.processException(e, i); } return resultArray; } getInterceptorsArray(controller, callback, module) { let controllerFromMap = this.mapControllerInterceptor.get(controller); if (!controllerFromMap) { controllerFromMap = new Map(); this.mapControllerInterceptor.set(controller, controllerFromMap); } const interceptorsFromMap = controllerFromMap.get(callback); if (interceptorsFromMap) { return interceptorsFromMap; } const interceptorsForController = this.interceptorsContextCreator.create(controller, callback, module.token); const interceptorsForMethode = new Set(Reflect.getMetadata(constants_1.INTERCEPTORS_METADATA, callback) || []); const resultInterceptors = interceptorsForController.filter((i) => interceptorsForMethode.has(i.constructor)); controllerFromMap.set(callback, resultInterceptors); return resultInterceptors; } replaceTmpIds(inputParams, tmpIdsMap) { const bodyInput = inputParams.at(-1); if (!bodyInput) { return inputParams; } if (typeof bodyInput === 'string') { return inputParams; } if (typeof bodyInput === 'number') { return inputParams; } if (Array.isArray(bodyInput)) { return inputParams; } if (!(typeof bodyInput === 'object' && 'relationships' in bodyInput)) { return inputParams; } const { relationships } = bodyInput; if (!relationships) { return inputParams; } bodyInput.relationships = nestjs_shared_1.ObjectTyped.entries(relationships).reduce((acum, [name, val]) => { if (!val) throw new Error('Va; undefined'); const { data } = val; if (Array.isArray(data)) { acum[name] = { data: data.map((i) => { if (i === null) return i; return { ...i, id: tmpIdsMap[i['id']] ? `${tmpIdsMap[i['id']]}` : i['id'], }; }), }; } else { if (!data) { acum[name] = val; } else { data['id'] = tmpIdsMap[data['id']] ? `${tmpIdsMap[data['id']]}` : data['id']; acum[name] = { data, }; } } return acum; }, { ...relationships }); inputParams[inputParams.length - 1] = bodyInput; return inputParams; } getControllerInstance(params) { const controllerClass = params.controller; const controllerInstanceWrapper = params.module.controllers.get(controllerClass); if (!controllerInstanceWrapper) { const error = { code: 'invalid_arguments', path: ['type'], message: `Controller "${controllerClass.name}" not found`, }; throw new common_1.NotFoundException([error]); } return controllerInstanceWrapper.instance; } processException(e, i) { if (e instanceof common_1.HttpException) { const response = e.getResponse(); if (isZodError(response)) { response['message'] = response['message'].map((m) => { m['path'] = [constants_2.KEY_MAIN_INPUT_SCHEMA, `${i}`, ...m['path']]; return m; }); } throw new common_1.HttpException(response, e.getStatus()); } throw e; } async runOneOperation(paramForExecute) { const { params, controller, methodName, module } = paramForExecute; const pramsPipe = Object.values(Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, controller, methodName)); const resultParams = new Array(params.length); for (const { pipes, index } of pramsPipe) { resultParams[index] = await this.runPipes(params[index], module, pipes); } return resultParams; } async runPipes(initialParams, module, pipes) { let modifiedParams = initialParams; for (const pipe of pipes) { const pipeInstance = this.getPipeInstance(pipe, module); modifiedParams = await pipeInstance.transform(modifiedParams, {}); } return modifiedParams; } getPipeInstance(pipe, module) { const instanceWrapper = module.getProviderByKey(pipe); if (!instanceWrapper) { return this.moduleRef.get(pipe, { strict: false }); } return instanceWrapper.instance; } }; exports.ExecuteService = ExecuteService; tslib_1.__decorate([ (0, common_1.Inject)(core_1.ModuleRef), tslib_1.__metadata("design:type", Object) ], ExecuteService.prototype, "moduleRef", void 0); tslib_1.__decorate([ (0, common_1.Inject)(constants_2.ASYNC_ITERATOR_FACTORY), tslib_1.__metadata("design:type", Object) ], ExecuteService.prototype, "asyncIteratorFactory", void 0); tslib_1.__decorate([ (0, common_1.Inject)(constants_3.RUN_IN_TRANSACTION_FUNCTION), tslib_1.__metadata("design:type", Function) ], ExecuteService.prototype, "runInTransaction", void 0); tslib_1.__decorate([ (0, common_1.Inject)(constants_2.MAP_CONTROLLER_INTERCEPTORS), tslib_1.__metadata("design:type", Object) ], ExecuteService.prototype, "mapControllerInterceptor", void 0); tslib_1.__decorate([ (0, common_1.Inject)(async_hooks_1.AsyncLocalStorage), tslib_1.__metadata("design:type", async_hooks_1.AsyncLocalStorage) ], ExecuteService.prototype, "asyncLocalStorage", void 0); exports.ExecuteService = ExecuteService = tslib_1.__decorate([ (0, common_1.Injectable)() ], ExecuteService); //# sourceMappingURL=execute.service.js.map