@arplyx/sdk 0.1.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,93 @@
1
+ # @arplyx/sdk
2
+
3
+ SDK oficial de **Arplyx** para Node.js / TypeScript: enviá mensajes y broadcasts de WhatsApp y consultá estados con una API tipada.
4
+
5
+ ## Instalación
6
+
7
+ ```bash
8
+ npm install @arplyx/sdk
9
+ ```
10
+
11
+ Requiere Node.js 18+. Funciona con ESM y CommonJS.
12
+
13
+ ## Uso
14
+
15
+ ```ts
16
+ import { Arplyx, ArplyxError } from '@arplyx/sdk';
17
+
18
+ const arplyx = new Arplyx({ apiKey: process.env.ARPLYX_API_KEY! });
19
+
20
+ // Enviar un texto
21
+ const msg = await arplyx.sendMessage({
22
+ externalId: 'pedido-10045',
23
+ to: '+5491155551234',
24
+ text: 'Tu pedido fue confirmado.',
25
+ channel: 'whatsapp_direct',
26
+ whatsappAccountId: 'TU_ACCOUNT_ID',
27
+ });
28
+ console.log(msg.messageId, msg.status);
29
+
30
+ // Consultar estado (por messageId o por tu externalId)
31
+ const status = await arplyx.getMessage('pedido-10045');
32
+ console.log(status.status); // pending | queued | sent | delivered | read | failed
33
+ ```
34
+
35
+ ### Plantillas (Meta Official)
36
+
37
+ ```ts
38
+ await arplyx.sendMessage({
39
+ externalId: 'pedido-10045',
40
+ to: '+5491155551234',
41
+ channel: 'whatsapp_meta',
42
+ template: { name: 'pedido_confirmado', language: 'es_AR', body: ['Juan', '10045'] },
43
+ });
44
+ ```
45
+
46
+ ### Broadcast a una lista (planes Basic/Pro)
47
+
48
+ ```ts
49
+ await arplyx.sendBroadcast({
50
+ externalId: 'promo-junio-2026',
51
+ listId: 'TU_LIST_ID',
52
+ channel: 'whatsapp_direct',
53
+ text: 'Este mes 2x1 en turnos.',
54
+ whatsappAccountId: 'TU_ACCOUNT_ID',
55
+ });
56
+ ```
57
+
58
+ ### Listar cuentas de WhatsApp
59
+
60
+ ```ts
61
+ const accounts = await arplyx.listWhatsappAccounts();
62
+ // accounts[].id se usa como whatsappAccountId al enviar
63
+ ```
64
+
65
+ ## Manejo de errores
66
+
67
+ Las respuestas no-2xx lanzan `ArplyxError`:
68
+
69
+ ```ts
70
+ try {
71
+ await arplyx.sendMessage({ externalId: 'x', to: '+549...', text: 'hola' });
72
+ } catch (err) {
73
+ if (err instanceof ArplyxError) {
74
+ console.error(err.status); // 400, 401, 409, 422, 429, 500…
75
+ console.error(err.code); // 'validation_error', 'conflict', 'quota_exceeded'…
76
+ console.error(err.details); // detalles por campo si es validation_error
77
+ }
78
+ }
79
+ ```
80
+
81
+ ## Idempotencia
82
+
83
+ Todos los envíos usan tu `externalId` como clave de idempotencia: reintentar con el mismo `externalId` y payload no duplica el envío (devuelve el original). Es seguro reintentar ante timeouts.
84
+
85
+ ## Configuración
86
+
87
+ | Opción | Requerida | Default |
88
+ |---|---|---|
89
+ | `apiKey` | Sí | — |
90
+ | `baseUrl` | No | `https://api.arplyx.com` |
91
+ | `fetch` | No | `globalThis.fetch` |
92
+
93
+ Docs de la API: https://docs.arplyx.com/api/ · OpenAPI: https://api.arplyx.com/openapi.yaml
package/dist/index.cjs ADDED
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Arplyx: () => Arplyx,
24
+ ArplyxError: () => ArplyxError
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/errors.ts
29
+ var ArplyxError = class _ArplyxError extends Error {
30
+ /** Código HTTP. */
31
+ status;
32
+ /** Código de error de Arplyx (campo `error` del cuerpo). */
33
+ code;
34
+ /** Cuerpo crudo de la respuesta. */
35
+ body;
36
+ /** Detalles de validación, si `code === 'validation_error'`. */
37
+ details;
38
+ constructor(status, body) {
39
+ const b = body ?? {};
40
+ const code = typeof b.error === "string" ? b.error : `http_${status}`;
41
+ const msg = typeof b.message === "string" ? b.message : code;
42
+ super(`Arplyx ${status} (${code}): ${msg}`);
43
+ this.name = "ArplyxError";
44
+ this.status = status;
45
+ this.code = code;
46
+ this.body = body;
47
+ if (Array.isArray(b.details)) {
48
+ this.details = b.details;
49
+ }
50
+ Object.setPrototypeOf(this, _ArplyxError.prototype);
51
+ }
52
+ };
53
+
54
+ // src/client.ts
55
+ var DEFAULT_BASE_URL = "https://api.arplyx.com";
56
+ var Arplyx = class {
57
+ apiKey;
58
+ baseUrl;
59
+ fetchImpl;
60
+ constructor(options) {
61
+ if (!options?.apiKey) {
62
+ throw new Error("Arplyx: falta `apiKey`.");
63
+ }
64
+ this.apiKey = options.apiKey;
65
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
66
+ const f = options.fetch ?? globalThis.fetch;
67
+ if (!f) {
68
+ throw new Error(
69
+ "Arplyx: no hay `fetch` disponible. Us\xE1 Node 18+ o pas\xE1 una implementaci\xF3n en `options.fetch`."
70
+ );
71
+ }
72
+ this.fetchImpl = f;
73
+ }
74
+ async request(method, path, body) {
75
+ const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
76
+ method,
77
+ headers: {
78
+ "x-api-key": this.apiKey,
79
+ "Content-Type": "application/json"
80
+ },
81
+ body: body === void 0 ? void 0 : JSON.stringify(body)
82
+ });
83
+ const text = await res.text();
84
+ let data = null;
85
+ if (text) {
86
+ try {
87
+ data = JSON.parse(text);
88
+ } catch {
89
+ data = text;
90
+ }
91
+ }
92
+ if (!res.ok) {
93
+ throw new ArplyxError(res.status, data);
94
+ }
95
+ return data;
96
+ }
97
+ /** Envía un mensaje de WhatsApp (texto o plantilla). */
98
+ async sendMessage(input) {
99
+ if (!input.text && !input.template || input.text && input.template) {
100
+ throw new Error("Arplyx.sendMessage: indic\xE1 exactamente uno de `text` o `template`.");
101
+ }
102
+ const content = input.text ? { type: "text", text: input.text } : {
103
+ type: "template",
104
+ template: {
105
+ name: input.template.name,
106
+ language: input.template.language,
107
+ ...input.template.body || input.template.header ? {
108
+ components: {
109
+ ...input.template.body ? { body: input.template.body } : {},
110
+ ...input.template.header ? { header: input.template.header } : {}
111
+ }
112
+ } : {}
113
+ }
114
+ };
115
+ return this.request("POST", "/messages", {
116
+ externalId: input.externalId,
117
+ to: { type: "phone", phoneE164: input.to },
118
+ content,
119
+ ...input.channel ? { channel: input.channel } : {},
120
+ ...input.whatsappAccountId ? { whatsappAccountId: input.whatsappAccountId } : {},
121
+ ...input.metadata !== void 0 ? { metadata: input.metadata } : {},
122
+ ...input.ttlSeconds !== void 0 ? { ttlSeconds: input.ttlSeconds } : {}
123
+ });
124
+ }
125
+ /** Envía un texto a todos los contactos de una lista (planes Basic/Pro). */
126
+ async sendBroadcast(input) {
127
+ return this.request("POST", "/messages/broadcast", {
128
+ externalId: input.externalId,
129
+ listId: input.listId,
130
+ channel: input.channel,
131
+ content: { type: "text", text: input.text },
132
+ ...input.whatsappAccountId ? { whatsappAccountId: input.whatsappAccountId } : {},
133
+ ...input.ttlSeconds !== void 0 ? { ttlSeconds: input.ttlSeconds } : {}
134
+ });
135
+ }
136
+ /** Lista las cuentas de WhatsApp del cliente. */
137
+ async listWhatsappAccounts() {
138
+ const data = await this.request(
139
+ "GET",
140
+ "/whatsapp-accounts"
141
+ );
142
+ return data.accounts;
143
+ }
144
+ /** Consulta el estado de un mensaje por su `messageId` o tu `externalId`. */
145
+ async getMessage(idOrExternalId) {
146
+ return this.request(
147
+ "GET",
148
+ `/messages/${encodeURIComponent(idOrExternalId)}`
149
+ );
150
+ }
151
+ };
152
+ // Annotate the CommonJS export names for ESM import in node:
153
+ 0 && (module.exports = {
154
+ Arplyx,
155
+ ArplyxError
156
+ });
@@ -0,0 +1,143 @@
1
+ /** Canal de envío. `whatsapp_direct` requiere `whatsappAccountId`. */
2
+ type Channel = 'whatsapp_meta' | 'whatsapp_direct';
3
+ /** Estados del ciclo de vida de un mensaje. */
4
+ type MessageState = 'pending' | 'queued' | 'sent' | 'delivered' | 'read' | 'failed';
5
+ interface TemplateInput {
6
+ /** Nombre de la plantilla aprobada en tu WhatsApp Manager. */
7
+ name: string;
8
+ /** Código de idioma, ej: `es_AR`. */
9
+ language: string;
10
+ /** Variables del cuerpo (`{{1}}`, `{{2}}`…) en orden. */
11
+ body?: string[];
12
+ /** Variables del header, si la plantilla las usa. */
13
+ header?: string[];
14
+ }
15
+ interface SendMessageInput {
16
+ /** Tu identificador único e idempotente del envío (1–200 chars). */
17
+ externalId: string;
18
+ /** Destinatario en formato E.164, ej: `+5491155551234`. */
19
+ to: string;
20
+ /** Cuerpo del mensaje de texto. Excluyente con `template`. */
21
+ text?: string;
22
+ /** Plantilla de Meta (solo `whatsapp_meta`). Excluyente con `text`. */
23
+ template?: TemplateInput;
24
+ /** Default: `whatsapp_meta`. */
25
+ channel?: Channel;
26
+ /** UUID de la cuenta. Obligatorio para `whatsapp_direct`. */
27
+ whatsappAccountId?: string;
28
+ /** Datos arbitrarios tuyos; se guardan junto al mensaje. */
29
+ metadata?: Record<string, unknown> | null;
30
+ /** Vigencia en cola (s). Default 604800 (7d), máx 2592000 (30d). */
31
+ ttlSeconds?: number;
32
+ }
33
+ interface SendBroadcastInput {
34
+ /** Tu identificador único e idempotente del broadcast. */
35
+ externalId: string;
36
+ /** UUID de la lista de contactos (sección Listas del portal). */
37
+ listId: string;
38
+ /** Cuerpo del mensaje (solo texto). */
39
+ text: string;
40
+ /** Canal: sin default, es obligatorio. */
41
+ channel: Channel;
42
+ /** UUID de la cuenta. Obligatorio para `whatsapp_direct`. */
43
+ whatsappAccountId?: string;
44
+ ttlSeconds?: number;
45
+ }
46
+ interface MessageResponse {
47
+ messageId: string;
48
+ externalId: string;
49
+ status: MessageState;
50
+ queued: boolean;
51
+ }
52
+ interface BroadcastResponse {
53
+ broadcastId: string;
54
+ externalId: string;
55
+ listId: string;
56
+ messageCount: number;
57
+ status: string;
58
+ }
59
+ interface MessageStatus {
60
+ messageId: string;
61
+ externalId: string;
62
+ recipient: string;
63
+ channel: Channel;
64
+ status: MessageState;
65
+ attemptCount: number;
66
+ lastErrorCode: string | null;
67
+ broadcastId: string | null;
68
+ createdAt: string;
69
+ sentAt: string | null;
70
+ deliveredAt: string | null;
71
+ failedAt: string | null;
72
+ }
73
+ interface WhatsAppAccount {
74
+ /** Se usa como `whatsappAccountId` al enviar. */
75
+ id: string;
76
+ type: string;
77
+ status: string;
78
+ phoneNumber: string | null;
79
+ displayName: string | null;
80
+ connectedAt: string | null;
81
+ }
82
+
83
+ interface ArplyxOptions {
84
+ /** API key de Arplyx (`ak_live_…`). Se genera en Portal → API Keys. */
85
+ apiKey: string;
86
+ /** Base URL. Default: `https://api.arplyx.com`. */
87
+ baseUrl?: string;
88
+ /** Implementación de fetch a usar (default: el `fetch` global, Node 18+). */
89
+ fetch?: typeof fetch;
90
+ }
91
+ /**
92
+ * Cliente de la API de Arplyx.
93
+ *
94
+ * ```ts
95
+ * const arplyx = new Arplyx({ apiKey: process.env.ARPLYX_API_KEY! });
96
+ * await arplyx.sendMessage({
97
+ * externalId: 'pedido-10045',
98
+ * to: '+5491155551234',
99
+ * text: 'Tu pedido fue confirmado',
100
+ * channel: 'whatsapp_direct',
101
+ * whatsappAccountId: '...',
102
+ * });
103
+ * ```
104
+ */
105
+ declare class Arplyx {
106
+ private readonly apiKey;
107
+ private readonly baseUrl;
108
+ private readonly fetchImpl;
109
+ constructor(options: ArplyxOptions);
110
+ private request;
111
+ /** Envía un mensaje de WhatsApp (texto o plantilla). */
112
+ sendMessage(input: SendMessageInput): Promise<MessageResponse>;
113
+ /** Envía un texto a todos los contactos de una lista (planes Basic/Pro). */
114
+ sendBroadcast(input: SendBroadcastInput): Promise<BroadcastResponse>;
115
+ /** Lista las cuentas de WhatsApp del cliente. */
116
+ listWhatsappAccounts(): Promise<WhatsAppAccount[]>;
117
+ /** Consulta el estado de un mensaje por su `messageId` o tu `externalId`. */
118
+ getMessage(idOrExternalId: string): Promise<MessageStatus>;
119
+ }
120
+
121
+ /** Detalle de un error de validación (`400 validation_error`). */
122
+ interface ValidationDetail {
123
+ path: string;
124
+ message: string;
125
+ }
126
+ /**
127
+ * Error devuelto por la API de Arplyx (respuesta HTTP no-2xx).
128
+ * `code` es el campo `error` del cuerpo (ej: `validation_error`, `conflict`,
129
+ * `quota_exceeded`, `invalid_whatsapp_account`, `templates_not_available`…).
130
+ */
131
+ declare class ArplyxError extends Error {
132
+ /** Código HTTP. */
133
+ readonly status: number;
134
+ /** Código de error de Arplyx (campo `error` del cuerpo). */
135
+ readonly code: string;
136
+ /** Cuerpo crudo de la respuesta. */
137
+ readonly body: unknown;
138
+ /** Detalles de validación, si `code === 'validation_error'`. */
139
+ readonly details?: ValidationDetail[];
140
+ constructor(status: number, body: unknown);
141
+ }
142
+
143
+ export { Arplyx, ArplyxError, type ArplyxOptions, type BroadcastResponse, type Channel, type MessageResponse, type MessageState, type MessageStatus, type SendBroadcastInput, type SendMessageInput, type TemplateInput, type ValidationDetail, type WhatsAppAccount };
@@ -0,0 +1,143 @@
1
+ /** Canal de envío. `whatsapp_direct` requiere `whatsappAccountId`. */
2
+ type Channel = 'whatsapp_meta' | 'whatsapp_direct';
3
+ /** Estados del ciclo de vida de un mensaje. */
4
+ type MessageState = 'pending' | 'queued' | 'sent' | 'delivered' | 'read' | 'failed';
5
+ interface TemplateInput {
6
+ /** Nombre de la plantilla aprobada en tu WhatsApp Manager. */
7
+ name: string;
8
+ /** Código de idioma, ej: `es_AR`. */
9
+ language: string;
10
+ /** Variables del cuerpo (`{{1}}`, `{{2}}`…) en orden. */
11
+ body?: string[];
12
+ /** Variables del header, si la plantilla las usa. */
13
+ header?: string[];
14
+ }
15
+ interface SendMessageInput {
16
+ /** Tu identificador único e idempotente del envío (1–200 chars). */
17
+ externalId: string;
18
+ /** Destinatario en formato E.164, ej: `+5491155551234`. */
19
+ to: string;
20
+ /** Cuerpo del mensaje de texto. Excluyente con `template`. */
21
+ text?: string;
22
+ /** Plantilla de Meta (solo `whatsapp_meta`). Excluyente con `text`. */
23
+ template?: TemplateInput;
24
+ /** Default: `whatsapp_meta`. */
25
+ channel?: Channel;
26
+ /** UUID de la cuenta. Obligatorio para `whatsapp_direct`. */
27
+ whatsappAccountId?: string;
28
+ /** Datos arbitrarios tuyos; se guardan junto al mensaje. */
29
+ metadata?: Record<string, unknown> | null;
30
+ /** Vigencia en cola (s). Default 604800 (7d), máx 2592000 (30d). */
31
+ ttlSeconds?: number;
32
+ }
33
+ interface SendBroadcastInput {
34
+ /** Tu identificador único e idempotente del broadcast. */
35
+ externalId: string;
36
+ /** UUID de la lista de contactos (sección Listas del portal). */
37
+ listId: string;
38
+ /** Cuerpo del mensaje (solo texto). */
39
+ text: string;
40
+ /** Canal: sin default, es obligatorio. */
41
+ channel: Channel;
42
+ /** UUID de la cuenta. Obligatorio para `whatsapp_direct`. */
43
+ whatsappAccountId?: string;
44
+ ttlSeconds?: number;
45
+ }
46
+ interface MessageResponse {
47
+ messageId: string;
48
+ externalId: string;
49
+ status: MessageState;
50
+ queued: boolean;
51
+ }
52
+ interface BroadcastResponse {
53
+ broadcastId: string;
54
+ externalId: string;
55
+ listId: string;
56
+ messageCount: number;
57
+ status: string;
58
+ }
59
+ interface MessageStatus {
60
+ messageId: string;
61
+ externalId: string;
62
+ recipient: string;
63
+ channel: Channel;
64
+ status: MessageState;
65
+ attemptCount: number;
66
+ lastErrorCode: string | null;
67
+ broadcastId: string | null;
68
+ createdAt: string;
69
+ sentAt: string | null;
70
+ deliveredAt: string | null;
71
+ failedAt: string | null;
72
+ }
73
+ interface WhatsAppAccount {
74
+ /** Se usa como `whatsappAccountId` al enviar. */
75
+ id: string;
76
+ type: string;
77
+ status: string;
78
+ phoneNumber: string | null;
79
+ displayName: string | null;
80
+ connectedAt: string | null;
81
+ }
82
+
83
+ interface ArplyxOptions {
84
+ /** API key de Arplyx (`ak_live_…`). Se genera en Portal → API Keys. */
85
+ apiKey: string;
86
+ /** Base URL. Default: `https://api.arplyx.com`. */
87
+ baseUrl?: string;
88
+ /** Implementación de fetch a usar (default: el `fetch` global, Node 18+). */
89
+ fetch?: typeof fetch;
90
+ }
91
+ /**
92
+ * Cliente de la API de Arplyx.
93
+ *
94
+ * ```ts
95
+ * const arplyx = new Arplyx({ apiKey: process.env.ARPLYX_API_KEY! });
96
+ * await arplyx.sendMessage({
97
+ * externalId: 'pedido-10045',
98
+ * to: '+5491155551234',
99
+ * text: 'Tu pedido fue confirmado',
100
+ * channel: 'whatsapp_direct',
101
+ * whatsappAccountId: '...',
102
+ * });
103
+ * ```
104
+ */
105
+ declare class Arplyx {
106
+ private readonly apiKey;
107
+ private readonly baseUrl;
108
+ private readonly fetchImpl;
109
+ constructor(options: ArplyxOptions);
110
+ private request;
111
+ /** Envía un mensaje de WhatsApp (texto o plantilla). */
112
+ sendMessage(input: SendMessageInput): Promise<MessageResponse>;
113
+ /** Envía un texto a todos los contactos de una lista (planes Basic/Pro). */
114
+ sendBroadcast(input: SendBroadcastInput): Promise<BroadcastResponse>;
115
+ /** Lista las cuentas de WhatsApp del cliente. */
116
+ listWhatsappAccounts(): Promise<WhatsAppAccount[]>;
117
+ /** Consulta el estado de un mensaje por su `messageId` o tu `externalId`. */
118
+ getMessage(idOrExternalId: string): Promise<MessageStatus>;
119
+ }
120
+
121
+ /** Detalle de un error de validación (`400 validation_error`). */
122
+ interface ValidationDetail {
123
+ path: string;
124
+ message: string;
125
+ }
126
+ /**
127
+ * Error devuelto por la API de Arplyx (respuesta HTTP no-2xx).
128
+ * `code` es el campo `error` del cuerpo (ej: `validation_error`, `conflict`,
129
+ * `quota_exceeded`, `invalid_whatsapp_account`, `templates_not_available`…).
130
+ */
131
+ declare class ArplyxError extends Error {
132
+ /** Código HTTP. */
133
+ readonly status: number;
134
+ /** Código de error de Arplyx (campo `error` del cuerpo). */
135
+ readonly code: string;
136
+ /** Cuerpo crudo de la respuesta. */
137
+ readonly body: unknown;
138
+ /** Detalles de validación, si `code === 'validation_error'`. */
139
+ readonly details?: ValidationDetail[];
140
+ constructor(status: number, body: unknown);
141
+ }
142
+
143
+ export { Arplyx, ArplyxError, type ArplyxOptions, type BroadcastResponse, type Channel, type MessageResponse, type MessageState, type MessageStatus, type SendBroadcastInput, type SendMessageInput, type TemplateInput, type ValidationDetail, type WhatsAppAccount };
package/dist/index.js ADDED
@@ -0,0 +1,128 @@
1
+ // src/errors.ts
2
+ var ArplyxError = class _ArplyxError extends Error {
3
+ /** Código HTTP. */
4
+ status;
5
+ /** Código de error de Arplyx (campo `error` del cuerpo). */
6
+ code;
7
+ /** Cuerpo crudo de la respuesta. */
8
+ body;
9
+ /** Detalles de validación, si `code === 'validation_error'`. */
10
+ details;
11
+ constructor(status, body) {
12
+ const b = body ?? {};
13
+ const code = typeof b.error === "string" ? b.error : `http_${status}`;
14
+ const msg = typeof b.message === "string" ? b.message : code;
15
+ super(`Arplyx ${status} (${code}): ${msg}`);
16
+ this.name = "ArplyxError";
17
+ this.status = status;
18
+ this.code = code;
19
+ this.body = body;
20
+ if (Array.isArray(b.details)) {
21
+ this.details = b.details;
22
+ }
23
+ Object.setPrototypeOf(this, _ArplyxError.prototype);
24
+ }
25
+ };
26
+
27
+ // src/client.ts
28
+ var DEFAULT_BASE_URL = "https://api.arplyx.com";
29
+ var Arplyx = class {
30
+ apiKey;
31
+ baseUrl;
32
+ fetchImpl;
33
+ constructor(options) {
34
+ if (!options?.apiKey) {
35
+ throw new Error("Arplyx: falta `apiKey`.");
36
+ }
37
+ this.apiKey = options.apiKey;
38
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
39
+ const f = options.fetch ?? globalThis.fetch;
40
+ if (!f) {
41
+ throw new Error(
42
+ "Arplyx: no hay `fetch` disponible. Us\xE1 Node 18+ o pas\xE1 una implementaci\xF3n en `options.fetch`."
43
+ );
44
+ }
45
+ this.fetchImpl = f;
46
+ }
47
+ async request(method, path, body) {
48
+ const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
49
+ method,
50
+ headers: {
51
+ "x-api-key": this.apiKey,
52
+ "Content-Type": "application/json"
53
+ },
54
+ body: body === void 0 ? void 0 : JSON.stringify(body)
55
+ });
56
+ const text = await res.text();
57
+ let data = null;
58
+ if (text) {
59
+ try {
60
+ data = JSON.parse(text);
61
+ } catch {
62
+ data = text;
63
+ }
64
+ }
65
+ if (!res.ok) {
66
+ throw new ArplyxError(res.status, data);
67
+ }
68
+ return data;
69
+ }
70
+ /** Envía un mensaje de WhatsApp (texto o plantilla). */
71
+ async sendMessage(input) {
72
+ if (!input.text && !input.template || input.text && input.template) {
73
+ throw new Error("Arplyx.sendMessage: indic\xE1 exactamente uno de `text` o `template`.");
74
+ }
75
+ const content = input.text ? { type: "text", text: input.text } : {
76
+ type: "template",
77
+ template: {
78
+ name: input.template.name,
79
+ language: input.template.language,
80
+ ...input.template.body || input.template.header ? {
81
+ components: {
82
+ ...input.template.body ? { body: input.template.body } : {},
83
+ ...input.template.header ? { header: input.template.header } : {}
84
+ }
85
+ } : {}
86
+ }
87
+ };
88
+ return this.request("POST", "/messages", {
89
+ externalId: input.externalId,
90
+ to: { type: "phone", phoneE164: input.to },
91
+ content,
92
+ ...input.channel ? { channel: input.channel } : {},
93
+ ...input.whatsappAccountId ? { whatsappAccountId: input.whatsappAccountId } : {},
94
+ ...input.metadata !== void 0 ? { metadata: input.metadata } : {},
95
+ ...input.ttlSeconds !== void 0 ? { ttlSeconds: input.ttlSeconds } : {}
96
+ });
97
+ }
98
+ /** Envía un texto a todos los contactos de una lista (planes Basic/Pro). */
99
+ async sendBroadcast(input) {
100
+ return this.request("POST", "/messages/broadcast", {
101
+ externalId: input.externalId,
102
+ listId: input.listId,
103
+ channel: input.channel,
104
+ content: { type: "text", text: input.text },
105
+ ...input.whatsappAccountId ? { whatsappAccountId: input.whatsappAccountId } : {},
106
+ ...input.ttlSeconds !== void 0 ? { ttlSeconds: input.ttlSeconds } : {}
107
+ });
108
+ }
109
+ /** Lista las cuentas de WhatsApp del cliente. */
110
+ async listWhatsappAccounts() {
111
+ const data = await this.request(
112
+ "GET",
113
+ "/whatsapp-accounts"
114
+ );
115
+ return data.accounts;
116
+ }
117
+ /** Consulta el estado de un mensaje por su `messageId` o tu `externalId`. */
118
+ async getMessage(idOrExternalId) {
119
+ return this.request(
120
+ "GET",
121
+ `/messages/${encodeURIComponent(idOrExternalId)}`
122
+ );
123
+ }
124
+ };
125
+ export {
126
+ Arplyx,
127
+ ArplyxError
128
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@arplyx/sdk",
3
+ "version": "0.1.0",
4
+ "description": "SDK oficial de Arplyx: enviá mensajes y broadcasts de WhatsApp y consultá estados desde Node/TypeScript.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "homepage": "https://docs.arplyx.com/api/",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "engines": {
22
+ "node": ">=18"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "typecheck": "tsc --noEmit",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "arplyx",
31
+ "whatsapp",
32
+ "whatsapp-api",
33
+ "sdk",
34
+ "mensajeria",
35
+ "broadcasts"
36
+ ],
37
+ "devDependencies": {
38
+ "tsup": "^8.3.0",
39
+ "typescript": "^5.6.0"
40
+ }
41
+ }