@quanticjs/core 1.1.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/QuanticCoreModule.d.ts +4 -0
- package/dist/QuanticCoreModule.js +53 -0
- package/dist/cqrs/behaviors/LogBehavior.d.ts +4 -1
- package/dist/cqrs/behaviors/LogBehavior.js +3 -0
- package/dist/cqrs/behaviors/TransactionalBehavior.d.ts +4 -11
- package/dist/cqrs/behaviors/TransactionalBehavior.js +3 -12
- package/dist/cqrs/behaviors/ValidationBehavior.d.ts +4 -1
- package/dist/cqrs/behaviors/ValidationBehavior.js +3 -0
- package/dist/cqrs/pipeline/QuanticCommandBus.d.ts +3 -28
- package/dist/cqrs/pipeline/QuanticCommandBus.js +11 -59
- package/dist/cqrs/pipeline/QuanticQueryBus.d.ts +3 -19
- package/dist/cqrs/pipeline/QuanticQueryBus.js +11 -38
- package/dist/cqrs/pipeline/behavior-order.d.ts +11 -0
- package/dist/cqrs/pipeline/behavior-order.js +14 -0
- package/dist/cqrs/pipeline/types.d.ts +8 -0
- package/dist/cqrs/pipeline/types.js +4 -0
- package/dist/index.d.ts +6 -22
- package/dist/index.js +13 -44
- package/package.json +26 -80
- package/dist/cqrs/PipelineExecutor.d.ts +0 -31
- package/dist/cqrs/PipelineExecutor.js +0 -81
- package/dist/cqrs/behaviors/CacheBehavior.d.ts +0 -9
- package/dist/cqrs/behaviors/CacheBehavior.js +0 -68
- package/dist/cqrs/behaviors/DistributedLockBehavior.d.ts +0 -12
- package/dist/cqrs/behaviors/DistributedLockBehavior.js +0 -90
- package/dist/cqrs/behaviors/FeatureFlagBehavior.d.ts +0 -8
- package/dist/cqrs/behaviors/FeatureFlagBehavior.js +0 -58
- package/dist/cqrs/behaviors/InvalidateCacheBehavior.d.ts +0 -9
- package/dist/cqrs/behaviors/InvalidateCacheBehavior.js +0 -61
- package/dist/cqrs/behaviors/PerformanceBehavior.d.ts +0 -12
- package/dist/cqrs/behaviors/PerformanceBehavior.js +0 -56
- package/dist/cqrs/behaviors/WorkflowBehavior.d.ts +0 -8
- package/dist/cqrs/behaviors/WorkflowBehavior.js +0 -61
- package/dist/events/DomainEvent.d.ts +0 -14
- package/dist/events/DomainEvent.js +0 -27
- package/dist/events/OutboxEvent.entity.d.ts +0 -18
- package/dist/events/OutboxEvent.entity.js +0 -87
- package/dist/events/OutboxPublisherService.d.ts +0 -14
- package/dist/events/OutboxPublisherService.js +0 -104
- package/dist/events/RedisStreamConsumer.d.ts +0 -43
- package/dist/events/RedisStreamConsumer.js +0 -158
- package/dist/events/RedisStreamPublisher.d.ts +0 -9
- package/dist/events/RedisStreamPublisher.js +0 -60
- package/dist/metrics/MetricsController.d.ts +0 -7
- package/dist/metrics/MetricsController.js +0 -42
- package/dist/metrics/MetricsService.d.ts +0 -13
- package/dist/metrics/MetricsService.js +0 -58
- package/dist/redis/redis.module.d.ts +0 -8
- package/dist/redis/redis.module.js +0 -49
- package/dist/shared-kernel.module.d.ts +0 -13
- package/dist/shared-kernel.module.js +0 -87
- package/dist/testing/TestingModuleFactory.d.ts +0 -23
- package/dist/testing/TestingModuleFactory.js +0 -63
- package/dist/testing/index.d.ts +0 -2
- package/dist/testing/index.js +0 -7
- package/dist/unleash/initial-flags.d.ts +0 -7
- package/dist/unleash/initial-flags.js +0 -9
- package/dist/unleash/unleash.module.d.ts +0 -9
- package/dist/unleash/unleash.module.js +0 -47
- package/src/bootstrap/bootstrapService.ts +0 -72
- package/src/cqrs/behaviors/CacheBehavior.spec.ts +0 -63
- package/src/cqrs/behaviors/CacheBehavior.ts +0 -54
- package/src/cqrs/behaviors/DistributedLockBehavior.ts +0 -88
- package/src/cqrs/behaviors/FeatureFlagBehavior.ts +0 -46
- package/src/cqrs/behaviors/InvalidateCacheBehavior.spec.ts +0 -89
- package/src/cqrs/behaviors/InvalidateCacheBehavior.ts +0 -50
- package/src/cqrs/behaviors/LogBehavior.spec.ts +0 -55
- package/src/cqrs/behaviors/LogBehavior.ts +0 -121
- package/src/cqrs/behaviors/PerformanceBehavior.spec.ts +0 -48
- package/src/cqrs/behaviors/PerformanceBehavior.ts +0 -43
- package/src/cqrs/behaviors/TransactionalBehavior.ts +0 -64
- package/src/cqrs/behaviors/ValidationBehavior.spec.ts +0 -114
- package/src/cqrs/behaviors/ValidationBehavior.ts +0 -29
- package/src/cqrs/behaviors/WorkflowBehavior.spec.ts +0 -97
- package/src/cqrs/behaviors/WorkflowBehavior.ts +0 -62
- package/src/cqrs/constants.ts +0 -2
- package/src/cqrs/decorators/Cache.decorator.ts +0 -24
- package/src/cqrs/decorators/DistributedLock.decorator.ts +0 -34
- package/src/cqrs/decorators/FeatureFlag.decorator.ts +0 -23
- package/src/cqrs/decorators/InvalidateCache.decorator.spec.ts +0 -20
- package/src/cqrs/decorators/InvalidateCache.decorator.ts +0 -17
- package/src/cqrs/decorators/IsolatedTransaction.decorator.ts +0 -24
- package/src/cqrs/decorators/Log.decorator.ts +0 -22
- package/src/cqrs/decorators/Validate.decorator.ts +0 -39
- package/src/cqrs/decorators/Workflow.decorator.ts +0 -22
- package/src/cqrs/interfaces/WorkflowEngine.ts +0 -19
- package/src/cqrs/pipeline/QuanticCommandBus.ts +0 -69
- package/src/cqrs/pipeline/QuanticQueryBus.ts +0 -56
- package/src/cqrs/pipeline/runPipeline.ts +0 -22
- package/src/cqrs/transaction/TransactionContext.ts +0 -26
- package/src/cqrs/transaction/getTransactionalRepo.ts +0 -23
- package/src/cqrs/validation/ICommandValidator.ts +0 -55
- package/src/entities/BaseEntity.ts +0 -16
- package/src/entities/TenantBaseEntity.ts +0 -7
- package/src/events/DomainEvent.ts +0 -27
- package/src/events/OutboxEvent.entity.ts +0 -56
- package/src/events/OutboxPublisherService.ts +0 -94
- package/src/events/RedisStreamConsumer.ts +0 -172
- package/src/events/RedisStreamPublisher.ts +0 -54
- package/src/filters/GlobalExceptionFilter.ts +0 -125
- package/src/guards/JwtAuthGuard.ts +0 -29
- package/src/guards/JwtStrategy.ts +0 -41
- package/src/guards/RolesGuard.ts +0 -39
- package/src/index.ts +0 -118
- package/src/interceptors/ResultInterceptor.ts +0 -93
- package/src/lifecycle/GracefulShutdownService.ts +0 -77
- package/src/logging/pino-config.ts +0 -80
- package/src/metrics/MetricsController.ts +0 -17
- package/src/metrics/MetricsService.ts +0 -55
- package/src/middleware/CorrelationIdMiddleware.ts +0 -27
- package/src/middleware/CorrelationStore.ts +0 -13
- package/src/middleware/TenantContextMiddleware.ts +0 -21
- package/src/middleware/TenantStore.ts +0 -11
- package/src/redis/redis.module.ts +0 -41
- package/src/resilience/CircuitBreakerFactory.ts +0 -33
- package/src/result/Result.ts +0 -66
- package/src/shared-kernel.module.ts +0 -87
- package/src/subscribers/TenantSubscriber.ts +0 -47
- package/src/testing/TestingModuleFactory.ts +0 -78
- package/src/testing/index.ts +0 -2
- package/src/testing/mocks.ts +0 -59
- package/src/unleash/unleash.module.ts +0 -45
- package/tsconfig.json +0 -22
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.MetricsController = void 0;
|
|
16
|
-
const common_1 = require("@nestjs/common");
|
|
17
|
-
const JwtAuthGuard_1 = require("../guards/JwtAuthGuard");
|
|
18
|
-
const MetricsService_1 = require("./MetricsService");
|
|
19
|
-
let MetricsController = class MetricsController {
|
|
20
|
-
metrics;
|
|
21
|
-
constructor(metrics) {
|
|
22
|
-
this.metrics = metrics;
|
|
23
|
-
}
|
|
24
|
-
async getMetrics(res) {
|
|
25
|
-
const metricsOutput = await this.metrics.getMetrics();
|
|
26
|
-
res.set('Content-Type', this.metrics.getContentType());
|
|
27
|
-
res.end(metricsOutput);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
exports.MetricsController = MetricsController;
|
|
31
|
-
__decorate([
|
|
32
|
-
(0, common_1.Get)('metrics'),
|
|
33
|
-
__param(0, (0, common_1.Res)()),
|
|
34
|
-
__metadata("design:type", Function),
|
|
35
|
-
__metadata("design:paramtypes", [Object]),
|
|
36
|
-
__metadata("design:returntype", Promise)
|
|
37
|
-
], MetricsController.prototype, "getMetrics", null);
|
|
38
|
-
exports.MetricsController = MetricsController = __decorate([
|
|
39
|
-
(0, JwtAuthGuard_1.Public)(),
|
|
40
|
-
(0, common_1.Controller)(),
|
|
41
|
-
__metadata("design:paramtypes", [MetricsService_1.MetricsService])
|
|
42
|
-
], MetricsController);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
-
import { Registry, Counter, Histogram, Gauge } from 'prom-client';
|
|
3
|
-
export declare class MetricsService implements OnModuleInit {
|
|
4
|
-
readonly registry: Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
5
|
-
readonly buildTotal: Counter<"status" | "tech_stack">;
|
|
6
|
-
readonly stageDuration: Histogram<"status" | "stage_type">;
|
|
7
|
-
readonly promptCacheHits: Counter<string>;
|
|
8
|
-
readonly queueDepth: Gauge<"queue">;
|
|
9
|
-
readonly handlerDuration: Histogram<"handler" | "result">;
|
|
10
|
-
onModuleInit(): void;
|
|
11
|
-
getMetrics(): Promise<string>;
|
|
12
|
-
getContentType(): string;
|
|
13
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.MetricsService = void 0;
|
|
10
|
-
const common_1 = require("@nestjs/common");
|
|
11
|
-
const prom_client_1 = require("prom-client");
|
|
12
|
-
let MetricsService = class MetricsService {
|
|
13
|
-
registry = new prom_client_1.Registry();
|
|
14
|
-
buildTotal = new prom_client_1.Counter({
|
|
15
|
-
name: 'arex_build_total',
|
|
16
|
-
help: 'Total number of builds',
|
|
17
|
-
labelNames: ['status', 'tech_stack'],
|
|
18
|
-
registers: [this.registry],
|
|
19
|
-
});
|
|
20
|
-
stageDuration = new prom_client_1.Histogram({
|
|
21
|
-
name: 'arex_stage_duration_seconds',
|
|
22
|
-
help: 'Duration of pipeline stages in seconds',
|
|
23
|
-
labelNames: ['stage_type', 'status'],
|
|
24
|
-
buckets: [0.5, 1, 2, 5, 10, 30, 60, 120, 300],
|
|
25
|
-
registers: [this.registry],
|
|
26
|
-
});
|
|
27
|
-
promptCacheHits = new prom_client_1.Counter({
|
|
28
|
-
name: 'arex_prompt_cache_hits_total',
|
|
29
|
-
help: 'Total prompt cache hits',
|
|
30
|
-
registers: [this.registry],
|
|
31
|
-
});
|
|
32
|
-
queueDepth = new prom_client_1.Gauge({
|
|
33
|
-
name: 'arex_queue_depth',
|
|
34
|
-
help: 'Current depth of Bull job queue',
|
|
35
|
-
labelNames: ['queue'],
|
|
36
|
-
registers: [this.registry],
|
|
37
|
-
});
|
|
38
|
-
handlerDuration = new prom_client_1.Histogram({
|
|
39
|
-
name: 'arex_handler_duration_seconds',
|
|
40
|
-
help: 'Duration of command/query handlers in seconds',
|
|
41
|
-
labelNames: ['handler', 'result'],
|
|
42
|
-
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5],
|
|
43
|
-
registers: [this.registry],
|
|
44
|
-
});
|
|
45
|
-
onModuleInit() {
|
|
46
|
-
(0, prom_client_1.collectDefaultMetrics)({ register: this.registry });
|
|
47
|
-
}
|
|
48
|
-
async getMetrics() {
|
|
49
|
-
return this.registry.metrics();
|
|
50
|
-
}
|
|
51
|
-
getContentType() {
|
|
52
|
-
return this.registry.contentType;
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
exports.MetricsService = MetricsService;
|
|
56
|
-
exports.MetricsService = MetricsService = __decorate([
|
|
57
|
-
(0, common_1.Injectable)()
|
|
58
|
-
], MetricsService);
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
var RedisModule_1;
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.RedisModule = void 0;
|
|
14
|
-
const common_1 = require("@nestjs/common");
|
|
15
|
-
const ioredis_1 = __importDefault(require("ioredis"));
|
|
16
|
-
const constants_1 = require("../cqrs/constants");
|
|
17
|
-
let RedisModule = class RedisModule {
|
|
18
|
-
static { RedisModule_1 = this; }
|
|
19
|
-
static logger = new common_1.Logger('RedisModule');
|
|
20
|
-
static forRoot(options = {}) {
|
|
21
|
-
const redisProvider = {
|
|
22
|
-
provide: constants_1.REDIS_CLIENT,
|
|
23
|
-
useFactory: () => {
|
|
24
|
-
const url = options.url || process.env.REDIS_URL || 'redis://localhost:6379';
|
|
25
|
-
const client = new ioredis_1.default(url, {
|
|
26
|
-
maxRetriesPerRequest: 3,
|
|
27
|
-
retryStrategy(times) {
|
|
28
|
-
const delay = Math.min(times * 200, 5000);
|
|
29
|
-
RedisModule_1.logger.warn(`Redis reconnecting (attempt ${times}, delay ${delay}ms)`);
|
|
30
|
-
return delay;
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
client.on('connect', () => RedisModule_1.logger.log('Redis connected'));
|
|
34
|
-
client.on('error', (err) => RedisModule_1.logger.error('Redis error', err.message));
|
|
35
|
-
return client;
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
return {
|
|
39
|
-
module: RedisModule_1,
|
|
40
|
-
providers: [redisProvider],
|
|
41
|
-
exports: [constants_1.REDIS_CLIENT],
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
exports.RedisModule = RedisModule;
|
|
46
|
-
exports.RedisModule = RedisModule = RedisModule_1 = __decorate([
|
|
47
|
-
(0, common_1.Global)(),
|
|
48
|
-
(0, common_1.Module)({})
|
|
49
|
-
], RedisModule);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { type RedisModuleOptions } from './redis/redis.module';
|
|
3
|
-
import { type UnleashModuleOptions } from './unleash/unleash.module';
|
|
4
|
-
export type SharedKernelModuleOptions = QuanticModuleOptions;
|
|
5
|
-
export interface QuanticModuleOptions {
|
|
6
|
-
redis?: RedisModuleOptions;
|
|
7
|
-
unleash?: UnleashModuleOptions | false;
|
|
8
|
-
}
|
|
9
|
-
export declare class QuanticModule {
|
|
10
|
-
static forRoot(options?: QuanticModuleOptions): DynamicModule;
|
|
11
|
-
}
|
|
12
|
-
/** @deprecated Use QuanticModule instead */
|
|
13
|
-
export declare const SharedKernelModule: typeof QuanticModule;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var QuanticModule_1;
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.SharedKernelModule = exports.QuanticModule = void 0;
|
|
11
|
-
const common_1 = require("@nestjs/common");
|
|
12
|
-
const cqrs_1 = require("@nestjs/cqrs");
|
|
13
|
-
const QuanticCommandBus_1 = require("./cqrs/pipeline/QuanticCommandBus");
|
|
14
|
-
const QuanticQueryBus_1 = require("./cqrs/pipeline/QuanticQueryBus");
|
|
15
|
-
const LogBehavior_1 = require("./cqrs/behaviors/LogBehavior");
|
|
16
|
-
const ValidationBehavior_1 = require("./cqrs/behaviors/ValidationBehavior");
|
|
17
|
-
const CacheBehavior_1 = require("./cqrs/behaviors/CacheBehavior");
|
|
18
|
-
const DistributedLockBehavior_1 = require("./cqrs/behaviors/DistributedLockBehavior");
|
|
19
|
-
const TransactionalBehavior_1 = require("./cqrs/behaviors/TransactionalBehavior");
|
|
20
|
-
const PerformanceBehavior_1 = require("./cqrs/behaviors/PerformanceBehavior");
|
|
21
|
-
const WorkflowBehavior_1 = require("./cqrs/behaviors/WorkflowBehavior");
|
|
22
|
-
const InvalidateCacheBehavior_1 = require("./cqrs/behaviors/InvalidateCacheBehavior");
|
|
23
|
-
const MetricsService_1 = require("./metrics/MetricsService");
|
|
24
|
-
const MetricsController_1 = require("./metrics/MetricsController");
|
|
25
|
-
const GracefulShutdownService_1 = require("./lifecycle/GracefulShutdownService");
|
|
26
|
-
const RedisStreamPublisher_1 = require("./events/RedisStreamPublisher");
|
|
27
|
-
const redis_module_1 = require("./redis/redis.module");
|
|
28
|
-
const unleash_module_1 = require("./unleash/unleash.module");
|
|
29
|
-
let QuanticModule = QuanticModule_1 = class QuanticModule {
|
|
30
|
-
static forRoot(options = {}) {
|
|
31
|
-
const imports = [
|
|
32
|
-
cqrs_1.CqrsModule.forRoot(),
|
|
33
|
-
redis_module_1.RedisModule.forRoot(options.redis),
|
|
34
|
-
];
|
|
35
|
-
if (options.unleash !== false) {
|
|
36
|
-
imports.push(unleash_module_1.UnleashModule.forRoot(options.unleash));
|
|
37
|
-
}
|
|
38
|
-
const exports = [
|
|
39
|
-
cqrs_1.CqrsModule,
|
|
40
|
-
redis_module_1.RedisModule,
|
|
41
|
-
RedisStreamPublisher_1.RedisStreamPublisher,
|
|
42
|
-
LogBehavior_1.LogBehavior,
|
|
43
|
-
ValidationBehavior_1.ValidationBehavior,
|
|
44
|
-
CacheBehavior_1.CacheBehavior,
|
|
45
|
-
InvalidateCacheBehavior_1.InvalidateCacheBehavior,
|
|
46
|
-
DistributedLockBehavior_1.DistributedLockBehavior,
|
|
47
|
-
TransactionalBehavior_1.TransactionalBehavior,
|
|
48
|
-
PerformanceBehavior_1.PerformanceBehavior,
|
|
49
|
-
WorkflowBehavior_1.WorkflowBehavior,
|
|
50
|
-
MetricsService_1.MetricsService,
|
|
51
|
-
GracefulShutdownService_1.GracefulShutdownService,
|
|
52
|
-
QuanticCommandBus_1.QuanticCommandBus,
|
|
53
|
-
QuanticQueryBus_1.QuanticQueryBus,
|
|
54
|
-
];
|
|
55
|
-
if (options.unleash !== false) {
|
|
56
|
-
exports.push(unleash_module_1.UnleashModule);
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
module: QuanticModule_1,
|
|
60
|
-
imports,
|
|
61
|
-
controllers: [MetricsController_1.MetricsController],
|
|
62
|
-
providers: [
|
|
63
|
-
LogBehavior_1.LogBehavior,
|
|
64
|
-
ValidationBehavior_1.ValidationBehavior,
|
|
65
|
-
CacheBehavior_1.CacheBehavior,
|
|
66
|
-
InvalidateCacheBehavior_1.InvalidateCacheBehavior,
|
|
67
|
-
DistributedLockBehavior_1.DistributedLockBehavior,
|
|
68
|
-
TransactionalBehavior_1.TransactionalBehavior,
|
|
69
|
-
PerformanceBehavior_1.PerformanceBehavior,
|
|
70
|
-
WorkflowBehavior_1.WorkflowBehavior,
|
|
71
|
-
MetricsService_1.MetricsService,
|
|
72
|
-
GracefulShutdownService_1.GracefulShutdownService,
|
|
73
|
-
RedisStreamPublisher_1.RedisStreamPublisher,
|
|
74
|
-
QuanticCommandBus_1.QuanticCommandBus,
|
|
75
|
-
QuanticQueryBus_1.QuanticQueryBus,
|
|
76
|
-
],
|
|
77
|
-
exports,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
exports.QuanticModule = QuanticModule;
|
|
82
|
-
exports.QuanticModule = QuanticModule = QuanticModule_1 = __decorate([
|
|
83
|
-
(0, common_1.Global)(),
|
|
84
|
-
(0, common_1.Module)({})
|
|
85
|
-
], QuanticModule);
|
|
86
|
-
/** @deprecated Use QuanticModule instead */
|
|
87
|
-
exports.SharedKernelModule = QuanticModule;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { TestingModuleBuilder } from '@nestjs/testing';
|
|
2
|
-
import { createMockRepository, createMockRedisClient } from './mocks';
|
|
3
|
-
export { createMockRepository, createMockRedisClient };
|
|
4
|
-
export interface TestingModuleOptions {
|
|
5
|
-
/** Providers to register (handlers, services, etc.) */
|
|
6
|
-
providers?: any[];
|
|
7
|
-
/** Entity classes to auto-mock their repositories */
|
|
8
|
-
entities?: any[];
|
|
9
|
-
/** Additional overrides to apply to the TestingModule builder */
|
|
10
|
-
overrides?: Array<{
|
|
11
|
-
provide: any;
|
|
12
|
-
useValue: any;
|
|
13
|
-
}>;
|
|
14
|
-
/** Whether to include the full CQRS pipeline behaviors (default: false) */
|
|
15
|
-
withPipeline?: boolean;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Factory for bootstrapping a NestJS TestingModule preconfigured
|
|
19
|
-
* with mocked repositories, Redis, and optionally the CQRS pipeline.
|
|
20
|
-
*/
|
|
21
|
-
export declare class TestingModuleFactory {
|
|
22
|
-
static create(options?: TestingModuleOptions): TestingModuleBuilder;
|
|
23
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TestingModuleFactory = exports.createMockRedisClient = exports.createMockRepository = void 0;
|
|
4
|
-
const testing_1 = require("@nestjs/testing");
|
|
5
|
-
const cqrs_1 = require("@nestjs/cqrs");
|
|
6
|
-
const typeorm_1 = require("@nestjs/typeorm");
|
|
7
|
-
const common_1 = require("@nestjs/common");
|
|
8
|
-
const QuanticCommandBus_1 = require("../cqrs/pipeline/QuanticCommandBus");
|
|
9
|
-
const QuanticQueryBus_1 = require("../cqrs/pipeline/QuanticQueryBus");
|
|
10
|
-
const LogBehavior_1 = require("../cqrs/behaviors/LogBehavior");
|
|
11
|
-
const ValidationBehavior_1 = require("../cqrs/behaviors/ValidationBehavior");
|
|
12
|
-
const CacheBehavior_1 = require("../cqrs/behaviors/CacheBehavior");
|
|
13
|
-
const DistributedLockBehavior_1 = require("../cqrs/behaviors/DistributedLockBehavior");
|
|
14
|
-
const TransactionalBehavior_1 = require("../cqrs/behaviors/TransactionalBehavior");
|
|
15
|
-
const PerformanceBehavior_1 = require("../cqrs/behaviors/PerformanceBehavior");
|
|
16
|
-
const MetricsService_1 = require("../metrics/MetricsService");
|
|
17
|
-
const constants_1 = require("../cqrs/constants");
|
|
18
|
-
const mocks_1 = require("./mocks");
|
|
19
|
-
Object.defineProperty(exports, "createMockRepository", { enumerable: true, get: function () { return mocks_1.createMockRepository; } });
|
|
20
|
-
Object.defineProperty(exports, "createMockRedisClient", { enumerable: true, get: function () { return mocks_1.createMockRedisClient; } });
|
|
21
|
-
/**
|
|
22
|
-
* Factory for bootstrapping a NestJS TestingModule preconfigured
|
|
23
|
-
* with mocked repositories, Redis, and optionally the CQRS pipeline.
|
|
24
|
-
*/
|
|
25
|
-
class TestingModuleFactory {
|
|
26
|
-
static create(options = {}) {
|
|
27
|
-
const { providers = [], entities = [], overrides = [], withPipeline = false } = options;
|
|
28
|
-
const mockRepos = entities.map((entity) => ({
|
|
29
|
-
provide: (0, typeorm_1.getRepositoryToken)(entity),
|
|
30
|
-
useValue: (0, mocks_1.createMockRepository)(),
|
|
31
|
-
}));
|
|
32
|
-
const mockRedis = { provide: constants_1.REDIS_CLIENT, useValue: (0, mocks_1.createMockRedisClient)() };
|
|
33
|
-
const pipelineProviders = withPipeline
|
|
34
|
-
? [
|
|
35
|
-
LogBehavior_1.LogBehavior,
|
|
36
|
-
ValidationBehavior_1.ValidationBehavior,
|
|
37
|
-
CacheBehavior_1.CacheBehavior,
|
|
38
|
-
DistributedLockBehavior_1.DistributedLockBehavior,
|
|
39
|
-
TransactionalBehavior_1.TransactionalBehavior,
|
|
40
|
-
PerformanceBehavior_1.PerformanceBehavior,
|
|
41
|
-
MetricsService_1.MetricsService,
|
|
42
|
-
QuanticCommandBus_1.QuanticCommandBus,
|
|
43
|
-
QuanticQueryBus_1.QuanticQueryBus,
|
|
44
|
-
]
|
|
45
|
-
: [];
|
|
46
|
-
let builder = testing_1.Test.createTestingModule({
|
|
47
|
-
imports: [cqrs_1.CqrsModule.forRoot()],
|
|
48
|
-
providers: [
|
|
49
|
-
...mockRepos,
|
|
50
|
-
mockRedis,
|
|
51
|
-
...pipelineProviders,
|
|
52
|
-
...providers,
|
|
53
|
-
],
|
|
54
|
-
});
|
|
55
|
-
for (const override of overrides) {
|
|
56
|
-
builder = builder.overrideProvider(override.provide).useValue(override.useValue);
|
|
57
|
-
}
|
|
58
|
-
// Silence NestJS logs during tests
|
|
59
|
-
common_1.Logger.overrideLogger(['error']);
|
|
60
|
-
return builder;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
exports.TestingModuleFactory = TestingModuleFactory;
|
package/dist/testing/index.d.ts
DELETED
package/dist/testing/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createMockRedisClient = exports.createMockRepository = exports.TestingModuleFactory = void 0;
|
|
4
|
-
var TestingModuleFactory_1 = require("./TestingModuleFactory");
|
|
5
|
-
Object.defineProperty(exports, "TestingModuleFactory", { enumerable: true, get: function () { return TestingModuleFactory_1.TestingModuleFactory; } });
|
|
6
|
-
Object.defineProperty(exports, "createMockRepository", { enumerable: true, get: function () { return TestingModuleFactory_1.createMockRepository; } });
|
|
7
|
-
Object.defineProperty(exports, "createMockRedisClient", { enumerable: true, get: function () { return TestingModuleFactory_1.createMockRedisClient; } });
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const FEATURE_FLAGS: {
|
|
2
|
-
readonly ENABLE_PREMIUM_MODE: "enable-premium-mode";
|
|
3
|
-
readonly ENABLE_AGENCY_PLAN: "enable-agency-plan";
|
|
4
|
-
readonly ENABLE_BACKLOG_GENERATION: "enable-backlog-generation";
|
|
5
|
-
};
|
|
6
|
-
export type FeatureFlagName = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS];
|
|
7
|
-
//# sourceMappingURL=initial-flags.d.ts.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FEATURE_FLAGS = void 0;
|
|
4
|
-
exports.FEATURE_FLAGS = {
|
|
5
|
-
ENABLE_PREMIUM_MODE: 'enable-premium-mode',
|
|
6
|
-
ENABLE_AGENCY_PLAN: 'enable-agency-plan',
|
|
7
|
-
ENABLE_BACKLOG_GENERATION: 'enable-backlog-generation',
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=initial-flags.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { DynamicModule } from '@nestjs/common';
|
|
2
|
-
export interface UnleashModuleOptions {
|
|
3
|
-
url?: string;
|
|
4
|
-
appName?: string;
|
|
5
|
-
customHeaders?: Record<string, string>;
|
|
6
|
-
}
|
|
7
|
-
export declare class UnleashModule {
|
|
8
|
-
static forRoot(options?: UnleashModuleOptions): DynamicModule;
|
|
9
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var UnleashModule_1;
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.UnleashModule = void 0;
|
|
11
|
-
const common_1 = require("@nestjs/common");
|
|
12
|
-
const unleash_client_1 = require("unleash-client");
|
|
13
|
-
const FeatureFlagBehavior_1 = require("../cqrs/behaviors/FeatureFlagBehavior");
|
|
14
|
-
let UnleashModule = UnleashModule_1 = class UnleashModule {
|
|
15
|
-
static forRoot(options) {
|
|
16
|
-
const unleashProvider = {
|
|
17
|
-
provide: unleash_client_1.Unleash,
|
|
18
|
-
useFactory: () => {
|
|
19
|
-
const logger = new common_1.Logger('UnleashModule');
|
|
20
|
-
const url = options?.url || process.env['UNLEASH_URL'] || 'http://localhost:4242/api';
|
|
21
|
-
const appName = options?.appName || process.env['UNLEASH_APP_NAME'] || 'arex';
|
|
22
|
-
const token = options?.customHeaders?.['Authorization'] ||
|
|
23
|
-
process.env['UNLEASH_API_TOKEN'] ||
|
|
24
|
-
'*:*.unleash-insecure-api-token';
|
|
25
|
-
logger.log(`Connecting to Unleash at ${url}`);
|
|
26
|
-
return (0, unleash_client_1.initialize)({
|
|
27
|
-
url,
|
|
28
|
-
appName,
|
|
29
|
-
customHeaders: {
|
|
30
|
-
Authorization: token,
|
|
31
|
-
},
|
|
32
|
-
refreshInterval: 10000,
|
|
33
|
-
});
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
module: UnleashModule_1,
|
|
38
|
-
providers: [unleashProvider, FeatureFlagBehavior_1.FeatureFlagBehavior],
|
|
39
|
-
exports: [unleash_client_1.Unleash, FeatureFlagBehavior_1.FeatureFlagBehavior],
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
exports.UnleashModule = UnleashModule;
|
|
44
|
-
exports.UnleashModule = UnleashModule = UnleashModule_1 = __decorate([
|
|
45
|
-
(0, common_1.Global)(),
|
|
46
|
-
(0, common_1.Module)({})
|
|
47
|
-
], UnleashModule);
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
|
2
|
-
import { NestFactory } from '@nestjs/core';
|
|
3
|
-
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
4
|
-
import { Logger } from 'nestjs-pino';
|
|
5
|
-
import helmet from 'helmet';
|
|
6
|
-
import cookieParser from 'cookie-parser';
|
|
7
|
-
import { GlobalExceptionFilter } from '../filters/GlobalExceptionFilter';
|
|
8
|
-
|
|
9
|
-
export interface BootstrapOptions {
|
|
10
|
-
module: any;
|
|
11
|
-
port: number;
|
|
12
|
-
serviceName: string;
|
|
13
|
-
rawBody?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export async function bootstrapService(options: BootstrapOptions): Promise<INestApplication> {
|
|
17
|
-
const { module, port, serviceName, rawBody } = options;
|
|
18
|
-
|
|
19
|
-
const app = await NestFactory.create(module, {
|
|
20
|
-
bufferLogs: true,
|
|
21
|
-
...(rawBody ? { rawBody: true } : {}),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
app.useLogger(app.get(Logger));
|
|
25
|
-
|
|
26
|
-
// Security headers
|
|
27
|
-
app.use(helmet());
|
|
28
|
-
|
|
29
|
-
// Cookie parsing (required for OAuth flows)
|
|
30
|
-
app.use(cookieParser());
|
|
31
|
-
|
|
32
|
-
// CORS
|
|
33
|
-
const allowedOrigins = (process.env.CORS_ORIGINS || 'http://localhost:5173').split(',');
|
|
34
|
-
app.enableCors({
|
|
35
|
-
origin: allowedOrigins,
|
|
36
|
-
credentials: true,
|
|
37
|
-
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
38
|
-
allowedHeaders: ['Content-Type', 'Authorization', 'X-Tenant-ID', 'X-Correlation-ID'],
|
|
39
|
-
exposedHeaders: ['X-Correlation-ID'],
|
|
40
|
-
maxAge: 86400,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Global exception filter
|
|
44
|
-
app.useGlobalFilters(new GlobalExceptionFilter());
|
|
45
|
-
|
|
46
|
-
// Global validation pipe
|
|
47
|
-
app.useGlobalPipes(
|
|
48
|
-
new ValidationPipe({
|
|
49
|
-
whitelist: true,
|
|
50
|
-
forbidNonWhitelisted: true,
|
|
51
|
-
transform: true,
|
|
52
|
-
}),
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Swagger — disabled in production
|
|
56
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
57
|
-
const config = new DocumentBuilder()
|
|
58
|
-
.setTitle(`AREX — ${serviceName}`)
|
|
59
|
-
.setDescription(`OpenAPI spec for ${serviceName}`)
|
|
60
|
-
.setVersion('1.0.0')
|
|
61
|
-
.addBearerAuth()
|
|
62
|
-
.build();
|
|
63
|
-
const document = SwaggerModule.createDocument(app, config);
|
|
64
|
-
SwaggerModule.setup('swagger', app, document);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Enable graceful shutdown hooks (SIGTERM, SIGINT)
|
|
68
|
-
app.enableShutdownHooks();
|
|
69
|
-
|
|
70
|
-
await app.listen(port);
|
|
71
|
-
return app;
|
|
72
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { CacheBehavior } from './CacheBehavior';
|
|
2
|
-
import { Result } from '../../result/Result';
|
|
3
|
-
import { Cache } from '../decorators/Cache.decorator';
|
|
4
|
-
|
|
5
|
-
@Cache('test:{id}', { ttlSeconds: 60 })
|
|
6
|
-
class CachedQuery {
|
|
7
|
-
constructor(public readonly id: string) {}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
class UncachedQuery {
|
|
11
|
-
constructor(public readonly id: string) {}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
describe('CacheBehavior', () => {
|
|
15
|
-
let redis: { get: jest.Mock; set: jest.Mock };
|
|
16
|
-
let behavior: CacheBehavior;
|
|
17
|
-
const next = jest.fn();
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
redis = {
|
|
21
|
-
get: jest.fn().mockResolvedValue(null),
|
|
22
|
-
set: jest.fn().mockResolvedValue('OK'),
|
|
23
|
-
};
|
|
24
|
-
behavior = new CacheBehavior(redis as any);
|
|
25
|
-
next.mockReset().mockResolvedValue(Result.success({ data: 'fresh' }));
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should skip cache for commands without @Cache decorator', async () => {
|
|
29
|
-
const result = await behavior.execute(new UncachedQuery('1'), next);
|
|
30
|
-
|
|
31
|
-
expect(result.isSuccess).toBe(true);
|
|
32
|
-
expect(redis.get).not.toHaveBeenCalled();
|
|
33
|
-
expect(next).toHaveBeenCalledTimes(1);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should return cached value on cache hit', async () => {
|
|
37
|
-
redis.get.mockResolvedValue(JSON.stringify({ data: 'cached' }));
|
|
38
|
-
|
|
39
|
-
const result = await behavior.execute(new CachedQuery('abc'), next);
|
|
40
|
-
|
|
41
|
-
expect(result.isSuccess).toBe(true);
|
|
42
|
-
expect(result.value).toEqual({ data: 'cached' });
|
|
43
|
-
expect(next).not.toHaveBeenCalled();
|
|
44
|
-
expect(redis.get).toHaveBeenCalledWith('test:abc');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should call handler and cache result on cache miss', async () => {
|
|
48
|
-
const result = await behavior.execute(new CachedQuery('abc'), next);
|
|
49
|
-
|
|
50
|
-
expect(result.isSuccess).toBe(true);
|
|
51
|
-
expect(result.value).toEqual({ data: 'fresh' });
|
|
52
|
-
expect(next).toHaveBeenCalledTimes(1);
|
|
53
|
-
expect(redis.set).toHaveBeenCalledWith('test:abc', JSON.stringify({ data: 'fresh' }), 'EX', 60);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should skip cache when redis is not available', async () => {
|
|
57
|
-
const noCacheBehavior = new CacheBehavior(undefined);
|
|
58
|
-
const result = await noCacheBehavior.execute(new CachedQuery('1'), next);
|
|
59
|
-
|
|
60
|
-
expect(result.isSuccess).toBe(true);
|
|
61
|
-
expect(next).toHaveBeenCalledTimes(1);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Injectable, Logger, Optional, Inject } from '@nestjs/common';
|
|
2
|
-
import { getCacheMetadata } from '../decorators/Cache.decorator';
|
|
3
|
-
import { Result } from '../../result/Result';
|
|
4
|
-
import { REDIS_CLIENT } from '../constants';
|
|
5
|
-
import type { Redis } from 'ioredis';
|
|
6
|
-
|
|
7
|
-
@Injectable()
|
|
8
|
-
export class CacheBehavior {
|
|
9
|
-
private readonly logger = new Logger(CacheBehavior.name);
|
|
10
|
-
|
|
11
|
-
constructor(
|
|
12
|
-
@Optional() @Inject(REDIS_CLIENT) private readonly redis?: Redis,
|
|
13
|
-
) {}
|
|
14
|
-
|
|
15
|
-
async execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>> {
|
|
16
|
-
const metadata = getCacheMetadata(command.constructor);
|
|
17
|
-
|
|
18
|
-
if (!metadata || !this.redis) {
|
|
19
|
-
return next();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const cacheKey = this.interpolateKey(metadata.key, command);
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const cached = await this.redis.get(cacheKey);
|
|
26
|
-
if (cached) {
|
|
27
|
-
this.logger.debug(`Cache hit: ${cacheKey}`);
|
|
28
|
-
return Result.success(JSON.parse(cached) as T);
|
|
29
|
-
}
|
|
30
|
-
} catch {
|
|
31
|
-
this.logger.warn(`Cache read failed for key: ${cacheKey}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const result = await next();
|
|
35
|
-
|
|
36
|
-
if (result.isSuccess && result.value !== undefined) {
|
|
37
|
-
try {
|
|
38
|
-
await this.redis.set(cacheKey, JSON.stringify(result.value), 'EX', metadata.ttlSeconds!);
|
|
39
|
-
this.logger.debug(`Cache set: ${cacheKey} (TTL: ${metadata.ttlSeconds}s)`);
|
|
40
|
-
} catch {
|
|
41
|
-
this.logger.warn(`Cache write failed for key: ${cacheKey}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private interpolateKey(template: string, command: object): string {
|
|
49
|
-
return template.replace(/\{(\w+)\}/g, (_, prop) => {
|
|
50
|
-
const value = (command as Record<string, unknown>)[prop];
|
|
51
|
-
return value != null ? String(value) : '';
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|