@takentrade/takentrade-libs 1.2.79 → 1.3.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/README.md +677 -78
- package/dist/nats/constants/nats.constants.d.ts +0 -57
- package/dist/nats/constants/nats.constants.js +0 -69
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/enums/subaccount.enum.d.ts +11 -7
- package/dist/utils/enums/subaccount.enum.js +11 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,62 +1,53 @@
|
|
|
1
1
|
# TakeNTrade Microservices Libraries
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This package contains shared libraries used across the TakeNTrade microservices architecture. It provides authentication, caching, messaging, notifications, utilities, and common functionality to all services.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
Redis-based caching implementation for the microservices.
|
|
5
|
+
## Installation
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install @takentrade/takentrade-libs
|
|
9
|
+
```
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
- REDIS_PORT: Default to 6379
|
|
15
|
-
- REDIS_USERNAME (Optional)
|
|
16
|
-
- REDIS_PASSWORD (Optional)
|
|
11
|
+
## Table of Contents
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
- [Authentication & Authorization](#authentication--authorization)
|
|
14
|
+
- [Cache Library (`@/libs/cache`)](#cache-library-libscache)
|
|
15
|
+
- [BullMQ Library (`@/libs/bullmq`)](#bullmq-library-libsbullmq)
|
|
16
|
+
- [NATS Library (`@/libs/nats`)](#nats-library-libsnats)
|
|
17
|
+
- [Notification Client](#notification-client)
|
|
18
|
+
- [Prisma Module](#prisma-module)
|
|
19
|
+
- [RPC Utilities](#rpc-utilities)
|
|
20
|
+
- [Common Utilities](#common-utilities)
|
|
21
|
+
- [Utils Module](#utils-module)
|
|
22
|
+
- [Configuration](#configuration)
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
import { CacheModule, CacheService } from '@/libs/cache';
|
|
24
|
+
---
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
imports: [
|
|
25
|
-
CacheModule.register()
|
|
26
|
-
]
|
|
27
|
-
})
|
|
26
|
+
## Authentication & Authorization
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
constructor(private readonly cacheService: CacheService) {}
|
|
28
|
+
### TNTBaseAuthGuard
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
await this.cacheService.set('key', 'value', ttlSeconds);
|
|
34
|
-
const value = await this.cacheService.get('key');
|
|
35
|
-
await this.cacheService.del('key');
|
|
30
|
+
A base implementation of the auth guard to be used across each service in the system.
|
|
36
31
|
|
|
37
|
-
|
|
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
|
-
```
|
|
32
|
+
#### Dependencies
|
|
42
33
|
|
|
43
|
-
|
|
34
|
+
- A JWT secret (provided via `ConfigService` or environment variable)
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
### Dependencies:
|
|
48
|
-
|
|
49
|
-
- A JWT secret.
|
|
50
|
-
|
|
51
|
-
### Basic Usage
|
|
36
|
+
#### Usage
|
|
52
37
|
|
|
53
38
|
```typescript
|
|
54
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
TNTBaseAuthGuard,
|
|
41
|
+
Public,
|
|
42
|
+
Roles,
|
|
43
|
+
ROLES_KEY,
|
|
44
|
+
} from '@takentrade/takentrade-libs';
|
|
45
|
+
import { Reflector } from '@nestjs/core';
|
|
46
|
+
import { ConfigService } from '@nestjs/config';
|
|
55
47
|
|
|
56
48
|
/**
|
|
57
|
-
* Create your own auth guard extending the TNTBaseAuthGuard.
|
|
58
|
-
*
|
|
59
|
-
* current NestJs application for better error capturing.
|
|
49
|
+
* Create your own auth guard extending the TNTBaseAuthGuard.
|
|
50
|
+
* This ensures the guard is in the same context as your NestJS application for better error capturing.
|
|
60
51
|
*/
|
|
61
52
|
export class AuthGuard extends TNTBaseAuthGuard {
|
|
62
53
|
constructor(
|
|
@@ -74,16 +65,116 @@ export class AuthGuard extends TNTBaseAuthGuard {
|
|
|
74
65
|
return result;
|
|
75
66
|
}
|
|
76
67
|
}
|
|
68
|
+
|
|
69
|
+
// In your controller
|
|
70
|
+
@Controller('example')
|
|
71
|
+
@UseGuards(AuthGuard)
|
|
72
|
+
export class ExampleController {
|
|
73
|
+
// Public endpoint (no authentication required)
|
|
74
|
+
@Public()
|
|
75
|
+
@Get('public')
|
|
76
|
+
publicEndpoint() {
|
|
77
|
+
return { message: 'This is public' };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Protected endpoint (authentication required)
|
|
81
|
+
@Get('protected')
|
|
82
|
+
protectedEndpoint() {
|
|
83
|
+
return { message: 'This requires authentication' };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Role-based access control
|
|
87
|
+
@Roles('admin', 'moderator')
|
|
88
|
+
@Get('admin')
|
|
89
|
+
adminEndpoint() {
|
|
90
|
+
return { message: 'This requires admin or moderator role' };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### Decorators
|
|
96
|
+
|
|
97
|
+
- **`@Public()`**: Marks a route as publicly accessible (bypasses authentication)
|
|
98
|
+
- **`@Roles(...roles: string[])`**: Restricts access to routes based on user roles
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Cache Library (`@/libs/cache`)
|
|
103
|
+
|
|
104
|
+
Redis-based caching implementation for the microservices.
|
|
105
|
+
|
|
106
|
+
### Cache Environment Variables
|
|
107
|
+
|
|
108
|
+
```env
|
|
109
|
+
REDIS_HOST=localhost # Default: localhost
|
|
110
|
+
REDIS_PORT=6379 # Default: 6379
|
|
111
|
+
REDIS_USERNAME= # Optional
|
|
112
|
+
REDIS_PASSWORD= # Optional
|
|
77
113
|
```
|
|
78
114
|
|
|
115
|
+
### Cache Usage
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { CacheModule, CacheService } from '@takentrade/takentrade-libs';
|
|
119
|
+
|
|
120
|
+
@Module({
|
|
121
|
+
imports: [CacheModule.register()],
|
|
122
|
+
})
|
|
123
|
+
export class AppModule {}
|
|
124
|
+
|
|
125
|
+
// In your service
|
|
126
|
+
@Injectable()
|
|
127
|
+
export class MyService {
|
|
128
|
+
constructor(private readonly cacheService: CacheService) {}
|
|
129
|
+
|
|
130
|
+
// Basic cache operations
|
|
131
|
+
async example() {
|
|
132
|
+
// Set with TTL (time to live in seconds)
|
|
133
|
+
await this.cacheService.set('key', 'value', 3600); // expires in 1 hour
|
|
134
|
+
|
|
135
|
+
// Get value
|
|
136
|
+
const value = await this.cacheService.get('key');
|
|
137
|
+
|
|
138
|
+
// Delete key
|
|
139
|
+
await this.cacheService.del('key');
|
|
140
|
+
|
|
141
|
+
// Hash operations (Redis hashes)
|
|
142
|
+
await this.cacheService.hset('hash-key', 'field', 'value');
|
|
143
|
+
const hashValue = await this.cacheService.hget('hash-key', 'field');
|
|
144
|
+
const allValues = await this.cacheService.hgetall('hash-key');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Cache Methods
|
|
150
|
+
|
|
151
|
+
- `set(key: string, value: any, ttlSeconds?: number)`: Set a key-value pair with optional TTL
|
|
152
|
+
- `get(key: string)`: Get a value by key
|
|
153
|
+
- `del(key: string)`: Delete a key
|
|
154
|
+
- `hset(key: string, field: string, value: any)`: Set a hash field
|
|
155
|
+
- `hget(key: string, field: string)`: Get a hash field value
|
|
156
|
+
- `hgetall(key: string)`: Get all fields and values from a hash
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
79
160
|
## BullMQ Library (`@/libs/bullmq`)
|
|
80
161
|
|
|
81
162
|
Background job processing library for handling long-running tasks, retries, and scheduled jobs.
|
|
82
163
|
|
|
83
|
-
###
|
|
164
|
+
### BullMQ Environment Variables
|
|
165
|
+
|
|
166
|
+
```env
|
|
167
|
+
REDIS_HOST=localhost
|
|
168
|
+
REDIS_PORT=6379
|
|
169
|
+
REDIS_PASSWORD=your_password
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### BullMQ Usage
|
|
84
173
|
|
|
85
174
|
```typescript
|
|
86
|
-
import { BullmqModule } from '
|
|
175
|
+
import { BullmqModule } from '@takentrade/takentrade-libs';
|
|
176
|
+
import { Queue, Job } from 'bullmq';
|
|
177
|
+
import { Inject } from '@nestjs/common';
|
|
87
178
|
import { join } from 'path';
|
|
88
179
|
|
|
89
180
|
// Register in your module
|
|
@@ -103,10 +194,9 @@ import { join } from 'path';
|
|
|
103
194
|
}),
|
|
104
195
|
],
|
|
105
196
|
})
|
|
197
|
+
export class AppModule {}
|
|
106
198
|
|
|
107
199
|
// Create a job processor (my.processor.ts)
|
|
108
|
-
import { Job } from 'bullmq';
|
|
109
|
-
|
|
110
200
|
export default async function myProcessor(job: Job) {
|
|
111
201
|
try {
|
|
112
202
|
console.log(`Processing job ${job.id}`);
|
|
@@ -124,19 +214,19 @@ export default async function myProcessor(job: Job) {
|
|
|
124
214
|
export class MyService {
|
|
125
215
|
constructor(
|
|
126
216
|
@Inject('BullQueue_my-queue')
|
|
127
|
-
private myQueue: Queue
|
|
217
|
+
private myQueue: Queue
|
|
128
218
|
) {}
|
|
129
219
|
|
|
130
220
|
async addJob(data: any) {
|
|
131
221
|
// Regular job
|
|
132
222
|
await this.myQueue.add('job-name', data);
|
|
133
223
|
|
|
134
|
-
// Delayed job
|
|
224
|
+
// Delayed job (executes after 5 seconds)
|
|
135
225
|
await this.myQueue.add('delayed-job', data, {
|
|
136
|
-
delay: 5000,
|
|
226
|
+
delay: 5000,
|
|
137
227
|
});
|
|
138
228
|
|
|
139
|
-
// Repeatable job
|
|
229
|
+
// Repeatable job (executes every minute)
|
|
140
230
|
await this.myQueue.add('repeatable-job', data, {
|
|
141
231
|
repeat: {
|
|
142
232
|
every: 1000 * 60, // Every minute
|
|
@@ -146,7 +236,7 @@ export class MyService {
|
|
|
146
236
|
}
|
|
147
237
|
```
|
|
148
238
|
|
|
149
|
-
### Features
|
|
239
|
+
### BullMQ Features
|
|
150
240
|
|
|
151
241
|
1. **Queue Management**: Create, pause, resume, and clean queues
|
|
152
242
|
2. **Job Processing**: Handle long-running tasks with progress tracking
|
|
@@ -155,62 +245,571 @@ export class MyService {
|
|
|
155
245
|
5. **Event Handling**: Monitor job completion and failures
|
|
156
246
|
6. **Resource Cleanup**: Automatic cleanup on application shutdown
|
|
157
247
|
|
|
158
|
-
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## NATS Library (`@/libs/nats`)
|
|
251
|
+
|
|
252
|
+
NATS messaging utilities for microservice communication.
|
|
253
|
+
|
|
254
|
+
### NATS Environment Variables
|
|
159
255
|
|
|
160
256
|
```env
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
257
|
+
NATS_URL=nats://localhost:4222
|
|
258
|
+
NATS_SERVICE_QUEUE=service_queue # Replace 'service' with your service name (e.g., payment_queue)
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### NATS Usage
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import {
|
|
265
|
+
NatsSubjects,
|
|
266
|
+
NatsEventPattern,
|
|
267
|
+
NatsMessageDto,
|
|
268
|
+
NatsLoggingInterceptor,
|
|
269
|
+
NATS_CLIENT,
|
|
270
|
+
DEFAULT_NATS_CONFIG,
|
|
271
|
+
} from '@takentrade/takentrade-libs';
|
|
272
|
+
import { ClientProxy, Inject } from '@nestjs/common';
|
|
273
|
+
|
|
274
|
+
// Event handler (listening to events)
|
|
275
|
+
@Controller()
|
|
276
|
+
export class MyController {
|
|
277
|
+
@NatsEventPattern(NatsSubjects.USER_CREATED)
|
|
278
|
+
async handleUserCreated(@Payload() data: NatsMessageDto) {
|
|
279
|
+
console.log('User created:', data);
|
|
280
|
+
// Handle the event
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Using the standard EventPattern with logging
|
|
284
|
+
@EventPattern('custom.event')
|
|
285
|
+
@UseInterceptors(NatsLoggingInterceptor)
|
|
286
|
+
async handleCustomEvent(@Payload() data: any) {
|
|
287
|
+
// Handle event
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Event publisher (sending events)
|
|
292
|
+
@Injectable()
|
|
293
|
+
export class MyService {
|
|
294
|
+
constructor(@Inject(NATS_CLIENT) private readonly natsClient: ClientProxy) {}
|
|
295
|
+
|
|
296
|
+
async publishEvent() {
|
|
297
|
+
this.natsClient.emit(NatsSubjects.USER_CREATED, {
|
|
298
|
+
userId: '123',
|
|
299
|
+
email: 'user@example.com',
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// RPC request-response pattern
|
|
304
|
+
async requestData() {
|
|
305
|
+
const response = await this.natsClient
|
|
306
|
+
.send(NatsSubjects.GET_USER_BY_ID, { userId: '123' })
|
|
307
|
+
.toPromise();
|
|
308
|
+
return response;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
165
311
|
```
|
|
166
312
|
|
|
313
|
+
### NATS Subjects
|
|
314
|
+
|
|
315
|
+
The library provides a comprehensive enum of NATS subjects:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { NatsSubjects } from '@takentrade/takentrade-libs';
|
|
319
|
+
|
|
320
|
+
// Available subjects include:
|
|
321
|
+
NatsSubjects.USER_CREATED;
|
|
322
|
+
NatsSubjects.SUBACCOUNT_UPDATE_AMOUNT;
|
|
323
|
+
NatsSubjects.NOTIFICATION_SEND;
|
|
324
|
+
NatsSubjects.AJO_CREATE;
|
|
325
|
+
NatsSubjects.CHAT_GET_CONVERSATIONS;
|
|
326
|
+
// ... and many more
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### NATS Decorators
|
|
330
|
+
|
|
331
|
+
- **`@NatsEventPattern(pattern: string)`**: Decorator for NATS event handlers with automatic logging
|
|
332
|
+
- **`NatsLoggingInterceptor`**: Interceptor for logging NATS events
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
167
336
|
## Notification Client
|
|
168
337
|
|
|
169
|
-
|
|
338
|
+
Service for sending notifications via email, SMS, and push notifications.
|
|
339
|
+
|
|
340
|
+
### Notification Client Usage
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import {
|
|
344
|
+
NotificationClientModule,
|
|
345
|
+
NotificationClient,
|
|
346
|
+
} from '@takentrade/takentrade-libs';
|
|
347
|
+
|
|
348
|
+
@Module({
|
|
349
|
+
imports: [NotificationClientModule],
|
|
350
|
+
})
|
|
351
|
+
export class AppModule {}
|
|
352
|
+
|
|
353
|
+
// In your service
|
|
354
|
+
@Injectable()
|
|
355
|
+
export class MyService {
|
|
356
|
+
constructor(private readonly notificationClient: NotificationClient) {}
|
|
357
|
+
|
|
358
|
+
async sendNotifications() {
|
|
359
|
+
// Send SMS
|
|
360
|
+
await this.notificationClient.sendSms(
|
|
361
|
+
'+2341234567890',
|
|
362
|
+
'Your OTP is 123456'
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
// Send Email
|
|
366
|
+
await this.notificationClient.sendEmailVerificationMail(
|
|
367
|
+
'user@example.com',
|
|
368
|
+
{
|
|
369
|
+
name: 'John Doe',
|
|
370
|
+
verificationLink: 'https://example.com/verify?token=abc123',
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// Send OTP Email
|
|
375
|
+
await this.notificationClient.sendOTPMail('user@example.com', {
|
|
376
|
+
name: 'John Doe',
|
|
377
|
+
otp: '123456',
|
|
378
|
+
purpose: 'phone_verification',
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Send Password Reset Email
|
|
382
|
+
await this.notificationClient.sendPasswordResetMail('user@example.com', {
|
|
383
|
+
name: 'John Doe',
|
|
384
|
+
resetLink: 'https://example.com/reset?token=abc123',
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Send Push Notification
|
|
388
|
+
await this.notificationClient.sendPushNotification({
|
|
389
|
+
userId: '123',
|
|
390
|
+
title: 'New Message',
|
|
391
|
+
body: 'You have a new message',
|
|
392
|
+
data: { messageId: '456' },
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Notification Client Methods
|
|
399
|
+
|
|
400
|
+
The `NotificationClient` provides numerous methods for different notification types:
|
|
401
|
+
|
|
402
|
+
- Email notifications (verification, OTP, password reset, transaction alerts, etc.)
|
|
403
|
+
- SMS notifications
|
|
404
|
+
- Push notifications
|
|
405
|
+
- Custom notifications
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Prisma Module
|
|
410
|
+
|
|
411
|
+
Global Prisma service module for database access.
|
|
412
|
+
|
|
413
|
+
### Prisma Usage
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { PrismaModule, PrismaService } from '@takentrade/takentrade-libs';
|
|
417
|
+
|
|
418
|
+
@Module({
|
|
419
|
+
imports: [PrismaModule], // Global module, available everywhere
|
|
420
|
+
})
|
|
421
|
+
export class AppModule {}
|
|
422
|
+
|
|
423
|
+
// In your service
|
|
424
|
+
@Injectable()
|
|
425
|
+
export class MyService {
|
|
426
|
+
constructor(private readonly prisma: PrismaService) {}
|
|
427
|
+
|
|
428
|
+
async getUsers() {
|
|
429
|
+
return this.prisma.user.findMany();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## RPC Utilities
|
|
437
|
+
|
|
438
|
+
Utilities for handling RPC (Request-Response) patterns in NATS.
|
|
439
|
+
|
|
440
|
+
### RPC Usage
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
import { TakeNTradeRpc, TakeNTradeRpcV2 } from '@takentrade/takentrade-libs';
|
|
444
|
+
import { NatsContext } from '@nestjs/microservices';
|
|
445
|
+
|
|
446
|
+
// RPC handler with automatic error handling
|
|
447
|
+
@Controller()
|
|
448
|
+
export class MyController {
|
|
449
|
+
@MessagePattern('get.user.by.id')
|
|
450
|
+
async getUserById(@Payload() data: any, @Ctx() ctx: NatsContext) {
|
|
451
|
+
return TakeNTradeRpc.handleRequest(
|
|
452
|
+
this.userService.findById(data.userId),
|
|
453
|
+
ctx
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Alternative version that returns error directly instead of RpcException
|
|
458
|
+
@MessagePattern('get.user.balance')
|
|
459
|
+
async getUserBalance(@Payload() data: any, @Ctx() ctx: NatsContext) {
|
|
460
|
+
return TakeNTradeRpcV2.handleRequest(
|
|
461
|
+
this.userService.getBalance(data.userId),
|
|
462
|
+
ctx
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
170
466
|
|
|
171
|
-
|
|
467
|
+
// RPC client (sending requests)
|
|
468
|
+
@Injectable()
|
|
469
|
+
export class MyService {
|
|
470
|
+
constructor(@Inject(NATS_CLIENT) private readonly natsClient: ClientProxy) {}
|
|
471
|
+
|
|
472
|
+
async getUserData(userId: string) {
|
|
473
|
+
const response = await TakeNTradeRpc.withReply(
|
|
474
|
+
this.natsClient.send('get.user.by.id', { userId })
|
|
475
|
+
);
|
|
476
|
+
return response.data;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### RPC Classes
|
|
482
|
+
|
|
483
|
+
- **`TakeNTradeRpc`**: Main RPC utility with automatic error handling that throws `RpcException`
|
|
484
|
+
- **`TakeNTradeRpcV2`**: Alternative RPC utility that returns error objects instead of throwing exceptions
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Common Utilities
|
|
489
|
+
|
|
490
|
+
### Common Constants
|
|
172
491
|
|
|
173
492
|
```typescript
|
|
174
493
|
import {
|
|
175
494
|
NOTIFICATION_QUEUE,
|
|
176
|
-
|
|
177
|
-
|
|
495
|
+
AJO_QUEUE,
|
|
496
|
+
PAYMENT_QUEUE,
|
|
497
|
+
// ... and other queue constants
|
|
498
|
+
} from '@takentrade/takentrade-libs';
|
|
499
|
+
|
|
500
|
+
// Queue names for BullMQ
|
|
501
|
+
const queueName = NOTIFICATION_QUEUE; // 'notification_queue'
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Common Enums
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
import {
|
|
178
508
|
OtpPurpose,
|
|
179
|
-
|
|
180
|
-
|
|
509
|
+
SubAccountType,
|
|
510
|
+
TicketStatus, // from common/enums
|
|
511
|
+
SupportActionType, // from common/enums
|
|
512
|
+
} from '@takentrade/takentrade-libs';
|
|
513
|
+
|
|
514
|
+
// OTP purposes
|
|
515
|
+
const purpose: OtpPurpose = OtpPurpose.PHONE_VERIFICATION;
|
|
516
|
+
|
|
517
|
+
// Subaccount types
|
|
518
|
+
const accountType: SubAccountType = SubAccountType.SAVINGS_ACCOUNT;
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### String Utilities
|
|
181
522
|
|
|
182
|
-
|
|
183
|
-
|
|
523
|
+
```typescript
|
|
524
|
+
import {
|
|
525
|
+
formatPhoneNumber,
|
|
526
|
+
maskPhoneNumber,
|
|
527
|
+
} from '@takentrade/takentrade-libs';
|
|
184
528
|
|
|
185
|
-
//
|
|
186
|
-
const
|
|
187
|
-
const formattedPhone = formatPhoneNumber('+2341234567890');
|
|
529
|
+
// Format phone number to international format
|
|
530
|
+
const formatted = formatPhoneNumber('08123456789'); // '2348123456789'
|
|
188
531
|
|
|
189
|
-
//
|
|
190
|
-
const
|
|
532
|
+
// Mask phone number for display
|
|
533
|
+
const masked = maskPhoneNumber('+2348123456789'); // '2348******789'
|
|
191
534
|
```
|
|
192
535
|
|
|
193
|
-
|
|
536
|
+
### Random Utilities
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
import {
|
|
540
|
+
generateRandomString,
|
|
541
|
+
RandomStringOptions,
|
|
542
|
+
} from '@takentrade/takentrade-libs';
|
|
543
|
+
|
|
544
|
+
// Generate random string (default: 6 digits)
|
|
545
|
+
const randomCode = generateRandomString(); // '123456'
|
|
546
|
+
|
|
547
|
+
// Custom options
|
|
548
|
+
const randomPassword = generateRandomString({
|
|
549
|
+
length: 12,
|
|
550
|
+
digits: true,
|
|
551
|
+
lowerCaseAlphabets: true,
|
|
552
|
+
upperCaseAlphabets: true,
|
|
553
|
+
specialChars: true,
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Reference Utilities
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
import { generateReference } from '@takentrade/takentrade-libs';
|
|
561
|
+
|
|
562
|
+
// Generate unique reference string
|
|
563
|
+
const ref = generateReference('TXN'); // 'TXN-1234567890-ABC'
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### Circuit Breaker
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
import {
|
|
570
|
+
CircuitBreakerModule,
|
|
571
|
+
CircuitBreakerService,
|
|
572
|
+
} from '@takentrade/takentrade-libs';
|
|
573
|
+
|
|
574
|
+
@Module({
|
|
575
|
+
imports: [CircuitBreakerModule],
|
|
576
|
+
})
|
|
577
|
+
export class AppModule {}
|
|
578
|
+
|
|
579
|
+
@Injectable()
|
|
580
|
+
export class MyService {
|
|
581
|
+
constructor(private readonly circuitBreaker: CircuitBreakerService) {}
|
|
582
|
+
|
|
583
|
+
async callExternalService() {
|
|
584
|
+
const breaker = this.circuitBreaker.createBreaker('external-api', {
|
|
585
|
+
failureThreshold: 5,
|
|
586
|
+
resetTimeout: 60000,
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
if (this.circuitBreaker.isOpen('external-api')) {
|
|
590
|
+
throw new Error('Circuit breaker is open');
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
try {
|
|
594
|
+
const result = await this.externalApiCall();
|
|
595
|
+
this.circuitBreaker.recordSuccess('external-api');
|
|
596
|
+
return result;
|
|
597
|
+
} catch (error) {
|
|
598
|
+
this.circuitBreaker.recordFailure('external-api');
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Health Module
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
import { HealthModule } from '@takentrade/takentrade-libs';
|
|
609
|
+
|
|
610
|
+
@Module({
|
|
611
|
+
imports: [HealthModule],
|
|
612
|
+
})
|
|
613
|
+
export class AppModule {}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
The health module provides a `/health` endpoint for service health checks.
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## Utils Module
|
|
621
|
+
|
|
622
|
+
### DTOs
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
import { PaginationDto } from '@takentrade/takentrade-libs';
|
|
626
|
+
|
|
627
|
+
// Pagination DTO for request queries
|
|
628
|
+
export class GetUsersDto extends PaginationDto {
|
|
629
|
+
@IsOptional()
|
|
630
|
+
@IsString()
|
|
631
|
+
search?: string;
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Pipes
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
import { PaginationQueryCleanerPipe } from '@takentrade/takentrade-libs';
|
|
639
|
+
|
|
640
|
+
@Controller('users')
|
|
641
|
+
export class UserController {
|
|
642
|
+
@Get()
|
|
643
|
+
async getUsers(
|
|
644
|
+
@Query(PaginationQueryCleanerPipe) query: any // Removes page and limit from query
|
|
645
|
+
) {
|
|
646
|
+
// query object will not contain page and limit fields
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### Interceptors
|
|
194
652
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
653
|
+
```typescript
|
|
654
|
+
import { ResponseInterceptor } from '@takentrade/takentrade-libs';
|
|
655
|
+
|
|
656
|
+
@Module({
|
|
657
|
+
providers: [
|
|
658
|
+
{
|
|
659
|
+
provide: APP_INTERCEPTOR,
|
|
660
|
+
useClass: ResponseInterceptor,
|
|
661
|
+
},
|
|
662
|
+
],
|
|
663
|
+
})
|
|
664
|
+
export class AppModule {}
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
The `ResponseInterceptor` automatically wraps all responses in a standard format:
|
|
668
|
+
|
|
669
|
+
```json
|
|
670
|
+
{
|
|
671
|
+
"success": true,
|
|
672
|
+
"message": "Operation successful",
|
|
673
|
+
"data": {
|
|
674
|
+
/* your data */
|
|
675
|
+
},
|
|
676
|
+
"metadata": {
|
|
677
|
+
"path": "/api/users",
|
|
678
|
+
"requestId": "uuid",
|
|
679
|
+
"timestamp": "2024-01-01T00:00:00Z"
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### Filters
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
import { HttpExceptionFilter } from '@takentrade/takentrade-libs';
|
|
688
|
+
|
|
689
|
+
@Module({
|
|
690
|
+
providers: [
|
|
691
|
+
{
|
|
692
|
+
provide: APP_FILTER,
|
|
693
|
+
useClass: HttpExceptionFilter,
|
|
694
|
+
},
|
|
695
|
+
],
|
|
696
|
+
})
|
|
697
|
+
export class AppModule {}
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
The `HttpExceptionFilter` catches all exceptions and formats them consistently.
|
|
701
|
+
|
|
702
|
+
### Validators
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
import { ValidateNatsMessage } from '@takentrade/takentrade-libs';
|
|
706
|
+
|
|
707
|
+
@Controller()
|
|
708
|
+
export class MyController {
|
|
709
|
+
@EventPattern('user.created')
|
|
710
|
+
async handleUserCreated(
|
|
711
|
+
@Payload(ValidateNatsMessage(UserCreatedDto)) data: UserCreatedDto
|
|
712
|
+
) {
|
|
713
|
+
// data is validated and typed
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### Response Utilities
|
|
719
|
+
|
|
720
|
+
```typescript
|
|
721
|
+
import { AppResponse } from '@takentrade/takentrade-libs';
|
|
722
|
+
|
|
723
|
+
@Controller()
|
|
724
|
+
export class MyController {
|
|
725
|
+
@Get('users')
|
|
726
|
+
async getUsers() {
|
|
727
|
+
const users = await this.userService.findAll();
|
|
728
|
+
return AppResponse.success(users, 'Users retrieved successfully');
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### Pagination Utilities
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
import { paginate } from '@takentrade/takentrade-libs';
|
|
737
|
+
|
|
738
|
+
const result = paginate([1, 2, 3, 4, 5], 1, 2);
|
|
739
|
+
// Returns: { data: [1, 2], total: 5, page: 1, limit: 2, totalPages: 3 }
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### OTP Utilities
|
|
743
|
+
|
|
744
|
+
```typescript
|
|
745
|
+
import { generateOTP, verifyOTP } from '@takentrade/takentrade-libs';
|
|
746
|
+
|
|
747
|
+
// Generate OTP
|
|
748
|
+
const otp = generateOTP(6); // 6-digit OTP
|
|
749
|
+
|
|
750
|
+
// Verify OTP (with expiration)
|
|
751
|
+
const isValid = verifyOTP(otp, storedOtp, expirationTime);
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Configuration Utilities
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
import { getConfiguration } from '@takentrade/takentrade-libs';
|
|
758
|
+
|
|
759
|
+
const config = getConfiguration();
|
|
760
|
+
// Returns typed configuration object
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
---
|
|
200
764
|
|
|
201
765
|
## Configuration
|
|
202
766
|
|
|
203
767
|
Most libraries require configuration through environment variables. Ensure these are set in your service's `.env` file:
|
|
204
768
|
|
|
205
769
|
```env
|
|
206
|
-
# Cache Configuration
|
|
770
|
+
# Cache & BullMQ Configuration
|
|
207
771
|
REDIS_HOST=localhost
|
|
208
772
|
REDIS_PORT=6379
|
|
773
|
+
REDIS_USERNAME=
|
|
209
774
|
REDIS_PASSWORD=your_password
|
|
210
775
|
|
|
211
776
|
# NATS Configuration
|
|
212
777
|
NATS_URL=nats://localhost:4222
|
|
213
|
-
NATS_SERVICE_QUEUE=service_queue # Replace 'service' with your service name
|
|
778
|
+
NATS_SERVICE_QUEUE=service_queue # Replace 'service' with your service name
|
|
779
|
+
|
|
780
|
+
# JWT Configuration
|
|
781
|
+
JWT_SECRET=your_jwt_secret
|
|
214
782
|
|
|
215
|
-
#
|
|
783
|
+
# Database (for Prisma)
|
|
784
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
|
216
785
|
```
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
## Best Practices
|
|
790
|
+
|
|
791
|
+
1. **Always import from the library's main entry point**: Use `@takentrade/takentrade-libs` instead of internal paths
|
|
792
|
+
2. **Use TypeScript types and interfaces**: Take advantage of the provided types for better type safety
|
|
793
|
+
3. **Follow async/await pattern**: Most library functions are promise-based
|
|
794
|
+
4. **Configure modules properly**: Register modules in your service's root module
|
|
795
|
+
5. **Handle errors appropriately**: Use the provided filters and interceptors for consistent error handling
|
|
796
|
+
6. **Use constants for NATS subjects**: Always use `NatsSubjects` enum instead of hardcoding subject strings
|
|
797
|
+
7. **Leverage RPC utilities**: Use `TakeNTradeRpc` for consistent RPC error handling
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
## Exports
|
|
802
|
+
|
|
803
|
+
The package exports the following sub-paths:
|
|
804
|
+
|
|
805
|
+
- `@takentrade/takentrade-libs` - Main entry point
|
|
806
|
+
- `@takentrade/takentrade-libs/bullmq` - BullMQ module
|
|
807
|
+
- `@takentrade/takentrade-libs/cache` - Cache module
|
|
808
|
+
- `@takentrade/takentrade-libs/common` - Common utilities
|
|
809
|
+
- `@takentrade/takentrade-libs/nats` - NATS utilities
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
## License
|
|
814
|
+
|
|
815
|
+
MIT
|