@quanticjs/core 1.1.1

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.
Files changed (181) hide show
  1. package/dist/bootstrap/bootstrapService.d.ts +8 -0
  2. package/dist/bootstrap/bootstrapService.js +58 -0
  3. package/dist/cqrs/PipelineExecutor.d.ts +31 -0
  4. package/dist/cqrs/PipelineExecutor.js +81 -0
  5. package/dist/cqrs/behaviors/CacheBehavior.d.ts +9 -0
  6. package/dist/cqrs/behaviors/CacheBehavior.js +68 -0
  7. package/dist/cqrs/behaviors/DistributedLockBehavior.d.ts +12 -0
  8. package/dist/cqrs/behaviors/DistributedLockBehavior.js +90 -0
  9. package/dist/cqrs/behaviors/FeatureFlagBehavior.d.ts +8 -0
  10. package/dist/cqrs/behaviors/FeatureFlagBehavior.js +58 -0
  11. package/dist/cqrs/behaviors/InvalidateCacheBehavior.d.ts +9 -0
  12. package/dist/cqrs/behaviors/InvalidateCacheBehavior.js +61 -0
  13. package/dist/cqrs/behaviors/LogBehavior.d.ts +9 -0
  14. package/dist/cqrs/behaviors/LogBehavior.js +125 -0
  15. package/dist/cqrs/behaviors/PerformanceBehavior.d.ts +12 -0
  16. package/dist/cqrs/behaviors/PerformanceBehavior.js +56 -0
  17. package/dist/cqrs/behaviors/TransactionalBehavior.d.ts +18 -0
  18. package/dist/cqrs/behaviors/TransactionalBehavior.js +77 -0
  19. package/dist/cqrs/behaviors/ValidationBehavior.d.ts +4 -0
  20. package/dist/cqrs/behaviors/ValidationBehavior.js +33 -0
  21. package/dist/cqrs/behaviors/WorkflowBehavior.d.ts +8 -0
  22. package/dist/cqrs/behaviors/WorkflowBehavior.js +61 -0
  23. package/dist/cqrs/constants.d.ts +2 -0
  24. package/dist/cqrs/constants.js +5 -0
  25. package/dist/cqrs/decorators/Cache.decorator.d.ts +13 -0
  26. package/dist/cqrs/decorators/Cache.decorator.js +18 -0
  27. package/dist/cqrs/decorators/DistributedLock.decorator.d.ts +15 -0
  28. package/dist/cqrs/decorators/DistributedLock.decorator.js +23 -0
  29. package/dist/cqrs/decorators/FeatureFlag.decorator.d.ts +9 -0
  30. package/dist/cqrs/decorators/FeatureFlag.decorator.js +14 -0
  31. package/dist/cqrs/decorators/InvalidateCache.decorator.d.ts +6 -0
  32. package/dist/cqrs/decorators/InvalidateCache.decorator.js +14 -0
  33. package/dist/cqrs/decorators/IsolatedTransaction.decorator.d.ts +14 -0
  34. package/dist/cqrs/decorators/IsolatedTransaction.decorator.js +25 -0
  35. package/dist/cqrs/decorators/Log.decorator.d.ts +11 -0
  36. package/dist/cqrs/decorators/Log.decorator.js +18 -0
  37. package/dist/cqrs/decorators/Validate.decorator.d.ts +24 -0
  38. package/dist/cqrs/decorators/Validate.decorator.js +37 -0
  39. package/dist/cqrs/decorators/Workflow.decorator.d.ts +8 -0
  40. package/dist/cqrs/decorators/Workflow.decorator.js +14 -0
  41. package/dist/cqrs/interfaces/WorkflowEngine.d.ts +14 -0
  42. package/dist/cqrs/interfaces/WorkflowEngine.js +4 -0
  43. package/dist/cqrs/pipeline/QuanticCommandBus.d.ts +37 -0
  44. package/dist/cqrs/pipeline/QuanticCommandBus.js +99 -0
  45. package/dist/cqrs/pipeline/QuanticQueryBus.d.ts +28 -0
  46. package/dist/cqrs/pipeline/QuanticQueryBus.js +78 -0
  47. package/dist/cqrs/pipeline/runPipeline.d.ts +3 -0
  48. package/dist/cqrs/pipeline/runPipeline.js +12 -0
  49. package/dist/cqrs/transaction/TransactionContext.d.ts +18 -0
  50. package/dist/cqrs/transaction/TransactionContext.js +26 -0
  51. package/dist/cqrs/transaction/getTransactionalRepo.d.ts +16 -0
  52. package/dist/cqrs/transaction/getTransactionalRepo.js +22 -0
  53. package/dist/cqrs/validation/ICommandValidator.d.ts +48 -0
  54. package/dist/cqrs/validation/ICommandValidator.js +21 -0
  55. package/dist/entities/BaseEntity.d.ts +5 -0
  56. package/dist/entities/BaseEntity.js +31 -0
  57. package/dist/entities/TenantBaseEntity.d.ts +4 -0
  58. package/dist/entities/TenantBaseEntity.js +22 -0
  59. package/dist/events/DomainEvent.d.ts +14 -0
  60. package/dist/events/DomainEvent.js +27 -0
  61. package/dist/events/OutboxEvent.entity.d.ts +18 -0
  62. package/dist/events/OutboxEvent.entity.js +87 -0
  63. package/dist/events/OutboxPublisherService.d.ts +14 -0
  64. package/dist/events/OutboxPublisherService.js +104 -0
  65. package/dist/events/RedisStreamConsumer.d.ts +43 -0
  66. package/dist/events/RedisStreamConsumer.js +158 -0
  67. package/dist/events/RedisStreamPublisher.d.ts +9 -0
  68. package/dist/events/RedisStreamPublisher.js +60 -0
  69. package/dist/filters/GlobalExceptionFilter.d.ts +11 -0
  70. package/dist/filters/GlobalExceptionFilter.js +102 -0
  71. package/dist/guards/JwtAuthGuard.d.ts +10 -0
  72. package/dist/guards/JwtAuthGuard.js +46 -0
  73. package/dist/guards/JwtStrategy.d.ts +22 -0
  74. package/dist/guards/JwtStrategy.js +47 -0
  75. package/dist/guards/RolesGuard.d.ts +8 -0
  76. package/dist/guards/RolesGuard.js +52 -0
  77. package/dist/index.d.ts +69 -0
  78. package/dist/index.js +146 -0
  79. package/dist/interceptors/ResultInterceptor.d.ts +7 -0
  80. package/dist/interceptors/ResultInterceptor.js +88 -0
  81. package/dist/lifecycle/GracefulShutdownService.d.ts +24 -0
  82. package/dist/lifecycle/GracefulShutdownService.js +93 -0
  83. package/dist/logging/pino-config.d.ts +35 -0
  84. package/dist/logging/pino-config.js +79 -0
  85. package/dist/metrics/MetricsController.d.ts +7 -0
  86. package/dist/metrics/MetricsController.js +42 -0
  87. package/dist/metrics/MetricsService.d.ts +13 -0
  88. package/dist/metrics/MetricsService.js +58 -0
  89. package/dist/middleware/CorrelationIdMiddleware.d.ts +4 -0
  90. package/dist/middleware/CorrelationIdMiddleware.js +33 -0
  91. package/dist/middleware/CorrelationStore.d.ts +11 -0
  92. package/dist/middleware/CorrelationStore.js +9 -0
  93. package/dist/middleware/TenantContextMiddleware.d.ts +7 -0
  94. package/dist/middleware/TenantContextMiddleware.js +27 -0
  95. package/dist/middleware/TenantStore.d.ts +9 -0
  96. package/dist/middleware/TenantStore.js +9 -0
  97. package/dist/redis/redis.module.d.ts +8 -0
  98. package/dist/redis/redis.module.js +49 -0
  99. package/dist/resilience/CircuitBreakerFactory.d.ts +12 -0
  100. package/dist/resilience/CircuitBreakerFactory.js +22 -0
  101. package/dist/result/Result.d.ts +26 -0
  102. package/dist/result/Result.js +62 -0
  103. package/dist/shared-kernel.module.d.ts +13 -0
  104. package/dist/shared-kernel.module.js +87 -0
  105. package/dist/subscribers/TenantSubscriber.d.ts +20 -0
  106. package/dist/subscribers/TenantSubscriber.js +52 -0
  107. package/dist/testing/TestingModuleFactory.d.ts +23 -0
  108. package/dist/testing/TestingModuleFactory.js +63 -0
  109. package/dist/testing/index.d.ts +2 -0
  110. package/dist/testing/index.js +7 -0
  111. package/dist/testing/mocks.d.ts +34 -0
  112. package/dist/testing/mocks.js +62 -0
  113. package/dist/unleash/initial-flags.d.ts +7 -0
  114. package/dist/unleash/initial-flags.js +9 -0
  115. package/dist/unleash/unleash.module.d.ts +9 -0
  116. package/dist/unleash/unleash.module.js +47 -0
  117. package/package.json +140 -0
  118. package/src/bootstrap/bootstrapService.ts +72 -0
  119. package/src/cqrs/behaviors/CacheBehavior.spec.ts +63 -0
  120. package/src/cqrs/behaviors/CacheBehavior.ts +54 -0
  121. package/src/cqrs/behaviors/DistributedLockBehavior.ts +88 -0
  122. package/src/cqrs/behaviors/FeatureFlagBehavior.ts +46 -0
  123. package/src/cqrs/behaviors/InvalidateCacheBehavior.spec.ts +89 -0
  124. package/src/cqrs/behaviors/InvalidateCacheBehavior.ts +50 -0
  125. package/src/cqrs/behaviors/LogBehavior.spec.ts +55 -0
  126. package/src/cqrs/behaviors/LogBehavior.ts +121 -0
  127. package/src/cqrs/behaviors/PerformanceBehavior.spec.ts +48 -0
  128. package/src/cqrs/behaviors/PerformanceBehavior.ts +43 -0
  129. package/src/cqrs/behaviors/TransactionalBehavior.ts +64 -0
  130. package/src/cqrs/behaviors/ValidationBehavior.spec.ts +114 -0
  131. package/src/cqrs/behaviors/ValidationBehavior.ts +29 -0
  132. package/src/cqrs/behaviors/WorkflowBehavior.spec.ts +97 -0
  133. package/src/cqrs/behaviors/WorkflowBehavior.ts +62 -0
  134. package/src/cqrs/constants.ts +2 -0
  135. package/src/cqrs/decorators/Cache.decorator.ts +24 -0
  136. package/src/cqrs/decorators/DistributedLock.decorator.ts +34 -0
  137. package/src/cqrs/decorators/FeatureFlag.decorator.ts +23 -0
  138. package/src/cqrs/decorators/InvalidateCache.decorator.spec.ts +20 -0
  139. package/src/cqrs/decorators/InvalidateCache.decorator.ts +17 -0
  140. package/src/cqrs/decorators/IsolatedTransaction.decorator.ts +24 -0
  141. package/src/cqrs/decorators/Log.decorator.ts +22 -0
  142. package/src/cqrs/decorators/Validate.decorator.ts +39 -0
  143. package/src/cqrs/decorators/Workflow.decorator.ts +22 -0
  144. package/src/cqrs/interfaces/WorkflowEngine.ts +19 -0
  145. package/src/cqrs/pipeline/QuanticCommandBus.ts +69 -0
  146. package/src/cqrs/pipeline/QuanticQueryBus.ts +56 -0
  147. package/src/cqrs/pipeline/runPipeline.ts +22 -0
  148. package/src/cqrs/transaction/TransactionContext.ts +26 -0
  149. package/src/cqrs/transaction/getTransactionalRepo.ts +23 -0
  150. package/src/cqrs/validation/ICommandValidator.ts +55 -0
  151. package/src/entities/BaseEntity.ts +16 -0
  152. package/src/entities/TenantBaseEntity.ts +7 -0
  153. package/src/events/DomainEvent.ts +27 -0
  154. package/src/events/OutboxEvent.entity.ts +56 -0
  155. package/src/events/OutboxPublisherService.ts +94 -0
  156. package/src/events/RedisStreamConsumer.ts +172 -0
  157. package/src/events/RedisStreamPublisher.ts +54 -0
  158. package/src/filters/GlobalExceptionFilter.ts +125 -0
  159. package/src/guards/JwtAuthGuard.ts +29 -0
  160. package/src/guards/JwtStrategy.ts +41 -0
  161. package/src/guards/RolesGuard.ts +39 -0
  162. package/src/index.ts +118 -0
  163. package/src/interceptors/ResultInterceptor.ts +93 -0
  164. package/src/lifecycle/GracefulShutdownService.ts +77 -0
  165. package/src/logging/pino-config.ts +80 -0
  166. package/src/metrics/MetricsController.ts +17 -0
  167. package/src/metrics/MetricsService.ts +55 -0
  168. package/src/middleware/CorrelationIdMiddleware.ts +27 -0
  169. package/src/middleware/CorrelationStore.ts +13 -0
  170. package/src/middleware/TenantContextMiddleware.ts +21 -0
  171. package/src/middleware/TenantStore.ts +11 -0
  172. package/src/redis/redis.module.ts +41 -0
  173. package/src/resilience/CircuitBreakerFactory.ts +33 -0
  174. package/src/result/Result.ts +66 -0
  175. package/src/shared-kernel.module.ts +87 -0
  176. package/src/subscribers/TenantSubscriber.ts +47 -0
  177. package/src/testing/TestingModuleFactory.ts +78 -0
  178. package/src/testing/index.ts +2 -0
  179. package/src/testing/mocks.ts +59 -0
  180. package/src/unleash/unleash.module.ts +45 -0
  181. package/tsconfig.json +22 -0
@@ -0,0 +1,8 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ export interface BootstrapOptions {
3
+ module: any;
4
+ port: number;
5
+ serviceName: string;
6
+ rawBody?: boolean;
7
+ }
8
+ export declare function bootstrapService(options: BootstrapOptions): Promise<INestApplication>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.bootstrapService = bootstrapService;
7
+ const common_1 = require("@nestjs/common");
8
+ const core_1 = require("@nestjs/core");
9
+ const swagger_1 = require("@nestjs/swagger");
10
+ const nestjs_pino_1 = require("nestjs-pino");
11
+ const helmet_1 = __importDefault(require("helmet"));
12
+ const cookie_parser_1 = __importDefault(require("cookie-parser"));
13
+ const GlobalExceptionFilter_1 = require("../filters/GlobalExceptionFilter");
14
+ async function bootstrapService(options) {
15
+ const { module, port, serviceName, rawBody } = options;
16
+ const app = await core_1.NestFactory.create(module, {
17
+ bufferLogs: true,
18
+ ...(rawBody ? { rawBody: true } : {}),
19
+ });
20
+ app.useLogger(app.get(nestjs_pino_1.Logger));
21
+ // Security headers
22
+ app.use((0, helmet_1.default)());
23
+ // Cookie parsing (required for OAuth flows)
24
+ app.use((0, cookie_parser_1.default)());
25
+ // CORS
26
+ const allowedOrigins = (process.env.CORS_ORIGINS || 'http://localhost:5173').split(',');
27
+ app.enableCors({
28
+ origin: allowedOrigins,
29
+ credentials: true,
30
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
31
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-Tenant-ID', 'X-Correlation-ID'],
32
+ exposedHeaders: ['X-Correlation-ID'],
33
+ maxAge: 86400,
34
+ });
35
+ // Global exception filter
36
+ app.useGlobalFilters(new GlobalExceptionFilter_1.GlobalExceptionFilter());
37
+ // Global validation pipe
38
+ app.useGlobalPipes(new common_1.ValidationPipe({
39
+ whitelist: true,
40
+ forbidNonWhitelisted: true,
41
+ transform: true,
42
+ }));
43
+ // Swagger — disabled in production
44
+ if (process.env.NODE_ENV !== 'production') {
45
+ const config = new swagger_1.DocumentBuilder()
46
+ .setTitle(`AREX — ${serviceName}`)
47
+ .setDescription(`OpenAPI spec for ${serviceName}`)
48
+ .setVersion('1.0.0')
49
+ .addBearerAuth()
50
+ .build();
51
+ const document = swagger_1.SwaggerModule.createDocument(app, config);
52
+ swagger_1.SwaggerModule.setup('swagger', app, document);
53
+ }
54
+ // Enable graceful shutdown hooks (SIGTERM, SIGINT)
55
+ app.enableShutdownHooks();
56
+ await app.listen(port);
57
+ return app;
58
+ }
@@ -0,0 +1,31 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { CommandBus, QueryBus } from '@nestjs/cqrs';
3
+ import { LogBehavior } from './behaviors/LogBehavior';
4
+ import { FeatureFlagBehavior } from './behaviors/FeatureFlagBehavior';
5
+ import { ValidationBehavior } from './behaviors/ValidationBehavior';
6
+ import { CacheBehavior } from './behaviors/CacheBehavior';
7
+ import { DistributedLockBehavior } from './behaviors/DistributedLockBehavior';
8
+ import { TransactionalBehavior } from './behaviors/TransactionalBehavior';
9
+ import { PerformanceBehavior } from './behaviors/PerformanceBehavior';
10
+ import { WorkflowBehavior } from './behaviors/WorkflowBehavior';
11
+ /**
12
+ * @deprecated Use QuanticCommandBus and QuanticQueryBus instead.
13
+ * This class is kept for backwards compatibility only.
14
+ */
15
+ export declare class PipelineExecutor implements OnModuleInit {
16
+ private readonly commandBus;
17
+ private readonly queryBus;
18
+ private readonly logBehavior;
19
+ private readonly featureFlagBehavior;
20
+ private readonly validationBehavior;
21
+ private readonly cacheBehavior;
22
+ private readonly distributedLockBehavior;
23
+ private readonly transactionalBehavior;
24
+ private readonly performanceBehavior;
25
+ private readonly workflowBehavior;
26
+ private readonly logger;
27
+ private readonly quanticCommandBus;
28
+ private readonly quanticQueryBus;
29
+ constructor(commandBus: CommandBus, queryBus: QueryBus, logBehavior: LogBehavior, featureFlagBehavior: FeatureFlagBehavior | undefined, validationBehavior: ValidationBehavior, cacheBehavior: CacheBehavior, distributedLockBehavior: DistributedLockBehavior, transactionalBehavior: TransactionalBehavior, performanceBehavior: PerformanceBehavior, workflowBehavior: WorkflowBehavior | undefined);
30
+ onModuleInit(): void;
31
+ }
@@ -0,0 +1,81 @@
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
+ var PipelineExecutor_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.PipelineExecutor = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const cqrs_1 = require("@nestjs/cqrs");
19
+ const LogBehavior_1 = require("./behaviors/LogBehavior");
20
+ const FeatureFlagBehavior_1 = require("./behaviors/FeatureFlagBehavior");
21
+ const ValidationBehavior_1 = require("./behaviors/ValidationBehavior");
22
+ const CacheBehavior_1 = require("./behaviors/CacheBehavior");
23
+ const DistributedLockBehavior_1 = require("./behaviors/DistributedLockBehavior");
24
+ const TransactionalBehavior_1 = require("./behaviors/TransactionalBehavior");
25
+ const PerformanceBehavior_1 = require("./behaviors/PerformanceBehavior");
26
+ const WorkflowBehavior_1 = require("./behaviors/WorkflowBehavior");
27
+ const QuanticCommandBus_1 = require("./pipeline/QuanticCommandBus");
28
+ const QuanticQueryBus_1 = require("./pipeline/QuanticQueryBus");
29
+ /**
30
+ * @deprecated Use QuanticCommandBus and QuanticQueryBus instead.
31
+ * This class is kept for backwards compatibility only.
32
+ */
33
+ let PipelineExecutor = PipelineExecutor_1 = class PipelineExecutor {
34
+ commandBus;
35
+ queryBus;
36
+ logBehavior;
37
+ featureFlagBehavior;
38
+ validationBehavior;
39
+ cacheBehavior;
40
+ distributedLockBehavior;
41
+ transactionalBehavior;
42
+ performanceBehavior;
43
+ workflowBehavior;
44
+ logger = new common_1.Logger(PipelineExecutor_1.name);
45
+ quanticCommandBus;
46
+ quanticQueryBus;
47
+ constructor(commandBus, queryBus, logBehavior, featureFlagBehavior, validationBehavior, cacheBehavior, distributedLockBehavior, transactionalBehavior, performanceBehavior, workflowBehavior) {
48
+ this.commandBus = commandBus;
49
+ this.queryBus = queryBus;
50
+ this.logBehavior = logBehavior;
51
+ this.featureFlagBehavior = featureFlagBehavior;
52
+ this.validationBehavior = validationBehavior;
53
+ this.cacheBehavior = cacheBehavior;
54
+ this.distributedLockBehavior = distributedLockBehavior;
55
+ this.transactionalBehavior = transactionalBehavior;
56
+ this.performanceBehavior = performanceBehavior;
57
+ this.workflowBehavior = workflowBehavior;
58
+ this.quanticCommandBus = new QuanticCommandBus_1.QuanticCommandBus(commandBus, logBehavior, performanceBehavior, featureFlagBehavior, validationBehavior, workflowBehavior, cacheBehavior, distributedLockBehavior, transactionalBehavior);
59
+ this.quanticQueryBus = new QuanticQueryBus_1.QuanticQueryBus(queryBus, logBehavior, performanceBehavior, featureFlagBehavior, validationBehavior, cacheBehavior);
60
+ }
61
+ onModuleInit() {
62
+ this.logger.warn('PipelineExecutor is deprecated. Use QuanticCommandBus and QuanticQueryBus instead.');
63
+ this.quanticCommandBus.onModuleInit();
64
+ this.quanticQueryBus.onModuleInit();
65
+ }
66
+ };
67
+ exports.PipelineExecutor = PipelineExecutor;
68
+ exports.PipelineExecutor = PipelineExecutor = PipelineExecutor_1 = __decorate([
69
+ (0, common_1.Injectable)(),
70
+ __param(3, (0, common_1.Optional)()),
71
+ __param(3, (0, common_1.Inject)(FeatureFlagBehavior_1.FeatureFlagBehavior)),
72
+ __param(9, (0, common_1.Optional)()),
73
+ __param(9, (0, common_1.Inject)(WorkflowBehavior_1.WorkflowBehavior)),
74
+ __metadata("design:paramtypes", [cqrs_1.CommandBus,
75
+ cqrs_1.QueryBus,
76
+ LogBehavior_1.LogBehavior, Object, ValidationBehavior_1.ValidationBehavior,
77
+ CacheBehavior_1.CacheBehavior,
78
+ DistributedLockBehavior_1.DistributedLockBehavior,
79
+ TransactionalBehavior_1.TransactionalBehavior,
80
+ PerformanceBehavior_1.PerformanceBehavior, Object])
81
+ ], PipelineExecutor);
@@ -0,0 +1,9 @@
1
+ import { Result } from '../../result/Result';
2
+ import type { Redis } from 'ioredis';
3
+ export declare class CacheBehavior {
4
+ private readonly redis?;
5
+ private readonly logger;
6
+ constructor(redis?: Redis | undefined);
7
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
8
+ private interpolateKey;
9
+ }
@@ -0,0 +1,68 @@
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
+ var CacheBehavior_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.CacheBehavior = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const Cache_decorator_1 = require("../decorators/Cache.decorator");
19
+ const Result_1 = require("../../result/Result");
20
+ const constants_1 = require("../constants");
21
+ let CacheBehavior = CacheBehavior_1 = class CacheBehavior {
22
+ redis;
23
+ logger = new common_1.Logger(CacheBehavior_1.name);
24
+ constructor(redis) {
25
+ this.redis = redis;
26
+ }
27
+ async execute(command, next) {
28
+ const metadata = (0, Cache_decorator_1.getCacheMetadata)(command.constructor);
29
+ if (!metadata || !this.redis) {
30
+ return next();
31
+ }
32
+ const cacheKey = this.interpolateKey(metadata.key, command);
33
+ try {
34
+ const cached = await this.redis.get(cacheKey);
35
+ if (cached) {
36
+ this.logger.debug(`Cache hit: ${cacheKey}`);
37
+ return Result_1.Result.success(JSON.parse(cached));
38
+ }
39
+ }
40
+ catch {
41
+ this.logger.warn(`Cache read failed for key: ${cacheKey}`);
42
+ }
43
+ const result = await next();
44
+ if (result.isSuccess && result.value !== undefined) {
45
+ try {
46
+ await this.redis.set(cacheKey, JSON.stringify(result.value), 'EX', metadata.ttlSeconds);
47
+ this.logger.debug(`Cache set: ${cacheKey} (TTL: ${metadata.ttlSeconds}s)`);
48
+ }
49
+ catch {
50
+ this.logger.warn(`Cache write failed for key: ${cacheKey}`);
51
+ }
52
+ }
53
+ return result;
54
+ }
55
+ interpolateKey(template, command) {
56
+ return template.replace(/\{(\w+)\}/g, (_, prop) => {
57
+ const value = command[prop];
58
+ return value != null ? String(value) : '';
59
+ });
60
+ }
61
+ };
62
+ exports.CacheBehavior = CacheBehavior;
63
+ exports.CacheBehavior = CacheBehavior = CacheBehavior_1 = __decorate([
64
+ (0, common_1.Injectable)(),
65
+ __param(0, (0, common_1.Optional)()),
66
+ __param(0, (0, common_1.Inject)(constants_1.REDIS_CLIENT)),
67
+ __metadata("design:paramtypes", [Function])
68
+ ], CacheBehavior);
@@ -0,0 +1,12 @@
1
+ import { Result } from '../../result/Result';
2
+ import type { Redis } from 'ioredis';
3
+ export declare class DistributedLockBehavior {
4
+ private readonly redis?;
5
+ private readonly logger;
6
+ constructor(redis?: Redis | undefined);
7
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
8
+ private tryAcquire;
9
+ private release;
10
+ private sleep;
11
+ private interpolateKey;
12
+ }
@@ -0,0 +1,90 @@
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
+ var DistributedLockBehavior_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.DistributedLockBehavior = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const DistributedLock_decorator_1 = require("../decorators/DistributedLock.decorator");
19
+ const Result_1 = require("../../result/Result");
20
+ const constants_1 = require("../constants");
21
+ const uuid_1 = require("uuid");
22
+ let DistributedLockBehavior = DistributedLockBehavior_1 = class DistributedLockBehavior {
23
+ redis;
24
+ logger = new common_1.Logger(DistributedLockBehavior_1.name);
25
+ constructor(redis) {
26
+ this.redis = redis;
27
+ }
28
+ async execute(command, next) {
29
+ const metadata = (0, DistributedLock_decorator_1.getDistributedLockMetadata)(command.constructor);
30
+ if (!metadata || !this.redis) {
31
+ return next();
32
+ }
33
+ const lockKey = `lock:${this.interpolateKey(metadata.key, command)}`;
34
+ const lockValue = (0, uuid_1.v4)();
35
+ const acquired = await this.tryAcquire(lockKey, lockValue, metadata.lockTtlSeconds, metadata.acquireTimeoutSeconds);
36
+ if (!acquired) {
37
+ this.logger.warn(`Failed to acquire lock: ${lockKey}`);
38
+ return Result_1.Result.failure(Result_1.ErrorType.Conflict, `Resource is locked: ${metadata.key}`);
39
+ }
40
+ try {
41
+ return await next();
42
+ }
43
+ finally {
44
+ await this.release(lockKey, lockValue);
45
+ }
46
+ }
47
+ async tryAcquire(key, value, ttlSeconds, timeoutSeconds) {
48
+ const deadline = Date.now() + timeoutSeconds * 1000;
49
+ const retryDelay = 50;
50
+ while (Date.now() < deadline) {
51
+ const result = await this.redis.set(key, value, 'EX', ttlSeconds, 'NX');
52
+ if (result === 'OK')
53
+ return true;
54
+ await this.sleep(retryDelay);
55
+ }
56
+ return false;
57
+ }
58
+ async release(key, value) {
59
+ // Lua script ensures only the owner releases the lock
60
+ const script = `
61
+ if redis.call("get", KEYS[1]) == ARGV[1] then
62
+ return redis.call("del", KEYS[1])
63
+ else
64
+ return 0
65
+ end
66
+ `;
67
+ try {
68
+ await this.redis.eval(script, 1, key, value);
69
+ }
70
+ catch {
71
+ this.logger.warn(`Failed to release lock: ${key}`);
72
+ }
73
+ }
74
+ sleep(ms) {
75
+ return new Promise((resolve) => setTimeout(resolve, ms));
76
+ }
77
+ interpolateKey(template, command) {
78
+ return template.replace(/\{(\w+)\}/g, (_, prop) => {
79
+ const value = command[prop];
80
+ return value != null ? String(value) : '';
81
+ });
82
+ }
83
+ };
84
+ exports.DistributedLockBehavior = DistributedLockBehavior;
85
+ exports.DistributedLockBehavior = DistributedLockBehavior = DistributedLockBehavior_1 = __decorate([
86
+ (0, common_1.Injectable)(),
87
+ __param(0, (0, common_1.Optional)()),
88
+ __param(0, (0, common_1.Inject)(constants_1.REDIS_CLIENT)),
89
+ __metadata("design:paramtypes", [Function])
90
+ ], DistributedLockBehavior);
@@ -0,0 +1,8 @@
1
+ import { Unleash } from 'unleash-client';
2
+ import { Result } from '../../result/Result';
3
+ export declare class FeatureFlagBehavior {
4
+ private readonly unleash?;
5
+ private readonly logger;
6
+ constructor(unleash?: Unleash | undefined);
7
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
8
+ }
@@ -0,0 +1,58 @@
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
+ var FeatureFlagBehavior_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.FeatureFlagBehavior = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const unleash_client_1 = require("unleash-client");
19
+ const FeatureFlag_decorator_1 = require("../decorators/FeatureFlag.decorator");
20
+ const Result_1 = require("../../result/Result");
21
+ let FeatureFlagBehavior = FeatureFlagBehavior_1 = class FeatureFlagBehavior {
22
+ unleash;
23
+ logger = new common_1.Logger(FeatureFlagBehavior_1.name);
24
+ constructor(unleash) {
25
+ this.unleash = unleash;
26
+ }
27
+ async execute(command, next) {
28
+ const metadata = (0, FeatureFlag_decorator_1.getFeatureFlagMetadata)(command.constructor);
29
+ if (!metadata) {
30
+ return next();
31
+ }
32
+ if (!this.unleash) {
33
+ this.logger.debug('Unleash not configured, skipping feature flag check');
34
+ return next();
35
+ }
36
+ const { flagName, fallback, defaultValue } = metadata;
37
+ const isEnabled = this.unleash.isEnabled(flagName);
38
+ if (isEnabled) {
39
+ return next();
40
+ }
41
+ this.logger.warn(`Feature flag "${flagName}" is disabled, applying fallback: ${fallback}`);
42
+ switch (fallback) {
43
+ case 'skip':
44
+ return Result_1.Result.success(undefined);
45
+ case 'default':
46
+ return Result_1.Result.success(defaultValue);
47
+ case 'throw':
48
+ default:
49
+ return Result_1.Result.failure(Result_1.ErrorType.Forbidden, `Feature "${flagName}" is currently disabled`);
50
+ }
51
+ }
52
+ };
53
+ exports.FeatureFlagBehavior = FeatureFlagBehavior;
54
+ exports.FeatureFlagBehavior = FeatureFlagBehavior = FeatureFlagBehavior_1 = __decorate([
55
+ (0, common_1.Injectable)(),
56
+ __param(0, (0, common_1.Optional)()),
57
+ __metadata("design:paramtypes", [unleash_client_1.Unleash])
58
+ ], FeatureFlagBehavior);
@@ -0,0 +1,9 @@
1
+ import { Result } from '../../result/Result';
2
+ import type { Redis } from 'ioredis';
3
+ export declare class InvalidateCacheBehavior {
4
+ private readonly redis?;
5
+ private readonly logger;
6
+ constructor(redis?: Redis | undefined);
7
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
8
+ private interpolateKey;
9
+ }
@@ -0,0 +1,61 @@
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
+ var InvalidateCacheBehavior_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.InvalidateCacheBehavior = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const InvalidateCache_decorator_1 = require("../decorators/InvalidateCache.decorator");
19
+ const constants_1 = require("../constants");
20
+ let InvalidateCacheBehavior = InvalidateCacheBehavior_1 = class InvalidateCacheBehavior {
21
+ redis;
22
+ logger = new common_1.Logger(InvalidateCacheBehavior_1.name);
23
+ constructor(redis) {
24
+ this.redis = redis;
25
+ }
26
+ async execute(command, next) {
27
+ const metadata = (0, InvalidateCache_decorator_1.getInvalidateCacheMetadata)(command.constructor);
28
+ if (!metadata || !this.redis) {
29
+ return next();
30
+ }
31
+ const result = await next();
32
+ if (!result.isSuccess) {
33
+ return result;
34
+ }
35
+ const resolvedKeys = metadata.keys.map((key) => this.interpolateKey(key, command));
36
+ if (resolvedKeys.length === 0) {
37
+ return result;
38
+ }
39
+ try {
40
+ await this.redis.del(...resolvedKeys);
41
+ this.logger.debug(`Cache invalidated: ${resolvedKeys.join(', ')}`);
42
+ }
43
+ catch {
44
+ this.logger.warn(`Cache invalidation failed for keys: ${resolvedKeys.join(', ')}`);
45
+ }
46
+ return result;
47
+ }
48
+ interpolateKey(template, command) {
49
+ return template.replace(/\{(\w+)\}/g, (_, prop) => {
50
+ const value = command[prop];
51
+ return value != null ? String(value) : '';
52
+ });
53
+ }
54
+ };
55
+ exports.InvalidateCacheBehavior = InvalidateCacheBehavior;
56
+ exports.InvalidateCacheBehavior = InvalidateCacheBehavior = InvalidateCacheBehavior_1 = __decorate([
57
+ (0, common_1.Injectable)(),
58
+ __param(0, (0, common_1.Optional)()),
59
+ __param(0, (0, common_1.Inject)(constants_1.REDIS_CLIENT)),
60
+ __metadata("design:paramtypes", [Function])
61
+ ], InvalidateCacheBehavior);
@@ -0,0 +1,9 @@
1
+ import { Result } from '../../result/Result';
2
+ export declare class LogBehavior {
3
+ private readonly logger;
4
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
5
+ private maskPayload;
6
+ private getExcludeFields;
7
+ private sanitize;
8
+ private extractBuildId;
9
+ }
@@ -0,0 +1,125 @@
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.LogBehavior = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const Result_1 = require("../../result/Result");
12
+ const CorrelationStore_1 = require("../../middleware/CorrelationStore");
13
+ const PII_FIELDS = new Set(['email', 'githubAccessToken', 'accessToken', 'token', 'secretKey', 'password']);
14
+ const MAX_STRING_LENGTH = 200;
15
+ const MAX_ARRAY_LENGTH = 5;
16
+ const MAX_DEPTH = 2;
17
+ let LogBehavior = class LogBehavior {
18
+ logger = new common_1.Logger('PipelineBehavior');
19
+ async execute(command, next) {
20
+ const commandName = command.constructor.name;
21
+ const startTime = Date.now();
22
+ const ctx = CorrelationStore_1.correlationStore.getStore();
23
+ const logContext = {
24
+ command: commandName,
25
+ correlationId: ctx?.correlationId,
26
+ userId: ctx?.userId,
27
+ orgId: ctx?.organizationId,
28
+ ...(this.extractBuildId(command)),
29
+ payload: this.maskPayload(command),
30
+ };
31
+ try {
32
+ const result = await next();
33
+ const durationMs = Date.now() - startTime;
34
+ if (result.isSuccess) {
35
+ this.logger.log({
36
+ msg: `${commandName} completed`,
37
+ ...logContext,
38
+ durationMs,
39
+ result: 'success',
40
+ });
41
+ }
42
+ else {
43
+ this.logger.warn({
44
+ msg: `${commandName} completed`,
45
+ ...logContext,
46
+ durationMs,
47
+ result: 'failure',
48
+ errorType: result.errorType ?? 'Unknown',
49
+ errorMessage: result.errorMessage,
50
+ });
51
+ }
52
+ return result;
53
+ }
54
+ catch (error) {
55
+ const durationMs = Date.now() - startTime;
56
+ const err = error instanceof Error ? error : new Error(String(error));
57
+ this.logger.error({
58
+ msg: `${commandName} failed`,
59
+ ...logContext,
60
+ durationMs,
61
+ result: 'exception',
62
+ error: err.message,
63
+ stack: err.stack,
64
+ });
65
+ return Result_1.Result.failure(Result_1.ErrorType.InternalError, err.message);
66
+ }
67
+ }
68
+ maskPayload(command) {
69
+ const excludeFields = this.getExcludeFields(command);
70
+ return this.sanitize(command, 0, excludeFields);
71
+ }
72
+ getExcludeFields(command) {
73
+ const ctor = command.constructor;
74
+ return new Set(ctor.logExclude ?? []);
75
+ }
76
+ sanitize(value, depth, excludeFields) {
77
+ if (value === null || value === undefined)
78
+ return value;
79
+ if (typeof value === 'string') {
80
+ return value.length > MAX_STRING_LENGTH
81
+ ? `${value.substring(0, MAX_STRING_LENGTH)}... (${value.length} chars)`
82
+ : value;
83
+ }
84
+ if (typeof value !== 'object')
85
+ return value;
86
+ if (depth >= MAX_DEPTH)
87
+ return '[nested]';
88
+ if (Array.isArray(value)) {
89
+ if (value.length > MAX_ARRAY_LENGTH) {
90
+ return [
91
+ ...value.slice(0, MAX_ARRAY_LENGTH).map((v) => this.sanitize(v, depth + 1)),
92
+ `... +${value.length - MAX_ARRAY_LENGTH} more`,
93
+ ];
94
+ }
95
+ return value.map((v) => this.sanitize(v, depth + 1));
96
+ }
97
+ const masked = {};
98
+ for (const [key, val] of Object.entries(value)) {
99
+ if (excludeFields?.has(key)) {
100
+ masked[key] = '[excluded]';
101
+ }
102
+ else if (PII_FIELDS.has(key)) {
103
+ if (key === 'email' && typeof val === 'string') {
104
+ const [local, domain] = val.split('@');
105
+ masked[key] = domain ? `${local?.[0]}***@${domain}` : '[REDACTED]';
106
+ }
107
+ else {
108
+ masked[key] = '[REDACTED]';
109
+ }
110
+ }
111
+ else {
112
+ masked[key] = this.sanitize(val, depth + 1);
113
+ }
114
+ }
115
+ return masked;
116
+ }
117
+ extractBuildId(command) {
118
+ const buildId = command['buildId'];
119
+ return typeof buildId === 'string' ? { buildId } : {};
120
+ }
121
+ };
122
+ exports.LogBehavior = LogBehavior;
123
+ exports.LogBehavior = LogBehavior = __decorate([
124
+ (0, common_1.Injectable)()
125
+ ], LogBehavior);
@@ -0,0 +1,12 @@
1
+ import { Result } from '../../result/Result';
2
+ import { MetricsService } from '../../metrics/MetricsService';
3
+ /**
4
+ * PerformanceBehavior logs a warning when a handler exceeds 500ms
5
+ * and records handler duration in Prometheus histogram.
6
+ */
7
+ export declare class PerformanceBehavior {
8
+ private readonly metrics?;
9
+ private readonly logger;
10
+ constructor(metrics?: MetricsService | undefined);
11
+ execute<T>(command: object, next: () => Promise<Result<T>>): Promise<Result<T>>;
12
+ }