szdl-utils-kit
v0.3.35
Published
utils-kit library
Readme
szdl-utils-kit
Набор утилит для удобной работы с Bitrix24 REST API: пакетные запросы, обёртка над BX24, вспомогательные хелперы, логирование обращений и фоновый исполнитель.
Установка
npm install szdl-utils-kitБыстрый старт
import {
Batch,
BxBoot,
BxHelper,
BxLogger,
BackgroundWorker,
tempus,
} from "szdl-utils-kit";Модули
Batch
Утилита для пакетного выполнения запросов Bitrix24 с автоматической пагинацией, трекингом прогресса и обработкой ограничений.
Рекомендуется работать через BxBoot, а Batch использовать напрямую только при необходимости.
Для crm.timeline.comment.list, crm.timeline.bindings.list,
crm.timeline.logmessage.list и department.get используется документированная
offset-пагинация без добавления ID-фильтра. Шаг start берётся из контракта
метода: 50 для комментариев, связей и подразделений и 10 для лог-записей.
department.get не принимает filter[>ID], поэтому список длиннее 50 записей
догружается через start 0, 50, 100…. Остальные списочные методы сохраняют
курсорную стратегию.
import { Batch } from "szdl-utils-kit";
const rest = new Batch({
callBatch: BX24.callBatch,
callMethod: BX24.callMethod,
});
const result = await rest.batch({
deals: { method: "crm.deal.list", params: { select: ["ID", "TITLE"] } },
users: { method: "user.get", params: { filter: { ACTIVE: "Y" } } },
});
console.log(result.deals);
console.log(rest.errors); // ошибки по ключам
console.log(rest.timeLimit); // { limit: boolean, date?: string }Основные свойства
result– объект с результатами по ключам командerrors– словарь ошибокlimit– текущий лимит команд в чанке (по умолчанию 50)canContinue– флаг выполненияtimeLimit– глобальный статус лимита ({ limit, date }), пригоден для отображения в UI
Методы
batch(commandList, progressCall?)– запрос данныхbatchTotalCount(commandList, progressCall?)– запрос количества данных без подробного текста (более быстрый, чемbatch)call({ method, params? })– одиночный REST-вызов с теми же retry/timeout правилами, что и batchstop()– принудительная остановка
BxBoot
Promise-обёртка над методами BX24 с продвинутой инициализацией, логированием и хелперами для работы с встройками. Фоновые встройки PAGE_BACKGROUND_WORKER обрабатываются только через BackgroundWorker и в placementBind/placementUnBind/placementCheck пропускаются.
import { BxBoot } from "szdl-utils-kit";
const bx = new BxBoot({
appName: "My App",
pathApp: "https://example.com/app",
});
await bx.init();
const currentUser = await bx.call({ method: "user.current" });
const deals = await bx.batch({
deals: { method: "crm.deal.list", params: { select: ["ID", "TITLE"] } },
});Ключевые свойства
domain– доменное имя портала, напримерexample.bitrix24.ruisAdmin– флаг администратора текущего пользователя; используется для условных сценариев и проверок правappInfo– объект из REST-методаApp.infoс идентификатором приложения, типом запуска, тарифами и статусами подпискиuserInfo– данные, полученные изuser.current(ID,NAME,EMAIL,TIME_ZONEи др.)placeData– исходные данные встроек, возвращаемыеBX24.getPlacement(), включаяplacement,placementId,optionsplaceInfo– результат REST-методаplacement.get, расширяетplaceDataподробностями о привязках и доступных действияхlogger– экземплярBxLogger(при активном логировании) илиBxLoggerStub; независимо от режима доступны методыinfo,warn,error
Основные методы
init()– инициализация SDK, получение основных данныхuserOption(key, value?)– чтение/запись пользовательских настроекappOption(key, value?)– чтение/запись пользовательских настроекcall({ method, params, updateList })– одиночный REST-вызовbatch(commandList, progressCall?, options?)– пакетные вызовы с обновлениями/логомerrorCall(errors)– вызывается после выполнения всего батча, получает объект с ключами запросов и списком ошибок Bitrix24updateList– массив описаний изменений для логера (method,name,list[{ id, fields }]), отображается в истории операций
batchTotalCount(commandList, progressCall?, options?)– подсчет элементов в пакетном режимеtimeLimit– глобальный статус лимита выполнения ({ limit, date }), можно напрямую читать в компонентах (например, в лоадере)placementBind(place, userId?),placementUnBind(...),placementCheck()– работа с встройками (кромеPAGE_BACKGROUND_WORKER, их ведётBackgroundWorker)getBotList(),regBot(),unRegBot()– управление чат-ботом
BxHelper
Набор мелких утилит для браузерного окружения.
import { BxHelper } from "szdl-utils-kit";
const helper = new BxHelper();
const hash = helper.hash; // случайный 8-символьный хэш
helper.actionFilter({
keyTimer: "submit",
duration: 300,
action: () => console.log("debounced action"),
});Полезные методы:
hash– геттер, возвращает случайный 8-символьный идентификатор; удобно для генерации ключей элементовcreateHash(length = 6)– позволяет задать длину хэша, полезно для кодов подтверждения и временных ссылокactionFilter({ keyTimer, duration = 10, action })– debounce-обертка; гарантирует, чтоactionзапустится один раз после серии быстрых вызовов с одинаковымkeyTimernoSleep()– предотвращает засыпание устройства, создавая и циклически воспроизводя скрытое видеоdownloadFileJson(data, filename)– сохраняет произвольные данные вfilename.json, удобно для отладки и экспорта отчётов
BxLogger
Логер для записи истории REST-запросов в пользовательское хранилище Bitrix24 с последующей выгрузкой.
import { BxLogger } from "szdl-utils-kit";
const logger = new BxLogger();
await logger.init();
const key = logger.start({
type: "call",
data: { method: "crm.deal.list", params: {} },
});
try {
// ... выполняем запрос
await logger.stop({ key, status: "success" });
} catch (error) {
await logger.stop({
key,
status: "fail",
errorList: { 0: error.toString() },
});
}Возможности:
- ведение истории запросов (
start/stop); - загрузка хранилища (
getEntityList,downAllEntityJson); - очистка устаревших записей.
BackgroundWorker
Координация фоновых задач между браузерными табами. Использует HL-подобное хранилище Bitrix24 для синхронизации и предотвращает одновременный запуск нескольких обработчиков.
import { BackgroundWorker } from "szdl-utils-kit";
const worker = new BackgroundWorker({
bx, // готовый экземпляр BxBoot с инициализированными константами приложения
appFunc: async () => {
// здесь размещаем длительную задачу
console.log("background job started");
},
users: [], // подготовленный список пользователей (опционально)
});
await worker.init();Опции:
bx– инициализированный экземплярBxBoot, используемый для работы с REST;appFunc– функция, которая должна выполниться в «активном» табе;users– подготовленные данные (если не переданы, будут запрошены через REST);continueBackground– опциональная функция-условие, которая определяет, можно ли запускать воркер. Должна вернутьtrue, чтобы продолжить цикл. По умолчанию всегда возвращаетtrue; см. пример ниже.timing– объект с таймингами poll-цикла, подтверждения лидерства и разнесённого старта приложений (см. Тайминги). Можно передать только нужные поля — остальные возьмутся изDEFAULT_BACKGROUND_WORKER_TIMING;coordinationScope– область координации лидера и пула вкладок (см. Область координации). По умолчанию'user'.bindGeneralPlacement– привязывать общую встройкуPAGE_BACKGROUND_WORKERбезUSER_ID. По умолчаниюtrue. Приfalse— только персональные встройки для админов (до 10); существующая общая отвязывается. Сочетается сcoordinationScope: 'portal'(один лидер на портал + персональные встройки у админов для перепривязки).
const worker = new BackgroundWorker({
bx,
appFunc: async () => {
/* ... */
},
continueBackground: async (worker) => {
const lastCheck = BX24.userOption.get("checkDate");
if (!lastCheck) return false;
const nextCheck = new Date(lastCheck).setMinutes(
new Date(lastCheck).getMinutes() + 30
);
return Date.now() >= nextCheck;
},
});Область координации (coordinationScope)
Передаётся строкой: 'user' или 'portal'. Другие значения игнорируются с предупреждением в консоль, используется 'user'.
| Значение | Поведение |
|----------|-----------|
| 'user' (по умолчанию) | Один запуск appFunc одновременно на пользователя. Вкладки разных пользователей не конкурируют. |
| 'portal' | Один запуск appFunc одновременно на портал. Все пользователи в общем пуле вкладок; лидер один на всё приложение. |
Как это работает:
- В режиме
'user'записи в entity хранятся сNAME = userId, Web Lock тоже per-user. - В режиме
'portal'все вкладки пишутся с общим ключомNAME = {appCodeName}:portal, Web Lock — per-portal (per-app). - В данных вкладки всегда сохраняется
userId— в portal-режиме видно, у кого открыта вкладка, хотяappFuncвыполняется только у лидера. - Персональные встройки (
USER_ID=…) для админов создаются в обоих режимах — это «крючки» для перепривязки и фоновых вкладок у админов. В'portal'они не конкурируют за отдельные задачи: все вкладки (и общая, и персональные) участвуют в одном пуле лидерства на портал. - При
bindGeneralPlacement: falseобщая встройка не нужна даже в'portal'— достаточно персональных у админов.
const worker = new BackgroundWorker({
bx,
appFunc: async () => {
console.log("background job started (once per portal)");
},
coordinationScope: "portal",
});
await worker.init();Тайминги (timing)
Экспортируются DEFAULT_BACKGROUND_WORKER_TIMING и resolveBackgroundWorkerTiming — удобно собирать конфиг заранее или переопределять отдельные поля.
import {
BackgroundWorker,
DEFAULT_BACKGROUND_WORKER_TIMING,
resolveBackgroundWorkerTiming,
} from "szdl-utils-kit";
const timing = resolveBackgroundWorkerTiming({
startDelayMs: 10_000,
leaderConfirmDelayMs: 10_000,
});
const worker = new BackgroundWorker({ bx, appFunc, timing });Поля объекта timing:
| Поле | По умолчанию | Назначение |
|------|--------------|------------|
| startDelayMs | 0 | Пауза перед первым poll-тиком. Разносит старт разных приложений (один апп — через 20 с, другой — через 4–5 мин). |
| pollIntervalMs | 60_000 | Базовый интервал фонового poll-цикла (обновление lastActive, выбор лидера, очистка мёртвых вкладок). |
| pollIntervalJitterMs | 30_000 | Случайная добавка к pollIntervalMs. Итоговый интервал: от pollIntervalMs до pollIntervalMs + pollIntervalJitterMs (по умолчанию 1–1,5 мин). |
| leaderConfirmDelayMs | 60_000 | Пауза после захвата Web Lock перед повторной проверкой лидерства и вызовом appFunc. Защита от гонки между вкладками. |
| activeMaxPauseMs | 180_000 | Порог «мёртвой» вкладки: если lastActive не обновлялся дольше — запись удаляется из entity. Должен быть больше startDelayMs + leaderConfirmDelayMs, иначе вкладка может удалиться во время пауз перед стартом. |
| quickCleanupThresholdMs | 300_000 | Отдельный порог для агрессивной очистки, когда достигнут лимит вкладок (maxTabs). |
| leaderHeartbeatMs | null | Интервал обновления lastActive лидером во время appFunc. Если не задан — вычисляется автоматически из pollInterval и activeMaxPauseMs. |
Как устроен старт (без лишних раундов):
- Регистрация вкладки в entity.
- Пауза
startDelayMs(если задана). - Poll-тик: выбор лидера по entity (самая старая вкладка).
- Если текущая вкладка — лидер: захват Web Lock → пауза
leaderConfirmDelayMs→ повторная проверка лидера →appFunc. - Далее poll-цикл продолжается с интервалом
pollIntervalMs…+ pollIntervalJitterMs.
Пример: старт через ~20 секунд
const START_DELAY_MS = 10_000;
const LEADER_CONFIRM_MS = 10_000;
const worker = new BackgroundWorker({
bx,
appFunc: async () => {
console.log("background job started");
},
timing: {
...DEFAULT_BACKGROUND_WORKER_TIMING,
startDelayMs: START_DELAY_MS,
leaderConfirmDelayMs: LEADER_CONFIRM_MS,
activeMaxPauseMs: Math.max(
60_000,
(START_DELAY_MS + LEADER_CONFIRM_MS) * 3,
),
},
});Пример: отложенный старт (~4–5 минут)
const worker = new BackgroundWorker({
bx,
appFunc: async () => {
/* ... */
},
timing: {
...DEFAULT_BACKGROUND_WORKER_TIMING,
startDelayMs: 4 * 60_000,
leaderConfirmDelayMs: 60_000,
},
});Методы:
init– регистрирует бек-встройку для текущего пользователя, создаёт запись текущего таба и запускает цикл наблюдения.ensureAdminPlacements– для админа, обновляет фоновые встройки без запуска фонового цикла.placement.unbindиplacement.bindвыполняются однимbatch(сначала отвязка, затем привязка), чтобы не оставлять портал без встройки между запросами.ensureAdminPlacementsBeforeAppInit– опция конструктора: передappFuncу админа вызватьensureAdminPlacements. Можно передатьtrueили функцию-условие(worker) => boolean.
loadBx24 — подключение BX24 с фолбэками
Библиотека BX24 подключается по цепочке: //api.bitrix24.com/api/v1/ → //api.bitrix24.tech/api/v1/ (по 3 секунды на каждый) → локальная копия, вшитая в utils-kit. Локальная копия лежит отдельным чанком и скачивается, только если оба удалённых источника не сработали.
BxBoot.init() вызывает loadBx24() сам — тег <script src="//api.bitrix24.com/api/v1/"> в HTML больше не нужен (если он остался, загрузчик увидит готовый BX24 и ничего не будет грузить). Для кода, который работает с BX24 без BxBoot:
import { loadBx24 } from "szdl-utils-kit";
const { source } = await loadBx24(); // "preloaded" | "com" | "tech" | "local"
BX24.init(() => { /* ... */ });Если скрипт загрузился, но BX24 не инициализировался (приложение открыто вне фрейма Битрикс24), остальные источники не перебираются — промис отклоняется с Bx24EnvironmentError.
Обновить локальную копию: npm run update:bx24-local.
Старые приложения (без обновления utils-kit)
npm run build дополнительно собирает самодостаточный файл dist/legacy/bx24-loader.legacy.js (та же логика + локальная копия BX24 внутри, без зависимостей). Положите его в статику приложения и замените им старый тег:
<script src="bx24-loader.legacy.js"></script>Загрузка асинхронная, поэтому до её завершения в window.BX24 стоит заглушка, которая копит вызовы BX24.init(cb) и BX24.install(cb) и передаёт их настоящему BX24 после загрузки. Старый BxBoot.init() и inline-вызовы BX24.init(...) сразу после тега продолжают работать. Другие методы BX24 до init вызывать нельзя. Промис загрузки доступен как window.szdlBx24Ready.
Консольный инжект (временно, без выкладки zip)
Если старый апп уже открыт и упал с BX24 is not defined, вставьте в консоль iframe приложения собранный dist/legacy/bx24-console-inject.js (копия: scripts/bx24-console-inject.js).
Цепочка та же: .com → .tech → встроенная local-копия. После успеха скрипт без reload заново подключает бандлы аппа. location.reload() делать нельзя — инжект пропадёт.
Сборка: npm run build:legacy (или полный npm run build).
tempus
Функции для работы с датами и временем (библиотека tempusjs). Используется внутри пакета, но может быть импортирована напрямую:
import { tempus } from "szdl-utils-kit";
const formatted = tempus().format("%Y-%m-%d");TypeScript
Все основные API описаны в папке types/. Импорты доступны напрямую из пакета, при необходимости можно посмотреть определения:
types/batch.d.ts– детальное описание Batch;types/bx-boot.d.ts,types/bx-helper.d.ts,types/bx-logger.d.ts;types/background-worker.d.ts– в том числеBackgroundWorkerTiming,DEFAULT_BACKGROUND_WORKER_TIMING;types/bx24-loader.d.ts–loadBx24,Bx24EnvironmentError.
Разработка и публикация
- Вносите изменения в исходники.
- Собирайте библиотеку
npm run build(результат вdist/, legacy-загрузчик BX24 — вdist/legacy/). - Авторизуйтесь в npm:
npm login. Если требуется, запросите временный пароль на [email protected]. - Публикуйте обновление:
npm run pub. Скрипт автоматически увеличит версию (при необходимости можно указать вручную).
