smart-saga-pattern
Version:
A library implementing the Saga pattern for microservice architecture
98 lines (97 loc) • 2.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SagaStepContainer = exports.COMPENSATION_METADATA = exports.INVOKE_METADATA = exports.SAGA_STEP_METADATA = void 0;
exports.SagaStepDecorator = SagaStepDecorator;
exports.Invoke = Invoke;
exports.CompensationDecorator = CompensationDecorator;
require("reflect-metadata");
// Metadata keys
exports.SAGA_STEP_METADATA = "saga:step";
exports.INVOKE_METADATA = "saga:invoke";
exports.COMPENSATION_METADATA = "saga:compensation";
/**
* Decorator to mark a class as a Saga step
* @param options Options for the step
*/
function SagaStepDecorator(options = {}) {
return (target) => {
// Set default options
const stepOptions = {
order: 0,
requiresCompensation: true,
...options,
};
// Store metadata on the class
Reflect.defineMetadata(exports.SAGA_STEP_METADATA, {
name: target.name,
options: stepOptions,
}, target);
// Register the step with the container
SagaStepContainer.registerStep(target);
};
}
/**
* Decorator to mark a method as the invoke function for a Saga step
* @param options Options for the invoke method
*/
function Invoke(options = {}) {
return (target, propertyKey, descriptor) => {
// Store metadata on the method
Reflect.defineMetadata(exports.INVOKE_METADATA, {
methodName: propertyKey,
options,
}, target.constructor, propertyKey);
return descriptor;
};
}
/**
* Decorator to mark a method as the compensation function for a Saga step
* @param options Options for the compensation method
*/
function CompensationDecorator(options = {}) {
return (target, propertyKey, descriptor) => {
// Store metadata on the method
Reflect.defineMetadata(exports.COMPENSATION_METADATA, {
methodName: propertyKey,
options,
}, target.constructor, propertyKey);
return descriptor;
};
}
/**
* Container for Saga steps
*/
class SagaStepContainer {
/**
* Registers a step with the container
* @param stepClass Step class to register
*/
static registerStep(stepClass) {
const metadata = Reflect.getMetadata(exports.SAGA_STEP_METADATA, stepClass);
if (!metadata) {
throw new Error(`Class ${stepClass.name} is not a valid Saga step`);
}
this.steps.set(stepClass.name, stepClass);
}
/**
* Gets a step by name
* @param name Name of the step
*/
static getStep(name) {
return this.steps.get(name);
}
/**
* Gets all registered steps
*/
static getAllSteps() {
return Array.from(this.steps.values());
}
/**
* Clears all registered steps
*/
static clear() {
this.steps.clear();
}
}
exports.SagaStepContainer = SagaStepContainer;
SagaStepContainer.steps = new Map();