@trm-market-pulse/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.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # @trm-market-pulse/utils
2
+
3
+ Utils functions for Tracker projects.
4
+
5
+ ## How to publish a new version?
6
+
7
+ ```bash
8
+ npm publish --access public --scope=@trm-market-pulse
9
+ ```
10
+
11
+ ## Installation
12
+
13
+ This is a private package. You can install it using one of the following methods:
14
+
15
+ ### Option 1: Install from Git Repository (Recommended for Serverless Functions)
16
+
17
+ If you have a private Git repository (GitHub, GitLab, Bitbucket), you can install directly from it:
18
+
19
+ ```bash
20
+ # Using npm
21
+ npm install git+https://github.com/your-org/shared-types.git
22
+
23
+ # Using pnpm
24
+ pnpm add git+https://github.com/your-org/shared-types.git
25
+
26
+ # Using yarn
27
+ yarn add git+https://github.com/your-org/shared-types.git
28
+
29
+ # For a specific branch or tag
30
+ pnpm add git+https://github.com/your-org/shared-types.git#branch-name
31
+ pnpm add git+https://github.com/your-org/shared-types.git#v1.0.0
32
+ ```
33
+
34
+ **For serverless functions**, this is the recommended approach as it works seamlessly during deployment.
35
+
36
+ ### Option 2: Install from Private npm Registry
37
+
38
+ If you're using a private npm registry (GitHub Packages, npm Enterprise, etc.):
39
+
40
+ 1. **Publish the package** to your registry:
41
+ ```bash
42
+ npm publish --registry=https://npm.pkg.github.com
43
+ ```
44
+
45
+ 2. **Configure authentication** in your `.npmrc` or serverless environment:
46
+ ```
47
+ @trm-market-pulse:registry=https://npm.pkg.github.com
48
+ //npm.pkg.github.com/:_authToken=YOUR_TOKEN
49
+ ```
50
+
51
+ 3. **Install the package**:
52
+ ```bash
53
+ npm install @trm-market-pulse/utils
54
+ ```
55
+
56
+ ### Option 3: Install from Local Path (Development)
57
+
58
+ For local development, you can link the package:
59
+
60
+ ```bash
61
+ # In the shared-types package directory
62
+ pnpm link
63
+
64
+ # In your project directory
65
+ pnpm link @trm-market-pulse/utils
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ ```typescript
71
+ // Import everything
72
+ import {
73
+ checkCondition
74
+ } from '@trm-market-pulse/utils';
75
+
76
+ ```
77
+
78
+ ## Development
79
+
80
+ ### Building
81
+
82
+ ```bash
83
+ pnpm install
84
+ pnpm build
85
+ ```
86
+
87
+ This will compile TypeScript files to the `dist` directory.
88
+
89
+ ### Publishing
90
+
91
+ Before publishing, make sure to:
92
+
93
+ 1. Update the version in `package.json`
94
+ 2. Build the package: `pnpm build`
95
+ 3. Publish to your registry or push to Git
96
+
97
+ ## Structure
98
+
99
+
100
+
101
+ ## Serverless Functions Setup
102
+
103
+ For serverless functions (AWS Lambda, Vercel, etc.), ensure your deployment configuration can access the Git repository:
104
+
105
+ ### AWS Lambda / Serverless Framework
106
+
107
+ Add to your `serverless.yml`:
108
+ ```yaml
109
+ package:
110
+ patterns:
111
+ - '!node_modules/**'
112
+ - 'node_modules/@trm-market-pulse/utils/**'
113
+ ```
114
+
115
+ ### Vercel
116
+
117
+ Vercel automatically installs dependencies from Git during build. Make sure your repository is accessible and the build has the necessary permissions.
118
+
119
+ ### Environment Variables
120
+
121
+ If using a private npm registry, set these in your serverless environment:
122
+ - `NPM_TOKEN` - Your npm authentication token
123
+ - `NPM_REGISTRY` - Your private registry URL (if different from default)
@@ -0,0 +1,5 @@
1
+ export * from './validators/check-conditions';
2
+ export * from './notifications/notification-factory';
3
+ export * from './notifications/build-message';
4
+ export * from './notifications/subscription-update-factory';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,+BAA+B,CAAC;AAK9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
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("./validators/check-conditions"), exports);
18
+ __exportStar(require("./notifications/notification-factory"), exports);
19
+ __exportStar(require("./notifications/build-message"), exports);
20
+ __exportStar(require("./notifications/subscription-update-factory"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAGA,gEAA8C;AAK9C,uEAAqD;AACrD,gEAA8C;AAC9C,8EAA4D"}
@@ -0,0 +1,3 @@
1
+ import { INotificationMessage, ITreshold, RateSource } from "@trm-market-pulse/shared-types";
2
+ export declare function buildNotificationMessage(threshold: ITreshold, currentRate: number, source: RateSource): INotificationMessage;
3
+ //# sourceMappingURL=build-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-message.d.ts","sourceRoot":"","sources":["../../src/notifications/build-message.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,UAAU,EAEX,MAAM,gCAAgC,CAAC;AAiExC,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,UAAU,GACjB,oBAAoB,CAkCtB"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildNotificationMessage = buildNotificationMessage;
4
+ const shared_types_1 = require("@trm-market-pulse/shared-types");
5
+ function buildHtmlEmail(threshold, currentRate, formattedRate, formattedTarget) {
6
+ const conditionEmojis = {
7
+ [shared_types_1.TresholdCondition.ABOVE]: "🚨",
8
+ [shared_types_1.TresholdCondition.BELOW]: "📉",
9
+ [shared_types_1.TresholdCondition.EQUAL]: "⚖️",
10
+ };
11
+ const conditionMessages = {
12
+ [shared_types_1.TresholdCondition.ABOVE]: `El dólar ha subido por encima de ${formattedTarget}`,
13
+ [shared_types_1.TresholdCondition.BELOW]: `El dólar ha bajado por debajo de ${formattedTarget}`,
14
+ [shared_types_1.TresholdCondition.EQUAL]: `El dólar ha alcanzado el valor de ${formattedTarget}`,
15
+ };
16
+ const emoji = conditionEmojis[threshold.condition] || "📊";
17
+ const message = conditionMessages[threshold.condition] || "Alerta activada";
18
+ return `
19
+ <!DOCTYPE html>
20
+ <html>
21
+ <head>
22
+ <meta charset="UTF-8">
23
+ <style>
24
+ body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
25
+ .container { max-width: 600px; margin: 0 auto; padding: 20px; }
26
+ .header { background-color: #f4f4f4; padding: 20px; border-radius: 5px; }
27
+ .content { padding: 20px; }
28
+ .rate { font-size: 24px; font-weight: bold; color: #2c3e50; }
29
+ .target { font-size: 18px; color: #7f8c8d; }
30
+ .footer { margin-top: 20px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 12px; color: #7f8c8d; }
31
+ </style>
32
+ </head>
33
+ <body>
34
+ <div class="container">
35
+ <div class="header">
36
+ <h1>${emoji} Alerta de Tipo de Cambio USD/COP</h1>
37
+ </div>
38
+ <div class="content">
39
+ <p>${message}</p>
40
+ <p class="rate">Valor actual: ${formattedRate}</p>
41
+ <p class="target">Valor objetivo: ${formattedTarget}</p>
42
+ <p><strong>Threshold:</strong> ${threshold.name}</p>
43
+ <p><strong>Fuente:</strong> ${threshold.source}</p>
44
+ </div>
45
+ <div class="footer">
46
+ <p>Esta es una notificación automática del sistema TRM Market Pulse.</p>
47
+ </div>
48
+ </div>
49
+ </body>
50
+ </html>
51
+ `;
52
+ }
53
+ function buildNotificationMessage(threshold, currentRate, source) {
54
+ const formattedRate = new Intl.NumberFormat("es-CO", {
55
+ style: "currency",
56
+ currency: "COP",
57
+ }).format(currentRate);
58
+ const formattedTarget = new Intl.NumberFormat("es-CO", {
59
+ style: "currency",
60
+ currency: "COP",
61
+ }).format(threshold.targetValue);
62
+ const conditionMessages = {
63
+ [shared_types_1.TresholdCondition.ABOVE]: `🚨 Alerta: El dólar ha subido por encima de ${formattedTarget}. Valor actual: ${formattedRate}`,
64
+ [shared_types_1.TresholdCondition.BELOW]: `📉 Alerta: El dólar ha bajado por debajo de ${formattedTarget}. Valor actual: ${formattedRate}`,
65
+ [shared_types_1.TresholdCondition.EQUAL]: `⚖️ Alerta: El dólar ha alcanzado el valor de ${formattedTarget}. Valor actual: ${formattedRate}`,
66
+ };
67
+ return {
68
+ title: "Alerta de Tipo de Cambio USD/COP",
69
+ body: conditionMessages[threshold.condition] ||
70
+ `Alerta activada. Valor actual: ${formattedRate}`,
71
+ data: {
72
+ threshold_id: threshold.uuid,
73
+ condition: threshold.condition,
74
+ target_value: threshold.targetValue,
75
+ current_value: currentRate,
76
+ source: source,
77
+ timestamp: new Date().toISOString(),
78
+ formatted_rate: formattedRate,
79
+ formatted_target: formattedTarget,
80
+ },
81
+ html: buildHtmlEmail(threshold, currentRate, formattedRate, formattedTarget),
82
+ };
83
+ }
84
+ //# sourceMappingURL=build-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-message.js","sourceRoot":"","sources":["../../src/notifications/build-message.ts"],"names":[],"mappings":";;AAsEA,4DAsCC;AA5GD,iEAKwC;AAKxC,SAAS,cAAc,CACrB,SAAoB,EACpB,WAAmB,EACnB,aAAqB,EACrB,eAAuB;IAEvB,MAAM,eAAe,GAA2B;QAC9C,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,IAAI;QAC/B,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,IAAI;QAC/B,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,IAAI;KAChC,CAAC;IAEF,MAAM,iBAAiB,GAA2B;QAChD,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,oCAAoC,eAAe,EAAE;QAChF,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,oCAAoC,eAAe,EAAE;QAChF,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,qCAAqC,eAAe,EAAE;KAClF,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IAC3D,MAAM,OAAO,GAAG,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,iBAAiB,CAAC;IAE5E,OAAO;;;;;;;;;;;;;;;;;;gBAkBO,KAAK;;;eAGN,OAAO;0CACoB,aAAa;8CACT,eAAe;2CAClB,SAAS,CAAC,IAAI;wCACjB,SAAS,CAAC,MAAM;;;;;;;;GAQrD,CAAC;AACJ,CAAC;AAKD,SAAgB,wBAAwB,CACtC,SAAoB,EACpB,WAAmB,EACnB,MAAkB;IAElB,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;QACnD,KAAK,EAAE,UAAU;QACjB,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,MAAM,eAAe,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;QACrD,KAAK,EAAE,UAAU;QACjB,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAEjC,MAAM,iBAAiB,GAA2B;QAChD,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,+CAA+C,eAAe,mBAAmB,aAAa,EAAE;QAC3H,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,+CAA+C,eAAe,mBAAmB,aAAa,EAAE;QAC3H,CAAC,gCAAiB,CAAC,KAAK,CAAC,EAAE,gDAAgD,eAAe,mBAAmB,aAAa,EAAE;KAC7H,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,kCAAkC;QACzC,IAAI,EACF,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC;YACtC,kCAAkC,aAAa,EAAE;QACnD,IAAI,EAAE;YACJ,YAAY,EAAE,SAAS,CAAC,IAAI;YAC5B,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,YAAY,EAAE,SAAS,CAAC,WAAW;YACnC,aAAa,EAAE,WAAW;YAC1B,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,cAAc,EAAE,aAAa;YAC7B,gBAAgB,EAAE,eAAe;SAClC;QACD,IAAI,EAAE,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,CAAC;KAC7E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { INotifications } from "@trm-market-pulse/shared-types";
2
+ export declare const notificationFactory: () => INotifications;
3
+ //# sourceMappingURL=notification-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-factory.d.ts","sourceRoot":"","sources":["../../src/notifications/notification-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAQf,MAAM,gCAAgC,CAAC;AAOxC,eAAO,MAAM,mBAAmB,QAAO,cAiIrC,CAAC"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notificationFactory = void 0;
4
+ const shared_types_1 = require("@trm-market-pulse/shared-types");
5
+ const build_message_1 = require("./build-message");
6
+ const notificationFactory = () => ({
7
+ buildNotificationMessage: build_message_1.buildNotificationMessage,
8
+ sendNotification: async (subscription, threshold, currentRate, source, handlers) => {
9
+ try {
10
+ let user;
11
+ if (handlers.getUserById) {
12
+ user = await handlers.getUserById(subscription.userId);
13
+ if (!user) {
14
+ return {
15
+ success: false,
16
+ error: `Usuario no encontrado: ${subscription.userId}`,
17
+ timestamp: new Date(),
18
+ };
19
+ }
20
+ }
21
+ else {
22
+ return {
23
+ success: false,
24
+ error: "getUserById handler is required",
25
+ timestamp: new Date(),
26
+ };
27
+ }
28
+ const messageData = (0, build_message_1.buildNotificationMessage)(threshold, currentRate, source);
29
+ let notificationResult;
30
+ switch (subscription.notificationMethod) {
31
+ case shared_types_1.NotificationMethod.EMAIL:
32
+ if (!handlers.sendEmail) {
33
+ return {
34
+ success: false,
35
+ error: "sendEmail handler is required for EMAIL notifications",
36
+ timestamp: new Date(),
37
+ };
38
+ }
39
+ notificationResult = await handlers.sendEmail(user, messageData);
40
+ break;
41
+ case shared_types_1.NotificationMethod.PUSH:
42
+ if (!handlers.sendPush) {
43
+ return {
44
+ success: false,
45
+ error: "sendPush handler is required for PUSH notifications",
46
+ timestamp: new Date(),
47
+ };
48
+ }
49
+ notificationResult = await handlers.sendPush(user, messageData);
50
+ break;
51
+ case shared_types_1.NotificationMethod.SMS:
52
+ if (!handlers.sendSms) {
53
+ return {
54
+ success: false,
55
+ error: "sendSms handler is required for SMS notifications",
56
+ timestamp: new Date(),
57
+ };
58
+ }
59
+ notificationResult = await handlers.sendSms(user, messageData);
60
+ break;
61
+ case shared_types_1.NotificationMethod.WHATS_APP:
62
+ if (!handlers.sendWhatsApp) {
63
+ return {
64
+ success: false,
65
+ error: "sendWhatsApp handler is required for WHATS_APP notifications",
66
+ timestamp: new Date(),
67
+ };
68
+ }
69
+ notificationResult = await handlers.sendWhatsApp(user, messageData);
70
+ break;
71
+ case shared_types_1.NotificationMethod.IN_APP:
72
+ if (!handlers.sendInApp) {
73
+ return {
74
+ success: false,
75
+ error: "sendInApp handler is required for IN_APP notifications",
76
+ timestamp: new Date(),
77
+ };
78
+ }
79
+ notificationResult = await handlers.sendInApp(user, messageData);
80
+ break;
81
+ default:
82
+ return {
83
+ success: false,
84
+ error: `Método de notificación no soportado: ${subscription.notificationMethod}`,
85
+ timestamp: new Date(),
86
+ };
87
+ }
88
+ if (notificationResult.success) {
89
+ return {
90
+ success: true,
91
+ method: subscription.notificationMethod,
92
+ timestamp: new Date(),
93
+ };
94
+ }
95
+ return notificationResult;
96
+ }
97
+ catch (error) {
98
+ const errorMessage = error instanceof Error ? error.message : "Error desconocido";
99
+ return {
100
+ success: false,
101
+ error: `Error enviando notificación: ${errorMessage}`,
102
+ timestamp: new Date(),
103
+ };
104
+ }
105
+ },
106
+ });
107
+ exports.notificationFactory = notificationFactory;
108
+ //# sourceMappingURL=notification-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-factory.js","sourceRoot":"","sources":["../../src/notifications/notification-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ISubscriptionUpdate } from "@trm-market-pulse/shared-types";
2
+ export declare const subscriptionUpdateFactory: () => ISubscriptionUpdate;
3
+ //# sourceMappingURL=subscription-update-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription-update-factory.d.ts","sourceRoot":"","sources":["../../src/notifications/subscription-update-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAKpB,MAAM,gCAAgC,CAAC;AAcxC,eAAO,MAAM,yBAAyB,QAAO,mBAkK3C,CAAC"}
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.subscriptionUpdateFactory = void 0;
4
+ const DEFAULT_RETRY_CONFIG = {
5
+ maxRetries: 3,
6
+ retryDelayMinutes: [5, 30, 60],
7
+ };
8
+ const subscriptionUpdateFactory = () => ({
9
+ updateSubscriptionAfterNotification: async (subscription, notificationResult, handlers) => {
10
+ let transactionSession = null;
11
+ try {
12
+ if (handlers.startTransaction) {
13
+ transactionSession = await handlers.startTransaction();
14
+ }
15
+ const now = new Date();
16
+ const session = transactionSession?.session;
17
+ if (handlers.updateSubscription) {
18
+ const updateResult = await handlers.updateSubscription({
19
+ subscriptionId: subscription.uuid,
20
+ lastTriggeredAt: now,
21
+ updatedAt: now,
22
+ }, session);
23
+ if (!updateResult.success) {
24
+ throw new Error(`Failed to update subscription: ${updateResult.error}`);
25
+ }
26
+ }
27
+ if (handlers.updateThreshold && subscription.lastTriggeredAt === null) {
28
+ const thresholdResult = await handlers.updateThreshold({
29
+ thresholdId: subscription.thresholdId,
30
+ incrementActiveSubscriberCount: true,
31
+ }, session);
32
+ if (!thresholdResult.success) {
33
+ console.warn(`Failed to update threshold: ${thresholdResult.error}`);
34
+ }
35
+ }
36
+ if (handlers.insertNotificationHistory) {
37
+ const historyResult = await handlers.insertNotificationHistory({
38
+ thresholdId: subscription.thresholdId,
39
+ userId: subscription.userId,
40
+ subscriptionId: subscription.uuid,
41
+ triggerValue: notificationResult.data?.current_value || null,
42
+ triggerSource: notificationResult.data?.source || null,
43
+ notificationMethod: subscription.notificationMethod,
44
+ triggeredAt: now,
45
+ notificationSent: notificationResult.success,
46
+ errorMessage: notificationResult.error || null,
47
+ retryCount: 0,
48
+ metadata: {
49
+ app_version: "1.0.0",
50
+ user_agent: "threshold-service",
51
+ },
52
+ }, session);
53
+ if (!historyResult.success) {
54
+ throw new Error(`Failed to insert notification history: ${historyResult.error}`);
55
+ }
56
+ }
57
+ if (!notificationResult.success && handlers.scheduleRetryNotification) {
58
+ await scheduleRetryNotification(subscription, notificationResult, handlers, session);
59
+ }
60
+ if (transactionSession) {
61
+ await transactionSession.commit();
62
+ }
63
+ return { success: true };
64
+ }
65
+ catch (error) {
66
+ if (transactionSession) {
67
+ try {
68
+ await transactionSession.abort();
69
+ }
70
+ catch (abortError) {
71
+ console.error(`Error aborting transaction: ${abortError}`);
72
+ }
73
+ }
74
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
75
+ console.error(`Error updating subscription: ${errorMessage}`);
76
+ if (handlers.insertNotificationHistory) {
77
+ try {
78
+ await handlers.insertNotificationHistory({
79
+ thresholdId: subscription.thresholdId,
80
+ userId: subscription.userId,
81
+ subscriptionId: subscription.uuid,
82
+ triggerValue: notificationResult.data?.current_value || null,
83
+ triggerSource: notificationResult.data?.source || null,
84
+ notificationMethod: subscription.notificationMethod,
85
+ triggeredAt: new Date(),
86
+ notificationSent: false,
87
+ errorMessage: `Transaction failed: ${errorMessage}`,
88
+ retryCount: 0,
89
+ });
90
+ }
91
+ catch (fallbackError) {
92
+ console.error(`Fallback notification history insert also failed: ${fallbackError}`);
93
+ }
94
+ }
95
+ return { success: false, error: errorMessage };
96
+ }
97
+ finally {
98
+ if (transactionSession) {
99
+ try {
100
+ await transactionSession.end();
101
+ }
102
+ catch (endError) {
103
+ console.error(`Error ending transaction session: ${endError}`);
104
+ }
105
+ }
106
+ }
107
+ },
108
+ });
109
+ exports.subscriptionUpdateFactory = subscriptionUpdateFactory;
110
+ async function scheduleRetryNotification(subscription, notificationResult, handlers, session) {
111
+ if (!handlers.scheduleRetryNotification || !handlers.getExistingRetry) {
112
+ return;
113
+ }
114
+ const config = DEFAULT_RETRY_CONFIG;
115
+ try {
116
+ const existingRetry = await handlers.getExistingRetry(subscription.uuid, session);
117
+ if (!existingRetry) {
118
+ await handlers.scheduleRetryNotification({
119
+ subscriptionId: subscription.uuid,
120
+ userId: subscription.userId,
121
+ thresholdId: subscription.thresholdId,
122
+ attemptCount: 1,
123
+ nextRetryAt: new Date(Date.now() + config.retryDelayMinutes[0] * 60000),
124
+ maxRetries: config.maxRetries,
125
+ errorHistory: [
126
+ {
127
+ attempt: 1,
128
+ error: notificationResult.error || "Unknown error",
129
+ timestamp: new Date(),
130
+ },
131
+ ],
132
+ }, session);
133
+ }
134
+ else if (existingRetry.attemptCount < existingRetry.maxRetries &&
135
+ !existingRetry.resolved) {
136
+ const nextAttempt = existingRetry.attemptCount + 1;
137
+ const delayIndex = Math.min(nextAttempt - 1, config.retryDelayMinutes.length - 1);
138
+ if (handlers.updateRetry) {
139
+ await handlers.updateRetry(existingRetry.id, {
140
+ subscriptionId: subscription.uuid,
141
+ userId: subscription.userId,
142
+ thresholdId: subscription.thresholdId,
143
+ attemptCount: nextAttempt,
144
+ nextRetryAt: new Date(Date.now() + config.retryDelayMinutes[delayIndex] * 60000),
145
+ maxRetries: existingRetry.maxRetries,
146
+ errorHistory: [
147
+ {
148
+ attempt: nextAttempt,
149
+ error: notificationResult.error || "Unknown error",
150
+ timestamp: new Date(),
151
+ },
152
+ ],
153
+ }, session);
154
+ }
155
+ }
156
+ }
157
+ catch (error) {
158
+ console.error(`Error scheduling retry notification: ${error instanceof Error ? error.message : "Unknown error"}`);
159
+ }
160
+ }
161
+ //# sourceMappingURL=subscription-update-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription-update-factory.js","sourceRoot":"","sources":["../../src/notifications/subscription-update-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ITresholdUtils } from "@trm-market-pulse/shared-types";
2
+ export declare const checkConditionsFactory: () => ITresholdUtils;
3
+ //# sourceMappingURL=check-conditions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-conditions.d.ts","sourceRoot":"","sources":["../../src/validators/check-conditions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAqB,MAAM,gCAAgC,CAAC;AAEnF,eAAO,MAAM,sBAAsB,QAAO,cAoCxC,CAAA"}
@@ -0,0 +1,41 @@
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.checkConditionsFactory = void 0;
7
+ const moment_timezone_1 = __importDefault(require("moment-timezone"));
8
+ const shared_types_1 = require("@trm-market-pulse/shared-types");
9
+ const checkConditionsFactory = () => ({
10
+ checkCondition: (currentRate, treshold, previousRate) => {
11
+ const { condition, targetValue } = treshold;
12
+ switch (condition) {
13
+ case shared_types_1.TresholdCondition.ABOVE:
14
+ if (previousRate !== null) {
15
+ return previousRate <= targetValue && currentRate > targetValue;
16
+ }
17
+ return currentRate > targetValue;
18
+ case shared_types_1.TresholdCondition.BELOW:
19
+ if (previousRate !== null) {
20
+ return previousRate >= targetValue && currentRate < targetValue;
21
+ }
22
+ return currentRate < targetValue;
23
+ case shared_types_1.TresholdCondition.EQUAL:
24
+ if (previousRate !== null) {
25
+ return previousRate === targetValue && currentRate === targetValue;
26
+ }
27
+ return currentRate === targetValue;
28
+ default:
29
+ return false;
30
+ }
31
+ },
32
+ calculateHoursSinceLastTrigger: (lastTriggeredAt) => {
33
+ if (!lastTriggeredAt)
34
+ return Infinity;
35
+ const now = (0, moment_timezone_1.default)().utc();
36
+ const lastTriggered = (0, moment_timezone_1.default)(lastTriggeredAt).utc();
37
+ return now.diff(lastTriggered, 'hours');
38
+ }
39
+ });
40
+ exports.checkConditionsFactory = checkConditionsFactory;
41
+ //# sourceMappingURL=check-conditions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-conditions.js","sourceRoot":"","sources":["../../src/validators/check-conditions.ts"],"names":[],"mappings":";;;;;;AAAA,sEAAqC;AACrC,iEAAmF;AAE5E,MAAM,sBAAsB,GAAG,GAAmB,EAAE,CAAC,CAAC;IAC3D,cAAc,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;QACtD,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;QAE5C,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,gCAAiB,CAAC,KAAK;gBAC1B,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBAC1B,OAAO,YAAY,IAAI,WAAW,IAAI,WAAW,GAAG,WAAW,CAAC;gBAClE,CAAC;gBAED,OAAO,WAAW,GAAG,WAAW,CAAC;YACnC,KAAK,gCAAiB,CAAC,KAAK;gBAC1B,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBAC1B,OAAO,YAAY,IAAI,WAAW,IAAI,WAAW,GAAG,WAAW,CAAC;gBAClE,CAAC;gBAED,OAAO,WAAW,GAAG,WAAW,CAAC;YACnC,KAAK,gCAAiB,CAAC,KAAK;gBAC1B,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBAC1B,OAAO,YAAY,KAAK,WAAW,IAAI,WAAW,KAAK,WAAW,CAAC;gBACrE,CAAC;gBAED,OAAO,WAAW,KAAK,WAAW,CAAC;YAErC;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IACD,8BAA8B,EAAE,CAAC,eAAe,EAAE,EAAE;QAClD,IAAI,CAAC,eAAe;YAAE,OAAO,QAAQ,CAAC;QAEtC,MAAM,GAAG,GAAG,IAAA,yBAAM,GAAE,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,IAAA,yBAAM,EAAC,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC;QAEpD,OAAO,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF,CAAC,CAAA;AApCW,QAAA,sBAAsB,0BAoCjC"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@trm-market-pulse/utils",
3
+ "version": "1.0.0",
4
+ "description": "Utils functions for Tracker projects",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "pnpm run build",
14
+ "clean": "rm -rf dist"
15
+ },
16
+ "keywords": [
17
+ "types",
18
+ "typescript",
19
+ "shared"
20
+ ],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "devDependencies": {
24
+ "typescript": "^5.9.3",
25
+ "@types/express": "^5.0.5",
26
+ "@types/node": "^24.10.0",
27
+ "@trm-market-pulse/shared-types": "workspace:*",
28
+ "moment-timezone": "^0.6.0"
29
+ },
30
+ "peerDependencies": {
31
+ "express": "^5.1.0",
32
+ "winston": "^3.18.3",
33
+ "mongodb": "^6.2.0"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ }
38
+ }
39
+