@andrey4emk/npm-app-back-b24 3.8.0 → 3.8.1
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 +5 -1
- package/bitrix24/eventB24.ts +54 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -474,6 +474,8 @@ const sent = await fetchWithTimeout("https://api.example.com/send", { method: "P
|
|
|
474
474
|
processId: "12345",
|
|
475
475
|
message: [
|
|
476
476
|
{
|
|
477
|
+
messageId: "7cf5d29bee90cc37382a9fff07fc2a43", // MESSAGE_ID записи очереди — ключ для clear()
|
|
478
|
+
eventId: "4821", // ID записи очереди, информационное; в clear() не передавать
|
|
477
479
|
connectorId: "...",
|
|
478
480
|
lineId: "...",
|
|
479
481
|
chatId: "...",
|
|
@@ -501,6 +503,8 @@ const sent = await fetchWithTimeout("https://api.example.com/send", { method: "P
|
|
|
501
503
|
- Автоматически фильтрует и удаляет события от системного пользователя (`user_id: '138'`).
|
|
502
504
|
- Для коннекторных событий конвертирует файлы в формат с типами `image`, `video`, `document`.
|
|
503
505
|
- Если событий нет, возвращает `data` с пустыми массивами.
|
|
506
|
+
- **Гранулярность очистки — запись очереди, а не сообщение.** Одна запись коннектора (один `MESSAGE_ID`) может нести несколько сообщений, и они приходят отдельными элементами `message` с одинаковым `messageId`. Очистка по этому ключу удаляет запись целиком: если из двух сообщений одной записи ушло одно, `clear()` заберёт и неотправленное. Строить поэлементную очистку с точностью до сообщения на `messageId` нельзя. Для дедупликации отдельных сообщений он не годится по той же причине — у сообщений одной записи он общий, для этого есть `im.id`. Обратная сторона: запись, из которой не разобрано ни одного сообщения, в `data.message` не попадёт вовсе, и очистка по собранным `messageId` её не заберёт. Безопасный режим — `clear(processId)` целиком.
|
|
507
|
+
- Типы `ConnectorMessage`, `ConnectorEvents` и `EntityEvents` экспортируются из пакета.
|
|
504
508
|
|
|
505
509
|
```js
|
|
506
510
|
const { error, data } = await event.get("ONCRMDYNAMICITEMUPDATE_149");
|
|
@@ -514,7 +518,7 @@ const sent = await fetchWithTimeout("https://api.example.com/send", { method: "P
|
|
|
514
518
|
- **Параметры:**
|
|
515
519
|
|
|
516
520
|
- `processId` (string) — ID процесса (получен из `get()`).
|
|
517
|
-
- `messageId` (string|string[]) — опциональный
|
|
521
|
+
- `messageId` (string|string[]) — опциональный `MESSAGE_ID` или массив `MESSAGE_ID` записей очереди для очистки. Без него очищается весь пакет `processId`. Пустой массив означает «очищать нечего»: вызов до API не доходит и возвращает `error: false` (раньше уезжало `message_id: []`). «Мягкая» ошибка портала, например `ERROR_ENTITY_NOT_FOUND` на протухшем `processId`, возвращается как `error: true`.
|
|
518
522
|
|
|
519
523
|
- **Возвращает:** промис с объектом `{ error, message, data }`.
|
|
520
524
|
|
package/bitrix24/eventB24.ts
CHANGED
|
@@ -3,7 +3,18 @@ import { $b24, getResultData, type B24MethodCaller } from "./b24.ts";
|
|
|
3
3
|
// ==================== Типы ====================
|
|
4
4
|
|
|
5
5
|
/** Сообщение из коннектора */
|
|
6
|
-
interface ConnectorMessage {
|
|
6
|
+
export interface ConnectorMessage {
|
|
7
|
+
/**
|
|
8
|
+
* `MESSAGE_ID` записи очереди офлайн-событий — ключ для `clear()`.
|
|
9
|
+
* Идентифицирует запись, а не отдельное сообщение: у сообщений одной записи
|
|
10
|
+
* он общий, поэтому для дедупликации сообщений не годится (для этого `im.id`)
|
|
11
|
+
*/
|
|
12
|
+
messageId: string;
|
|
13
|
+
/**
|
|
14
|
+
* `ID` записи очереди офлайн-событий. Поле информационное, для сверки
|
|
15
|
+
* с `event.offline.list`. В `clear()` не передавать — метод принимает `MESSAGE_ID`
|
|
16
|
+
*/
|
|
17
|
+
eventId: string;
|
|
7
18
|
connectorId: string;
|
|
8
19
|
lineId: string;
|
|
9
20
|
chatId: string;
|
|
@@ -14,7 +25,7 @@ interface ConnectorMessage {
|
|
|
14
25
|
}
|
|
15
26
|
|
|
16
27
|
/** События коннектора */
|
|
17
|
-
interface ConnectorEvents {
|
|
28
|
+
export interface ConnectorEvents {
|
|
18
29
|
processId: string | null;
|
|
19
30
|
message: ConnectorMessage[];
|
|
20
31
|
}
|
|
@@ -26,7 +37,7 @@ interface MessageEntityLink {
|
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
/** События сущностей (сделки, смарт-процессы) */
|
|
29
|
-
interface EntityEvents {
|
|
40
|
+
export interface EntityEvents {
|
|
30
41
|
processId: string | null;
|
|
31
42
|
entitysId: string[];
|
|
32
43
|
arrMessageIdAndEntityId: MessageEntityLink[];
|
|
@@ -41,6 +52,7 @@ interface StandardResult {
|
|
|
41
52
|
|
|
42
53
|
/** Офлайн-событие Bitrix24 */
|
|
43
54
|
interface OfflineEvent {
|
|
55
|
+
ID: string;
|
|
44
56
|
MESSAGE_ID: string;
|
|
45
57
|
EVENT_NAME: string;
|
|
46
58
|
EVENT_DATA: any;
|
|
@@ -148,7 +160,19 @@ export class Event {
|
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
/**
|
|
151
|
-
* Получает офлайн-события по
|
|
163
|
+
* Получает офлайн-события по имени.
|
|
164
|
+
*
|
|
165
|
+
* Гранулярность очистки — запись очереди, а не сообщение. Для коннектора одна
|
|
166
|
+
* запись (один `MESSAGE_ID`) может нести несколько сообщений, и `get()` раскладывает
|
|
167
|
+
* их через `flatMap` — у таких сообщений `messageId` совпадает. Очистка по этому
|
|
168
|
+
* ключу удалит запись целиком: если из двух сообщений одной записи ушло одно,
|
|
169
|
+
* `clear()` заберёт и неотправленное. Поэлементную очистку с точностью до
|
|
170
|
+
* сообщения на этом ключе построить нельзя.
|
|
171
|
+
*
|
|
172
|
+
* Обратная сторона: запись, из которой не разобрано ни одного сообщения
|
|
173
|
+
* (пустой или битый `MESSAGES`), в `data.message` не попадает вовсе — очистка
|
|
174
|
+
* по собранным `messageId` её не заберёт, и она останется зарезервированной
|
|
175
|
+
* под тем же `process_id`. Безопасный режим — `clear(processId)` целиком.
|
|
152
176
|
*/
|
|
153
177
|
async get(eventName: string): Promise<StandardResult> {
|
|
154
178
|
try {
|
|
@@ -184,6 +208,10 @@ export class Event {
|
|
|
184
208
|
return normalizeMessages(eventData.MESSAGES)
|
|
185
209
|
.filter((messageData) => messageData?.chat && messageData?.message)
|
|
186
210
|
.map((messageData) => ({
|
|
211
|
+
// Портал отдаёт идентификаторы то строкой, то числом —
|
|
212
|
+
// приводим, чтобы тип `string` не врал
|
|
213
|
+
messageId: String(event.MESSAGE_ID ?? ""),
|
|
214
|
+
eventId: String(event.ID ?? ""),
|
|
187
215
|
connectorId: eventData.CONNECTOR,
|
|
188
216
|
lineId: eventData.LINE,
|
|
189
217
|
chatId: messageData.chat.id,
|
|
@@ -210,6 +238,9 @@ export class Event {
|
|
|
210
238
|
|
|
211
239
|
if (arrEventsToClear.length > 0) {
|
|
212
240
|
const arrMessageIdToClear = arrEventsToClear.map((event) => event.MESSAGE_ID);
|
|
241
|
+
// Результат намеренно не проверяется: отказ здесь не фатален — те же
|
|
242
|
+
// записи придут следующим опросом, а бросок лишил бы потребителя всей
|
|
243
|
+
// выборки активных событий
|
|
213
244
|
await this.b24.callMethod("event.offline.clear", {
|
|
214
245
|
process_id: arrOfflineEvents.process_id,
|
|
215
246
|
message_id: arrMessageIdToClear,
|
|
@@ -243,11 +274,29 @@ export class Event {
|
|
|
243
274
|
*/
|
|
244
275
|
async clear(processId: string, messageId?: string | string[]): Promise<StandardResult> {
|
|
245
276
|
try {
|
|
277
|
+
// Пустой массив в JavaScript истинен и уезжал в теле запроса как `message_id: []` —
|
|
278
|
+
// это не документированный режим «очистить весь пакет» (что портал делает с
|
|
279
|
+
// пустым списком, не проверялось). Считаем пустой список за «очищать нечего»
|
|
280
|
+
// и до API не доходим: молча сносить весь пакет по пустому списку опасно —
|
|
281
|
+
// зарезервированный пакет портал повторно не выдаёт
|
|
282
|
+
if (Array.isArray(messageId) && messageId.length === 0) {
|
|
283
|
+
return { error: false, message: "Список записей пуст, очищать нечего", data: null };
|
|
284
|
+
}
|
|
285
|
+
|
|
246
286
|
const params: any = { process_id: processId };
|
|
247
287
|
if (messageId) {
|
|
248
288
|
params.message_id = messageId;
|
|
249
289
|
}
|
|
250
|
-
await this.b24.callMethod("event.offline.clear", params);
|
|
290
|
+
const response = await this.b24.callMethod("event.offline.clear", params);
|
|
291
|
+
// «Мягкую» ошибку (например, ERROR_ENTITY_NOT_FOUND на протухшем process_id)
|
|
292
|
+
// SDK не бросает, а возвращает AjaxResult с isSuccess: false. Без проверки
|
|
293
|
+
// метод рапортовал бы «События очищены» при неочищенной очереди.
|
|
294
|
+
// Именно isSuccess, а не getResultData(): та бросает ещё и на result == null,
|
|
295
|
+
// а что портал кладёт в result этого метода, не проверено
|
|
296
|
+
if (!response.isSuccess) {
|
|
297
|
+
const messages = response.getErrorMessages().join("; ") || "неизвестная ошибка";
|
|
298
|
+
throw new Error(`event.offline.clear: Bitrix24 вернул ошибку — ${messages}`);
|
|
299
|
+
}
|
|
251
300
|
|
|
252
301
|
return { error: false, message: "События очищены", data: null };
|
|
253
302
|
} catch (error: any) {
|