@royalinvest/dto 0.57.0 → 0.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/logger/index.d.ts +6 -0
- package/dist/logger/index.js +36 -0
- package/dist/metrics/business.d.ts +5 -0
- package/dist/metrics/business.js +33 -0
- package/dist/metrics/core.d.ts +9 -0
- package/dist/metrics/core.js +59 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.js +18 -0
- package/dist/property.d.ts +0 -1
- package/dist/rabbitmq/constants.d.ts +76 -0
- package/dist/rabbitmq/constants.js +79 -0
- package/dist/rabbitmq/consumer.d.ts +19 -0
- package/dist/rabbitmq/consumer.js +86 -0
- package/dist/rabbitmq/index.d.ts +3 -0
- package/dist/rabbitmq/index.js +19 -0
- package/dist/rabbitmq/producer.d.ts +13 -0
- package/dist/rabbitmq/producer.js +101 -0
- package/dist/user.d.ts +2 -0
- package/package.json +12 -3
- package/dist/billing.d.ts +0 -1
- package/dist/billing.js +0 -2
- package/dist/invoiceFormData.d.ts +0 -51
- package/dist/invoiceFormData.js +0 -2
- package/dist/payment.d.ts +0 -1
- package/dist/payment.js +0 -2
- package/dist/reportData.d.ts +0 -2
- package/dist/reportData.js +0 -2
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -90,3 +90,6 @@ __exportStar(require("./template"), exports);
|
|
|
90
90
|
__exportStar(require("./types"), exports);
|
|
91
91
|
__exportStar(require("./user"), exports);
|
|
92
92
|
__exportStar(require("./yes-no"), exports);
|
|
93
|
+
__exportStar(require("./metrics"), exports);
|
|
94
|
+
__exportStar(require("./rabbitmq"), exports);
|
|
95
|
+
__exportStar(require("./logger"), exports);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.baseLogger = void 0;
|
|
7
|
+
exports.createScopedLogger = createScopedLogger;
|
|
8
|
+
const pino_1 = __importDefault(require("pino"));
|
|
9
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
10
|
+
const LOG_LEVEL = process.env.LOG_LEVEL || "info";
|
|
11
|
+
exports.baseLogger = (0, pino_1.default)({
|
|
12
|
+
level: LOG_LEVEL,
|
|
13
|
+
formatters: {
|
|
14
|
+
level(label) {
|
|
15
|
+
return { level: label };
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
timestamp: pino_1.default.stdTimeFunctions.isoTime,
|
|
19
|
+
transport: isDev
|
|
20
|
+
? {
|
|
21
|
+
target: "pino-pretty",
|
|
22
|
+
options: {
|
|
23
|
+
colorize: true,
|
|
24
|
+
translateTime: "yyyy-mm-dd HH:MM:ss",
|
|
25
|
+
ignore: "pid,hostname",
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
: undefined,
|
|
29
|
+
});
|
|
30
|
+
function createScopedLogger({ requestId, userId }) {
|
|
31
|
+
let scoped = exports.baseLogger.child({ request_id: requestId });
|
|
32
|
+
if (userId) {
|
|
33
|
+
scoped = scoped.child({ user_id: userId });
|
|
34
|
+
}
|
|
35
|
+
return scoped;
|
|
36
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import client from "prom-client";
|
|
2
|
+
export declare const leaseAgreementsCreated: client.Counter<string>;
|
|
3
|
+
export declare const documentsSigned: client.Counter<string>;
|
|
4
|
+
export declare const creditChecksPerformed: client.Counter<"status" | "bureau">;
|
|
5
|
+
export declare const creditCheckProcessingDuration: client.Histogram<"queue" | "bureau">;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.creditCheckProcessingDuration = exports.creditChecksPerformed = exports.documentsSigned = exports.leaseAgreementsCreated = void 0;
|
|
7
|
+
const prom_client_1 = __importDefault(require("prom-client"));
|
|
8
|
+
const core_1 = require("./core");
|
|
9
|
+
// --- Business Metrics ---
|
|
10
|
+
exports.leaseAgreementsCreated = new prom_client_1.default.Counter({
|
|
11
|
+
name: "lease_agreements_created_total",
|
|
12
|
+
help: "Total number of lease agreements created",
|
|
13
|
+
});
|
|
14
|
+
exports.documentsSigned = new prom_client_1.default.Counter({
|
|
15
|
+
name: "documents_signed_total",
|
|
16
|
+
help: "Total number of documents signed successfully",
|
|
17
|
+
});
|
|
18
|
+
exports.creditChecksPerformed = new prom_client_1.default.Counter({
|
|
19
|
+
name: "credit_checks_performed_total",
|
|
20
|
+
help: "Total number of credit checks performed",
|
|
21
|
+
labelNames: ["bureau", "status"],
|
|
22
|
+
});
|
|
23
|
+
exports.creditCheckProcessingDuration = new prom_client_1.default.Histogram({
|
|
24
|
+
name: "credit_check_processing_duration_seconds",
|
|
25
|
+
help: "Duration of credit check processing in seconds",
|
|
26
|
+
labelNames: ["queue", "bureau"],
|
|
27
|
+
buckets: [0.5, 1, 2, 3, 5, 10, 30],
|
|
28
|
+
});
|
|
29
|
+
// Register business metrics
|
|
30
|
+
core_1.register.registerMetric(exports.leaseAgreementsCreated);
|
|
31
|
+
core_1.register.registerMetric(exports.documentsSigned);
|
|
32
|
+
core_1.register.registerMetric(exports.creditChecksPerformed);
|
|
33
|
+
core_1.register.registerMetric(exports.creditCheckProcessingDuration);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import client from "prom-client";
|
|
2
|
+
export declare const register: client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
3
|
+
export declare const apiRequests: client.Counter<"method" | "route" | "status">;
|
|
4
|
+
export declare const apiRequestDuration: client.Histogram<"method" | "route" | "status">;
|
|
5
|
+
export declare const messagesReceived: client.Counter<"queue" | "routingKey" | "bureau">;
|
|
6
|
+
export declare const messagesProcessed: client.Counter<"queue" | "routingKey" | "bureau">;
|
|
7
|
+
export declare const messagesFailed: client.Counter<"queue" | "routingKey" | "bureau" | "exchange">;
|
|
8
|
+
export declare const messageRetries: client.Counter<"queue" | "routingKey" | "bureau" | "exchange">;
|
|
9
|
+
export declare const messagesPublished: client.Counter<"routingKey" | "bureau" | "exchange">;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.messagesPublished = exports.messageRetries = exports.messagesFailed = exports.messagesProcessed = exports.messagesReceived = exports.apiRequestDuration = exports.apiRequests = exports.register = void 0;
|
|
7
|
+
const prom_client_1 = __importDefault(require("prom-client"));
|
|
8
|
+
// Registry for this service
|
|
9
|
+
exports.register = new prom_client_1.default.Registry();
|
|
10
|
+
// Collect default Node.js metrics
|
|
11
|
+
prom_client_1.default.collectDefaultMetrics({
|
|
12
|
+
register: exports.register,
|
|
13
|
+
prefix: "royalinvest_platform_",
|
|
14
|
+
});
|
|
15
|
+
// --- Infrastructure Metrics ---
|
|
16
|
+
exports.apiRequests = new prom_client_1.default.Counter({
|
|
17
|
+
name: "api_requests_total",
|
|
18
|
+
help: "Total number of API requests",
|
|
19
|
+
labelNames: ["method", "route", "status"],
|
|
20
|
+
});
|
|
21
|
+
exports.apiRequestDuration = new prom_client_1.default.Histogram({
|
|
22
|
+
name: "api_request_duration_seconds",
|
|
23
|
+
help: "Duration of API requests in seconds",
|
|
24
|
+
labelNames: ["method", "route", "status"],
|
|
25
|
+
buckets: [0.1, 0.5, 1, 2, 5, 10],
|
|
26
|
+
});
|
|
27
|
+
exports.messagesReceived = new prom_client_1.default.Counter({
|
|
28
|
+
name: "messages_received_total",
|
|
29
|
+
help: "Total number of RabbitMQ messages received",
|
|
30
|
+
labelNames: ["queue", "routingKey", "bureau"],
|
|
31
|
+
});
|
|
32
|
+
exports.messagesProcessed = new prom_client_1.default.Counter({
|
|
33
|
+
name: "messages_processed_total",
|
|
34
|
+
help: "Total number of RabbitMQ messages successfully processed",
|
|
35
|
+
labelNames: ["queue", "routingKey", "bureau"],
|
|
36
|
+
});
|
|
37
|
+
exports.messagesFailed = new prom_client_1.default.Counter({
|
|
38
|
+
name: "messages_failed_total",
|
|
39
|
+
help: "Total number of RabbitMQ messages failed",
|
|
40
|
+
labelNames: ["exchange", "queue", "routingKey", "bureau"],
|
|
41
|
+
});
|
|
42
|
+
exports.messageRetries = new prom_client_1.default.Counter({
|
|
43
|
+
name: "messages_retried_total",
|
|
44
|
+
help: "Total number of RabbitMQ messages retried",
|
|
45
|
+
labelNames: ["exchange", "queue", "routingKey", "bureau"],
|
|
46
|
+
});
|
|
47
|
+
exports.messagesPublished = new prom_client_1.default.Counter({
|
|
48
|
+
name: "messages_published_total",
|
|
49
|
+
help: "Total number of RabbitMQ messages published",
|
|
50
|
+
labelNames: ["exchange", "routingKey", "bureau"],
|
|
51
|
+
});
|
|
52
|
+
// Register all core metrics
|
|
53
|
+
exports.register.registerMetric(exports.apiRequests);
|
|
54
|
+
exports.register.registerMetric(exports.apiRequestDuration);
|
|
55
|
+
exports.register.registerMetric(exports.messagesReceived);
|
|
56
|
+
exports.register.registerMetric(exports.messagesProcessed);
|
|
57
|
+
exports.register.registerMetric(exports.messagesFailed);
|
|
58
|
+
exports.register.registerMetric(exports.messageRetries);
|
|
59
|
+
exports.register.registerMetric(exports.messagesPublished);
|
|
@@ -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("./core"), exports);
|
|
18
|
+
__exportStar(require("./business"), exports);
|
package/dist/property.d.ts
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export declare const RABBITMQ_EXCHANGES: {
|
|
2
|
+
readonly log: {
|
|
3
|
+
readonly name: "LOG_EXCHANGE";
|
|
4
|
+
readonly keys: {
|
|
5
|
+
readonly error: "*.error";
|
|
6
|
+
readonly other: "*.other";
|
|
7
|
+
};
|
|
8
|
+
readonly queues: {
|
|
9
|
+
readonly log: "log_queue";
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
readonly notification: {
|
|
13
|
+
readonly name: "NOTIFICATION_EXCHANGE";
|
|
14
|
+
readonly keys: {
|
|
15
|
+
readonly generated: "notification.generated";
|
|
16
|
+
readonly signed: "notification.signed";
|
|
17
|
+
readonly voided: "notification.voided";
|
|
18
|
+
readonly generated_certificate: "notification.generated_certificate";
|
|
19
|
+
readonly generated_invoice: "notification.generated_invoice";
|
|
20
|
+
readonly generated_credit_check_report: "notification.generated_credit_check_report";
|
|
21
|
+
readonly credit_check_completed: "notification.credit_check_completed";
|
|
22
|
+
readonly credit_check_failed: "notification.credit_check_failed";
|
|
23
|
+
};
|
|
24
|
+
readonly queues: {
|
|
25
|
+
readonly notification: "notification_queue";
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
readonly generate: {
|
|
29
|
+
readonly name: "GENERATE_EXCHANGE";
|
|
30
|
+
readonly keys: {
|
|
31
|
+
readonly generate: "generate";
|
|
32
|
+
readonly signature: "signature";
|
|
33
|
+
readonly void: "void";
|
|
34
|
+
readonly generate_certificate: "generate_certificate";
|
|
35
|
+
readonly generate_invoice: "generate_invoice";
|
|
36
|
+
readonly generated_credit_check_report: "generate_credit_check_report";
|
|
37
|
+
};
|
|
38
|
+
readonly queues: {
|
|
39
|
+
readonly lease_generate: "lease_generate_queue";
|
|
40
|
+
readonly invoice_generate: "invoice_generate_queue";
|
|
41
|
+
readonly credit_generate: "credit_generate_queue";
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
readonly process: {
|
|
45
|
+
readonly name: "PROCESS_EXCHANGE";
|
|
46
|
+
readonly keys: {
|
|
47
|
+
readonly process_json: "process_json";
|
|
48
|
+
};
|
|
49
|
+
readonly queues: {
|
|
50
|
+
readonly process: "process_queue";
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly payment: {
|
|
54
|
+
readonly name: "PAYMENT_EXCHANGE";
|
|
55
|
+
readonly keys: {
|
|
56
|
+
readonly pending: "payment.pending";
|
|
57
|
+
readonly completed: "payment.completed";
|
|
58
|
+
readonly subscribed: "subscribed.completed";
|
|
59
|
+
readonly subscribedRenewal: "subscribedRenewal.completed";
|
|
60
|
+
};
|
|
61
|
+
readonly queues: {
|
|
62
|
+
readonly payment: "payment_queue";
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
readonly credit_check: {
|
|
66
|
+
readonly name: "CREDIT_CHECK_EXCHANGE";
|
|
67
|
+
readonly keys: {
|
|
68
|
+
readonly requested: "credit_check.requested";
|
|
69
|
+
readonly completed: "credit_check.completed";
|
|
70
|
+
readonly failed: "credit_check.failed";
|
|
71
|
+
};
|
|
72
|
+
readonly queues: {
|
|
73
|
+
readonly credit_check: "credit_check_queue";
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RABBITMQ_EXCHANGES = void 0;
|
|
4
|
+
exports.RABBITMQ_EXCHANGES = {
|
|
5
|
+
log: {
|
|
6
|
+
name: "LOG_EXCHANGE",
|
|
7
|
+
keys: {
|
|
8
|
+
error: "*.error",
|
|
9
|
+
other: "*.other",
|
|
10
|
+
},
|
|
11
|
+
queues: {
|
|
12
|
+
log: "log_queue",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
notification: {
|
|
16
|
+
name: "NOTIFICATION_EXCHANGE",
|
|
17
|
+
keys: {
|
|
18
|
+
generated: "notification.generated",
|
|
19
|
+
signed: "notification.signed",
|
|
20
|
+
voided: "notification.voided",
|
|
21
|
+
generated_certificate: "notification.generated_certificate",
|
|
22
|
+
generated_invoice: "notification.generated_invoice",
|
|
23
|
+
generated_credit_check_report: "notification.generated_credit_check_report",
|
|
24
|
+
credit_check_completed: "notification.credit_check_completed",
|
|
25
|
+
credit_check_failed: "notification.credit_check_failed",
|
|
26
|
+
},
|
|
27
|
+
queues: {
|
|
28
|
+
notification: "notification_queue",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
generate: {
|
|
32
|
+
name: "GENERATE_EXCHANGE",
|
|
33
|
+
keys: {
|
|
34
|
+
generate: "generate",
|
|
35
|
+
signature: "signature",
|
|
36
|
+
void: "void",
|
|
37
|
+
generate_certificate: "generate_certificate",
|
|
38
|
+
generate_invoice: "generate_invoice",
|
|
39
|
+
generated_credit_check_report: "generate_credit_check_report",
|
|
40
|
+
},
|
|
41
|
+
queues: {
|
|
42
|
+
lease_generate: "lease_generate_queue",
|
|
43
|
+
invoice_generate: "invoice_generate_queue",
|
|
44
|
+
credit_generate: "credit_generate_queue",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
process: {
|
|
48
|
+
name: "PROCESS_EXCHANGE",
|
|
49
|
+
keys: {
|
|
50
|
+
process_json: "process_json",
|
|
51
|
+
},
|
|
52
|
+
queues: {
|
|
53
|
+
process: "process_queue",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
payment: {
|
|
57
|
+
name: "PAYMENT_EXCHANGE",
|
|
58
|
+
keys: {
|
|
59
|
+
pending: "payment.pending",
|
|
60
|
+
completed: "payment.completed",
|
|
61
|
+
subscribed: "subscribed.completed",
|
|
62
|
+
subscribedRenewal: "subscribedRenewal.completed",
|
|
63
|
+
},
|
|
64
|
+
queues: {
|
|
65
|
+
payment: "payment_queue",
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
credit_check: {
|
|
69
|
+
name: "CREDIT_CHECK_EXCHANGE",
|
|
70
|
+
keys: {
|
|
71
|
+
requested: "credit_check.requested",
|
|
72
|
+
completed: "credit_check.completed",
|
|
73
|
+
failed: "credit_check.failed",
|
|
74
|
+
},
|
|
75
|
+
queues: {
|
|
76
|
+
credit_check: "credit_check_queue",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ConsumeMessage } from "amqplib";
|
|
2
|
+
export declare const RETRY_HEADER_KEY = "x-retry-count";
|
|
3
|
+
export declare const MAX_RETRIES = 5;
|
|
4
|
+
export declare class Consumer<T = any> {
|
|
5
|
+
private readonly rabbitmqUrl;
|
|
6
|
+
private readonly exchange;
|
|
7
|
+
private readonly queue;
|
|
8
|
+
private readonly routingKeys;
|
|
9
|
+
private readonly handler;
|
|
10
|
+
private readonly useDLX;
|
|
11
|
+
private readonly onErrorLog?;
|
|
12
|
+
private readonly exchangeType;
|
|
13
|
+
private connection;
|
|
14
|
+
private channel;
|
|
15
|
+
constructor(rabbitmqUrl: string, exchange: string, queue: string, routingKeys: string[], handler: (data: T, msg: ConsumeMessage) => Promise<void>, useDLX?: boolean, onErrorLog?: ((queue: string, error: unknown) => void) | undefined, exchangeType?: "direct" | "topic" | "fanout");
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
private processMessage;
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Consumer = exports.MAX_RETRIES = exports.RETRY_HEADER_KEY = void 0;
|
|
4
|
+
const amqplib_1 = require("amqplib");
|
|
5
|
+
const metrics_1 = require("../metrics");
|
|
6
|
+
exports.RETRY_HEADER_KEY = "x-retry-count";
|
|
7
|
+
exports.MAX_RETRIES = 5;
|
|
8
|
+
class Consumer {
|
|
9
|
+
rabbitmqUrl;
|
|
10
|
+
exchange;
|
|
11
|
+
queue;
|
|
12
|
+
routingKeys;
|
|
13
|
+
handler;
|
|
14
|
+
useDLX;
|
|
15
|
+
onErrorLog;
|
|
16
|
+
exchangeType;
|
|
17
|
+
connection;
|
|
18
|
+
channel;
|
|
19
|
+
constructor(rabbitmqUrl, exchange, queue, routingKeys, handler, useDLX = true, onErrorLog, exchangeType = "direct") {
|
|
20
|
+
this.rabbitmqUrl = rabbitmqUrl;
|
|
21
|
+
this.exchange = exchange;
|
|
22
|
+
this.queue = queue;
|
|
23
|
+
this.routingKeys = routingKeys;
|
|
24
|
+
this.handler = handler;
|
|
25
|
+
this.useDLX = useDLX;
|
|
26
|
+
this.onErrorLog = onErrorLog;
|
|
27
|
+
this.exchangeType = exchangeType;
|
|
28
|
+
}
|
|
29
|
+
async init() {
|
|
30
|
+
this.connection = await (0, amqplib_1.connect)(this.rabbitmqUrl);
|
|
31
|
+
this.channel = await this.connection.createChannel();
|
|
32
|
+
await this.channel.assertExchange(this.exchange, this.exchangeType, { durable: true });
|
|
33
|
+
const queueOptions = { durable: true };
|
|
34
|
+
if (this.useDLX) {
|
|
35
|
+
const dlxExchange = `${this.exchange}.dlx`;
|
|
36
|
+
const dlqName = `${this.queue}.dlq`;
|
|
37
|
+
await this.channel.assertExchange(dlxExchange, "fanout", { durable: true });
|
|
38
|
+
await this.channel.assertQueue(dlqName, { durable: true });
|
|
39
|
+
await this.channel.bindQueue(dlqName, dlxExchange, "");
|
|
40
|
+
queueOptions.arguments = {
|
|
41
|
+
"x-dead-letter-exchange": dlxExchange,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
await this.channel.assertQueue(this.queue, queueOptions);
|
|
45
|
+
for (const key of this.routingKeys) {
|
|
46
|
+
await this.channel.bindQueue(this.queue, this.exchange, key);
|
|
47
|
+
}
|
|
48
|
+
this.channel.consume(this.queue, this.processMessage.bind(this), { noAck: false });
|
|
49
|
+
}
|
|
50
|
+
async processMessage(msg) {
|
|
51
|
+
if (!msg)
|
|
52
|
+
return;
|
|
53
|
+
metrics_1.messagesReceived?.inc?.({ queue: this.queue });
|
|
54
|
+
const retryCount = parseInt(msg.properties.headers?.[exports.RETRY_HEADER_KEY] || "0", 10);
|
|
55
|
+
try {
|
|
56
|
+
const data = JSON.parse(msg.content.toString());
|
|
57
|
+
await this.handler(data, msg);
|
|
58
|
+
this.channel.ack(msg);
|
|
59
|
+
metrics_1.messagesProcessed?.inc?.({ queue: this.queue });
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
console.error(`[Consumer Error] ${this.queue}:`, err);
|
|
63
|
+
this.onErrorLog?.(this.queue, err);
|
|
64
|
+
if (retryCount >= exports.MAX_RETRIES) {
|
|
65
|
+
this.channel.reject(msg, false);
|
|
66
|
+
metrics_1.messagesFailed?.inc?.({ queue: this.queue });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.channel.publish(this.exchange, msg.fields.routingKey, msg.content, {
|
|
70
|
+
persistent: true,
|
|
71
|
+
headers: {
|
|
72
|
+
...msg.properties.headers,
|
|
73
|
+
[exports.RETRY_HEADER_KEY]: retryCount + 1,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
this.channel.ack(msg);
|
|
77
|
+
metrics_1.messageRetries?.inc?.({ queue: this.queue });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async close() {
|
|
82
|
+
await this.channel?.close();
|
|
83
|
+
await this.connection?.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.Consumer = Consumer;
|
|
@@ -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
|
+
__exportStar(require("./producer"), exports);
|
|
18
|
+
__exportStar(require("./consumer"), exports);
|
|
19
|
+
__exportStar(require("./constants"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class Producer {
|
|
2
|
+
private readonly rabbitmqUrl;
|
|
3
|
+
private readonly exchange;
|
|
4
|
+
private readonly exchangeType;
|
|
5
|
+
private connection;
|
|
6
|
+
private channel;
|
|
7
|
+
constructor(rabbitmqUrl: string, exchange: string, exchangeType?: "direct" | "fanout" | "topic");
|
|
8
|
+
private delay;
|
|
9
|
+
createChannel(retries?: number, delayMs?: number): Promise<void>;
|
|
10
|
+
publishMessage<T extends object>(routingKey: string, message: T, headers?: Record<string, any>): Promise<void>;
|
|
11
|
+
ready(): Promise<boolean>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Producer = void 0;
|
|
4
|
+
const amqplib_1 = require("amqplib");
|
|
5
|
+
const metrics_1 = require("../metrics");
|
|
6
|
+
class Producer {
|
|
7
|
+
rabbitmqUrl;
|
|
8
|
+
exchange;
|
|
9
|
+
exchangeType;
|
|
10
|
+
connection = null;
|
|
11
|
+
channel = null;
|
|
12
|
+
constructor(rabbitmqUrl, exchange, exchangeType = "direct") {
|
|
13
|
+
this.rabbitmqUrl = rabbitmqUrl;
|
|
14
|
+
this.exchange = exchange;
|
|
15
|
+
this.exchangeType = exchangeType;
|
|
16
|
+
}
|
|
17
|
+
async delay(ms) {
|
|
18
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
20
|
+
async createChannel(retries = 3, delayMs = 1000) {
|
|
21
|
+
if (this.channel && this.connection)
|
|
22
|
+
return;
|
|
23
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
24
|
+
try {
|
|
25
|
+
console.log(`Producer:: Connecting to RabbitMQ at ${this.rabbitmqUrl}`);
|
|
26
|
+
this.connection = await (0, amqplib_1.connect)(this.rabbitmqUrl);
|
|
27
|
+
console.log(`Producer:: Creating channel and asserting exchange "${this.exchange}"`);
|
|
28
|
+
this.channel = await this.connection.createChannel();
|
|
29
|
+
await this.channel.assertExchange(this.exchange, this.exchangeType, { durable: true });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.warn(`Producer:: Connection attempt ${attempt} failed`, err);
|
|
34
|
+
if (attempt < retries) {
|
|
35
|
+
await this.delay(delayMs);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error(`Producer:: Unable to establish RabbitMQ connection after ${retries} attempts.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async publishMessage(routingKey, message, headers = {}) {
|
|
44
|
+
await this.createChannel();
|
|
45
|
+
if (!this.channel) {
|
|
46
|
+
console.error("Producer:: Channel not initialized.");
|
|
47
|
+
metrics_1.messagesFailed?.inc?.({ exchange: this.exchange, routingKey });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let buffer;
|
|
51
|
+
try {
|
|
52
|
+
buffer = Buffer.from(JSON.stringify(message));
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.error("Producer:: Failed to serialize message", { message, error: err });
|
|
56
|
+
metrics_1.messagesFailed?.inc?.({ exchange: this.exchange, routingKey });
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
const success = this.channel.publish(this.exchange, routingKey, buffer, {
|
|
60
|
+
persistent: true,
|
|
61
|
+
headers,
|
|
62
|
+
});
|
|
63
|
+
if (!success) {
|
|
64
|
+
console.warn("Producer:: publish returned false - backpressure, waiting for drain");
|
|
65
|
+
await new Promise((resolve) => this.channel.once("drain", resolve));
|
|
66
|
+
}
|
|
67
|
+
metrics_1.messagesPublished?.inc?.({ exchange: this.exchange, routingKey });
|
|
68
|
+
const retryCount = headers["x-retry-count"];
|
|
69
|
+
if (typeof retryCount === "number" && retryCount > 0) {
|
|
70
|
+
metrics_1.messageRetries?.inc?.({ exchange: this.exchange, routingKey });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async ready() {
|
|
74
|
+
try {
|
|
75
|
+
await this.createChannel();
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.warn("Producer:: Not ready", err);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async close() {
|
|
84
|
+
try {
|
|
85
|
+
if (this.channel) {
|
|
86
|
+
await this.channel.close();
|
|
87
|
+
}
|
|
88
|
+
if (this.connection) {
|
|
89
|
+
await this.connection.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.warn("Producer:: Error during close", err);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
this.channel = null;
|
|
97
|
+
this.connection = null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.Producer = Producer;
|
package/dist/user.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface IUser {
|
|
|
10
10
|
is_active?: boolean;
|
|
11
11
|
login_type?: string;
|
|
12
12
|
stripe_customer_id?: string;
|
|
13
|
+
role?: UserRoleType;
|
|
13
14
|
}
|
|
14
15
|
export interface IAddEditUser {
|
|
15
16
|
id?: string;
|
|
@@ -18,3 +19,4 @@ export interface IAddEditUser {
|
|
|
18
19
|
company_name: string;
|
|
19
20
|
email: string;
|
|
20
21
|
}
|
|
22
|
+
export type UserRoleType = "admin" | "landlord" | "tenant";
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@royalinvest/dto",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.1",
|
|
4
4
|
"description": "Data Transfer Objects (DTOs) to carry data between frontend and backend processes.",
|
|
5
|
-
"main": "./
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"module": "./dist/index.js",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
11
12
|
"import": "./dist/index.js"
|
|
12
13
|
}
|
|
13
14
|
},
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
"url": "git@ssh.dev.azure.com:v3/royalinvest/royalinvest/npm-package"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
|
-
"
|
|
20
|
+
"dist"
|
|
20
21
|
],
|
|
21
22
|
"publishConfig": {
|
|
22
23
|
"access": "public"
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
"clear-all": "rm -rf node_modules .next out dist build",
|
|
31
32
|
"re-start": "rm -rf node_modules .next out dist build && npm install && npm run dev",
|
|
32
33
|
"re-build": "rm -rf node_modules .next out dist build && npm install && npm run build",
|
|
34
|
+
"prepublishOnly": "npm run build",
|
|
33
35
|
"test": "echo \"Not implemented yet\""
|
|
34
36
|
},
|
|
35
37
|
"lint-staged": {
|
|
@@ -49,6 +51,8 @@
|
|
|
49
51
|
"license": "ISC",
|
|
50
52
|
"devDependencies": {
|
|
51
53
|
"@eslint/js": "^9.11.1",
|
|
54
|
+
"@types/amqplib": "^0.10.6",
|
|
55
|
+
"@types/node": "^24.1.0",
|
|
52
56
|
"eslint": "^9.11.1",
|
|
53
57
|
"eslint-plugin-react": "^7.37.0",
|
|
54
58
|
"globals": "^15.9.0",
|
|
@@ -56,5 +60,10 @@
|
|
|
56
60
|
"lint-staged": "^15.2.10",
|
|
57
61
|
"prettier": "^3.3.3",
|
|
58
62
|
"typescript-eslint": "^8.7.0"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"amqplib": "^0.10.3",
|
|
66
|
+
"pino": "^9.7.0",
|
|
67
|
+
"prom-client": "^15.1.3"
|
|
59
68
|
}
|
|
60
69
|
}
|
package/dist/billing.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type BillingIntervalType = "month" | "year" | "once";
|
package/dist/billing.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
export interface IInvoiceContact {
|
|
2
|
-
name: string;
|
|
3
|
-
address: string;
|
|
4
|
-
city: string;
|
|
5
|
-
postal: string;
|
|
6
|
-
country: string;
|
|
7
|
-
phone?: string;
|
|
8
|
-
email: string;
|
|
9
|
-
website?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface IInvoiceField {
|
|
12
|
-
label: string;
|
|
13
|
-
value: string | number | IInvoiceContact | null;
|
|
14
|
-
}
|
|
15
|
-
export interface IInvoiceTable<T> {
|
|
16
|
-
headers: string[];
|
|
17
|
-
items: T[];
|
|
18
|
-
}
|
|
19
|
-
export interface IInvoiceItem {
|
|
20
|
-
description: string;
|
|
21
|
-
quantity: number;
|
|
22
|
-
unit_price: string;
|
|
23
|
-
total_price: string;
|
|
24
|
-
}
|
|
25
|
-
export interface ITax {
|
|
26
|
-
description: string;
|
|
27
|
-
rate: string;
|
|
28
|
-
amount: string;
|
|
29
|
-
}
|
|
30
|
-
export interface IPaymentInfo {
|
|
31
|
-
message: IInvoiceField;
|
|
32
|
-
support: IInvoiceField;
|
|
33
|
-
}
|
|
34
|
-
export interface IInvoiceFormData {
|
|
35
|
-
invoice_number: IInvoiceField;
|
|
36
|
-
currency: string;
|
|
37
|
-
date: IInvoiceField;
|
|
38
|
-
status: IInvoiceField;
|
|
39
|
-
company_info: IInvoiceField;
|
|
40
|
-
customer_info: IInvoiceField;
|
|
41
|
-
tax_registration_numbers: IInvoiceField[];
|
|
42
|
-
items_table: IInvoiceTable<IInvoiceItem>;
|
|
43
|
-
taxes_table: IInvoiceTable<ITax>;
|
|
44
|
-
subtotal: IInvoiceField;
|
|
45
|
-
total: IInvoiceField;
|
|
46
|
-
payment_info: IPaymentInfo;
|
|
47
|
-
payment_method: IInvoiceField;
|
|
48
|
-
last4_digits: IInvoiceField;
|
|
49
|
-
stripe_transaction_id: string;
|
|
50
|
-
stripe_session_id: string;
|
|
51
|
-
}
|
package/dist/invoiceFormData.js
DELETED
package/dist/payment.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type PaymentIntervalType = "month" | "year";
|
package/dist/payment.js
DELETED
package/dist/reportData.d.ts
DELETED
package/dist/reportData.js
DELETED