plenna_utilities 1.10.0 → 1.12.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/dist/index.d.ts CHANGED
@@ -9,3 +9,4 @@ export * from './src/airTable';
9
9
  export * from './src/alerts/presenter';
10
10
  export * from './src/common/domain/shared';
11
11
  export * from './src/AI/bedrock';
12
+ export * from './src/respira';
package/dist/index.js CHANGED
@@ -30,3 +30,4 @@ __exportStar(require("./src/airTable"), exports);
30
30
  __exportStar(require("./src/alerts/presenter"), exports);
31
31
  __exportStar(require("./src/common/domain/shared"), exports);
32
32
  __exportStar(require("./src/AI/bedrock"), exports);
33
+ __exportStar(require("./src/respira"), exports);
@@ -1,5 +1,21 @@
1
+ import { type FieldSet, type Records } from 'airtable';
2
+ export type { FieldSet } from 'airtable';
3
+ export type { Records } from 'airtable';
1
4
  export declare class AirTable {
2
5
  private readonly webhook;
3
6
  constructor(webhook: string);
4
7
  sendToAirTable(payload: Record<string, unknown>): Promise<boolean>;
5
8
  }
9
+ export declare class AirtableAPI {
10
+ private readonly apiKey;
11
+ private readonly baseId;
12
+ private readonly tableName;
13
+ constructor(apiKey: string, baseId: string, tableName: string);
14
+ getRecords(valuesToSearch: string[], fieldToSearch: string, maxRecords: number, view?: string, options?: {
15
+ fields?: string[];
16
+ }): Promise<Array<Records<FieldSet>[number]>>;
17
+ updateRecords(records: Array<{
18
+ id: string;
19
+ fields: Record<string, unknown>;
20
+ }>): Promise<void>;
21
+ }
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AirTable = void 0;
6
+ exports.AirtableAPI = exports.AirTable = void 0;
7
+ const airtable_1 = __importDefault(require("airtable"));
4
8
  class AirTable {
5
9
  webhook;
6
10
  constructor(webhook) {
@@ -25,3 +29,54 @@ class AirTable {
25
29
  }
26
30
  }
27
31
  exports.AirTable = AirTable;
32
+ class AirtableAPI {
33
+ apiKey;
34
+ baseId;
35
+ tableName;
36
+ constructor(apiKey, baseId, tableName) {
37
+ this.apiKey = apiKey;
38
+ this.baseId = baseId;
39
+ this.tableName = tableName;
40
+ }
41
+ async getRecords(valuesToSearch, fieldToSearch, maxRecords, view, options) {
42
+ return await new Promise((resolve, reject) => {
43
+ const base = new airtable_1.default({ apiKey: this.apiKey }).base(this.baseId);
44
+ const allRecords = [];
45
+ const filterByFormula = valuesToSearch.length === 1
46
+ ? `{${fieldToSearch}} = '${valuesToSearch[0]}'`
47
+ : `OR(${valuesToSearch.map(v => `{${fieldToSearch}} = '${v}'`).join(', ')})`;
48
+ base(this.tableName)
49
+ .select({ filterByFormula, maxRecords, view: view ?? 'Grid view', ...options })
50
+ .eachPage((records, fetchNextPage) => {
51
+ console.log('records: ', records);
52
+ allRecords.push(...records);
53
+ fetchNextPage();
54
+ }, (err) => {
55
+ if (err !== null) {
56
+ console.error('❌ Error de Airtable:', err);
57
+ reject(err);
58
+ return;
59
+ }
60
+ resolve(allRecords);
61
+ });
62
+ });
63
+ }
64
+ async updateRecords(records) {
65
+ const base = new airtable_1.default({ apiKey: this.apiKey }).base(this.baseId);
66
+ const chunkSize = 10;
67
+ for (let i = 0; i < records.length; i += chunkSize) {
68
+ const batch = records.slice(i, i + chunkSize).map((record) => (record));
69
+ console.log(`Actualizando batch ${i / chunkSize + 1}...`);
70
+ try {
71
+ await base(this.tableName).update(batch);
72
+ console.log(`✅ Update completado del batch ${i / chunkSize + 1}`);
73
+ }
74
+ catch (error) {
75
+ console.error('❌ Error de Airtable:', error);
76
+ throw error;
77
+ }
78
+ await new Promise((resolve) => setTimeout(resolve, 200));
79
+ }
80
+ }
81
+ }
82
+ exports.AirtableAPI = AirtableAPI;
@@ -77,6 +77,13 @@ templates:
77
77
  type: plain_text
78
78
  emoji: true
79
79
  text: '🕵️‍ Verifica que hayan horarios configurados en Huli para esta doctora.'
80
+ - type: divider
81
+ - type: section
82
+ fields:
83
+ - type: mrkdwn
84
+ text: "*¿Es paciente recurrente?:*\n{isRecurringPatient}"
85
+ - type: mrkdwn
86
+ text: "*Doctor@ en su health team:*\n{doctorRecurringPatient}"
80
87
 
81
88
  patientNeedsACloserAppointment:
82
89
  channel: 'C09ELN5A92S'
@@ -6,4 +6,6 @@ export declare class CustomerIo {
6
6
  constructor(key: string);
7
7
  sendPushNotification(requestOptions: PushRequestOptions): Promise<boolean>;
8
8
  sendEmail(requestOptions: EmailRequestOptions): Promise<boolean>;
9
+ sendPushNotificationWithResponse(requestOptions: PushRequestOptions): Promise<Record<string, unknown>>;
10
+ sendEmailWithResponse(requestOptions: EmailRequestOptions): Promise<Record<string, unknown>>;
9
11
  }
@@ -33,5 +33,31 @@ class CustomerIo {
33
33
  return false;
34
34
  }
35
35
  }
36
+ async sendPushNotificationWithResponse(requestOptions) {
37
+ try {
38
+ const request = new customerio_node_1.SendPushRequest(requestOptions);
39
+ const api = new customerio_node_1.APIClient(this.key, { region: customerio_node_1.RegionUS });
40
+ const response = await api.sendPush(request);
41
+ console.log('Sent push notification success: ', response);
42
+ return response;
43
+ }
44
+ catch (error) {
45
+ console.error('Failed to send push notification: ', error);
46
+ return { error };
47
+ }
48
+ }
49
+ async sendEmailWithResponse(requestOptions) {
50
+ try {
51
+ const request = new customerio_node_1.SendEmailRequest(requestOptions);
52
+ const api = new customerio_node_1.APIClient(this.key, { region: customerio_node_1.RegionUS });
53
+ const response = await api.sendEmail(request);
54
+ console.log('Sent email success: ', response);
55
+ return response;
56
+ }
57
+ catch (error) {
58
+ console.error('Failed to send email: ', error);
59
+ return { error };
60
+ }
61
+ }
36
62
  }
37
63
  exports.CustomerIo = CustomerIo;
@@ -0,0 +1,65 @@
1
+ export interface IWhatsAppMessage {
2
+ phone: string;
3
+ name?: string;
4
+ email?: string;
5
+ ri_body_param_1?: string;
6
+ ri_body_param_2?: string;
7
+ ri_body_param_3?: string;
8
+ ri_body_param_4?: string;
9
+ ri_body_param_5?: string;
10
+ ri_body_param_6?: string;
11
+ ri_body_param_7?: string;
12
+ ri_body_param_8?: string;
13
+ ri_body_param_9?: string;
14
+ ri_body_param_10?: string;
15
+ ri_body_param_11?: string;
16
+ ri_body_param_12?: string;
17
+ ri_body_param_13?: string;
18
+ ri_body_param_14?: string;
19
+ ri_body_param_15?: string;
20
+ ri_body_param_16?: string;
21
+ ri_body_param_17?: string;
22
+ ri_body_param_18?: string;
23
+ ri_body_param_19?: string;
24
+ ri_body_param_20?: string;
25
+ ri_footer_param_1?: string;
26
+ ri_footer_param_2?: string;
27
+ ri_footer_param_3?: string;
28
+ ri_footer_param_4?: string;
29
+ ri_footer_param_5?: string;
30
+ ri_header_type?: string;
31
+ ri_header_text?: string;
32
+ ri_header_link?: string;
33
+ delivery_date?: string;
34
+ delivery_time?: string;
35
+ iana_timezone?: string;
36
+ tags?: string;
37
+ }
38
+ export interface ISendWhatsAppMessagesOptions {
39
+ template_name: string;
40
+ language: string;
41
+ omit_ticket_creation: string;
42
+ ticket_id?: number;
43
+ tags?: string;
44
+ add_to_queue?: boolean;
45
+ origin?: string;
46
+ subdomain?: string;
47
+ messages: IWhatsAppMessage[];
48
+ }
49
+ export interface IWhatsAppMessageDetailQuery {
50
+ id_single_notification: string;
51
+ phone?: string;
52
+ template_name?: string;
53
+ sunco_notification_id?: string;
54
+ origin?: string;
55
+ delivery_date_from?: string;
56
+ delivery_date_to?: string;
57
+ }
58
+ export declare class RespiraInternet {
59
+ private readonly apiKey;
60
+ private readonly username;
61
+ private readonly apiUrl;
62
+ constructor(apiKey: string, username: string, apiUrl: string);
63
+ sendWhatsAppMessages(options: ISendWhatsAppMessagesOptions): Promise<Response>;
64
+ getWhatsAppMessageDetail(query: IWhatsAppMessageDetailQuery): Promise<Response>;
65
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RespiraInternet = void 0;
4
+ class RespiraInternet {
5
+ apiKey;
6
+ username;
7
+ apiUrl;
8
+ constructor(apiKey, username, apiUrl) {
9
+ this.apiKey = apiKey;
10
+ this.username = username;
11
+ this.apiUrl = apiUrl;
12
+ }
13
+ sendWhatsAppMessages(options) {
14
+ const auth = Buffer.from(`${this.username}:${this.apiKey}`).toString('base64');
15
+ return fetch(`${this.apiUrl}/messages/`, {
16
+ method: 'POST',
17
+ headers: {
18
+ Authorization: `Basic ${auth}`,
19
+ 'Content-Type': 'application/json'
20
+ },
21
+ body: JSON.stringify(options)
22
+ });
23
+ }
24
+ getWhatsAppMessageDetail(query) {
25
+ const params = {};
26
+ Object.entries(query).forEach(([key, value]) => {
27
+ if (value !== undefined) {
28
+ params[key] = value;
29
+ }
30
+ });
31
+ const queryString = new URLSearchParams(params).toString();
32
+ const auth = Buffer.from(`${this.username}:${this.apiKey}`).toString('base64');
33
+ return fetch(`${this.apiUrl}/messages?${queryString}`, {
34
+ method: 'GET',
35
+ headers: {
36
+ Authorization: `Basic ${auth}`,
37
+ 'Content-Type': 'application/json'
38
+ }
39
+ });
40
+ }
41
+ }
42
+ exports.RespiraInternet = RespiraInternet;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plenna_utilities",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "plenna's utils for backend projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -43,6 +43,7 @@
43
43
  "@googleapis/drive": "^8.10.0",
44
44
  "@googleapis/sheets": "^8.0.0",
45
45
  "@slack/web-api": "^6.9.1",
46
+ "airtable": "^0.12.2",
46
47
  "customerio-node": "^4.1.1",
47
48
  "dotenv": "^16.4.5",
48
49
  "google-auth-library": "^9.11.0",