nestjs-temporal-core
Version:
Complete NestJS integration for Temporal.io with auto-discovery, declarative scheduling, enhanced monitoring, and enterprise-ready features
512 lines • 19.8 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var TemporalMetadataAccessor_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TemporalMetadataAccessor = void 0;
const common_1 = require("@nestjs/common");
const constants_1 = require("../constants");
const logger_1 = require("../utils/logger");
let TemporalMetadataAccessor = TemporalMetadataAccessor_1 = class TemporalMetadataAccessor {
constructor() {
this.activityMethodCache = new Map();
this.logger = (0, logger_1.createLogger)(TemporalMetadataAccessor_1.name);
}
isActivity(target) {
try {
return (Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY, target) ||
Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY, target.prototype));
}
catch {
return false;
}
}
isActivityMethod(target, methodName) {
try {
if (!target || typeof target === 'string')
return false;
const targetObj = target;
return (Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, target, methodName || '') ||
(targetObj.constructor?.prototype !== undefined &&
Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, targetObj.constructor.prototype, methodName || '')));
}
catch {
return false;
}
}
getActivityMetadata(target) {
try {
return (Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY, target) ||
Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY, target.prototype) ||
null);
}
catch {
return null;
}
}
getActivityMethodMetadata(instance, methodName) {
try {
if (!instance)
return null;
const prototype = Object.getPrototypeOf(instance);
if (!prototype)
return null;
const metadata = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype, methodName);
if (!metadata)
return null;
if (!(methodName in prototype))
return null;
return {
name: metadata.name || methodName,
originalName: methodName,
methodName,
className: prototype.constructor?.name || 'Unknown',
options: metadata.options || metadata,
handler: prototype[methodName],
};
}
catch {
return null;
}
}
getActivityMethodNames(target) {
try {
if (!target || typeof target !== 'function' || !target.prototype)
return [];
const prototype = target.prototype;
const propertyNames = Object.getOwnPropertyNames(prototype);
const methodNames = [];
for (const propertyName of propertyNames) {
if (propertyName === 'constructor')
continue;
try {
if (Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype, propertyName)) {
methodNames.push(propertyName);
}
}
catch {
}
}
return methodNames;
}
catch {
return [];
}
}
getActivityMethodName(target, methodName) {
try {
if (!target || typeof target === 'string')
return null;
const metadata = this.getActivityMethodMetadata(target, methodName || '');
return metadata?.name || methodName || null;
}
catch {
return null;
}
}
getActivityOptions(target) {
try {
const metadata = this.getActivityMetadata(target);
return metadata || null;
}
catch {
return null;
}
}
extractActivityMethods(instance) {
const errors = [];
const methods = new Map();
let extractedCount = 0;
if (!instance) {
return {
success: true,
methods,
errors,
extractedCount: 0,
};
}
const constructor = instance.constructor;
if (constructor && this.activityMethodCache.has(constructor)) {
const cachedMethods = this.activityMethodCache.get(constructor);
for (const [name, method] of cachedMethods.entries()) {
if (typeof method === 'function') {
methods.set(name, {
name,
originalName: name,
methodName: name,
className: constructor.name || 'Unknown',
handler: method,
});
extractedCount++;
}
else if (method && typeof method === 'object') {
methods.set(name, method);
extractedCount++;
}
}
return {
success: true,
methods,
errors,
extractedCount,
};
}
try {
const prototype = Object.getPrototypeOf(instance);
if (!prototype) {
this.logger.warn('No prototype found for instance');
return {
success: false,
methods,
errors: [{ method: 'prototype', error: 'No prototype found for instance' }],
extractedCount: 0,
};
}
const storedActivityMethods = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype);
if (storedActivityMethods && typeof storedActivityMethods === 'object') {
for (const [methodName, methodMetadata] of Object.entries(storedActivityMethods)) {
try {
if (typeof prototype[methodName] === 'function') {
const metadata = methodMetadata;
const activityName = metadata.name || methodName;
methods.set(activityName, {
name: activityName,
originalName: methodName,
methodName: methodName,
className: prototype.constructor?.name || 'Unknown',
options: {
name: activityName,
methodName: methodName,
className: prototype.constructor?.name || 'Unknown',
...metadata,
},
handler: prototype[methodName].bind(instance),
});
extractedCount++;
this.logger.debug(`Found activity method: ${activityName}`);
}
}
catch (methodError) {
const errorMessage = methodError instanceof Error ? methodError.message : 'Unknown error';
errors.push({ method: methodName, error: errorMessage });
this.logger.warn(`Failed to process method ${methodName}`, methodError);
}
}
}
else {
const propertyNames = Object.getOwnPropertyNames(prototype);
for (const propertyName of propertyNames) {
if (propertyName === 'constructor')
continue;
try {
const methodMetadata = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype, propertyName);
if (methodMetadata && typeof prototype[propertyName] === 'function') {
const activityName = methodMetadata.name ||
propertyName;
methods.set(activityName, {
name: activityName,
originalName: propertyName,
methodName: propertyName,
className: prototype.constructor?.name || 'Unknown',
options: {
name: activityName,
methodName: propertyName,
className: prototype.constructor?.name || 'Unknown',
...methodMetadata,
},
handler: prototype[propertyName].bind(instance),
});
extractedCount++;
this.logger.debug(`Found activity method: ${activityName}`);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
errors.push({ method: propertyName, error: errorMessage });
this.logger.warn(`Failed to process method ${propertyName}`, error);
}
}
}
if (constructor) {
this.activityMethodCache.set(constructor, methods);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
this.logger.error('Failed to extract activity methods', error);
errors.push({ method: 'extraction', error: errorMessage });
}
return {
success: errors.length === 0,
methods,
errors,
extractedCount,
};
}
extractActivityMethodsFromClass(target) {
const methods = [];
try {
const prototype = target.prototype;
const prototypeMetadata = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype);
if (prototypeMetadata && typeof prototypeMetadata === 'object') {
for (const [methodName, metadata] of Object.entries(prototypeMetadata)) {
const metadataObj = metadata;
methods.push({
methodName,
name: metadataObj.name || methodName,
metadata: {
name: metadataObj.name || methodName,
methodName,
className: target.name || 'Unknown',
options: metadataObj.options,
},
});
}
}
}
catch (error) {
this.logger.warn('Failed to extract activity methods from class', error);
}
return methods;
}
extractMethodsFromPrototype(instance) {
return this.extractActivityMethods(instance);
}
getActivityMethodOptions(target, methodName) {
try {
if (!target || !methodName)
return null;
const metadata = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, target, methodName);
return metadata || null;
}
catch {
return null;
}
}
getSignalMethods(prototype) {
try {
const methods = Reflect.getMetadata(constants_1.TEMPORAL_SIGNAL_METHOD, prototype) || {};
return {
success: true,
methods: methods,
errors: [],
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
success: false,
methods: {},
errors: [{ method: 'signal', error: errorMessage }],
};
}
}
getQueryMethods(prototype) {
try {
const methods = Reflect.getMetadata(constants_1.TEMPORAL_QUERY_METHOD, prototype) || {};
return {
success: true,
methods: methods,
errors: [],
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
success: false,
methods: {},
errors: [{ method: 'query', error: errorMessage }],
};
}
}
getChildWorkflows(prototype) {
try {
const workflows = Reflect.getMetadata(constants_1.TEMPORAL_CHILD_WORKFLOW, prototype) || {};
return {
success: true,
workflows: workflows,
errors: [],
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
return {
success: false,
workflows: {},
errors: [{ workflow: 'child', error: errorMessage }],
};
}
}
validateActivityClass(constructor) {
const issues = [];
const warnings = [];
try {
const className = constructor.name || 'Unknown';
const prototype = constructor.prototype;
const methodCount = this.getActivityMethodNames(constructor).length;
if (!this.isActivity(constructor)) {
issues.push('Class is not marked with @Activity decorator');
}
const hasActivityMethods = this.hasActivityMethods(prototype);
if (!hasActivityMethods) {
issues.push('Activity class has no methods marked with @ActivityMethod');
}
if (methodCount === 0) {
warnings.push('No activity methods found in class');
}
if (methodCount > 50) {
warnings.push('Class has many activity methods, consider splitting');
}
return {
isValid: issues.length === 0,
issues,
warnings: warnings.length > 0 ? warnings : undefined,
className,
methodCount,
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
issues.push(`Validation failed: ${errorMessage}`);
return {
isValid: false,
issues,
className: constructor.name || 'Unknown',
methodCount: 0,
};
}
}
hasActivityMethods(prototype) {
if (!prototype)
return false;
try {
const activityMethods = Reflect.getMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype);
if (activityMethods && typeof activityMethods === 'object') {
return Object.keys(activityMethods).length > 0;
}
const propertyNames = Object.getOwnPropertyNames(prototype);
return propertyNames.some((propertyName) => {
if (propertyName === 'constructor')
return false;
try {
return Reflect.hasMetadata(constants_1.TEMPORAL_ACTIVITY_METHOD, prototype, propertyName);
}
catch {
return false;
}
});
}
catch {
return false;
}
}
getAllMetadataKeys(target) {
try {
return Reflect.getMetadataKeys(target);
}
catch {
return [];
}
}
getActivityName(target) {
try {
const metadata = this.getActivityMetadata(target);
return metadata?.name || target.name || null;
}
catch {
return null;
}
}
getActivityInfo(target) {
try {
if (!target || typeof target !== 'function') {
return {
className: 'Unknown',
isActivity: false,
activityName: null,
methodNames: [],
metadata: null,
activityOptions: null,
methodCount: 0,
};
}
const className = target.name || 'Unknown';
const isActivity = this.isActivity(target);
const activityName = this.getActivityName(target);
const methodNames = this.getActivityMethodNames(target);
const metadata = this.getActivityMetadata(target);
const activityOptions = this.getActivityOptions(target);
return {
className,
isActivity,
activityName,
methodNames,
metadata,
activityOptions,
methodCount: methodNames.length,
};
}
catch {
return {
className: 'Unknown',
isActivity: false,
activityName: null,
methodNames: [],
metadata: null,
activityOptions: null,
methodCount: 0,
};
}
}
validateMetadata(target, expectedKeys) {
const missing = [];
const present = [];
const targetName = typeof target === 'function' ? target.name || 'Unknown' : 'Unknown';
for (const key of expectedKeys) {
try {
if (!Reflect.hasMetadata(key, target)) {
missing.push(key);
}
else {
present.push(key);
}
}
catch {
missing.push(key);
}
}
return {
isValid: missing.length === 0,
missing,
present,
target: targetName,
};
}
clearCache() {
this.activityMethodCache.clear();
}
getCacheStats() {
const entries = Array.from(this.activityMethodCache.keys()).map((k) => k.name || 'Unknown');
return {
size: this.activityMethodCache.size,
entries,
message: 'Cache statistics not available',
note: 'WeakMap-based caching prevents memory leaks but limits size reporting',
hitRate: 0,
missRate: 0,
};
}
};
exports.TemporalMetadataAccessor = TemporalMetadataAccessor;
exports.TemporalMetadataAccessor = TemporalMetadataAccessor = TemporalMetadataAccessor_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [])
], TemporalMetadataAccessor);
//# sourceMappingURL=temporal-metadata.service.js.map