@notifica/node 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/LICENSE +21 -0
- package/README.md +444 -0
- package/dist/index.cjs +1751 -0
- package/dist/index.d.cts +1912 -0
- package/dist/index.d.ts +1912 -0
- package/dist/index.js +1705 -0
- package/package.json +60 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1751 @@
|
|
|
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
|
+
Analytics: () => Analytics,
|
|
24
|
+
ApiError: () => ApiError,
|
|
25
|
+
ApiKeys: () => ApiKeys,
|
|
26
|
+
Billing: () => Billing,
|
|
27
|
+
Channels: () => Channels,
|
|
28
|
+
Domains: () => Domains,
|
|
29
|
+
Inbox: () => Inbox,
|
|
30
|
+
InboxEmbed: () => InboxEmbed,
|
|
31
|
+
Notifica: () => Notifica,
|
|
32
|
+
NotificaClient: () => NotificaClient,
|
|
33
|
+
NotificaError: () => NotificaError,
|
|
34
|
+
Notifications: () => Notifications,
|
|
35
|
+
RateLimitError: () => RateLimitError,
|
|
36
|
+
Sms: () => Sms,
|
|
37
|
+
Subscribers: () => Subscribers,
|
|
38
|
+
Templates: () => Templates,
|
|
39
|
+
TimeoutError: () => TimeoutError,
|
|
40
|
+
ValidationError: () => ValidationError,
|
|
41
|
+
Webhooks: () => Webhooks,
|
|
42
|
+
Workflows: () => Workflows
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
45
|
+
|
|
46
|
+
// src/errors.ts
|
|
47
|
+
var NotificaError = class extends Error {
|
|
48
|
+
constructor(message) {
|
|
49
|
+
super(message);
|
|
50
|
+
this.name = "NotificaError";
|
|
51
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var ApiError = class extends NotificaError {
|
|
55
|
+
/** HTTP status code */
|
|
56
|
+
status;
|
|
57
|
+
/** Código do erro retornado pela API (ex: "validation_failed") */
|
|
58
|
+
code;
|
|
59
|
+
/** Detalhes de validação por campo */
|
|
60
|
+
details;
|
|
61
|
+
/** ID da request para suporte/debugging */
|
|
62
|
+
requestId;
|
|
63
|
+
constructor(message, status, code, details = {}, requestId = null) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.name = "ApiError";
|
|
66
|
+
this.status = status;
|
|
67
|
+
this.code = code;
|
|
68
|
+
this.details = details;
|
|
69
|
+
this.requestId = requestId;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var ValidationError = class extends ApiError {
|
|
73
|
+
constructor(message, details = {}, requestId = null) {
|
|
74
|
+
super(message, 422, "validation_failed", details, requestId);
|
|
75
|
+
this.name = "ValidationError";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var RateLimitError = class extends ApiError {
|
|
79
|
+
/** Segundos até poder tentar novamente */
|
|
80
|
+
retryAfter;
|
|
81
|
+
constructor(message, retryAfter = null, requestId = null) {
|
|
82
|
+
super(message, 429, "rate_limit_exceeded", {}, requestId);
|
|
83
|
+
this.name = "RateLimitError";
|
|
84
|
+
this.retryAfter = retryAfter;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var TimeoutError = class extends NotificaError {
|
|
88
|
+
constructor(timeoutMs) {
|
|
89
|
+
super(`Request timed out after ${timeoutMs}ms`);
|
|
90
|
+
this.name = "TimeoutError";
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/client.ts
|
|
95
|
+
var DEFAULT_BASE_URL = "https://app.usenotifica.com.br/v1";
|
|
96
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
97
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
98
|
+
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
99
|
+
var NotificaClient = class {
|
|
100
|
+
apiKey;
|
|
101
|
+
baseUrl;
|
|
102
|
+
timeout;
|
|
103
|
+
maxRetries;
|
|
104
|
+
autoIdempotency;
|
|
105
|
+
constructor(config) {
|
|
106
|
+
if (!config.apiKey) {
|
|
107
|
+
throw new NotificaError(
|
|
108
|
+
'API key \xE9 obrigat\xF3ria. Passe via: new Notifica("nk_live_...")'
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
this.apiKey = config.apiKey;
|
|
112
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
113
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
114
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
115
|
+
this.autoIdempotency = config.autoIdempotency ?? true;
|
|
116
|
+
}
|
|
117
|
+
// ── Public methods ──────────────────────────────────
|
|
118
|
+
async get(path, query, options) {
|
|
119
|
+
return this.request("GET", path, void 0, query, options);
|
|
120
|
+
}
|
|
121
|
+
async post(path, body, options) {
|
|
122
|
+
return this.request("POST", path, body, void 0, options);
|
|
123
|
+
}
|
|
124
|
+
async put(path, body, options) {
|
|
125
|
+
return this.request("PUT", path, body, void 0, options);
|
|
126
|
+
}
|
|
127
|
+
async patch(path, body, options) {
|
|
128
|
+
return this.request("PATCH", path, body, void 0, options);
|
|
129
|
+
}
|
|
130
|
+
async delete(path, options) {
|
|
131
|
+
return this.request("DELETE", path, void 0, void 0, options);
|
|
132
|
+
}
|
|
133
|
+
// ── Pagination helpers ──────────────────────────────
|
|
134
|
+
/**
|
|
135
|
+
* Lista com paginação manual.
|
|
136
|
+
* Retorna { data, meta } com cursor para próxima página.
|
|
137
|
+
*/
|
|
138
|
+
async list(path, query, options) {
|
|
139
|
+
return this.get(path, query, options);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Async iterator para auto-paginação.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* for await (const notification of client.paginate<Notification>('/notifications')) {
|
|
147
|
+
* console.log(notification.id);
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
async *paginate(path, query) {
|
|
152
|
+
let cursor;
|
|
153
|
+
do {
|
|
154
|
+
const params = { ...query, ...cursor ? { cursor } : {} };
|
|
155
|
+
const response = await this.list(path, params);
|
|
156
|
+
for (const item of response.data) {
|
|
157
|
+
yield item;
|
|
158
|
+
}
|
|
159
|
+
cursor = response.meta.has_more && response.meta.cursor ? response.meta.cursor : void 0;
|
|
160
|
+
} while (cursor);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Wrapper para respostas { data: T }.
|
|
164
|
+
*/
|
|
165
|
+
async getOne(path, options) {
|
|
166
|
+
const response = await this.get(path, void 0, options);
|
|
167
|
+
return response.data;
|
|
168
|
+
}
|
|
169
|
+
// ── Private methods ─────────────────────────────────
|
|
170
|
+
async request(method, path, body, query, options) {
|
|
171
|
+
const url = this.buildUrl(path, query);
|
|
172
|
+
const headers = this.buildHeaders(method, options);
|
|
173
|
+
const timeoutMs = options?.timeout ?? this.timeout;
|
|
174
|
+
let lastError;
|
|
175
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
176
|
+
if (attempt > 0) {
|
|
177
|
+
await this.backoff(attempt, lastError);
|
|
178
|
+
}
|
|
179
|
+
const controller = new AbortController();
|
|
180
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
181
|
+
if (options?.signal) {
|
|
182
|
+
if (options.signal.aborted) {
|
|
183
|
+
clearTimeout(timeoutId);
|
|
184
|
+
throw new NotificaError("Request aborted");
|
|
185
|
+
}
|
|
186
|
+
options.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const response = await fetch(url, {
|
|
190
|
+
method,
|
|
191
|
+
headers,
|
|
192
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
193
|
+
signal: controller.signal
|
|
194
|
+
});
|
|
195
|
+
clearTimeout(timeoutId);
|
|
196
|
+
if (response.ok) {
|
|
197
|
+
if (response.status === 204) {
|
|
198
|
+
return void 0;
|
|
199
|
+
}
|
|
200
|
+
return await response.json();
|
|
201
|
+
}
|
|
202
|
+
const errorBody = await this.safeParseJson(response);
|
|
203
|
+
const requestId = response.headers.get("x-request-id");
|
|
204
|
+
if (response.status === 429) {
|
|
205
|
+
const retryAfter = this.parseRetryAfter(response);
|
|
206
|
+
const error = new RateLimitError(
|
|
207
|
+
errorBody?.error?.message ?? "Rate limit exceeded",
|
|
208
|
+
retryAfter,
|
|
209
|
+
requestId
|
|
210
|
+
);
|
|
211
|
+
if (attempt < this.maxRetries) {
|
|
212
|
+
lastError = error;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
if (RETRYABLE_STATUS_CODES.has(response.status) && attempt < this.maxRetries) {
|
|
218
|
+
lastError = new ApiError(
|
|
219
|
+
errorBody?.error?.message ?? `Server error (${response.status})`,
|
|
220
|
+
response.status,
|
|
221
|
+
errorBody?.error?.code ?? "server_error",
|
|
222
|
+
errorBody?.error?.details ?? {},
|
|
223
|
+
requestId
|
|
224
|
+
);
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (response.status === 422) {
|
|
228
|
+
throw new ValidationError(
|
|
229
|
+
errorBody?.error?.message ?? "Validation failed",
|
|
230
|
+
errorBody?.error?.details ?? {},
|
|
231
|
+
requestId
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
throw new ApiError(
|
|
235
|
+
errorBody?.error?.message ?? `API error (${response.status})`,
|
|
236
|
+
response.status,
|
|
237
|
+
errorBody?.error?.code ?? "api_error",
|
|
238
|
+
errorBody?.error?.details ?? {},
|
|
239
|
+
requestId
|
|
240
|
+
);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
clearTimeout(timeoutId);
|
|
243
|
+
if (error instanceof NotificaError) {
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
247
|
+
if (attempt < this.maxRetries) {
|
|
248
|
+
lastError = new TimeoutError(timeoutMs);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
throw new TimeoutError(timeoutMs);
|
|
252
|
+
}
|
|
253
|
+
if (attempt < this.maxRetries) {
|
|
254
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
throw new NotificaError(
|
|
258
|
+
`Request failed: ${error instanceof Error ? error.message : String(error)}`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
throw lastError ?? new NotificaError("Request failed after max retries");
|
|
263
|
+
}
|
|
264
|
+
buildUrl(path, query) {
|
|
265
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
266
|
+
if (query) {
|
|
267
|
+
for (const [key, value] of Object.entries(query)) {
|
|
268
|
+
if (value !== void 0 && value !== null) {
|
|
269
|
+
url.searchParams.set(key, String(value));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return url.toString();
|
|
274
|
+
}
|
|
275
|
+
buildHeaders(method, options) {
|
|
276
|
+
const headers = {
|
|
277
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
278
|
+
"Content-Type": "application/json",
|
|
279
|
+
"Accept": "application/json",
|
|
280
|
+
"User-Agent": "@notifica/node/0.1.0"
|
|
281
|
+
};
|
|
282
|
+
if (method === "POST") {
|
|
283
|
+
if (options?.idempotencyKey) {
|
|
284
|
+
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
285
|
+
} else if (this.autoIdempotency) {
|
|
286
|
+
headers["Idempotency-Key"] = this.generateIdempotencyKey();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return headers;
|
|
290
|
+
}
|
|
291
|
+
generateIdempotencyKey() {
|
|
292
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
293
|
+
return crypto.randomUUID();
|
|
294
|
+
}
|
|
295
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
296
|
+
}
|
|
297
|
+
async backoff(attempt, lastError) {
|
|
298
|
+
let delayMs;
|
|
299
|
+
if (lastError instanceof RateLimitError && lastError.retryAfter !== null) {
|
|
300
|
+
delayMs = lastError.retryAfter * 1e3;
|
|
301
|
+
} else {
|
|
302
|
+
const base = 500 * Math.pow(2, attempt - 1);
|
|
303
|
+
const jitter = Math.random() * base * 0.5;
|
|
304
|
+
delayMs = base + jitter;
|
|
305
|
+
}
|
|
306
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
307
|
+
}
|
|
308
|
+
parseRetryAfter(response) {
|
|
309
|
+
const header = response.headers.get("retry-after");
|
|
310
|
+
if (!header) return null;
|
|
311
|
+
const seconds = Number(header);
|
|
312
|
+
if (!Number.isNaN(seconds)) return seconds;
|
|
313
|
+
const date = Date.parse(header);
|
|
314
|
+
if (!Number.isNaN(date)) {
|
|
315
|
+
return Math.max(0, Math.ceil((date - Date.now()) / 1e3));
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
async safeParseJson(response) {
|
|
320
|
+
try {
|
|
321
|
+
return await response.json();
|
|
322
|
+
} catch {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// src/resources/notifications.ts
|
|
329
|
+
var Notifications = class {
|
|
330
|
+
client;
|
|
331
|
+
constructor(client) {
|
|
332
|
+
this.client = client;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Envia uma notificação.
|
|
336
|
+
* A notificação é enfileirada para entrega assíncrona.
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```ts
|
|
340
|
+
* const notification = await notifica.notifications.send({
|
|
341
|
+
* channel: 'whatsapp',
|
|
342
|
+
* to: '+5511999999999',
|
|
343
|
+
* template: 'welcome',
|
|
344
|
+
* data: { name: 'João' },
|
|
345
|
+
* });
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
async send(params, options) {
|
|
349
|
+
const response = await this.client.post(
|
|
350
|
+
"/notifications",
|
|
351
|
+
params,
|
|
352
|
+
options
|
|
353
|
+
);
|
|
354
|
+
return response.data;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Lista notificações com paginação.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```ts
|
|
361
|
+
* const { data, meta } = await notifica.notifications.list({ channel: 'email', limit: 50 });
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
async list(params, options) {
|
|
365
|
+
return this.client.list("/notifications", params, options);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Itera automaticamente por todas as notificações.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```ts
|
|
372
|
+
* for await (const notification of notifica.notifications.listAll({ channel: 'email' })) {
|
|
373
|
+
* console.log(notification.id);
|
|
374
|
+
* }
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
listAll(params) {
|
|
378
|
+
return this.client.paginate("/notifications", params);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Obtém detalhes de uma notificação.
|
|
382
|
+
*/
|
|
383
|
+
async get(id, options) {
|
|
384
|
+
return this.client.getOne(`/notifications/${id}`, options);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Lista tentativas de entrega de uma notificação.
|
|
388
|
+
*/
|
|
389
|
+
async listAttempts(notificationId, options) {
|
|
390
|
+
const response = await this.client.get(
|
|
391
|
+
`/notifications/${notificationId}/attempts`,
|
|
392
|
+
void 0,
|
|
393
|
+
options
|
|
394
|
+
);
|
|
395
|
+
return response.data;
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// src/resources/templates.ts
|
|
400
|
+
var Templates = class {
|
|
401
|
+
client;
|
|
402
|
+
constructor(client) {
|
|
403
|
+
this.client = client;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Cria um novo template.
|
|
407
|
+
*
|
|
408
|
+
* @example
|
|
409
|
+
* ```ts
|
|
410
|
+
* const template = await notifica.templates.create({
|
|
411
|
+
* channel: 'email',
|
|
412
|
+
* slug: 'welcome-email',
|
|
413
|
+
* name: 'Email de Boas-Vindas',
|
|
414
|
+
* content: 'Olá {{name}}, bem-vindo!',
|
|
415
|
+
* });
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
async create(params, options) {
|
|
419
|
+
const response = await this.client.post(
|
|
420
|
+
"/templates",
|
|
421
|
+
params,
|
|
422
|
+
options
|
|
423
|
+
);
|
|
424
|
+
return response.data;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Lista templates com paginação.
|
|
428
|
+
*/
|
|
429
|
+
async list(params, options) {
|
|
430
|
+
return this.client.list("/templates", params, options);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Itera automaticamente por todos os templates.
|
|
434
|
+
*/
|
|
435
|
+
listAll(params) {
|
|
436
|
+
return this.client.paginate("/templates", params);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Obtém detalhes de um template.
|
|
440
|
+
*/
|
|
441
|
+
async get(id, options) {
|
|
442
|
+
return this.client.getOne(`/templates/${id}`, options);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Atualiza um template.
|
|
446
|
+
*/
|
|
447
|
+
async update(id, params, options) {
|
|
448
|
+
const response = await this.client.put(
|
|
449
|
+
`/templates/${id}`,
|
|
450
|
+
params,
|
|
451
|
+
options
|
|
452
|
+
);
|
|
453
|
+
return response.data;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Deleta um template.
|
|
457
|
+
*/
|
|
458
|
+
async delete(id, options) {
|
|
459
|
+
await this.client.delete(`/templates/${id}`, options);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Preview de um template salvo com variáveis.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* const preview = await notifica.templates.preview('tpl_abc', {
|
|
467
|
+
* variables: { name: 'João' },
|
|
468
|
+
* });
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
async preview(id, params, options) {
|
|
472
|
+
const response = await this.client.post(
|
|
473
|
+
`/templates/${id}/preview`,
|
|
474
|
+
params,
|
|
475
|
+
options
|
|
476
|
+
);
|
|
477
|
+
return response.data;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Preview de conteúdo arbitrário (útil para editor em tempo real).
|
|
481
|
+
*/
|
|
482
|
+
async previewContent(params, options) {
|
|
483
|
+
const response = await this.client.post(
|
|
484
|
+
"/templates/preview",
|
|
485
|
+
params,
|
|
486
|
+
options
|
|
487
|
+
);
|
|
488
|
+
return response.data;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Valida um template salvo.
|
|
492
|
+
*/
|
|
493
|
+
async validate(id, options) {
|
|
494
|
+
const response = await this.client.post(
|
|
495
|
+
`/templates/${id}/validate`,
|
|
496
|
+
void 0,
|
|
497
|
+
options
|
|
498
|
+
);
|
|
499
|
+
return response.data;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Valida conteúdo arbitrário.
|
|
503
|
+
*/
|
|
504
|
+
async validateContent(params, options) {
|
|
505
|
+
const response = await this.client.post(
|
|
506
|
+
"/templates/validate",
|
|
507
|
+
params,
|
|
508
|
+
options
|
|
509
|
+
);
|
|
510
|
+
return response.data;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/resources/workflows.ts
|
|
515
|
+
var Workflows = class {
|
|
516
|
+
client;
|
|
517
|
+
constructor(client) {
|
|
518
|
+
this.client = client;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Cria um novo workflow.
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```ts
|
|
525
|
+
* const workflow = await notifica.workflows.create({
|
|
526
|
+
* slug: 'welcome-flow',
|
|
527
|
+
* name: 'Fluxo de Boas-Vindas',
|
|
528
|
+
* steps: [
|
|
529
|
+
* { type: 'send', channel: 'email', template: 'welcome-email' },
|
|
530
|
+
* { type: 'delay', duration: '1h' },
|
|
531
|
+
* { type: 'send', channel: 'whatsapp', template: 'welcome-whatsapp' },
|
|
532
|
+
* ],
|
|
533
|
+
* });
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
async create(params, options) {
|
|
537
|
+
const response = await this.client.post(
|
|
538
|
+
"/workflows",
|
|
539
|
+
params,
|
|
540
|
+
options
|
|
541
|
+
);
|
|
542
|
+
return response.data;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Lista workflows com paginação.
|
|
546
|
+
*/
|
|
547
|
+
async list(params, options) {
|
|
548
|
+
return this.client.list("/workflows", params, options);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Itera automaticamente por todos os workflows.
|
|
552
|
+
*/
|
|
553
|
+
listAll(params) {
|
|
554
|
+
return this.client.paginate("/workflows", params);
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Obtém detalhes de um workflow.
|
|
558
|
+
*/
|
|
559
|
+
async get(id, options) {
|
|
560
|
+
return this.client.getOne(`/workflows/${id}`, options);
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Atualiza um workflow (cria nova versão).
|
|
564
|
+
*/
|
|
565
|
+
async update(id, params, options) {
|
|
566
|
+
const response = await this.client.put(
|
|
567
|
+
`/workflows/${id}`,
|
|
568
|
+
params,
|
|
569
|
+
options
|
|
570
|
+
);
|
|
571
|
+
return response.data;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Deleta um workflow (soft delete).
|
|
575
|
+
*/
|
|
576
|
+
async delete(id, options) {
|
|
577
|
+
await this.client.delete(`/workflows/${id}`, options);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Dispara a execução de um workflow.
|
|
581
|
+
*
|
|
582
|
+
* @param slug — Slug do workflow
|
|
583
|
+
* @param params — Recipient e dados
|
|
584
|
+
*
|
|
585
|
+
* @example
|
|
586
|
+
* ```ts
|
|
587
|
+
* const run = await notifica.workflows.trigger('welcome-flow', {
|
|
588
|
+
* recipient: '+5511999999999',
|
|
589
|
+
* data: { name: 'João', plan: 'pro' },
|
|
590
|
+
* });
|
|
591
|
+
* ```
|
|
592
|
+
*/
|
|
593
|
+
async trigger(slug, params, options) {
|
|
594
|
+
const response = await this.client.post(
|
|
595
|
+
`/workflows/${slug}/trigger`,
|
|
596
|
+
params,
|
|
597
|
+
options
|
|
598
|
+
);
|
|
599
|
+
return response.data;
|
|
600
|
+
}
|
|
601
|
+
// ── Workflow Runs ───────────────────────────────────
|
|
602
|
+
/**
|
|
603
|
+
* Lista execuções de workflows.
|
|
604
|
+
*/
|
|
605
|
+
async listRuns(params, options) {
|
|
606
|
+
return this.client.list("/workflow-runs", params, options);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Obtém detalhes de uma execução (incluindo step_results).
|
|
610
|
+
*/
|
|
611
|
+
async getRun(id, options) {
|
|
612
|
+
return this.client.getOne(`/workflow-runs/${id}`, options);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Cancela uma execução em andamento.
|
|
616
|
+
*/
|
|
617
|
+
async cancelRun(id, options) {
|
|
618
|
+
const response = await this.client.post(
|
|
619
|
+
`/workflow-runs/${id}/cancel`,
|
|
620
|
+
void 0,
|
|
621
|
+
options
|
|
622
|
+
);
|
|
623
|
+
return response.data;
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
// src/resources/subscribers.ts
|
|
628
|
+
var Subscribers = class {
|
|
629
|
+
client;
|
|
630
|
+
constructor(client) {
|
|
631
|
+
this.client = client;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Cria ou atualiza um subscriber (upsert por external_id).
|
|
635
|
+
* LGPD: registra consentimento automaticamente.
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```ts
|
|
639
|
+
* const subscriber = await notifica.subscribers.create({
|
|
640
|
+
* external_id: 'user-123',
|
|
641
|
+
* email: 'joao@empresa.com.br',
|
|
642
|
+
* phone: '+5511999998888',
|
|
643
|
+
* name: 'João Silva',
|
|
644
|
+
* });
|
|
645
|
+
* ```
|
|
646
|
+
*/
|
|
647
|
+
async create(params, options) {
|
|
648
|
+
const response = await this.client.post(
|
|
649
|
+
"/subscribers",
|
|
650
|
+
params,
|
|
651
|
+
options
|
|
652
|
+
);
|
|
653
|
+
return response.data;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Lista subscribers com paginação.
|
|
657
|
+
*/
|
|
658
|
+
async list(params, options) {
|
|
659
|
+
return this.client.list("/subscribers", params, options);
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Itera automaticamente por todos os subscribers.
|
|
663
|
+
*/
|
|
664
|
+
listAll(params) {
|
|
665
|
+
return this.client.paginate("/subscribers", params);
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Obtém detalhes de um subscriber.
|
|
669
|
+
*/
|
|
670
|
+
async get(id, options) {
|
|
671
|
+
return this.client.getOne(`/subscribers/${id}`, options);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Atualiza um subscriber.
|
|
675
|
+
*/
|
|
676
|
+
async update(id, params, options) {
|
|
677
|
+
const response = await this.client.put(
|
|
678
|
+
`/subscribers/${id}`,
|
|
679
|
+
params,
|
|
680
|
+
options
|
|
681
|
+
);
|
|
682
|
+
return response.data;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Deleta um subscriber (soft delete com nullificação de PII — LGPD).
|
|
686
|
+
* ⚠️ Irreversível: email, telefone e nome são removidos.
|
|
687
|
+
*/
|
|
688
|
+
async delete(id, options) {
|
|
689
|
+
await this.client.delete(`/subscribers/${id}`, options);
|
|
690
|
+
}
|
|
691
|
+
// ── Preferences ─────────────────────────────────────
|
|
692
|
+
/**
|
|
693
|
+
* Obtém preferências de notificação do subscriber.
|
|
694
|
+
*/
|
|
695
|
+
async getPreferences(id, options) {
|
|
696
|
+
return this.client.getOne(`/subscribers/${id}/preferences`, options);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Atualiza preferências de notificação do subscriber.
|
|
700
|
+
*
|
|
701
|
+
* @example
|
|
702
|
+
* ```ts
|
|
703
|
+
* await notifica.subscribers.updatePreferences('sub_123', {
|
|
704
|
+
* preferences: [
|
|
705
|
+
* { category: 'marketing', channel: 'email', enabled: false },
|
|
706
|
+
* { category: 'transactional', channel: 'whatsapp', enabled: true },
|
|
707
|
+
* ],
|
|
708
|
+
* });
|
|
709
|
+
* ```
|
|
710
|
+
*/
|
|
711
|
+
async updatePreferences(id, params, options) {
|
|
712
|
+
const response = await this.client.put(
|
|
713
|
+
`/subscribers/${id}/preferences`,
|
|
714
|
+
params,
|
|
715
|
+
options
|
|
716
|
+
);
|
|
717
|
+
return response.data;
|
|
718
|
+
}
|
|
719
|
+
// ── Bulk import ─────────────────────────────────────
|
|
720
|
+
/**
|
|
721
|
+
* Importa subscribers em lote (upsert transacional).
|
|
722
|
+
* Se um subscriber falhar validação, todo o lote é revertido.
|
|
723
|
+
*/
|
|
724
|
+
async bulkImport(params, options) {
|
|
725
|
+
const response = await this.client.post(
|
|
726
|
+
"/subscribers/import",
|
|
727
|
+
params,
|
|
728
|
+
options
|
|
729
|
+
);
|
|
730
|
+
return response.data;
|
|
731
|
+
}
|
|
732
|
+
// ── In-App Notifications ────────────────────────────
|
|
733
|
+
/**
|
|
734
|
+
* Lista notificações in-app de um subscriber.
|
|
735
|
+
*/
|
|
736
|
+
async listNotifications(subscriberId, params, options) {
|
|
737
|
+
return this.client.get(
|
|
738
|
+
`/subscribers/${subscriberId}/notifications`,
|
|
739
|
+
params,
|
|
740
|
+
options
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Marca uma notificação in-app como lida.
|
|
745
|
+
*/
|
|
746
|
+
async markRead(subscriberId, notificationId, options) {
|
|
747
|
+
await this.client.post(
|
|
748
|
+
`/subscribers/${subscriberId}/notifications/${notificationId}/read`,
|
|
749
|
+
void 0,
|
|
750
|
+
options
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Marca todas as notificações in-app como lidas.
|
|
755
|
+
*/
|
|
756
|
+
async markAllRead(subscriberId, options) {
|
|
757
|
+
await this.client.post(
|
|
758
|
+
`/subscribers/${subscriberId}/notifications/read-all`,
|
|
759
|
+
void 0,
|
|
760
|
+
options
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Obtém contagem de notificações não lidas.
|
|
765
|
+
*/
|
|
766
|
+
async getUnreadCount(subscriberId, options) {
|
|
767
|
+
const response = await this.client.get(
|
|
768
|
+
`/subscribers/${subscriberId}/notifications/unread-count`,
|
|
769
|
+
void 0,
|
|
770
|
+
options
|
|
771
|
+
);
|
|
772
|
+
return response.data.count;
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
// src/resources/channels.ts
|
|
777
|
+
var Channels = class {
|
|
778
|
+
client;
|
|
779
|
+
constructor(client) {
|
|
780
|
+
this.client = client;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Configura um canal de notificação.
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```ts
|
|
787
|
+
* const channel = await notifica.channels.create({
|
|
788
|
+
* channel: 'email',
|
|
789
|
+
* provider: 'aws_ses',
|
|
790
|
+
* credentials: {
|
|
791
|
+
* access_key_id: 'AKIA...',
|
|
792
|
+
* secret_access_key: '...',
|
|
793
|
+
* region: 'us-east-1',
|
|
794
|
+
* },
|
|
795
|
+
* settings: {
|
|
796
|
+
* from_address: 'noreply@empresa.com.br',
|
|
797
|
+
* from_name: 'Empresa',
|
|
798
|
+
* },
|
|
799
|
+
* });
|
|
800
|
+
* ```
|
|
801
|
+
*/
|
|
802
|
+
async create(params, options) {
|
|
803
|
+
const response = await this.client.post(
|
|
804
|
+
"/channels",
|
|
805
|
+
params,
|
|
806
|
+
options
|
|
807
|
+
);
|
|
808
|
+
return response.data;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Lista todas as configurações de canal.
|
|
812
|
+
*/
|
|
813
|
+
async list(options) {
|
|
814
|
+
const response = await this.client.get(
|
|
815
|
+
"/channels",
|
|
816
|
+
void 0,
|
|
817
|
+
options
|
|
818
|
+
);
|
|
819
|
+
return response.data;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Obtém a configuração de um canal específico.
|
|
823
|
+
*/
|
|
824
|
+
async get(channel, options) {
|
|
825
|
+
return this.client.getOne(`/channels/${channel}`, options);
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Atualiza a configuração de um canal.
|
|
829
|
+
*/
|
|
830
|
+
async update(channel, params, options) {
|
|
831
|
+
const response = await this.client.put(
|
|
832
|
+
`/channels/${channel}`,
|
|
833
|
+
params,
|
|
834
|
+
options
|
|
835
|
+
);
|
|
836
|
+
return response.data;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Remove a configuração de um canal.
|
|
840
|
+
*/
|
|
841
|
+
async delete(channel, options) {
|
|
842
|
+
await this.client.delete(`/channels/${channel}`, options);
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Envia uma notificação de teste usando a configuração atual do canal.
|
|
846
|
+
*/
|
|
847
|
+
async test(channel, options) {
|
|
848
|
+
const response = await this.client.post(
|
|
849
|
+
`/channels/${channel}/test`,
|
|
850
|
+
void 0,
|
|
851
|
+
options
|
|
852
|
+
);
|
|
853
|
+
return response.data;
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
// src/resources/domains.ts
|
|
858
|
+
var Domains = class {
|
|
859
|
+
client;
|
|
860
|
+
constructor(client) {
|
|
861
|
+
this.client = client;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Registra um novo domínio de envio.
|
|
865
|
+
*
|
|
866
|
+
* @example
|
|
867
|
+
* ```ts
|
|
868
|
+
* const domain = await notifica.domains.create({ domain: 'suaempresa.com.br' });
|
|
869
|
+
* // Configure os registros DNS retornados em domain.dns_records
|
|
870
|
+
* ```
|
|
871
|
+
*/
|
|
872
|
+
async create(params, options) {
|
|
873
|
+
const response = await this.client.post(
|
|
874
|
+
"/domains",
|
|
875
|
+
params,
|
|
876
|
+
options
|
|
877
|
+
);
|
|
878
|
+
return response.data;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Lista domínios registrados.
|
|
882
|
+
*/
|
|
883
|
+
async list(params, options) {
|
|
884
|
+
return this.client.list("/domains", params, options);
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Obtém detalhes de um domínio.
|
|
888
|
+
*/
|
|
889
|
+
async get(id, options) {
|
|
890
|
+
return this.client.getOne(`/domains/${id}`, options);
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Dispara verificação DNS do domínio.
|
|
894
|
+
*/
|
|
895
|
+
async verify(id, options) {
|
|
896
|
+
const response = await this.client.post(
|
|
897
|
+
`/domains/${id}/verify`,
|
|
898
|
+
void 0,
|
|
899
|
+
options
|
|
900
|
+
);
|
|
901
|
+
return response.data;
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Remove um domínio.
|
|
905
|
+
*/
|
|
906
|
+
async delete(id, options) {
|
|
907
|
+
await this.client.delete(`/domains/${id}`, options);
|
|
908
|
+
}
|
|
909
|
+
// ── Health ──────────────────────────────────────────
|
|
910
|
+
/**
|
|
911
|
+
* Obtém status de saúde do domínio.
|
|
912
|
+
*/
|
|
913
|
+
async getHealth(domainId, options) {
|
|
914
|
+
return this.client.getOne(`/domains/${domainId}/health`, options);
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Força verificação de saúde (rate limit: 1/min).
|
|
918
|
+
*/
|
|
919
|
+
async checkHealth(domainId, options) {
|
|
920
|
+
const response = await this.client.post(
|
|
921
|
+
`/domains/${domainId}/health/check`,
|
|
922
|
+
void 0,
|
|
923
|
+
options
|
|
924
|
+
);
|
|
925
|
+
return response.data;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Lista alertas de domínio.
|
|
929
|
+
*/
|
|
930
|
+
async listAlerts(options) {
|
|
931
|
+
const response = await this.client.get(
|
|
932
|
+
"/domains/alerts",
|
|
933
|
+
void 0,
|
|
934
|
+
options
|
|
935
|
+
);
|
|
936
|
+
return response.data;
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
// src/resources/webhooks.ts
|
|
941
|
+
var Webhooks = class {
|
|
942
|
+
client;
|
|
943
|
+
constructor(client) {
|
|
944
|
+
this.client = client;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Cria um novo webhook.
|
|
948
|
+
* ⚠️ O signing_secret é retornado apenas na criação. Salve-o!
|
|
949
|
+
*
|
|
950
|
+
* @example
|
|
951
|
+
* ```ts
|
|
952
|
+
* const webhook = await notifica.webhooks.create({
|
|
953
|
+
* url: 'https://meuapp.com.br/webhooks/notifica',
|
|
954
|
+
* events: ['notification.delivered', 'notification.failed'],
|
|
955
|
+
* });
|
|
956
|
+
* // Salve: webhook.signing_secret
|
|
957
|
+
* ```
|
|
958
|
+
*/
|
|
959
|
+
async create(params, options) {
|
|
960
|
+
const response = await this.client.post(
|
|
961
|
+
"/webhooks",
|
|
962
|
+
params,
|
|
963
|
+
options
|
|
964
|
+
);
|
|
965
|
+
return response.data;
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Lista webhooks com paginação.
|
|
969
|
+
*/
|
|
970
|
+
async list(params, options) {
|
|
971
|
+
return this.client.list("/webhooks", params, options);
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Obtém detalhes de um webhook.
|
|
975
|
+
*/
|
|
976
|
+
async get(id, options) {
|
|
977
|
+
return this.client.getOne(`/webhooks/${id}`, options);
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Atualiza um webhook.
|
|
981
|
+
*/
|
|
982
|
+
async update(id, params, options) {
|
|
983
|
+
const response = await this.client.put(
|
|
984
|
+
`/webhooks/${id}`,
|
|
985
|
+
params,
|
|
986
|
+
options
|
|
987
|
+
);
|
|
988
|
+
return response.data;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Deleta um webhook.
|
|
992
|
+
*/
|
|
993
|
+
async delete(id, options) {
|
|
994
|
+
await this.client.delete(`/webhooks/${id}`, options);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Envia um evento de teste para o webhook.
|
|
998
|
+
*/
|
|
999
|
+
async test(id, options) {
|
|
1000
|
+
await this.client.post(`/webhooks/${id}/test`, void 0, options);
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Lista entregas recentes de um webhook.
|
|
1004
|
+
*/
|
|
1005
|
+
async listDeliveries(id, params, options) {
|
|
1006
|
+
const response = await this.client.get(
|
|
1007
|
+
`/webhooks/${id}/deliveries`,
|
|
1008
|
+
params,
|
|
1009
|
+
options
|
|
1010
|
+
);
|
|
1011
|
+
return response.data;
|
|
1012
|
+
}
|
|
1013
|
+
// ── Webhook signature verification ──────────────────
|
|
1014
|
+
/**
|
|
1015
|
+
* Verifica a assinatura HMAC de um payload de webhook.
|
|
1016
|
+
*
|
|
1017
|
+
* Use para validar que o payload foi realmente enviado pelo Notifica.
|
|
1018
|
+
*
|
|
1019
|
+
* @param payload — Body da request (string ou Buffer)
|
|
1020
|
+
* @param signature — Valor do header `X-Notifica-Signature`
|
|
1021
|
+
* @param secret — signing_secret do webhook
|
|
1022
|
+
* @returns true se a assinatura é válida
|
|
1023
|
+
*
|
|
1024
|
+
* @example
|
|
1025
|
+
* ```ts
|
|
1026
|
+
* app.post('/webhooks/notifica', (req, res) => {
|
|
1027
|
+
* const payload = req.body; // raw body string
|
|
1028
|
+
* const signature = req.headers['x-notifica-signature'];
|
|
1029
|
+
* const secret = process.env.WEBHOOK_SECRET;
|
|
1030
|
+
*
|
|
1031
|
+
* if (!notifica.webhooks.verify(payload, signature, secret)) {
|
|
1032
|
+
* return res.status(401).send('Invalid signature');
|
|
1033
|
+
* }
|
|
1034
|
+
*
|
|
1035
|
+
* // Processar evento...
|
|
1036
|
+
* res.status(200).send('OK');
|
|
1037
|
+
* });
|
|
1038
|
+
* ```
|
|
1039
|
+
*/
|
|
1040
|
+
async verify(payload, signature, secret) {
|
|
1041
|
+
if (!payload || !signature || !secret) {
|
|
1042
|
+
return false;
|
|
1043
|
+
}
|
|
1044
|
+
try {
|
|
1045
|
+
const encoder = new TextEncoder();
|
|
1046
|
+
const key = await crypto.subtle.importKey(
|
|
1047
|
+
"raw",
|
|
1048
|
+
encoder.encode(secret),
|
|
1049
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
1050
|
+
false,
|
|
1051
|
+
["sign"]
|
|
1052
|
+
);
|
|
1053
|
+
const payloadBytes = typeof payload === "string" ? encoder.encode(payload) : payload instanceof ArrayBuffer ? new Uint8Array(payload) : payload;
|
|
1054
|
+
const signatureBytes = await crypto.subtle.sign("HMAC", key, payloadBytes);
|
|
1055
|
+
const computed = this.toHex(new Uint8Array(signatureBytes));
|
|
1056
|
+
return this.timingSafeEqual(computed, signature);
|
|
1057
|
+
} catch {
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Verifica a assinatura e lança erro se inválida.
|
|
1063
|
+
* Versão "fail-fast" do verify().
|
|
1064
|
+
*/
|
|
1065
|
+
async verifyOrThrow(payload, signature, secret) {
|
|
1066
|
+
const valid = await this.verify(payload, signature, secret);
|
|
1067
|
+
if (!valid) {
|
|
1068
|
+
throw new NotificaError("Invalid webhook signature");
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
toHex(bytes) {
|
|
1072
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Constant-time string comparison to prevent timing attacks.
|
|
1076
|
+
*/
|
|
1077
|
+
timingSafeEqual(a, b) {
|
|
1078
|
+
if (a.length !== b.length) return false;
|
|
1079
|
+
let result = 0;
|
|
1080
|
+
for (let i = 0; i < a.length; i++) {
|
|
1081
|
+
result |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
1082
|
+
}
|
|
1083
|
+
return result === 0;
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
|
|
1087
|
+
// src/resources/api-keys.ts
|
|
1088
|
+
var ApiKeys = class {
|
|
1089
|
+
client;
|
|
1090
|
+
constructor(client) {
|
|
1091
|
+
this.client = client;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Cria uma nova API key.
|
|
1095
|
+
* ⚠️ O raw_key é retornado apenas na criação. Salve-o!
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* ```ts
|
|
1099
|
+
* const key = await notifica.apiKeys.create({
|
|
1100
|
+
* key_type: 'secret',
|
|
1101
|
+
* label: 'Backend Production',
|
|
1102
|
+
* environment: 'production',
|
|
1103
|
+
* });
|
|
1104
|
+
* // Salve: key.raw_key
|
|
1105
|
+
* ```
|
|
1106
|
+
*/
|
|
1107
|
+
async create(params, options) {
|
|
1108
|
+
const response = await this.client.post(
|
|
1109
|
+
"/api-keys",
|
|
1110
|
+
params,
|
|
1111
|
+
options
|
|
1112
|
+
);
|
|
1113
|
+
return response.data;
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Lista API keys (sem raw_key).
|
|
1117
|
+
*/
|
|
1118
|
+
async list(options) {
|
|
1119
|
+
const response = await this.client.get(
|
|
1120
|
+
"/api-keys",
|
|
1121
|
+
void 0,
|
|
1122
|
+
options
|
|
1123
|
+
);
|
|
1124
|
+
return response.data;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Revoga (deleta) uma API key.
|
|
1128
|
+
*/
|
|
1129
|
+
async revoke(id, options) {
|
|
1130
|
+
await this.client.delete(`/api-keys/${id}`, options);
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
|
|
1134
|
+
// src/resources/analytics.ts
|
|
1135
|
+
var Analytics = class {
|
|
1136
|
+
client;
|
|
1137
|
+
constructor(client) {
|
|
1138
|
+
this.client = client;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Métricas gerais (total enviado, entregue, falhas, taxa de entrega).
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* ```ts
|
|
1145
|
+
* const overview = await notifica.analytics.overview({ period: '7d' });
|
|
1146
|
+
* console.log(`Taxa de entrega: ${overview.delivery_rate}%`);
|
|
1147
|
+
* ```
|
|
1148
|
+
*/
|
|
1149
|
+
async overview(params, options) {
|
|
1150
|
+
const response = await this.client.get(
|
|
1151
|
+
"/analytics/overview",
|
|
1152
|
+
params,
|
|
1153
|
+
options
|
|
1154
|
+
);
|
|
1155
|
+
return response.data;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Métricas por canal.
|
|
1159
|
+
*/
|
|
1160
|
+
async byChannel(params, options) {
|
|
1161
|
+
const response = await this.client.get(
|
|
1162
|
+
"/analytics/channels",
|
|
1163
|
+
params,
|
|
1164
|
+
options
|
|
1165
|
+
);
|
|
1166
|
+
return response.data;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Série temporal de envios.
|
|
1170
|
+
*/
|
|
1171
|
+
async timeseries(params, options) {
|
|
1172
|
+
const response = await this.client.get(
|
|
1173
|
+
"/analytics/timeseries",
|
|
1174
|
+
params,
|
|
1175
|
+
options
|
|
1176
|
+
);
|
|
1177
|
+
return response.data;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Templates mais utilizados.
|
|
1181
|
+
*/
|
|
1182
|
+
async topTemplates(params, options) {
|
|
1183
|
+
const response = await this.client.get(
|
|
1184
|
+
"/analytics/templates",
|
|
1185
|
+
params,
|
|
1186
|
+
options
|
|
1187
|
+
);
|
|
1188
|
+
return response.data;
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
|
|
1192
|
+
// src/resources/sms.ts
|
|
1193
|
+
var SmsProviders = class {
|
|
1194
|
+
client;
|
|
1195
|
+
constructor(client) {
|
|
1196
|
+
this.client = client;
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Lista todos os provedores SMS configurados.
|
|
1200
|
+
*/
|
|
1201
|
+
async list(options) {
|
|
1202
|
+
const response = await this.client.get(
|
|
1203
|
+
"/channels/sms/providers",
|
|
1204
|
+
void 0,
|
|
1205
|
+
options
|
|
1206
|
+
);
|
|
1207
|
+
return response.data;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Cria um novo provedor SMS (idempotent).
|
|
1211
|
+
*/
|
|
1212
|
+
async create(params, options) {
|
|
1213
|
+
const response = await this.client.post(
|
|
1214
|
+
"/channels/sms/providers",
|
|
1215
|
+
params,
|
|
1216
|
+
options
|
|
1217
|
+
);
|
|
1218
|
+
return response.data;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Obtém detalhes de um provedor SMS.
|
|
1222
|
+
*/
|
|
1223
|
+
async get(id, options) {
|
|
1224
|
+
return this.client.getOne(`/channels/sms/providers/${id}`, options);
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Atualiza um provedor SMS (PATCH parcial).
|
|
1228
|
+
*/
|
|
1229
|
+
async update(id, params, options) {
|
|
1230
|
+
const response = await this.client.patch(
|
|
1231
|
+
`/channels/sms/providers/${id}`,
|
|
1232
|
+
params,
|
|
1233
|
+
options
|
|
1234
|
+
);
|
|
1235
|
+
return response.data;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Ativa um provedor SMS.
|
|
1239
|
+
*/
|
|
1240
|
+
async activate(id, options) {
|
|
1241
|
+
const response = await this.client.post(
|
|
1242
|
+
`/channels/sms/providers/${id}/activate`,
|
|
1243
|
+
void 0,
|
|
1244
|
+
options
|
|
1245
|
+
);
|
|
1246
|
+
return response.data;
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Remove um provedor SMS.
|
|
1250
|
+
*/
|
|
1251
|
+
async delete(id, options) {
|
|
1252
|
+
await this.client.delete(`/channels/sms/providers/${id}`, options);
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Valida a configuração de um provedor SMS.
|
|
1256
|
+
*/
|
|
1257
|
+
async validate(params, options) {
|
|
1258
|
+
const response = await this.client.post(
|
|
1259
|
+
"/channels/sms/providers/validate",
|
|
1260
|
+
params,
|
|
1261
|
+
options
|
|
1262
|
+
);
|
|
1263
|
+
return response.data;
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Envia um SMS de teste.
|
|
1267
|
+
*/
|
|
1268
|
+
async test(params, options) {
|
|
1269
|
+
const response = await this.client.post(
|
|
1270
|
+
"/channels/sms/providers/test",
|
|
1271
|
+
params,
|
|
1272
|
+
options
|
|
1273
|
+
);
|
|
1274
|
+
return response.data;
|
|
1275
|
+
}
|
|
1276
|
+
};
|
|
1277
|
+
var SmsCompliance = class {
|
|
1278
|
+
client;
|
|
1279
|
+
constructor(client) {
|
|
1280
|
+
this.client = client;
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Obtém as configurações de compliance SMS.
|
|
1284
|
+
*/
|
|
1285
|
+
async show(options) {
|
|
1286
|
+
return this.client.getOne("/channels/sms/compliance", options);
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Atualiza as configurações de compliance SMS (PATCH parcial).
|
|
1290
|
+
*/
|
|
1291
|
+
async update(params, options) {
|
|
1292
|
+
const response = await this.client.patch(
|
|
1293
|
+
"/channels/sms/compliance",
|
|
1294
|
+
params,
|
|
1295
|
+
options
|
|
1296
|
+
);
|
|
1297
|
+
return response.data;
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Obtém estatísticas de compliance.
|
|
1301
|
+
*/
|
|
1302
|
+
async analytics(options) {
|
|
1303
|
+
return this.client.getOne("/channels/sms/compliance/analytics", options);
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Lista logs de compliance com paginação.
|
|
1307
|
+
*/
|
|
1308
|
+
async logs(params, options) {
|
|
1309
|
+
return this.client.list("/channels/sms/compliance/logs", params, options);
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
var SmsConsents = class {
|
|
1313
|
+
client;
|
|
1314
|
+
constructor(client) {
|
|
1315
|
+
this.client = client;
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Lista consentimentos SMS com paginação.
|
|
1319
|
+
*/
|
|
1320
|
+
async list(params, options) {
|
|
1321
|
+
return this.client.list("/channels/sms/consents", params, options);
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Obtém resumo estatístico dos consentimentos.
|
|
1325
|
+
*/
|
|
1326
|
+
async summary(options) {
|
|
1327
|
+
return this.client.getOne("/channels/sms/consents/summary", options);
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Obtém o consentimento de um número específico.
|
|
1331
|
+
*/
|
|
1332
|
+
async get(phone, options) {
|
|
1333
|
+
return this.client.getOne(`/channels/sms/consents/${encodeURIComponent(phone)}`, options);
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Revoga o consentimento de um número (DELETE).
|
|
1337
|
+
*/
|
|
1338
|
+
async revoke(phone, options) {
|
|
1339
|
+
await this.client.delete(`/channels/sms/consents/${encodeURIComponent(phone)}`, options);
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Cria ou atualiza um consentimento SMS (idempotent).
|
|
1343
|
+
*/
|
|
1344
|
+
async create(params, options) {
|
|
1345
|
+
const response = await this.client.post(
|
|
1346
|
+
"/channels/sms/consents",
|
|
1347
|
+
params,
|
|
1348
|
+
options
|
|
1349
|
+
);
|
|
1350
|
+
return response.data;
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* Importa consentimentos em lote.
|
|
1354
|
+
*/
|
|
1355
|
+
async import(params, options) {
|
|
1356
|
+
const response = await this.client.post(
|
|
1357
|
+
"/channels/sms/consents/import",
|
|
1358
|
+
params,
|
|
1359
|
+
options
|
|
1360
|
+
);
|
|
1361
|
+
return response.data;
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
var Sms = class {
|
|
1365
|
+
providers;
|
|
1366
|
+
compliance;
|
|
1367
|
+
consents;
|
|
1368
|
+
constructor(client) {
|
|
1369
|
+
this.providers = new SmsProviders(client);
|
|
1370
|
+
this.compliance = new SmsCompliance(client);
|
|
1371
|
+
this.consents = new SmsConsents(client);
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
|
|
1375
|
+
// src/resources/billing.ts
|
|
1376
|
+
var BillingPlans = class {
|
|
1377
|
+
client;
|
|
1378
|
+
constructor(client) {
|
|
1379
|
+
this.client = client;
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Lista todos os planos disponíveis.
|
|
1383
|
+
*/
|
|
1384
|
+
async list(options) {
|
|
1385
|
+
const response = await this.client.get(
|
|
1386
|
+
"/billing/plans",
|
|
1387
|
+
void 0,
|
|
1388
|
+
options
|
|
1389
|
+
);
|
|
1390
|
+
return response.data;
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Obtém detalhes de um plano específico.
|
|
1394
|
+
*/
|
|
1395
|
+
async get(name, options) {
|
|
1396
|
+
return this.client.getOne(`/billing/plans/${name}`, options);
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
var BillingSettingsResource = class {
|
|
1400
|
+
client;
|
|
1401
|
+
constructor(client) {
|
|
1402
|
+
this.client = client;
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Obtém as configurações de faturamento do tenant.
|
|
1406
|
+
*/
|
|
1407
|
+
async get(options) {
|
|
1408
|
+
return this.client.getOne("/billing/settings", options);
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
var BillingSubscription = class {
|
|
1412
|
+
client;
|
|
1413
|
+
constructor(client) {
|
|
1414
|
+
this.client = client;
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Obtém a assinatura atual.
|
|
1418
|
+
*/
|
|
1419
|
+
async get(options) {
|
|
1420
|
+
return this.client.getOne("/billing/subscription", options);
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Cria uma nova assinatura (idempotent).
|
|
1424
|
+
*/
|
|
1425
|
+
async subscribe(params, options) {
|
|
1426
|
+
const response = await this.client.post(
|
|
1427
|
+
"/billing/subscribe",
|
|
1428
|
+
params,
|
|
1429
|
+
options
|
|
1430
|
+
);
|
|
1431
|
+
return response.data;
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Altera o plano da assinatura (idempotent).
|
|
1435
|
+
*/
|
|
1436
|
+
async changePlan(params, options) {
|
|
1437
|
+
const response = await this.client.post(
|
|
1438
|
+
"/billing/change-plan",
|
|
1439
|
+
params,
|
|
1440
|
+
options
|
|
1441
|
+
);
|
|
1442
|
+
return response.data;
|
|
1443
|
+
}
|
|
1444
|
+
/**
|
|
1445
|
+
* Cancela a assinatura (idempotent).
|
|
1446
|
+
*/
|
|
1447
|
+
async cancel(params, options) {
|
|
1448
|
+
const response = await this.client.post(
|
|
1449
|
+
"/billing/cancel",
|
|
1450
|
+
params,
|
|
1451
|
+
options
|
|
1452
|
+
);
|
|
1453
|
+
return response.data;
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Calcula o valor de proration para mudança de plano.
|
|
1457
|
+
*/
|
|
1458
|
+
async calculateProration(params, options) {
|
|
1459
|
+
const response = await this.client.post(
|
|
1460
|
+
"/billing/calculate-proration",
|
|
1461
|
+
params,
|
|
1462
|
+
options
|
|
1463
|
+
);
|
|
1464
|
+
return response.data;
|
|
1465
|
+
}
|
|
1466
|
+
/**
|
|
1467
|
+
* Reativa uma assinatura cancelada (idempotent).
|
|
1468
|
+
*/
|
|
1469
|
+
async reactivate(params, options) {
|
|
1470
|
+
const response = await this.client.post(
|
|
1471
|
+
"/billing/reactivate",
|
|
1472
|
+
params,
|
|
1473
|
+
options
|
|
1474
|
+
);
|
|
1475
|
+
return response.data;
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
var BillingUsageResource = class {
|
|
1479
|
+
client;
|
|
1480
|
+
constructor(client) {
|
|
1481
|
+
this.client = client;
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Obtém o uso atual e quotas do tenant.
|
|
1485
|
+
*/
|
|
1486
|
+
async get(options) {
|
|
1487
|
+
return this.client.getOne("/billing/usage", options);
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
var BillingInvoices = class {
|
|
1491
|
+
client;
|
|
1492
|
+
constructor(client) {
|
|
1493
|
+
this.client = client;
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* Lista faturas com paginação.
|
|
1497
|
+
*/
|
|
1498
|
+
async list(params, options) {
|
|
1499
|
+
return this.client.list("/billing/invoices", params, options);
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Obtém detalhes de uma fatura.
|
|
1503
|
+
*/
|
|
1504
|
+
async get(id, options) {
|
|
1505
|
+
return this.client.getOne(`/billing/invoices/${id}`, options);
|
|
1506
|
+
}
|
|
1507
|
+
};
|
|
1508
|
+
var BillingPaymentMethods = class {
|
|
1509
|
+
client;
|
|
1510
|
+
constructor(client) {
|
|
1511
|
+
this.client = client;
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Lista métodos de pagamento.
|
|
1515
|
+
*/
|
|
1516
|
+
async list(options) {
|
|
1517
|
+
const response = await this.client.get(
|
|
1518
|
+
"/billing/payment-methods",
|
|
1519
|
+
void 0,
|
|
1520
|
+
options
|
|
1521
|
+
);
|
|
1522
|
+
return response.data;
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Cria um novo método de pagamento (idempotent).
|
|
1526
|
+
*/
|
|
1527
|
+
async create(params, options) {
|
|
1528
|
+
const response = await this.client.post(
|
|
1529
|
+
"/billing/payment-methods",
|
|
1530
|
+
params,
|
|
1531
|
+
options
|
|
1532
|
+
);
|
|
1533
|
+
return response.data;
|
|
1534
|
+
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Obtém detalhes de um método de pagamento.
|
|
1537
|
+
*/
|
|
1538
|
+
async get(id, options) {
|
|
1539
|
+
return this.client.getOne(`/billing/payment-methods/${id}`, options);
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* Atualiza um método de pagamento.
|
|
1543
|
+
*/
|
|
1544
|
+
async update(id, params, options) {
|
|
1545
|
+
const response = await this.client.put(
|
|
1546
|
+
`/billing/payment-methods/${id}`,
|
|
1547
|
+
params,
|
|
1548
|
+
options
|
|
1549
|
+
);
|
|
1550
|
+
return response.data;
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Remove um método de pagamento.
|
|
1554
|
+
*/
|
|
1555
|
+
async delete(id, options) {
|
|
1556
|
+
await this.client.delete(`/billing/payment-methods/${id}`, options);
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Define um método de pagamento como padrão.
|
|
1560
|
+
*/
|
|
1561
|
+
async setDefault(id, options) {
|
|
1562
|
+
const response = await this.client.post(
|
|
1563
|
+
`/billing/payment-methods/${id}/set-default`,
|
|
1564
|
+
void 0,
|
|
1565
|
+
options
|
|
1566
|
+
);
|
|
1567
|
+
return response.data;
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
var Billing = class {
|
|
1571
|
+
plans;
|
|
1572
|
+
settings;
|
|
1573
|
+
subscription;
|
|
1574
|
+
usage;
|
|
1575
|
+
invoices;
|
|
1576
|
+
paymentMethods;
|
|
1577
|
+
constructor(client) {
|
|
1578
|
+
this.plans = new BillingPlans(client);
|
|
1579
|
+
this.settings = new BillingSettingsResource(client);
|
|
1580
|
+
this.subscription = new BillingSubscription(client);
|
|
1581
|
+
this.usage = new BillingUsageResource(client);
|
|
1582
|
+
this.invoices = new BillingInvoices(client);
|
|
1583
|
+
this.paymentMethods = new BillingPaymentMethods(client);
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
// src/resources/inbox-embed.ts
|
|
1588
|
+
var InboxEmbed = class {
|
|
1589
|
+
client;
|
|
1590
|
+
constructor(client) {
|
|
1591
|
+
this.client = client;
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Obtém as configurações do inbox embed.
|
|
1595
|
+
*/
|
|
1596
|
+
async getSettings(options) {
|
|
1597
|
+
return this.client.getOne("/inbox-embed/settings", options);
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Atualiza as configurações do inbox embed.
|
|
1601
|
+
*/
|
|
1602
|
+
async updateSettings(params, options) {
|
|
1603
|
+
const response = await this.client.put(
|
|
1604
|
+
"/inbox-embed/settings",
|
|
1605
|
+
params,
|
|
1606
|
+
options
|
|
1607
|
+
);
|
|
1608
|
+
return response.data;
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Rotaciona a chave de embed.
|
|
1612
|
+
* A chave antiga continua funcionando por um período de grace period.
|
|
1613
|
+
*/
|
|
1614
|
+
async rotateKey(options) {
|
|
1615
|
+
const response = await this.client.post(
|
|
1616
|
+
"/inbox-embed/keys/rotate",
|
|
1617
|
+
void 0,
|
|
1618
|
+
options
|
|
1619
|
+
);
|
|
1620
|
+
return response.data;
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1623
|
+
|
|
1624
|
+
// src/resources/inbox.ts
|
|
1625
|
+
var Inbox = class {
|
|
1626
|
+
client;
|
|
1627
|
+
constructor(client) {
|
|
1628
|
+
this.client = client;
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* Lista notificações do inbox.
|
|
1632
|
+
* Requer subscriber_id ou external_id como parâmetro de query.
|
|
1633
|
+
*/
|
|
1634
|
+
async listNotifications(subscriberId, params, options) {
|
|
1635
|
+
return this.client.list(
|
|
1636
|
+
"/inbox/notifications",
|
|
1637
|
+
{ subscriber_id: subscriberId, ...params },
|
|
1638
|
+
options
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Obtém a contagem de notificações não lidas.
|
|
1643
|
+
*/
|
|
1644
|
+
async getUnreadCount(subscriberId, options) {
|
|
1645
|
+
const response = await this.client.get(
|
|
1646
|
+
"/inbox/notifications/unread-count",
|
|
1647
|
+
{ subscriber_id: subscriberId },
|
|
1648
|
+
options
|
|
1649
|
+
);
|
|
1650
|
+
return response.data.count;
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Marca uma notificação como lida.
|
|
1654
|
+
*/
|
|
1655
|
+
async markRead(notificationId, options) {
|
|
1656
|
+
const response = await this.client.post(
|
|
1657
|
+
`/inbox/notifications/${notificationId}/read`,
|
|
1658
|
+
void 0,
|
|
1659
|
+
options
|
|
1660
|
+
);
|
|
1661
|
+
return response.data;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Marca todas as notificações como lidas.
|
|
1665
|
+
* Requer subscriber_id como parâmetro de query.
|
|
1666
|
+
*/
|
|
1667
|
+
async markAllRead(subscriberId, options) {
|
|
1668
|
+
const response = await this.client.post(
|
|
1669
|
+
"/inbox/notifications/read-all",
|
|
1670
|
+
{ subscriber_id: subscriberId },
|
|
1671
|
+
options
|
|
1672
|
+
);
|
|
1673
|
+
return response.data;
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
1676
|
+
|
|
1677
|
+
// src/index.ts
|
|
1678
|
+
var Notifica = class {
|
|
1679
|
+
notifications;
|
|
1680
|
+
templates;
|
|
1681
|
+
workflows;
|
|
1682
|
+
subscribers;
|
|
1683
|
+
channels;
|
|
1684
|
+
domains;
|
|
1685
|
+
webhooks;
|
|
1686
|
+
apiKeys;
|
|
1687
|
+
analytics;
|
|
1688
|
+
sms;
|
|
1689
|
+
billing;
|
|
1690
|
+
inboxEmbed;
|
|
1691
|
+
inbox;
|
|
1692
|
+
/**
|
|
1693
|
+
* Cria uma nova instância do cliente Notifica.
|
|
1694
|
+
*
|
|
1695
|
+
* @param apiKeyOrConfig — API key (string) ou objeto de configuração completo
|
|
1696
|
+
*
|
|
1697
|
+
* @example
|
|
1698
|
+
* ```ts
|
|
1699
|
+
* // Simples — apenas API key
|
|
1700
|
+
* const notifica = new Notifica('nk_live_...');
|
|
1701
|
+
*
|
|
1702
|
+
* // Configuração completa
|
|
1703
|
+
* const notifica = new Notifica({
|
|
1704
|
+
* apiKey: 'nk_live_...',
|
|
1705
|
+
* baseUrl: 'https://app.usenotifica.com.br/v1',
|
|
1706
|
+
* timeout: 15000,
|
|
1707
|
+
* maxRetries: 5,
|
|
1708
|
+
* });
|
|
1709
|
+
* ```
|
|
1710
|
+
*/
|
|
1711
|
+
constructor(apiKeyOrConfig) {
|
|
1712
|
+
const config = typeof apiKeyOrConfig === "string" ? { apiKey: apiKeyOrConfig } : apiKeyOrConfig;
|
|
1713
|
+
const client = new NotificaClient(config);
|
|
1714
|
+
this.notifications = new Notifications(client);
|
|
1715
|
+
this.templates = new Templates(client);
|
|
1716
|
+
this.workflows = new Workflows(client);
|
|
1717
|
+
this.subscribers = new Subscribers(client);
|
|
1718
|
+
this.channels = new Channels(client);
|
|
1719
|
+
this.domains = new Domains(client);
|
|
1720
|
+
this.webhooks = new Webhooks(client);
|
|
1721
|
+
this.apiKeys = new ApiKeys(client);
|
|
1722
|
+
this.analytics = new Analytics(client);
|
|
1723
|
+
this.sms = new Sms(client);
|
|
1724
|
+
this.billing = new Billing(client);
|
|
1725
|
+
this.inboxEmbed = new InboxEmbed(client);
|
|
1726
|
+
this.inbox = new Inbox(client);
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1730
|
+
0 && (module.exports = {
|
|
1731
|
+
Analytics,
|
|
1732
|
+
ApiError,
|
|
1733
|
+
ApiKeys,
|
|
1734
|
+
Billing,
|
|
1735
|
+
Channels,
|
|
1736
|
+
Domains,
|
|
1737
|
+
Inbox,
|
|
1738
|
+
InboxEmbed,
|
|
1739
|
+
Notifica,
|
|
1740
|
+
NotificaClient,
|
|
1741
|
+
NotificaError,
|
|
1742
|
+
Notifications,
|
|
1743
|
+
RateLimitError,
|
|
1744
|
+
Sms,
|
|
1745
|
+
Subscribers,
|
|
1746
|
+
Templates,
|
|
1747
|
+
TimeoutError,
|
|
1748
|
+
ValidationError,
|
|
1749
|
+
Webhooks,
|
|
1750
|
+
Workflows
|
|
1751
|
+
});
|