@takentrade/takentrade-libs 0.0.57
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/README.md +216 -0
- package/dist/bullmq/bullmq.module.d.ts +2 -0
- package/dist/bullmq/bullmq.module.js +16 -0
- package/dist/bullmq/bullmq.service.d.ts +2 -0
- package/dist/bullmq/bullmq.service.js +16 -0
- package/dist/bullmq/config/bull.config.d.ts +22 -0
- package/dist/bullmq/config/bull.config.js +28 -0
- package/dist/bullmq/index.d.ts +1 -0
- package/dist/bullmq/index.js +17 -0
- package/dist/cache/cache.interface.d.ts +2 -0
- package/dist/cache/cache.interface.js +2 -0
- package/dist/cache/cache.module.d.ts +5 -0
- package/dist/cache/cache.module.js +27 -0
- package/dist/cache/cache.service.d.ts +24 -0
- package/dist/cache/cache.service.js +91 -0
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.js +18 -0
- package/dist/common/circuit-breaker/circuit-breaker.module.d.ts +2 -0
- package/dist/common/circuit-breaker/circuit-breaker.module.js +20 -0
- package/dist/common/circuit-breaker/circuit-breaker.service.d.ts +13 -0
- package/dist/common/circuit-breaker/circuit-breaker.service.js +120 -0
- package/dist/common/circuit-breaker/circuit-breaker.types.d.ts +19 -0
- package/dist/common/circuit-breaker/circuit-breaker.types.js +9 -0
- package/dist/common/config/index.d.ts +1 -0
- package/dist/common/config/index.js +2 -0
- package/dist/common/config/nats.config.d.ts +9 -0
- package/dist/common/config/nats.config.js +12 -0
- package/dist/common/constants/index.d.ts +2 -0
- package/dist/common/constants/index.js +18 -0
- package/dist/common/constants/otp.constants.d.ts +15 -0
- package/dist/common/constants/otp.constants.js +18 -0
- package/dist/common/constants/queues.constants.d.ts +9 -0
- package/dist/common/constants/queues.constants.js +12 -0
- package/dist/common/dto/index.d.ts +3 -0
- package/dist/common/dto/index.js +19 -0
- package/dist/common/dto/payment/index.d.ts +1 -0
- package/dist/common/dto/payment/index.js +17 -0
- package/dist/common/dto/payment/withdrawal.dto.d.ts +19 -0
- package/dist/common/dto/payment/withdrawal.dto.js +97 -0
- package/dist/common/dto/support/create-message.dto.d.ts +4 -0
- package/dist/common/dto/support/create-message.dto.js +25 -0
- package/dist/common/dto/support/create-ticket.dto.d.ts +7 -0
- package/dist/common/dto/support/create-ticket.dto.js +43 -0
- package/dist/common/dto/support/index.d.ts +3 -0
- package/dist/common/dto/support/index.js +19 -0
- package/dist/common/dto/support/update-ticket.dto.d.ts +6 -0
- package/dist/common/dto/support/update-ticket.dto.js +41 -0
- package/dist/common/dto/users/index.d.ts +6 -0
- package/dist/common/dto/users/index.js +22 -0
- package/dist/common/dto/users/login.dto.d.ts +9 -0
- package/dist/common/dto/users/login.dto.js +40 -0
- package/dist/common/dto/users/passcode.dto.d.ts +12 -0
- package/dist/common/dto/users/passcode.dto.js +51 -0
- package/dist/common/dto/users/phone.dto.d.ts +4 -0
- package/dist/common/dto/users/phone.dto.js +26 -0
- package/dist/common/dto/users/register.dto.d.ts +8 -0
- package/dist/common/dto/users/register.dto.js +46 -0
- package/dist/common/dto/users/request-phone-verification.dto.d.ts +3 -0
- package/dist/common/dto/users/request-phone-verification.dto.js +20 -0
- package/dist/common/dto/users/verify-phone.dto.d.ts +3 -0
- package/dist/common/dto/users/verify-phone.dto.js +20 -0
- package/dist/common/enums/index.d.ts +2 -0
- package/dist/common/enums/index.js +18 -0
- package/dist/common/enums/support-action.enum.d.ts +7 -0
- package/dist/common/enums/support-action.enum.js +11 -0
- package/dist/common/enums/ticket.enum.d.ts +19 -0
- package/dist/common/enums/ticket.enum.js +25 -0
- package/dist/common/health/health.controller.d.ts +9 -0
- package/dist/common/health/health.controller.js +51 -0
- package/dist/common/health/health.module.d.ts +2 -0
- package/dist/common/health/health.module.js +22 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.js +23 -0
- package/dist/common/utils/index.d.ts +3 -0
- package/dist/common/utils/index.js +19 -0
- package/dist/common/utils/random.utils.d.ts +10 -0
- package/dist/common/utils/random.utils.js +27 -0
- package/dist/common/utils/reference.utils.d.ts +1 -0
- package/dist/common/utils/reference.utils.js +17 -0
- package/dist/common/utils/string.utils.d.ts +2 -0
- package/dist/common/utils/string.utils.js +17 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +24 -0
- package/dist/logger/fake/FakeLogger.service.d.ts +13 -0
- package/dist/logger/fake/FakeLogger.service.js +21 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.js +18 -0
- package/dist/logger/logger.module.d.ts +7 -0
- package/dist/logger/logger.module.js +69 -0
- package/dist/logger/real/pinoLogger.service.d.ts +14 -0
- package/dist/logger/real/pinoLogger.service.js +76 -0
- package/dist/nats/constants/nats.constants.d.ts +9 -0
- package/dist/nats/constants/nats.constants.js +12 -0
- package/dist/nats/decorators/nats-event-pattern.decorator.d.ts +2 -0
- package/dist/nats/decorators/nats-event-pattern.decorator.js +11 -0
- package/dist/nats/dto/nats-message.dto.d.ts +5 -0
- package/dist/nats/dto/nats-message.dto.js +27 -0
- package/dist/nats/index.d.ts +5 -0
- package/dist/nats/index.js +21 -0
- package/dist/nats/interceptors/nats-logging.interceptor.d.ts +6 -0
- package/dist/nats/interceptors/nats-logging.interceptor.js +33 -0
- package/dist/nats/interfaces/nats-options.interface.d.ts +23 -0
- package/dist/nats/interfaces/nats-options.interface.js +2 -0
- package/dist/prisma/index.d.ts +2 -0
- package/dist/prisma/index.js +18 -0
- package/dist/prisma/prisma.module.d.ts +2 -0
- package/dist/prisma/prisma.module.js +21 -0
- package/dist/prisma/prisma.service.d.ts +6 -0
- package/dist/prisma/prisma.service.js +25 -0
- package/dist/rpc/index.d.ts +50 -0
- package/dist/rpc/index.js +131 -0
- package/dist/utils/dto/index.d.ts +4 -0
- package/dist/utils/dto/index.js +31 -0
- package/dist/utils/filters/http-exception.filter.d.ts +6 -0
- package/dist/utils/filters/http-exception.filter.js +56 -0
- package/dist/utils/filters/index.d.ts +1 -0
- package/dist/utils/filters/index.js +17 -0
- package/dist/utils/index.d.ts +26 -0
- package/dist/utils/index.js +66 -0
- package/dist/utils/interceptors/index.d.ts +2 -0
- package/dist/utils/interceptors/index.js +18 -0
- package/dist/utils/interceptors/pagination.interceptor.d.ts +19 -0
- package/dist/utils/interceptors/pagination.interceptor.js +49 -0
- package/dist/utils/interceptors/response.interceptor.d.ts +15 -0
- package/dist/utils/interceptors/response.interceptor.js +86 -0
- package/dist/utils/interfaces/config.interface.d.ts +39 -0
- package/dist/utils/interfaces/config.interface.js +2 -0
- package/dist/utils/interfaces/general.interface.d.ts +13 -0
- package/dist/utils/interfaces/general.interface.js +2 -0
- package/dist/utils/interfaces/index.d.ts +6 -0
- package/dist/utils/interfaces/index.js +22 -0
- package/dist/utils/interfaces/interceptor.interface.d.ts +15 -0
- package/dist/utils/interfaces/interceptor.interface.js +2 -0
- package/dist/utils/interfaces/multer-file.interface.d.ts +8 -0
- package/dist/utils/interfaces/multer-file.interface.js +2 -0
- package/dist/utils/interfaces/pagination.interface.d.ts +17 -0
- package/dist/utils/interfaces/pagination.interface.js +2 -0
- package/dist/utils/interfaces/response.interface.d.ts +21 -0
- package/dist/utils/interfaces/response.interface.js +9 -0
- package/dist/utils/pipes/file.pipe.d.ts +6 -0
- package/dist/utils/pipes/file.pipe.js +44 -0
- package/dist/utils/pipes/index.d.ts +3 -0
- package/dist/utils/pipes/index.js +19 -0
- package/dist/utils/pipes/pagination.pipe.d.ts +7 -0
- package/dist/utils/pipes/pagination.pipe.js +24 -0
- package/dist/utils/pipes/validation.pipe.d.ts +4 -0
- package/dist/utils/pipes/validation.pipe.js +24 -0
- package/dist/utils/utils/configuration.d.ts +3 -0
- package/dist/utils/utils/configuration.js +87 -0
- package/dist/utils/utils/country.utils.d.ts +4 -0
- package/dist/utils/utils/country.utils.js +41 -0
- package/dist/utils/utils/index.d.ts +5 -0
- package/dist/utils/utils/index.js +21 -0
- package/dist/utils/utils/otp.d.ts +1 -0
- package/dist/utils/utils/otp.js +102 -0
- package/dist/utils/utils/response.utils.d.ts +15 -0
- package/dist/utils/utils/response.utils.js +39 -0
- package/dist/utils/utils/utils.d.ts +4 -0
- package/dist/utils/utils/utils.js +40 -0
- package/dist/utils/validators/index.d.ts +1 -0
- package/dist/utils/validators/index.js +17 -0
- package/dist/utils/validators/nats.validator.d.ts +7 -0
- package/dist/utils/validators/nats.validator.js +47 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# TakeNTrade Microservices Libraries
|
|
2
|
+
|
|
3
|
+
This directory contains shared libraries used across the TakeNTrade microservices architecture. Below is a guide on how to use each library in your services.
|
|
4
|
+
|
|
5
|
+
## Cache Library (`@/libs/cache`)
|
|
6
|
+
|
|
7
|
+
Redis-based caching implementation for the microservices.
|
|
8
|
+
|
|
9
|
+
### Environment Variables
|
|
10
|
+
|
|
11
|
+
Each service should have these Redis-related environment variables:
|
|
12
|
+
|
|
13
|
+
- REDIS_HOST: Defaults to localhost
|
|
14
|
+
- REDIS_PORT: Default to 6379
|
|
15
|
+
- REDIS_USERNAME (Optional)
|
|
16
|
+
- REDIS_PASSWORD (Optional)
|
|
17
|
+
|
|
18
|
+
### Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { CacheModule, CacheService } from '@/libs/cache';
|
|
22
|
+
|
|
23
|
+
@Module({
|
|
24
|
+
imports: [
|
|
25
|
+
CacheModule.register()
|
|
26
|
+
]
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// In your service:
|
|
30
|
+
constructor(private readonly cacheService: CacheService) {}
|
|
31
|
+
|
|
32
|
+
// Basic cache operations
|
|
33
|
+
await this.cacheService.set('key', 'value', ttlSeconds);
|
|
34
|
+
const value = await this.cacheService.get('key');
|
|
35
|
+
await this.cacheService.del('key');
|
|
36
|
+
|
|
37
|
+
// Hash operations
|
|
38
|
+
await this.cacheService.hset('key', 'field', 'value');
|
|
39
|
+
const hashValue = await this.cacheService.hget('key', 'field');
|
|
40
|
+
const allValues = await this.cacheService.hgetall('key');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## TNTBaseAuthGuard
|
|
44
|
+
|
|
45
|
+
A base implementation of the auth guard to be used across each service in the system
|
|
46
|
+
|
|
47
|
+
### Dependencies:
|
|
48
|
+
|
|
49
|
+
- A JWT secret.
|
|
50
|
+
|
|
51
|
+
### Basic Usage
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { TNTBaseAuthGuard } from '@takentrade/takentrade-libs';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create your own auth guard extending the TNTBaseAuthGuard. We
|
|
58
|
+
* do this to put the TNTBaseAuthGuard in the same context as the
|
|
59
|
+
* current NestJs application for better error capturing.
|
|
60
|
+
*/
|
|
61
|
+
export class AuthGuard extends TNTBaseAuthGuard {
|
|
62
|
+
constructor(
|
|
63
|
+
private reflector: Reflector,
|
|
64
|
+
private configService: ConfigService
|
|
65
|
+
) {
|
|
66
|
+
super(reflector);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
70
|
+
const result = await super.canActivate(
|
|
71
|
+
context,
|
|
72
|
+
this.configService.get('JWT_SECRET') as string
|
|
73
|
+
);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## BullMQ Library (`@/libs/bullmq`)
|
|
80
|
+
|
|
81
|
+
Background job processing library for handling long-running tasks, retries, and scheduled jobs.
|
|
82
|
+
|
|
83
|
+
### Usage
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { BullmqModule } from '@/libs/bullmq';
|
|
87
|
+
import { join } from 'path';
|
|
88
|
+
|
|
89
|
+
// Register in your module
|
|
90
|
+
@Module({
|
|
91
|
+
imports: [
|
|
92
|
+
BullmqModule.forFeature({
|
|
93
|
+
queueName: 'my-queue',
|
|
94
|
+
processorPath: join(__dirname, 'processors', 'my.processor.js'),
|
|
95
|
+
concurrency: 3,
|
|
96
|
+
defaultJobOptions: {
|
|
97
|
+
attempts: 3,
|
|
98
|
+
backoff: {
|
|
99
|
+
type: 'exponential',
|
|
100
|
+
delay: 1000,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
],
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Create a job processor (my.processor.ts)
|
|
108
|
+
import { Job } from 'bullmq';
|
|
109
|
+
|
|
110
|
+
export default async function myProcessor(job: Job) {
|
|
111
|
+
try {
|
|
112
|
+
console.log(`Processing job ${job.id}`);
|
|
113
|
+
await job.updateProgress(50);
|
|
114
|
+
// Your job logic here
|
|
115
|
+
return { processed: true };
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(`Error processing job ${job.id}:`, error);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// In your service
|
|
123
|
+
@Injectable()
|
|
124
|
+
export class MyService {
|
|
125
|
+
constructor(
|
|
126
|
+
@Inject('BullQueue_my-queue')
|
|
127
|
+
private myQueue: Queue,
|
|
128
|
+
) {}
|
|
129
|
+
|
|
130
|
+
async addJob(data: any) {
|
|
131
|
+
// Regular job
|
|
132
|
+
await this.myQueue.add('job-name', data);
|
|
133
|
+
|
|
134
|
+
// Delayed job
|
|
135
|
+
await this.myQueue.add('delayed-job', data, {
|
|
136
|
+
delay: 5000, // 5 seconds
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Repeatable job
|
|
140
|
+
await this.myQueue.add('repeatable-job', data, {
|
|
141
|
+
repeat: {
|
|
142
|
+
every: 1000 * 60, // Every minute
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Features
|
|
150
|
+
|
|
151
|
+
1. **Queue Management**: Create, pause, resume, and clean queues
|
|
152
|
+
2. **Job Processing**: Handle long-running tasks with progress tracking
|
|
153
|
+
3. **Automatic Retries**: Configure retry attempts and backoff strategies
|
|
154
|
+
4. **Job Scheduling**: Delayed and repeatable jobs
|
|
155
|
+
5. **Event Handling**: Monitor job completion and failures
|
|
156
|
+
6. **Resource Cleanup**: Automatic cleanup on application shutdown
|
|
157
|
+
|
|
158
|
+
### Environment Variables
|
|
159
|
+
|
|
160
|
+
```env
|
|
161
|
+
# BullMQ Configuration
|
|
162
|
+
REDIS_HOST=localhost
|
|
163
|
+
REDIS_PORT=6379
|
|
164
|
+
REDIS_PASSWORD=your_password
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Notification Client
|
|
168
|
+
|
|
169
|
+
Shared utilities, constants, interfaces, and enums used across services.
|
|
170
|
+
|
|
171
|
+
### Usage
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import {
|
|
175
|
+
NOTIFICATION_QUEUE,
|
|
176
|
+
generateRandomString,
|
|
177
|
+
formatPhoneNumber,
|
|
178
|
+
OtpPurpose,
|
|
179
|
+
SwaggerConfig,
|
|
180
|
+
} from '@/libs/common';
|
|
181
|
+
|
|
182
|
+
// Use constants
|
|
183
|
+
console.log(NOTIFICATION_QUEUE); // 'notification'
|
|
184
|
+
|
|
185
|
+
// Use utility functions
|
|
186
|
+
const randomStr = generateRandomString();
|
|
187
|
+
const formattedPhone = formatPhoneNumber('+2341234567890');
|
|
188
|
+
|
|
189
|
+
// Use enums and interfaces
|
|
190
|
+
const purpose: OtpPurpose = OtpPurpose.REGISTRATION;
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Best Practices
|
|
194
|
+
|
|
195
|
+
1. Always import from the library's main entry point (e.g., `@/libs/auth` not `@/libs/auth/src/*`)
|
|
196
|
+
2. Use TypeScript types and interfaces provided by the libraries
|
|
197
|
+
3. Follow the async/await pattern when working with services
|
|
198
|
+
4. Configure modules properly in your service's root module
|
|
199
|
+
5. Handle errors appropriately as most library functions are promise-based
|
|
200
|
+
|
|
201
|
+
## Configuration
|
|
202
|
+
|
|
203
|
+
Most libraries require configuration through environment variables. Ensure these are set in your service's `.env` file:
|
|
204
|
+
|
|
205
|
+
```env
|
|
206
|
+
# Cache Configuration
|
|
207
|
+
REDIS_HOST=localhost
|
|
208
|
+
REDIS_PORT=6379
|
|
209
|
+
REDIS_PASSWORD=your_password
|
|
210
|
+
|
|
211
|
+
# NATS Configuration
|
|
212
|
+
NATS_URL=nats://localhost:4222
|
|
213
|
+
NATS_SERVICE_QUEUE=service_queue # Replace 'service' with your service name (e.g., payment_queue)
|
|
214
|
+
|
|
215
|
+
# Other configurations...
|
|
216
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
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.BullmqModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
let BullmqModule = class BullmqModule {
|
|
12
|
+
};
|
|
13
|
+
exports.BullmqModule = BullmqModule;
|
|
14
|
+
exports.BullmqModule = BullmqModule = __decorate([
|
|
15
|
+
(0, common_1.Module)({})
|
|
16
|
+
], BullmqModule);
|
|
@@ -0,0 +1,16 @@
|
|
|
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.BullmqService = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
let BullmqService = class BullmqService {
|
|
12
|
+
};
|
|
13
|
+
exports.BullmqService = BullmqService;
|
|
14
|
+
exports.BullmqService = BullmqService = __decorate([
|
|
15
|
+
(0, common_1.Injectable)()
|
|
16
|
+
], BullmqService);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ConfigService } from '@nestjs/config';
|
|
2
|
+
import { SharedBullConfigurationFactory } from '@nestjs/bullmq';
|
|
3
|
+
export declare class BullConfigFactory implements SharedBullConfigurationFactory {
|
|
4
|
+
private configService;
|
|
5
|
+
constructor(configService: ConfigService);
|
|
6
|
+
createSharedConfiguration(): {
|
|
7
|
+
connection: {
|
|
8
|
+
host: string | undefined;
|
|
9
|
+
port: number | undefined;
|
|
10
|
+
password: string | undefined;
|
|
11
|
+
};
|
|
12
|
+
defaultJobOptions: {
|
|
13
|
+
removeOnComplete: boolean;
|
|
14
|
+
removeOnFail: boolean;
|
|
15
|
+
attempts: number;
|
|
16
|
+
backoff: {
|
|
17
|
+
type: string;
|
|
18
|
+
delay: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BullConfigFactory = void 0;
|
|
4
|
+
class BullConfigFactory {
|
|
5
|
+
configService;
|
|
6
|
+
constructor(configService) {
|
|
7
|
+
this.configService = configService;
|
|
8
|
+
}
|
|
9
|
+
createSharedConfiguration() {
|
|
10
|
+
return {
|
|
11
|
+
connection: {
|
|
12
|
+
host: this.configService.get('REDIS_HOST'),
|
|
13
|
+
port: this.configService.get('REDIS_PORT'),
|
|
14
|
+
password: this.configService.get('REDIS_PASSWORD'),
|
|
15
|
+
},
|
|
16
|
+
defaultJobOptions: {
|
|
17
|
+
removeOnComplete: false, // Keep completed jobs for monitoring
|
|
18
|
+
removeOnFail: false, // Keep failed jobs for debugging
|
|
19
|
+
attempts: 3, // Default retry attempts
|
|
20
|
+
backoff: {
|
|
21
|
+
type: 'exponential',
|
|
22
|
+
delay: 1000,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.BullConfigFactory = BullConfigFactory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './bullmq.module';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bullmq.module"), exports);
|
|
@@ -0,0 +1,27 @@
|
|
|
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 CacheModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CacheModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const config_1 = require("@nestjs/config");
|
|
13
|
+
const cache_service_1 = require("./cache.service");
|
|
14
|
+
let CacheModule = CacheModule_1 = class CacheModule {
|
|
15
|
+
static register(options = {}) {
|
|
16
|
+
return {
|
|
17
|
+
module: CacheModule_1,
|
|
18
|
+
imports: [config_1.ConfigModule],
|
|
19
|
+
providers: [cache_service_1.CacheService, { provide: 'options', useValue: options }],
|
|
20
|
+
exports: [cache_service_1.CacheService],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.CacheModule = CacheModule;
|
|
25
|
+
exports.CacheModule = CacheModule = CacheModule_1 = __decorate([
|
|
26
|
+
(0, common_1.Module)({})
|
|
27
|
+
], CacheModule);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import Redis from 'ioredis';
|
|
3
|
+
import type { CacheOptions } from './cache.interface';
|
|
4
|
+
export declare class CacheService implements OnModuleInit, OnModuleDestroy {
|
|
5
|
+
private readonly options;
|
|
6
|
+
private redisClient;
|
|
7
|
+
constructor(options: CacheOptions);
|
|
8
|
+
onModuleInit(): Promise<void>;
|
|
9
|
+
onModuleDestroy(): Promise<void>;
|
|
10
|
+
getClient(): Redis;
|
|
11
|
+
set(key: string, value: string, ttlSeconds?: number): Promise<void>;
|
|
12
|
+
get(key: string): Promise<string | null>;
|
|
13
|
+
del(key: string): Promise<void>;
|
|
14
|
+
exists(key: string): Promise<boolean>;
|
|
15
|
+
ttl(key: string): Promise<number>;
|
|
16
|
+
keys(pattern: string): Promise<string[]>;
|
|
17
|
+
flushAll(): Promise<void>;
|
|
18
|
+
incr(key: string): Promise<number>;
|
|
19
|
+
decr(key: string): Promise<number>;
|
|
20
|
+
hset(key: string, field: string, value: string): Promise<void>;
|
|
21
|
+
hget(key: string, field: string): Promise<string | null>;
|
|
22
|
+
hgetall(key: string): Promise<Record<string, string>>;
|
|
23
|
+
hdel(key: string, field: string): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
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 __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
9
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CacheService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
18
|
+
let CacheService = class CacheService {
|
|
19
|
+
options;
|
|
20
|
+
redisClient;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
async onModuleInit() {
|
|
25
|
+
const options = this.options || {};
|
|
26
|
+
this.redisClient = new ioredis_1.default({
|
|
27
|
+
...options,
|
|
28
|
+
host: options.host || process.env.REDIS_HOST || 'localhost',
|
|
29
|
+
port: options.port || +(process.env?.REDIS_PORT || 6379),
|
|
30
|
+
username: options.username || process.env?.REDIS_USERNAME,
|
|
31
|
+
password: options.password || process.env?.REDIS_PASSWORD,
|
|
32
|
+
keyPrefix: options.keyPrefix || 'monita:',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async onModuleDestroy() {
|
|
36
|
+
await this.redisClient.quit();
|
|
37
|
+
}
|
|
38
|
+
getClient() {
|
|
39
|
+
return this.redisClient;
|
|
40
|
+
}
|
|
41
|
+
async set(key, value, ttlSeconds) {
|
|
42
|
+
if (ttlSeconds) {
|
|
43
|
+
await this.redisClient.setex(key, ttlSeconds, value);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
await this.redisClient.set(key, value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async get(key) {
|
|
50
|
+
return this.redisClient.get(key);
|
|
51
|
+
}
|
|
52
|
+
async del(key) {
|
|
53
|
+
await this.redisClient.del(key);
|
|
54
|
+
}
|
|
55
|
+
async exists(key) {
|
|
56
|
+
const result = await this.redisClient.exists(key);
|
|
57
|
+
return result === 1;
|
|
58
|
+
}
|
|
59
|
+
async ttl(key) {
|
|
60
|
+
return this.redisClient.ttl(key);
|
|
61
|
+
}
|
|
62
|
+
async keys(pattern) {
|
|
63
|
+
return this.redisClient.keys(pattern);
|
|
64
|
+
}
|
|
65
|
+
async flushAll() {
|
|
66
|
+
await this.redisClient.flushall();
|
|
67
|
+
}
|
|
68
|
+
async incr(key) {
|
|
69
|
+
return this.redisClient.incr(key);
|
|
70
|
+
}
|
|
71
|
+
async decr(key) {
|
|
72
|
+
return this.redisClient.decr(key);
|
|
73
|
+
}
|
|
74
|
+
async hset(key, field, value) {
|
|
75
|
+
await this.redisClient.hset(key, field, value);
|
|
76
|
+
}
|
|
77
|
+
async hget(key, field) {
|
|
78
|
+
return this.redisClient.hget(key, field);
|
|
79
|
+
}
|
|
80
|
+
async hgetall(key) {
|
|
81
|
+
return this.redisClient.hgetall(key);
|
|
82
|
+
}
|
|
83
|
+
async hdel(key, field) {
|
|
84
|
+
await this.redisClient.hdel(key, field);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
exports.CacheService = CacheService;
|
|
88
|
+
exports.CacheService = CacheService = __decorate([
|
|
89
|
+
(0, common_1.Injectable)(),
|
|
90
|
+
__param(0, (0, common_1.Inject)('options'))
|
|
91
|
+
], CacheService);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./cache.module"), exports);
|
|
18
|
+
__exportStar(require("./cache.service"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
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.CircuitBreakerModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const circuit_breaker_service_1 = require("./circuit-breaker.service");
|
|
12
|
+
let CircuitBreakerModule = class CircuitBreakerModule {
|
|
13
|
+
};
|
|
14
|
+
exports.CircuitBreakerModule = CircuitBreakerModule;
|
|
15
|
+
exports.CircuitBreakerModule = CircuitBreakerModule = __decorate([
|
|
16
|
+
(0, common_1.Module)({
|
|
17
|
+
providers: [circuit_breaker_service_1.CircuitBreakerService],
|
|
18
|
+
exports: [circuit_breaker_service_1.CircuitBreakerService],
|
|
19
|
+
})
|
|
20
|
+
], CircuitBreakerModule);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CircuitBreaker, CircuitBreakerOptions, CircuitState } from './circuit-breaker.types';
|
|
2
|
+
export declare class CircuitBreakerService {
|
|
3
|
+
private readonly logger;
|
|
4
|
+
private readonly breakers;
|
|
5
|
+
createBreaker(name: string, options?: Partial<CircuitBreakerOptions>): CircuitBreaker;
|
|
6
|
+
private startHealthCheck;
|
|
7
|
+
execute<T>(name: string, operation: () => Promise<T>): Promise<T>;
|
|
8
|
+
private onSuccess;
|
|
9
|
+
private onFailure;
|
|
10
|
+
private setState;
|
|
11
|
+
getState(name: string): CircuitState;
|
|
12
|
+
reset(name: string): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
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 CircuitBreakerService_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CircuitBreakerService = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const circuit_breaker_types_1 = require("./circuit-breaker.types");
|
|
13
|
+
let CircuitBreakerService = CircuitBreakerService_1 = class CircuitBreakerService {
|
|
14
|
+
logger = new common_1.Logger(CircuitBreakerService_1.name);
|
|
15
|
+
breakers = new Map();
|
|
16
|
+
createBreaker(name, options = {}) {
|
|
17
|
+
const defaultOptions = {
|
|
18
|
+
failureThreshold: 5,
|
|
19
|
+
resetTimeout: 60000,
|
|
20
|
+
monitorTimeout: 30000,
|
|
21
|
+
healthCheckInterval: 5000,
|
|
22
|
+
};
|
|
23
|
+
const finalOptions = { ...defaultOptions, ...options };
|
|
24
|
+
const breaker = {
|
|
25
|
+
name,
|
|
26
|
+
state: circuit_breaker_types_1.CircuitState.CLOSED,
|
|
27
|
+
failures: 0,
|
|
28
|
+
lastFailureTime: null,
|
|
29
|
+
lastSuccessTime: null,
|
|
30
|
+
options: finalOptions,
|
|
31
|
+
};
|
|
32
|
+
this.breakers.set(name, breaker);
|
|
33
|
+
this.startHealthCheck(name);
|
|
34
|
+
return breaker;
|
|
35
|
+
}
|
|
36
|
+
startHealthCheck(name) {
|
|
37
|
+
const interval = setInterval(() => {
|
|
38
|
+
const breaker = this.breakers.get(name);
|
|
39
|
+
if (!breaker) {
|
|
40
|
+
clearInterval(interval);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (breaker.state === circuit_breaker_types_1.CircuitState.OPEN) {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
const resetTime = breaker.lastFailureTime
|
|
46
|
+
? breaker.lastFailureTime + breaker.options.resetTimeout
|
|
47
|
+
: 0;
|
|
48
|
+
if (now >= resetTime) {
|
|
49
|
+
this.setState(name, circuit_breaker_types_1.CircuitState.HALF_OPEN);
|
|
50
|
+
this.logger.log(`Circuit ${name} moved to HALF_OPEN state for testing`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, this.breakers.get(name)?.options.healthCheckInterval);
|
|
54
|
+
}
|
|
55
|
+
async execute(name, operation) {
|
|
56
|
+
const breaker = this.breakers.get(name);
|
|
57
|
+
if (!breaker) {
|
|
58
|
+
throw new Error(`Circuit breaker ${name} not found`);
|
|
59
|
+
}
|
|
60
|
+
if (breaker.state === circuit_breaker_types_1.CircuitState.OPEN) {
|
|
61
|
+
throw new Error(`Circuit ${name} is OPEN`);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const result = await operation();
|
|
65
|
+
this.onSuccess(name);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.onFailure(name);
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
onSuccess(name) {
|
|
74
|
+
const breaker = this.breakers.get(name);
|
|
75
|
+
if (!breaker)
|
|
76
|
+
return;
|
|
77
|
+
breaker.failures = 0;
|
|
78
|
+
breaker.lastSuccessTime = Date.now();
|
|
79
|
+
if (breaker.state === circuit_breaker_types_1.CircuitState.HALF_OPEN) {
|
|
80
|
+
this.setState(name, circuit_breaker_types_1.CircuitState.CLOSED);
|
|
81
|
+
this.logger.log(`Circuit ${name} closed after successful test`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
onFailure(name) {
|
|
85
|
+
const breaker = this.breakers.get(name);
|
|
86
|
+
if (!breaker)
|
|
87
|
+
return;
|
|
88
|
+
breaker.failures++;
|
|
89
|
+
breaker.lastFailureTime = Date.now();
|
|
90
|
+
if (breaker.state === circuit_breaker_types_1.CircuitState.CLOSED &&
|
|
91
|
+
breaker.failures >= breaker.options.failureThreshold) {
|
|
92
|
+
this.setState(name, circuit_breaker_types_1.CircuitState.OPEN);
|
|
93
|
+
this.logger.warn(`Circuit ${name} opened after ${breaker.failures} failures`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
setState(name, state) {
|
|
97
|
+
const breaker = this.breakers.get(name);
|
|
98
|
+
if (breaker) {
|
|
99
|
+
breaker.state = state;
|
|
100
|
+
this.breakers.set(name, breaker);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
getState(name) {
|
|
104
|
+
return this.breakers.get(name)?.state || circuit_breaker_types_1.CircuitState.CLOSED;
|
|
105
|
+
}
|
|
106
|
+
reset(name) {
|
|
107
|
+
const breaker = this.breakers.get(name);
|
|
108
|
+
if (breaker) {
|
|
109
|
+
breaker.failures = 0;
|
|
110
|
+
breaker.state = circuit_breaker_types_1.CircuitState.CLOSED;
|
|
111
|
+
breaker.lastFailureTime = null;
|
|
112
|
+
breaker.lastSuccessTime = null;
|
|
113
|
+
this.breakers.set(name, breaker);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
exports.CircuitBreakerService = CircuitBreakerService;
|
|
118
|
+
exports.CircuitBreakerService = CircuitBreakerService = CircuitBreakerService_1 = __decorate([
|
|
119
|
+
(0, common_1.Injectable)()
|
|
120
|
+
], CircuitBreakerService);
|