@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
132 lines (128 loc) • 7.49 kB
JavaScript
;
var contextStorage_class = require('../../class/api/function/context-storage.class.js');
var runtime_class = require('../../class/api/function/transaction/runtime.class.js');
var service_constant = require('../../constant/decorator/api/service.constant.js');
require('../../enum/decorator/api/action.enum.js');
require('../../enum/decorator/api/authentication-type.enum.js');
require('../../enum/decorator/api/controller/get-list/query/filter/missing-behavior.enum.js');
require('../../enum/decorator/api/controller/get-list/query/unlisted-fields.enum.js');
require('../../enum/decorator/api/controller/relation-reference-shape.enum.js');
require('../../enum/decorator/api/controller/request/target.enum.js');
require('../../enum/decorator/api/controller/request/transformer-type.enum.js');
require('../../enum/decorator/api/controller/response-target.enum.js');
require('../../enum/decorator/api/dto-type.enum.js');
require('../../enum/decorator/api/function/context-storage-kind.enum.js');
require('../../enum/decorator/api/function/subscriber-transaction-expectation.enum.js');
require('../../enum/decorator/api/function/transaction/event-status.enum.js');
require('../../enum/decorator/api/function/transaction/failure-stage.enum.js');
var mode_enum = require('../../enum/decorator/api/function/transaction/mode.enum.js');
require('../../enum/decorator/api/function/transaction/outcome.enum.js');
var ownerKind_enum = require('../../enum/decorator/api/function/transaction/owner-kind.enum.js');
require('../../enum/decorator/api/function/transaction/trace-type.enum.js');
require('../../enum/decorator/api/function/type.enum.js');
require('../../enum/decorator/api/on-type.enum.js');
require('../../enum/decorator/api/property/data-type.enum.js');
require('../../enum/decorator/api/property/date/identifier.enum.js');
require('../../enum/decorator/api/property/date/type.enum.js');
require('../../enum/decorator/api/property/desribe-type.enum.js');
require('../../enum/decorator/api/property/number-type.enum.js');
require('../../enum/decorator/api/property/string-type.enum.js');
require('../../enum/decorator/api/route/subscriber-authorization-expectation.enum.js');
require('../../enum/decorator/api/route/type.enum.js');
var exception_utility = require('../error/exception.utility.js');
/**
* Executes an ApiFunction callback according to its transaction mode.
* @template E - Entity type owned by the function repository.
* @template R - Callback result type.
* @param {object} options - Transaction execution options.
* @param {string} [options.action] - Custom function action used for subscriber matching.
* @param {(eventManager: EntityManager | undefined) => Promise<R>} options.callback - Function body to run with the resolved transaction manager.
* @param {new (...arguments_: Array<unknown>) => E} options.entity - Entity constructor associated with the function.
* @param {TApiFunctionTransactionTraceType} options.functionType - Function trace type.
* @param {string} [options.label] - Error message label for the decorated function primitive.
* @param {string} options.methodName - Decorated service method name.
* @param {EApiFunctionTransactionMode} options.mode - Transaction mode to enforce.
* @param {(eventManager: EntityManager | undefined, error: Error) => Promise<void>} [options.onPreflightError] - Error hook for transaction mode conflicts before the function body starts.
* @param {Repository<E>} [options.repository] - Repository used to open new transactions when required.
* @param {new (...arguments_: Array<unknown>) => unknown} [options.serviceConstructor] - Observable service constructor used for subscriber matching.
* @returns {Promise<R>} Callback result.
*/
async function ApiFunctionExecuteWithTransaction(options) {
const activeRegistry = contextStorage_class.ApiFunctionContextStorage.getTransactionRegistry();
const activeEventManager = activeRegistry ? contextStorage_class.ApiFunctionContextStorage.getEventManager() : undefined;
const label = options.label ?? "ApiFunction";
const isSubscriberObservable = Boolean(options.serviceConstructor && Reflect.hasMetadata(service_constant.SERVICE_API_DECORATOR_CONSTANT.OBSERVABLE_METADATA_KEY, options.serviceConstructor));
const executeWithEventManager = async (eventManager) => {
const registry = contextStorage_class.ApiFunctionContextStorage.getTransactionRegistry();
const sequence = registry?.beginEvent({
action: options.action,
entityName: options.entity.name,
functionType: options.functionType,
isSubscriberObservable,
methodName: options.methodName,
});
try {
const result = await options.callback(eventManager);
if (sequence !== undefined) {
registry?.succeedEvent(sequence);
}
return result;
}
catch (error) {
if (sequence !== undefined) {
registry?.failEvent(sequence, error);
}
throw error;
}
};
if (options.mode === mode_enum.EApiFunctionTransactionMode.NONE && activeEventManager) {
const error = exception_utility.ErrorException(`${label} transaction mode NONE cannot run inside an active transaction`);
const sequence = activeRegistry?.beginEvent({
action: options.action,
entityName: options.entity.name,
functionType: options.functionType,
isSubscriberObservable,
methodName: options.methodName,
});
try {
await options.onPreflightError?.(activeEventManager, error);
}
catch (preflightError) {
if (sequence !== undefined) {
activeRegistry?.failEvent(sequence, preflightError);
}
throw preflightError;
}
if (sequence !== undefined) {
activeRegistry?.failEvent(sequence, error);
}
throw error;
}
if (options.mode === mode_enum.EApiFunctionTransactionMode.MANDATORY && !activeEventManager) {
const error = exception_utility.ErrorException(`${label} transaction mode MANDATORY requires an active transaction`);
await options.onPreflightError?.(undefined, error);
throw error;
}
const eventManager = options.mode === mode_enum.EApiFunctionTransactionMode.NONE ? undefined : activeEventManager;
if (options.mode === mode_enum.EApiFunctionTransactionMode.REQUIRED && !eventManager) {
if (!options.repository) {
const error = exception_utility.ErrorException("Repository is not available in this context");
await options.onPreflightError?.(undefined, error);
throw error;
}
return await runtime_class.ApiFunctionTransactionRuntime.execute({
callback: executeWithEventManager,
dataSource: options.repository.manager.connection,
owner: {
action: options.action,
entityName: options.entity.name,
functionType: options.functionType,
kind: ownerKind_enum.EApiFunctionTransactionOwnerKind.FUNCTION,
methodName: options.methodName,
},
});
}
return await executeWithEventManager(eventManager);
}
exports.ApiFunctionExecuteWithTransaction = ApiFunctionExecuteWithTransaction;
//# sourceMappingURL=function-transaction.utility.js.map