kommo-aiatende-api 1.2.2 → 1.2.3
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.mts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +67 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -41,12 +41,30 @@ var AuthManager = class {
|
|
|
41
41
|
// src/resources/leads/index.ts
|
|
42
42
|
import qs from "qs";
|
|
43
43
|
|
|
44
|
+
// src/utils/idempotency.ts
|
|
45
|
+
import { randomUUID } from "crypto";
|
|
46
|
+
function ensureRequestId(item) {
|
|
47
|
+
if (item.request_id) return item;
|
|
48
|
+
return { ...item, request_id: randomUUID() };
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
// src/base.ts
|
|
45
52
|
var BaseResource = class {
|
|
46
53
|
client;
|
|
47
54
|
constructor(client) {
|
|
48
55
|
this.client = client;
|
|
49
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* POST de criação em lote marcado como seguro para retry: cada item recebe um
|
|
59
|
+
* request_id (se ainda não tiver um) para que a Kommo deduplique reenvios após
|
|
60
|
+
* falhas transitórias de rede, e a requisição fica elegível ao retry automático.
|
|
61
|
+
*/
|
|
62
|
+
async postIdempotent(url, items) {
|
|
63
|
+
const payload = items.map(ensureRequestId);
|
|
64
|
+
const config = { _idempotentRetry: true };
|
|
65
|
+
const response = await this.client.post(url, payload, config);
|
|
66
|
+
return response.data;
|
|
67
|
+
}
|
|
50
68
|
};
|
|
51
69
|
|
|
52
70
|
// src/resources/leads/index.ts
|
|
@@ -118,8 +136,7 @@ var LeadsResource = class extends BaseResource {
|
|
|
118
136
|
}
|
|
119
137
|
async create(items) {
|
|
120
138
|
const payload = Array.isArray(items) ? items : [items];
|
|
121
|
-
|
|
122
|
-
return response.data;
|
|
139
|
+
return this.postIdempotent("/api/v4/leads", payload);
|
|
123
140
|
}
|
|
124
141
|
async update(items) {
|
|
125
142
|
const payload = Array.isArray(items) ? items : [items];
|
|
@@ -132,8 +149,7 @@ var LeadsResource = class extends BaseResource {
|
|
|
132
149
|
}
|
|
133
150
|
async createComplex(items) {
|
|
134
151
|
const payload = Array.isArray(items) ? items : [items];
|
|
135
|
-
|
|
136
|
-
return response.data;
|
|
152
|
+
return this.postIdempotent("/api/v4/leads/complex", payload);
|
|
137
153
|
}
|
|
138
154
|
async listLossReasons() {
|
|
139
155
|
const response = await this.client.get("/api/v4/leads/loss_reasons");
|
|
@@ -210,8 +226,7 @@ var ContactsResource = class extends BaseResource {
|
|
|
210
226
|
}
|
|
211
227
|
async create(items) {
|
|
212
228
|
const payload = Array.isArray(items) ? items : [items];
|
|
213
|
-
|
|
214
|
-
return response.data;
|
|
229
|
+
return this.postIdempotent("/api/v4/contacts", payload);
|
|
215
230
|
}
|
|
216
231
|
async update(items) {
|
|
217
232
|
const payload = Array.isArray(items) ? items : [items];
|
|
@@ -678,8 +693,7 @@ var CompaniesResource = class extends BaseResource {
|
|
|
678
693
|
}
|
|
679
694
|
async create(items) {
|
|
680
695
|
const payload = Array.isArray(items) ? items : [items];
|
|
681
|
-
|
|
682
|
-
return response.data;
|
|
696
|
+
return this.postIdempotent("/api/v4/companies", payload);
|
|
683
697
|
}
|
|
684
698
|
async update(items) {
|
|
685
699
|
const payload = Array.isArray(items) ? items : [items];
|
|
@@ -1394,6 +1408,47 @@ var KommoApiError = class extends Error {
|
|
|
1394
1408
|
}
|
|
1395
1409
|
};
|
|
1396
1410
|
|
|
1411
|
+
// src/http/retry.ts
|
|
1412
|
+
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["get", "delete", "patch", "put", "head", "options"]);
|
|
1413
|
+
var TRANSIENT_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
1414
|
+
"ECONNRESET",
|
|
1415
|
+
"ECONNABORTED",
|
|
1416
|
+
"ETIMEDOUT",
|
|
1417
|
+
"EAI_AGAIN",
|
|
1418
|
+
"EPIPE"
|
|
1419
|
+
]);
|
|
1420
|
+
function isTransientNetworkError(error) {
|
|
1421
|
+
if (error.response) return false;
|
|
1422
|
+
if (error.code && TRANSIENT_ERROR_CODES.has(error.code)) return true;
|
|
1423
|
+
return /socket hang up|network error/i.test(error.message || "");
|
|
1424
|
+
}
|
|
1425
|
+
function isRetryableRequest(config) {
|
|
1426
|
+
const method = (config.method || "get").toLowerCase();
|
|
1427
|
+
if (IDEMPOTENT_METHODS.has(method)) return true;
|
|
1428
|
+
return method === "post" && config._idempotentRetry === true;
|
|
1429
|
+
}
|
|
1430
|
+
function wait(ms) {
|
|
1431
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1432
|
+
}
|
|
1433
|
+
function attachRetryInterceptor(client, retryConfig = {}) {
|
|
1434
|
+
const { retries = 2, baseDelayMs = 300, maxDelayMs = 3e3 } = retryConfig;
|
|
1435
|
+
client.interceptors.response.use(void 0, async (error) => {
|
|
1436
|
+
const config = error.config;
|
|
1437
|
+
if (!config || retries <= 0 || !isTransientNetworkError(error) || !isRetryableRequest(config)) {
|
|
1438
|
+
throw error;
|
|
1439
|
+
}
|
|
1440
|
+
const attempt = config._retryCount ?? 0;
|
|
1441
|
+
if (attempt >= retries) {
|
|
1442
|
+
throw error;
|
|
1443
|
+
}
|
|
1444
|
+
config._retryCount = attempt + 1;
|
|
1445
|
+
const backoff = Math.min(maxDelayMs, baseDelayMs * 2 ** attempt);
|
|
1446
|
+
const jitter = backoff * 0.3 * Math.random();
|
|
1447
|
+
await wait(backoff + jitter);
|
|
1448
|
+
return client.request(config);
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1397
1452
|
// src/client.ts
|
|
1398
1453
|
var KommoClient = class {
|
|
1399
1454
|
config;
|
|
@@ -1433,6 +1488,7 @@ var KommoClient = class {
|
|
|
1433
1488
|
const baseURL = `https://${config.domain}.kommo.com`;
|
|
1434
1489
|
this.httpClient = axios2.create({
|
|
1435
1490
|
baseURL,
|
|
1491
|
+
timeout: config.timeout ?? 3e4,
|
|
1436
1492
|
headers: {
|
|
1437
1493
|
"Content-Type": "application/json"
|
|
1438
1494
|
},
|
|
@@ -1440,6 +1496,9 @@ var KommoClient = class {
|
|
|
1440
1496
|
return qs19.stringify(params, { arrayFormat: "brackets" });
|
|
1441
1497
|
}
|
|
1442
1498
|
});
|
|
1499
|
+
if (config.retry !== false) {
|
|
1500
|
+
attachRetryInterceptor(this.httpClient, config.retry || {});
|
|
1501
|
+
}
|
|
1443
1502
|
this.httpClient.interceptors.response.use(
|
|
1444
1503
|
(response) => response,
|
|
1445
1504
|
(error) => {
|