@easyweb/rabbitmq-utils 1.0.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.
Files changed (38) hide show
  1. package/README.md +426 -0
  2. package/dist/events/base-publisher.d.ts +20 -0
  3. package/dist/events/base-publisher.d.ts.map +1 -0
  4. package/dist/events/base-publisher.js +34 -0
  5. package/dist/events/base-publisher.js.map +1 -0
  6. package/dist/events/base-subscriber.d.ts +23 -0
  7. package/dist/events/base-subscriber.d.ts.map +1 -0
  8. package/dist/events/base-subscriber.js +76 -0
  9. package/dist/events/base-subscriber.js.map +1 -0
  10. package/dist/events/exchanges.d.ts +6 -0
  11. package/dist/events/exchanges.d.ts.map +1 -0
  12. package/dist/events/exchanges.js +10 -0
  13. package/dist/events/exchanges.js.map +1 -0
  14. package/dist/events/index.d.ts +8 -0
  15. package/dist/events/index.d.ts.map +1 -0
  16. package/dist/events/index.js +29 -0
  17. package/dist/events/index.js.map +1 -0
  18. package/dist/events/routing-keys.d.ts +35 -0
  19. package/dist/events/routing-keys.d.ts.map +1 -0
  20. package/dist/events/routing-keys.js +39 -0
  21. package/dist/events/routing-keys.js.map +1 -0
  22. package/dist/events/types/auth-events.d.ts +54 -0
  23. package/dist/events/types/auth-events.d.ts.map +1 -0
  24. package/dist/events/types/auth-events.js +3 -0
  25. package/dist/events/types/auth-events.js.map +1 -0
  26. package/dist/events/types/billing-events.d.ts +143 -0
  27. package/dist/events/types/billing-events.d.ts.map +1 -0
  28. package/dist/events/types/billing-events.js +3 -0
  29. package/dist/events/types/billing-events.js.map +1 -0
  30. package/dist/events/types/website-events.d.ts +57 -0
  31. package/dist/events/types/website-events.d.ts.map +1 -0
  32. package/dist/events/types/website-events.js +3 -0
  33. package/dist/events/types/website-events.js.map +1 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +19 -0
  37. package/dist/index.js.map +1 -0
  38. package/package.json +67 -0
package/README.md ADDED
@@ -0,0 +1,426 @@
1
+ # @myfoto/easyweb-common
2
+
3
+ A shared utility library for Easyweb microservices built with TypeScript. This package provides common functionality including a type-safe RabbitMQ event system (publishers, subscribers, exchanges, and routing keys).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @myfoto/easyweb-common
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - 🚨 **Error Handling** - Custom error classes with consistent serialization
14
+ - ✅ **Validation** - Zod-based request/response validation with common patterns
15
+ - 🗃️ **Database Utilities** - Prisma helpers, transactions, and health checks
16
+ - 🔐 **Password Management** - Hashing, validation, and secure token generation
17
+ - 📄 **Response Formatting** - Standardized API responses with pagination
18
+ - 📊 **Pagination** - Cursor and offset-based pagination utilities
19
+ - 📝 **Logging** - Structured logging with performance monitoring
20
+ - 🛡️ **Middleware** - Rate limiting, error handling, and more
21
+ - 🐰 **RabbitMQ Event System** - Type-safe event-driven architecture with publishers and subscribers
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import {
27
+ // Error classes
28
+ BadRequestError,
29
+ NotFoundError,
30
+ ValidationPatterns,
31
+
32
+ // Utilities
33
+ PasswordService,
34
+ ResponseFormatter,
35
+ PaginationService,
36
+ Logger,
37
+ DatabaseService,
38
+
39
+ // Middleware
40
+ errorHandler,
41
+ validateRequest,
42
+ responseFormatter,
43
+ } from '@glow-up/common-shared';
44
+
45
+ // Use in your Express app
46
+ import express from 'express';
47
+
48
+ const app = express();
49
+
50
+ // Add response formatter middleware
51
+ app.use(responseFormatter);
52
+
53
+ // Add error handler (should be last)
54
+ app.use(errorHandler);
55
+ ```
56
+
57
+ ## Error Handling
58
+
59
+ ### Custom Error Classes
60
+
61
+ ```typescript
62
+ import {
63
+ BadRequestError,
64
+ NotFoundError,
65
+ ValidationError,
66
+ } from '@glow-up/common-shared';
67
+
68
+ // Throw errors that will be automatically handled
69
+ throw new BadRequestError('Invalid input data');
70
+ throw new NotFoundError('User not found');
71
+ throw new ValidationError([
72
+ { field: 'email', message: 'Invalid email format' },
73
+ ]);
74
+ ```
75
+
76
+ ### Error Handler Middleware
77
+
78
+ ```typescript
79
+ import { errorHandler } from '@glow-up/common-shared';
80
+
81
+ // Add as the last middleware
82
+ app.use(errorHandler);
83
+ ```
84
+
85
+ ## Validation
86
+
87
+ ### Request Validation with Zod
88
+
89
+ ```typescript
90
+ import { validateRequest, ValidationPatterns } from '@glow-up/common-shared';
91
+ import { z } from 'zod';
92
+
93
+ // Use predefined patterns
94
+ const loginSchema = {
95
+ body: z.object({
96
+ email: ValidationPatterns.email(),
97
+ password: z.string().min(1),
98
+ }),
99
+ };
100
+
101
+ app.post('/login', validateRequest(loginSchema), (req, res) => {
102
+ // req.body is now validated and typed
103
+ const { email, password } = req.body;
104
+ res.success({ message: 'Login successful' });
105
+ });
106
+
107
+ // Common validation middleware
108
+ import { ValidationMiddleware } from '@glow-up/common-shared';
109
+
110
+ app.post(
111
+ '/register',
112
+ ValidationMiddleware.validateRegistration(),
113
+ (req, res) => {
114
+ // Handles email, password, name validation
115
+ },
116
+ );
117
+ ```
118
+
119
+ ## Response Formatting
120
+
121
+ ### Standardized API Responses
122
+
123
+ ```typescript
124
+ import { ResponseFormatter } from '@glow-up/common-shared';
125
+
126
+ // Success response
127
+ ResponseFormatter.success(res, { user: userData }, 'User created');
128
+ // { success: true, message: 'User created', data: { user: userData }, metadata: { timestamp: ... } }
129
+
130
+ // Error response
131
+ ResponseFormatter.error(res, 'Invalid credentials', 'Login failed', 401);
132
+
133
+ // Paginated response
134
+ ResponseFormatter.paginated(res, users, { page: 1, limit: 10, total: 100 });
135
+
136
+ // Using middleware (adds methods to res object)
137
+ app.use(responseFormatter);
138
+
139
+ app.get('/users', (req, res) => {
140
+ res.success(users, 'Users retrieved');
141
+ res.paginated(users, paginationInfo);
142
+ res.notFound('User not found');
143
+ });
144
+ ```
145
+
146
+ ## Pagination
147
+
148
+ ```typescript
149
+ import { PaginationService, parseSort } from '@glow-up/common-shared';
150
+
151
+ // Parse pagination params
152
+ const pagination = PaginationService.parsePagination({
153
+ page: req.query.page,
154
+ limit: req.query.limit,
155
+ });
156
+
157
+ // For Prisma
158
+ const prismaOptions = PaginationService.toPrisma(pagination, sort);
159
+ const users = await prisma.user.findMany(prismaOptions);
160
+
161
+ // Generate metadata
162
+ const metadata = PaginationService.generateMetadata(
163
+ pagination.page,
164
+ pagination.limit,
165
+ totalUsers,
166
+ );
167
+
168
+ res.paginated(users, metadata);
169
+ ```
170
+
171
+ ## Database Utilities
172
+
173
+ ```typescript
174
+ import { DatabaseService } from '@glow-up/common-shared';
175
+ import { PrismaClient } from '@prisma/client';
176
+
177
+ const prisma = new PrismaClient();
178
+ const dbService = new DatabaseService(prisma);
179
+
180
+ // Health check
181
+ const health = await dbService.healthCheck();
182
+
183
+ // Transactions
184
+ const result = await dbService.withTransaction(async tx => {
185
+ const user = await tx.user.create({ data: userData });
186
+ const profile = await tx.profile.create({
187
+ data: { userId: user.id, ...profileData },
188
+ });
189
+ return { user, profile };
190
+ });
191
+
192
+ // Batch operations
193
+ await dbService.batchCreate('user', userDataArray, 50);
194
+
195
+ // Soft delete
196
+ await dbService.softDelete('user', { id: userId });
197
+ ```
198
+
199
+ ## Password Management
200
+
201
+ ```typescript
202
+ import { PasswordService } from '@glow-up/common-shared';
203
+
204
+ // Hash password
205
+ const hashedPassword = await PasswordService.hashPassword('mypassword');
206
+
207
+ // Compare password
208
+ const isValid = await PasswordService.comparePassword(
209
+ 'mypassword',
210
+ hashedPassword,
211
+ );
212
+
213
+ // Generate secure tokens
214
+ const token = PasswordService.generateSecureToken(32);
215
+ const resetToken = PasswordService.generatePasswordResetToken();
216
+
217
+ // Check password strength
218
+ const strength = PasswordService.checkPasswordStrength('mypassword');
219
+ console.log(strength.isStrong); // boolean
220
+ console.log(strength.feedback); // array of suggestions
221
+ ```
222
+
223
+ ## RabbitMQ Event System
224
+
225
+ ### Quick Start
226
+
227
+ ```typescript
228
+ import {
229
+ Publisher,
230
+ Subscriber,
231
+ Exchanges,
232
+ RoutingKeys,
233
+ UserProfileCreatedEvent,
234
+ } from '@myfoto/common-shared';
235
+ import { Channel } from 'amqplib';
236
+
237
+ // Create a publisher
238
+ export class UserProfileCreatedPublisher extends Publisher<UserProfileCreatedEvent> {
239
+ exchange = Exchanges.UserProfile;
240
+ routingKey = RoutingKeys.UserProfileCreated;
241
+ }
242
+
243
+ // Publish an event
244
+ const publisher = new UserProfileCreatedPublisher(channel);
245
+ await publisher.publish({
246
+ userId: '123',
247
+ name: 'John Doe',
248
+ email: 'john@example.com',
249
+ });
250
+
251
+ // Create a subscriber
252
+ export class UserProfileCreatedSubscriber extends Subscriber<UserProfileCreatedEvent> {
253
+ exchange = Exchanges.UserProfile;
254
+ routingKey = RoutingKeys.UserProfileCreated;
255
+
256
+ async onMessage(
257
+ data: UserProfileCreatedEvent['data'],
258
+ msg: ConsumeMessage,
259
+ ): Promise<void> {
260
+ console.log('User created:', data);
261
+ // Your business logic here
262
+ }
263
+ }
264
+
265
+ // Subscribe to events
266
+ const subscriber = new UserProfileCreatedSubscriber(channel);
267
+ await subscriber.subscribe();
268
+ ```
269
+
270
+ ### Features
271
+
272
+ - ✅ **Type-safe events** - Full TypeScript support with autocomplete
273
+ - ✅ **Centralized definitions** - All events defined in one package
274
+ - ✅ **Consistent naming** - Clear routing key conventions
275
+ - ✅ **Durable queues** - Messages persist across restarts
276
+ - ✅ **Error handling** - Automatic message requeuing on failures
277
+ - ✅ **Documentation** - Comprehensive guides and examples
278
+
279
+ ### Available Events
280
+
281
+ **User Profile**: `UserProfileCreatedEvent`, `UserProfileUpdatedEvent`, `UserProfileDeletedEvent`
282
+
283
+ **Product**: `ProductCreatedEvent`, `ProductUpdatedEvent`, `ProductDeletedEvent`, `ProductStockChangedEvent`
284
+
285
+ **Order**: `OrderCreatedEvent`, `OrderUpdatedEvent`, `OrderCompletedEvent`, `OrderCancelledEvent`
286
+
287
+ ### Routing Key Convention
288
+
289
+ Format: `<service>.<entity>.<action>`
290
+
291
+ Examples:
292
+
293
+ - `user_profile.profile.created`
294
+ - `product.product.updated`
295
+ - `order.order.completed`
296
+
297
+ ### Documentation
298
+
299
+ - 📚 [Full Event System Documentation](src/events/README.md)
300
+ - 📋 [Event Guidelines](EVENT_GUIDELINES.md)
301
+ - 🚀 [Quick Reference](QUICK_REFERENCE.md)
302
+ - 🔄 [Migration Guide](MIGRATION.md)
303
+
304
+ ## Logging
305
+
306
+ ```typescript
307
+ import { Logger, createLogger, requestLogger } from '@myfoto/common-shared';
308
+
309
+ // Use default logger
310
+ import { log } from '@glow-up/common-shared';
311
+
312
+ log.info('Application started');
313
+ log.error('Something went wrong', error, { userId: '123' });
314
+
315
+ // Create custom logger
316
+ const logger = createLogger({
317
+ level: 'debug',
318
+ enableFile: true,
319
+ filePath: './logs/app.log',
320
+ });
321
+
322
+ // Add request logging middleware
323
+ app.use(requestLogger(logger));
324
+
325
+ // Performance logging
326
+ import { timeOperation } from '@glow-up/common-shared';
327
+
328
+ const result = await timeOperation(
329
+ 'database-query',
330
+ () => prisma.user.findMany(),
331
+ logger,
332
+ );
333
+ ```
334
+
335
+ ## Validation Patterns
336
+
337
+ ```typescript
338
+ import { ValidationPatterns } from '@glow-up/common-shared';
339
+
340
+ // Email with normalization
341
+ ValidationPatterns.email();
342
+
343
+ // Strong password requirements
344
+ ValidationPatterns.password();
345
+
346
+ // UUID validation
347
+ ValidationPatterns.uuid();
348
+
349
+ // Pagination parameters
350
+ ValidationPatterns.pagination();
351
+
352
+ // Phone number
353
+ ValidationPatterns.phoneNumber();
354
+
355
+ // Custom enum with case insensitive matching
356
+ ValidationPatterns.enumCaseInsensitive(['ACTIVE', 'INACTIVE']);
357
+ ```
358
+
359
+ ## TypeScript Support
360
+
361
+ This package is built with TypeScript and provides full type definitions. All utilities are properly typed for the best development experience.
362
+
363
+ ```typescript
364
+ // Types are automatically inferred
365
+ import {
366
+ ApiResponse,
367
+ PaginatedResponse,
368
+ LogLevel,
369
+ } from '@glow-up/common-shared';
370
+
371
+ // Extend Express types (automatically included)
372
+ declare global {
373
+ namespace Express {
374
+ interface Request {
375
+ user?: {
376
+ id: string;
377
+ email: string;
378
+ roles?: string[];
379
+ };
380
+ }
381
+ interface Response {
382
+ success: (data?: any, message?: string) => void;
383
+ error: (errors: any, message?: string, statusCode?: number) => void;
384
+ // ... other response methods
385
+ }
386
+ }
387
+ }
388
+ ```
389
+
390
+ ## Peer Dependencies
391
+
392
+ Make sure to install peer dependencies if you're using related features:
393
+
394
+ ```bash
395
+ # For database utilities
396
+ npm install @prisma/client
397
+
398
+ # For logging to files (if using file logging)
399
+ npm install winston
400
+ ```
401
+
402
+ ## Contributing
403
+
404
+ This package is part of the Glow Up microservices ecosystem. When adding new utilities:
405
+
406
+ 1. Follow the existing patterns and TypeScript conventions
407
+ 2. Add proper JSDoc documentation
408
+ 3. Include unit tests
409
+ 4. Update this README with usage examples
410
+
411
+ ## License
412
+
413
+ MIT License - see LICENSE file for details.
414
+
415
+ ## Changelog
416
+
417
+ ### 1.0.0
418
+
419
+ - Initial release with core utilities
420
+ - Error handling system
421
+ - Validation middleware
422
+ - Database utilities
423
+ - Response formatting
424
+ - Pagination helpers
425
+ - Logging system
426
+ - Password management
@@ -0,0 +1,20 @@
1
+ import { Channel } from "amqplib";
2
+ interface Event {
3
+ exchange: string;
4
+ routingKey: string;
5
+ data: any;
6
+ }
7
+ export declare abstract class Publisher<T extends Event> {
8
+ abstract exchange: T["exchange"];
9
+ abstract routingKey: T["routingKey"];
10
+ protected channel: Channel;
11
+ protected options?: {
12
+ exchangeType?: "direct" | "fanout" | "topic" | "headers";
13
+ exchangeOptions?: any;
14
+ messageOptions?: any;
15
+ };
16
+ constructor(channel: Channel);
17
+ publish(data: T["data"]): Promise<void>;
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=base-publisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-publisher.d.ts","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,GAAG,CAAC;CACX;AAED,8BAAsB,SAAS,CAAC,CAAC,SAAS,KAAK;IAC7C,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IAErC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,OAAO,CAAC,EAAE;QAClB,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;QACzD,eAAe,CAAC,EAAE,GAAG,CAAC;QACtB,cAAc,CAAC,EAAE,GAAG,CAAC;KACtB,CAEC;gBAEU,OAAO,EAAE,OAAO;IAItB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAmC9C"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Publisher = void 0;
4
+ class Publisher {
5
+ constructor(channel) {
6
+ this.options = {
7
+ exchangeType: "topic",
8
+ };
9
+ this.channel = channel;
10
+ }
11
+ async publish(data) {
12
+ try {
13
+ await this.channel.assertExchange(this.exchange, this.options?.exchangeType || "topic", {
14
+ durable: true,
15
+ ...this.options?.exchangeOptions,
16
+ });
17
+ const dataString = JSON.stringify(data);
18
+ const published = this.channel.publish(this.exchange, this.routingKey, Buffer.from(dataString), {
19
+ persistent: true,
20
+ ...this.options?.messageOptions,
21
+ });
22
+ if (!published) {
23
+ throw new Error("Failed to publish message - channel buffer full");
24
+ }
25
+ console.log(`A Message published to exchange ${this.exchange} with routing key ${this.routingKey}`);
26
+ }
27
+ catch (error) {
28
+ console.error(`Failed to publish to exchange ${this.exchange}:`, error);
29
+ throw error;
30
+ }
31
+ }
32
+ }
33
+ exports.Publisher = Publisher;
34
+ //# sourceMappingURL=base-publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-publisher.js","sourceRoot":"","sources":["../../src/events/base-publisher.ts"],"names":[],"mappings":";;;AAQA,MAAsB,SAAS;IAa7B,YAAY,OAAgB;QARlB,YAAO,GAIb;YACF,YAAY,EAAE,OAAO;SACtB,CAAC;QAGA,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAe;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAC/B,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,OAAO,EACrC;gBACE,OAAO,EAAE,IAAI;gBACb,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe;aACjC,CACF,CAAC;YAEF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAExC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CACpC,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,UAAU,EACf,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EACvB;gBACE,UAAU,EAAE,IAAI;gBAChB,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc;aAChC,CACF,CAAC;YAEF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YAED,OAAO,CAAC,GAAG,CACT,mCAAmC,IAAI,CAAC,QAAQ,qBAAqB,IAAI,CAAC,UAAU,EAAE,CACvF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;YACxE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF;AApDD,8BAoDC"}
@@ -0,0 +1,23 @@
1
+ import { Channel, ConsumeMessage } from "amqplib";
2
+ interface Event {
3
+ exchange: string;
4
+ routingKey: string;
5
+ data: any;
6
+ }
7
+ export declare abstract class Subscriber<T extends Event> {
8
+ abstract exchange: T["exchange"];
9
+ abstract routingKey: T["routingKey"];
10
+ abstract onMessage(data: T["data"], msg: ConsumeMessage): Promise<void>;
11
+ protected queueName?: string;
12
+ protected channel: Channel;
13
+ protected options?: {
14
+ exchangeType?: "direct" | "fanout" | "topic" | "headers";
15
+ exchangeOptions?: any;
16
+ messageOptions?: any;
17
+ queueOptions?: any;
18
+ };
19
+ constructor(channel: Channel);
20
+ subscribe(): Promise<void>;
21
+ }
22
+ export {};
23
+ //# sourceMappingURL=base-subscriber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-subscriber.d.ts","sourceRoot":"","sources":["../../src/events/base-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAElD,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,GAAG,CAAC;CACX;AAED,8BAAsB,UAAU,CAAC,CAAC,SAAS,KAAK;IAC9C,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAEvE,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,OAAO,CAAC,EAAE;QAClB,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;QACzD,eAAe,CAAC,EAAE,GAAG,CAAC;QACtB,cAAc,CAAC,EAAE,GAAG,CAAC;QACrB,YAAY,CAAC,EAAE,GAAG,CAAC;KACpB,CAEC;gBAEU,OAAO,EAAE,OAAO;IAItB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CAgGjC"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Subscriber = void 0;
4
+ class Subscriber {
5
+ constructor(channel) {
6
+ this.options = {
7
+ exchangeType: "topic",
8
+ };
9
+ this.channel = channel;
10
+ }
11
+ async subscribe() {
12
+ if (!this.channel) {
13
+ throw new Error("Channel not initialized. Call connect() first.");
14
+ }
15
+ try {
16
+ // Assert exchange
17
+ await this.channel.assertExchange(this.exchange, this.options?.exchangeType || "topic", {
18
+ durable: true,
19
+ ...this.options?.exchangeOptions,
20
+ });
21
+ // Create durable named queue to persist messages across restarts
22
+ // Queue name format: exchange.routingKey
23
+ const queueName = this.queueName ?? `${this.exchange}.${this.routingKey}`;
24
+ const queueResult = await this.channel.assertQueue(queueName, {
25
+ durable: true,
26
+ arguments: {
27
+ "x-dead-letter-exchange": `${this.exchange}.dlx`,
28
+ "x-dead-letter-routing-key": `${this.routingKey}.dead`,
29
+ },
30
+ ...this.options?.queueOptions,
31
+ });
32
+ await this.channel.assertExchange(`${this.exchange}.dlx`, "topic", {
33
+ durable: true,
34
+ });
35
+ await this.channel.assertQueue(`${queueName}.dead`, { durable: true });
36
+ await this.channel.bindQueue(`${queueName}.dead`, `${this.exchange}.dlx`, `${this.routingKey}.dead`);
37
+ // Bind queue to exchange
38
+ await this.channel.bindQueue(queueResult.queue, this.exchange, this.routingKey);
39
+ // Set prefetch
40
+ await this.channel.prefetch(1);
41
+ // Consume messages
42
+ await this.channel.consume(queueResult.queue, async (msg) => {
43
+ if (!msg)
44
+ return;
45
+ const retryCount = (msg.properties.headers?.["x-retry-count"] ??
46
+ 0);
47
+ const MAX_RETRIES = 3;
48
+ try {
49
+ console.log(`Received message on queue: ${queueResult.queue}`);
50
+ const content = JSON.parse(msg.content.toString());
51
+ await this.onMessage(content, msg);
52
+ this.channel.ack(msg);
53
+ }
54
+ catch (error) {
55
+ console.error(`Error processing message on queue ${queueResult.queue}:`, error);
56
+ if (retryCount < MAX_RETRIES) {
57
+ // Republish with incremented retry count instead of nack requeue
58
+ this.channel.publish(this.exchange, this.routingKey, msg.content, {
59
+ persistent: true,
60
+ headers: { "x-retry-count": retryCount + 1 },
61
+ });
62
+ }
63
+ // Always ack the original to remove it from queue
64
+ this.channel.ack(msg);
65
+ }
66
+ }, { noAck: false });
67
+ console.log(`Subscribed to exchange: ${this.exchange} with routing key: ${this.routingKey} on queue: ${queueResult.queue}`);
68
+ }
69
+ catch (error) {
70
+ console.error(`Failed to subscribe to exchange ${this.exchange}:`, error);
71
+ throw error;
72
+ }
73
+ }
74
+ }
75
+ exports.Subscriber = Subscriber;
76
+ //# sourceMappingURL=base-subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-subscriber.js","sourceRoot":"","sources":["../../src/events/base-subscriber.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare enum Exchanges {
2
+ AuthService = "auth",
3
+ PaymentService = "billing",
4
+ WebsiteService = "website"
5
+ }
6
+ //# sourceMappingURL=exchanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchanges.d.ts","sourceRoot":"","sources":["../../src/events/exchanges.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,WAAW,SAAS;IACpB,cAAc,YAAY;IAC1B,cAAc,YAAY;CAC3B"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Exchanges = void 0;
4
+ var Exchanges;
5
+ (function (Exchanges) {
6
+ Exchanges["AuthService"] = "auth";
7
+ Exchanges["PaymentService"] = "billing";
8
+ Exchanges["WebsiteService"] = "website";
9
+ })(Exchanges || (exports.Exchanges = Exchanges = {}));
10
+ //# sourceMappingURL=exchanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchanges.js","sourceRoot":"","sources":["../../src/events/exchanges.ts"],"names":[],"mappings":";;;AAAA,IAAY,SAIX;AAJD,WAAY,SAAS;IACnB,iCAAoB,CAAA;IACpB,uCAA0B,CAAA;IAC1B,uCAA0B,CAAA;AAC5B,CAAC,EAJW,SAAS,yBAAT,SAAS,QAIpB"}
@@ -0,0 +1,8 @@
1
+ export * from "./base-publisher";
2
+ export * from "./base-subscriber";
3
+ export * from "./exchanges";
4
+ export * from "./routing-keys";
5
+ export * from "./types/auth-events";
6
+ export * from "./types/website-events";
7
+ export * from "./types/billing-events";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,29 @@
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
+ // Base
18
+ __exportStar(require("./base-publisher"), exports);
19
+ __exportStar(require("./base-subscriber"), exports);
20
+ // Enums
21
+ __exportStar(require("./exchanges"), exports);
22
+ __exportStar(require("./routing-keys"), exports);
23
+ // Auth
24
+ __exportStar(require("./types/auth-events"), exports);
25
+ // Website
26
+ __exportStar(require("./types/website-events"), exports);
27
+ // Billing
28
+ __exportStar(require("./types/billing-events"), exports);
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,OAAO;AACP,mDAAiC;AACjC,oDAAkC;AAElC,QAAQ;AACR,8CAA4B;AAC5B,iDAA+B;AAE/B,OAAO;AACP,sDAAoC;AAEpC,UAAU;AACV,yDAAuC;AAEvC,UAAU;AACV,yDAAuC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Routing Keys for RabbitMQ events
3
+ * Format: <service>.<entity>.<action>
4
+ *
5
+ * Examples:
6
+ * - user_profile.profile.created
7
+ * - product.product.updated
8
+ * - order.order.completed
9
+ */
10
+ export declare enum RoutingKeys {
11
+ PROSPECT_CREATED = "auth.prospect.created",
12
+ PROSPECT_UPDATED = "auth.prospect.updated",
13
+ PROSPECT_CLOSED = "auth.prospect.closed",
14
+ USER_CREATED = "auth.user.created",
15
+ USER_ACTIVATED = "auth.user.activated",
16
+ CUSTOMER_CREATED = "billing.customer.created",
17
+ SUBSCRIPTION_CREATE = "billing.subscription.create",// worker: buat recurring plan
18
+ SUBSCRIPTION_CREATED = "billing.subscription.created",
19
+ SUBSCRIPTION_ACTIVATED = "billing.subscription.activated",
20
+ SUBSCRIPTION_PAST_DUE = "billing.subscription.past_due",
21
+ SUBSCRIPTION_CANCELED = "billing.subscription.canceled",
22
+ INVOICE_PAID = "billing.invoice.paid",
23
+ PAYMENT_FAILED = "billing.payment.failed",
24
+ DOMAIN_PROCESS = "billing.domain.process",// worker: register/transfer/renew
25
+ DOMAIN_ACTIVATED = "billing.domain.activated",
26
+ ORDER_CREATED = "billing.order.created",
27
+ ORDER_PAID = "billing.order.paid",// worker: kirim email konfirmasi
28
+ PROJECT_CREATED = "website.project.created",
29
+ PROJECT_APPROVED = "website.project.approved",
30
+ PROJECT_DEPLOYED = "website.project.deployed",
31
+ PROJECT_FAILED = "website.project.failed",
32
+ PROJECT_ARCHIVED = "website.project.archived",
33
+ CUSTOMER_NEED_ASSISTANCE = "website.customer.need_assistance"
34
+ }
35
+ //# sourceMappingURL=routing-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-keys.d.ts","sourceRoot":"","sources":["../../src/events/routing-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,oBAAY,WAAW;IACrB,gBAAgB,0BAA0B;IAC1C,gBAAgB,0BAA0B;IAC1C,eAAe,yBAAyB;IAExC,YAAY,sBAAsB;IAClC,cAAc,wBAAwB;IAEtC,gBAAgB,6BAA6B;IAC7C,mBAAmB,gCAAgC,CAAE,8BAA8B;IACnF,oBAAoB,iCAAiC;IACrD,sBAAsB,mCAAmC;IACzD,qBAAqB,kCAAkC;IACvD,qBAAqB,kCAAkC;IACvD,YAAY,yBAAyB;IACrC,cAAc,2BAA2B;IAEzC,cAAc,2BAA2B,CAAE,kCAAkC;IAC7E,gBAAgB,6BAA6B;IAC7C,aAAa,0BAA0B;IACvC,UAAU,uBAAuB,CAAE,iCAAiC;IAEpE,eAAe,4BAA4B;IAC3C,gBAAgB,6BAA6B;IAC7C,gBAAgB,6BAA6B;IAC7C,cAAc,2BAA2B;IACzC,gBAAgB,6BAA6B;IAE7C,wBAAwB,qCAAqC;CAC9D"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RoutingKeys = void 0;
4
+ /**
5
+ * Routing Keys for RabbitMQ events
6
+ * Format: <service>.<entity>.<action>
7
+ *
8
+ * Examples:
9
+ * - user_profile.profile.created
10
+ * - product.product.updated
11
+ * - order.order.completed
12
+ */
13
+ var RoutingKeys;
14
+ (function (RoutingKeys) {
15
+ RoutingKeys["PROSPECT_CREATED"] = "auth.prospect.created";
16
+ RoutingKeys["PROSPECT_UPDATED"] = "auth.prospect.updated";
17
+ RoutingKeys["PROSPECT_CLOSED"] = "auth.prospect.closed";
18
+ RoutingKeys["USER_CREATED"] = "auth.user.created";
19
+ RoutingKeys["USER_ACTIVATED"] = "auth.user.activated";
20
+ RoutingKeys["CUSTOMER_CREATED"] = "billing.customer.created";
21
+ RoutingKeys["SUBSCRIPTION_CREATE"] = "billing.subscription.create";
22
+ RoutingKeys["SUBSCRIPTION_CREATED"] = "billing.subscription.created";
23
+ RoutingKeys["SUBSCRIPTION_ACTIVATED"] = "billing.subscription.activated";
24
+ RoutingKeys["SUBSCRIPTION_PAST_DUE"] = "billing.subscription.past_due";
25
+ RoutingKeys["SUBSCRIPTION_CANCELED"] = "billing.subscription.canceled";
26
+ RoutingKeys["INVOICE_PAID"] = "billing.invoice.paid";
27
+ RoutingKeys["PAYMENT_FAILED"] = "billing.payment.failed";
28
+ RoutingKeys["DOMAIN_PROCESS"] = "billing.domain.process";
29
+ RoutingKeys["DOMAIN_ACTIVATED"] = "billing.domain.activated";
30
+ RoutingKeys["ORDER_CREATED"] = "billing.order.created";
31
+ RoutingKeys["ORDER_PAID"] = "billing.order.paid";
32
+ RoutingKeys["PROJECT_CREATED"] = "website.project.created";
33
+ RoutingKeys["PROJECT_APPROVED"] = "website.project.approved";
34
+ RoutingKeys["PROJECT_DEPLOYED"] = "website.project.deployed";
35
+ RoutingKeys["PROJECT_FAILED"] = "website.project.failed";
36
+ RoutingKeys["PROJECT_ARCHIVED"] = "website.project.archived";
37
+ RoutingKeys["CUSTOMER_NEED_ASSISTANCE"] = "website.customer.need_assistance";
38
+ })(RoutingKeys || (exports.RoutingKeys = RoutingKeys = {}));
39
+ //# sourceMappingURL=routing-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-keys.js","sourceRoot":"","sources":["../../src/events/routing-keys.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,IAAY,WA6BX;AA7BD,WAAY,WAAW;IACrB,yDAA0C,CAAA;IAC1C,yDAA0C,CAAA;IAC1C,uDAAwC,CAAA;IAExC,iDAAkC,CAAA;IAClC,qDAAsC,CAAA;IAEtC,4DAA6C,CAAA;IAC7C,kEAAmD,CAAA;IACnD,oEAAqD,CAAA;IACrD,wEAAyD,CAAA;IACzD,sEAAuD,CAAA;IACvD,sEAAuD,CAAA;IACvD,oDAAqC,CAAA;IACrC,wDAAyC,CAAA;IAEzC,wDAAyC,CAAA;IACzC,4DAA6C,CAAA;IAC7C,sDAAuC,CAAA;IACvC,gDAAiC,CAAA;IAEjC,0DAA2C,CAAA;IAC3C,4DAA6C,CAAA;IAC7C,4DAA6C,CAAA;IAC7C,wDAAyC,CAAA;IACzC,4DAA6C,CAAA;IAE7C,4EAA6D,CAAA;AAC/D,CAAC,EA7BW,WAAW,2BAAX,WAAW,QA6BtB"}
@@ -0,0 +1,54 @@
1
+ import { Exchanges } from "../exchanges";
2
+ import { RoutingKeys } from "../routing-keys";
3
+ /**
4
+ * Auth Profile Service Events
5
+ */
6
+ export interface UserProfileCreatedEvent {
7
+ exchange: Exchanges.AuthService;
8
+ routingKey: RoutingKeys.USER_CREATED;
9
+ data: {
10
+ userId: string;
11
+ name?: string;
12
+ email?: string;
13
+ };
14
+ }
15
+ export interface UserProfileActivateEvent {
16
+ exchange: Exchanges.AuthService;
17
+ routingKey: RoutingKeys.USER_ACTIVATED;
18
+ data: {
19
+ isActive: boolean;
20
+ emailVerified: boolean;
21
+ emailVerifiedAt: Date;
22
+ };
23
+ }
24
+ export interface ProspectCreatedEvent {
25
+ exchange: Exchanges.AuthService;
26
+ routingKey: RoutingKeys.PROSPECT_CREATED;
27
+ data: {
28
+ prospectId: string;
29
+ contact: string;
30
+ email?: string;
31
+ };
32
+ }
33
+ export interface ProspectUpdatedEvent {
34
+ exchange: Exchanges.AuthService;
35
+ routingKey: RoutingKeys.PROSPECT_UPDATED;
36
+ data: {
37
+ prospectId: string;
38
+ status: string;
39
+ };
40
+ }
41
+ export interface ProspectClosedEvent {
42
+ exchange: Exchanges.AuthService;
43
+ routingKey: RoutingKeys.PROSPECT_CLOSED;
44
+ data: {
45
+ name: string;
46
+ prospectId: string;
47
+ externalUserId: string;
48
+ contact: string;
49
+ surveyContext?: string;
50
+ createdBy: string;
51
+ updatedAt: Date;
52
+ };
53
+ }
54
+ //# sourceMappingURL=auth-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-events.d.ts","sourceRoot":"","sources":["../../../src/events/types/auth-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;GAEG;AAEH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC;IACrC,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,cAAc,CAAC;IACvC,IAAI,EAAE;QACJ,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,IAAI,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC;IACzC,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC;IACzC,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,IAAI,CAAC;KACjB,CAAC;CACH"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=auth-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-events.js","sourceRoot":"","sources":["../../../src/events/types/auth-events.ts"],"names":[],"mappings":""}
@@ -0,0 +1,143 @@
1
+ import { Exchanges } from "../exchanges";
2
+ import { RoutingKeys } from "../routing-keys";
3
+ export type PlanType = "MONTHLY" | "ANNUAL";
4
+ export type DomainMode = "REGISTER" | "TRANSFER" | "RENEW" | "BYOD";
5
+ export type AddonCode = "PROFESSIONAL_EMAIL";
6
+ export interface CustomerCreatedEvent {
7
+ exchange: Exchanges.PaymentService;
8
+ routingKey: RoutingKeys.CUSTOMER_CREATED;
9
+ data: {
10
+ customerId: string;
11
+ externalUserId: string;
12
+ };
13
+ }
14
+ export interface SubscriptionCreatedEvent {
15
+ exchange: Exchanges.PaymentService;
16
+ routingKey: RoutingKeys.SUBSCRIPTION_CREATED;
17
+ data: {
18
+ externalUserId: string;
19
+ subscriptionId: string;
20
+ projectId: string;
21
+ };
22
+ }
23
+ export interface SubscriptionActivatedEvent {
24
+ exchange: Exchanges.PaymentService;
25
+ routingKey: RoutingKeys.SUBSCRIPTION_ACTIVATED;
26
+ data: {
27
+ externalUserId: string;
28
+ subscriptionId: string;
29
+ projectId: string;
30
+ activatedAt: Date;
31
+ addons?: AddonCode[];
32
+ };
33
+ }
34
+ export interface SubscriptionCanceledEvent {
35
+ exchange: Exchanges.PaymentService;
36
+ routingKey: RoutingKeys.SUBSCRIPTION_CANCELED;
37
+ data: {
38
+ externalUserId: string;
39
+ subscriptionId: string;
40
+ projectId: string;
41
+ canceledAt: Date;
42
+ };
43
+ }
44
+ export interface InvoicePaidEvent {
45
+ exchange: Exchanges.PaymentService;
46
+ routingKey: RoutingKeys.INVOICE_PAID;
47
+ data: {
48
+ externalUserId: string;
49
+ invoiceId: string;
50
+ projectId: string;
51
+ amount: number;
52
+ };
53
+ }
54
+ /**
55
+ * Dipublish oleh XenditWebhookService saat invoice.paid untuk item WEBSITE_SUBSCRIPTION.
56
+ * Dikonsumsi oleh SubscriptionCreateSubscriber → buat Xendit recurring plan.
57
+ */
58
+ export interface SubscriptionCreateEvent {
59
+ exchange: Exchanges.PaymentService;
60
+ routingKey: RoutingKeys.SUBSCRIPTION_CREATE;
61
+ data: {
62
+ orderId: string;
63
+ externalUserId: string;
64
+ projectId: string;
65
+ planType: PlanType;
66
+ email: string;
67
+ name?: string;
68
+ paymentTokenId?: string | null;
69
+ addons?: AddonCode[];
70
+ };
71
+ }
72
+ /**
73
+ * Dipublish oleh XenditWebhookService saat invoice.paid untuk item DOMAIN_*.
74
+ * Dikonsumsi oleh DomainProcessSubscriber → register/transfer/renew domain.
75
+ */
76
+ export interface DomainProcessEvent {
77
+ exchange: Exchanges.PaymentService;
78
+ routingKey: RoutingKeys.DOMAIN_PROCESS;
79
+ data: {
80
+ orderId: string;
81
+ orderItemId: string;
82
+ projectId: string;
83
+ domainName: string;
84
+ domainZoneId: string;
85
+ mode: DomainMode;
86
+ years?: number;
87
+ transferCode?: string;
88
+ };
89
+ }
90
+ export interface DomainActivatedEvent {
91
+ exchange: Exchanges.PaymentService;
92
+ routingKey: RoutingKeys.DOMAIN_ACTIVATED;
93
+ data: {
94
+ orderId: string;
95
+ orderItemId: string;
96
+ projectId: string;
97
+ domainName: string;
98
+ domainZoneId: string;
99
+ mode: "REGISTER" | "TRANSFER" | "RENEW" | "BYOD";
100
+ activatedAt: Date;
101
+ };
102
+ }
103
+ /**
104
+ * Dipublish oleh XenditWebhookService saat invoice.paid (selalu, untuk semua order).
105
+ * Dikonsumsi oleh OrderPaidEmailSubscriber → kirim email konfirmasi order.
106
+ */
107
+ export interface OrderPaidEvent {
108
+ exchange: Exchanges.PaymentService;
109
+ routingKey: RoutingKeys.ORDER_PAID;
110
+ data: {
111
+ orderId: string;
112
+ orderNumber: string;
113
+ externalUserId: string;
114
+ email: string;
115
+ name?: string;
116
+ total: number;
117
+ currency: string;
118
+ planType?: PlanType | null;
119
+ paymentMethod?: string;
120
+ items: Array<{
121
+ name: string;
122
+ quantity: number;
123
+ price: number;
124
+ total: number;
125
+ }>;
126
+ };
127
+ }
128
+ /**
129
+ * Dipublish oleh PaymentService saat order pertama kali dibuat.
130
+ * Dikonsumsi oleh auth service → simpan OrderReference awal.
131
+ */
132
+ export interface OrderCreatedEvent {
133
+ exchange: Exchanges.PaymentService;
134
+ routingKey: RoutingKeys.ORDER_CREATED;
135
+ data: {
136
+ orderId: string;
137
+ orderNumber: string;
138
+ externalUserId: string;
139
+ total: number;
140
+ currency: string;
141
+ };
142
+ }
143
+ //# sourceMappingURL=billing-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-events.d.ts","sourceRoot":"","sources":["../../../src/events/types/billing-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=billing-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-events.js","sourceRoot":"","sources":["../../../src/events/types/billing-events.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import { Exchanges } from "../exchanges";
2
+ import { RoutingKeys } from "../routing-keys";
3
+ /**
4
+ * Website Project Events
5
+ */
6
+ export interface ProjectCreatedEvent {
7
+ exchange: Exchanges.WebsiteService;
8
+ routingKey: RoutingKeys.PROJECT_CREATED;
9
+ data: {
10
+ projectId: string;
11
+ externalUserId: string;
12
+ prospectId?: string;
13
+ slug: string;
14
+ createdBy: string;
15
+ };
16
+ }
17
+ export interface ProjectApprovedEvent {
18
+ exchange: Exchanges.WebsiteService;
19
+ routingKey: RoutingKeys.PROJECT_APPROVED;
20
+ data: {
21
+ projectId: string;
22
+ approvedAt: Date;
23
+ };
24
+ }
25
+ export interface ProjectDeployedEvent {
26
+ exchange: Exchanges.WebsiteService;
27
+ routingKey: RoutingKeys.PROJECT_DEPLOYED;
28
+ data: {
29
+ projectId: string;
30
+ url: string;
31
+ deployedAt: Date;
32
+ };
33
+ }
34
+ export interface ProjectFailedEvent {
35
+ exchange: Exchanges.WebsiteService;
36
+ routingKey: RoutingKeys.PROJECT_FAILED;
37
+ data: {
38
+ projectId: string;
39
+ reason: string;
40
+ };
41
+ }
42
+ export interface ProjectArchivedEvent {
43
+ exchange: Exchanges.WebsiteService;
44
+ routingKey: RoutingKeys.PROJECT_ARCHIVED;
45
+ data: {
46
+ projectId: string;
47
+ };
48
+ }
49
+ export interface CustomerNeedAssistanceEvent {
50
+ exchange: Exchanges.WebsiteService;
51
+ routingKey: RoutingKeys.CUSTOMER_NEED_ASSISTANCE;
52
+ data: {
53
+ userId: string;
54
+ projectId: string;
55
+ };
56
+ }
57
+ //# sourceMappingURL=website-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-events.d.ts","sourceRoot":"","sources":["../../../src/events/types/website-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;GAEG;AAEH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC;IACxC,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC;IACzC,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,IAAI,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC;IACzC,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,IAAI,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,cAAc,CAAC;IACvC,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC;IACzC,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC;IACnC,UAAU,EAAE,WAAW,CAAC,wBAAwB,CAAC;IACjD,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=website-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-events.js","sourceRoot":"","sources":["../../../src/events/types/website-events.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export * from "./events";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
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
+ // Events - RabbitMQ Event System
18
+ __exportStar(require("./events"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iCAAiC;AACjC,2CAAyB"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@easyweb/rabbitmq-utils",
3
+ "version": "1.0.0",
4
+ "description": "Common utilities and middleware for Easyweb microservices architecture",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/index.js",
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "build:watch": "tsc --watch",
21
+ "prepublishOnly": "npm run build",
22
+ "clean": "rimraf dist",
23
+ "test": "jest",
24
+ "test:watch": "jest --watch",
25
+ "test:coverage": "jest --coverage",
26
+ "lint": "eslint src/**/*.ts",
27
+ "lint:fix": "eslint src/**/*.ts --fix"
28
+ },
29
+ "keywords": [
30
+ "microservices",
31
+ "express",
32
+ "middleware",
33
+ "validation",
34
+ "authentication",
35
+ "error-handling",
36
+ "utilities"
37
+ ],
38
+ "author": "Easy Web Team",
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/ibad-myfoto/glow-up.git",
43
+ "directory": "main-app/common-shared"
44
+ },
45
+ "dependencies": {
46
+ "amqplib": "^0.10.9"
47
+ },
48
+ "devDependencies": {
49
+ "@types/amqplib": "^0.10.8",
50
+ "@types/express": "^5.0.6",
51
+ "@types/jest": "^29.5.14",
52
+ "@types/node": "^25.2.3",
53
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
54
+ "@typescript-eslint/parser": "^8.56.1",
55
+ "eslint": "^8.50.0",
56
+ "jest": "^29.7.0",
57
+ "rimraf": "^5.0.5",
58
+ "ts-jest": "^29.1.1",
59
+ "typescript": "^5.9.3"
60
+ },
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }