Лицензия
Настройка авторизации экспорта Exchange, запрос оставшейся квоты и обработка ошибок лицензии.
Exchange читает лицензию в серверном процессе, где работает @univerjs-pro/exchange-node. Конвертация описана в разделе Импорт и экспорт файлов Office.
Настройка авторизации
Передайте лицензию через переменные окружения UNIVER_LICENSE и UNIVER_LICENSE_KEY. Вызывать configureExchange необязательно: SDK один раз читает окружение при первом экспорте или запросе квоты и затем использует эту конфигурацию. Без учётных данных в окружении действует Free. Переданные, но недействительные учётные данные возвращают ошибку и не могут использоваться для экспорта.
Для явной настройки configureExchange({ license, licenseKey }) возвращает Promise<void> и полностью игнорирует окружение. Дождитесь его завершения, прежде чем запускать экспорты с новыми учётными данными.
import { configureExchange, getExportQuota } from '@univerjs-pro/exchange-node'await configureExchange({ license: '<license content>', licenseKey: '<licenseKey content>',})const quota = await getExportQuota()Используйте полное содержимое license и licenseKey, полученное от поставщика лицензии, а не пути к файлам. Задавайте оба значения вместе через систему управления секретами вашего приложения.
| Входные данные | Поведение |
|---|---|
configureExchange не вызывается | При первом использовании читаются обе переменные окружения; если ни одна не задана, используется Free. |
configureExchange({ license, licenseKey }) | Используются только явные учётные данные; окружение игнорируется. |
configureExchange({}) | Явно выбирается Free; окружение игнорируется. |
| Выбранный источник передаёт только одно значение | Возвращается INVALID_ARGUMENT; второе значение никогда не берётся из другого источника. |
Прочитанная полная конфигурация окружения остаётся неизменной, даже если последующая операция завершится ошибкой. Чтобы заменить учётные данные по умолчанию во время работы, явно вызовите configureExchange и дождитесь его завершения. При ошибке настройки продолжает действовать прежняя конфигурация; обработайте ошибку, прежде чем запускать новые экспорты.
ESM и CommonJS используют общую конфигурацию в одном контексте JavaScript. Каждый Worker из worker_threads должен настраиваться сам или инициализироваться из своего окружения. Экспорт использует конфигурацию на момент вызова публичного метода экспорта; последующая смена учётных данных не влияет на уже запущенные экспорты.
Авторизация одной операции
Передайте полную пару license и licenseKey в параметрах API экспорта или getExportQuota, чтобы авторизовать только эту операцию, не меняя конфигурацию по умолчанию. Например, запросите квоту и выполните экспорт с одними и теми же учётными данными:
import { UniverInstanceType } from '@univerjs/core'import { ExchangeFormat, exportToBuffer, getExportQuota } from '@univerjs-pro/exchange-node'const credentials = { license: '<license content>', licenseKey: '<licenseKey content>' }const quota = await getExportQuota(credentials)const output = await exportToBuffer(workbook, { type: UniverInstanceType.UNIVER_SHEET, format: ExchangeFormat.XLSX, ...credentials,})Это относится и к экспорту в файл, экспорту Snapshot и необязательному экспорту в PDF. Если оба поля опущены, используется конфигурация по умолчанию; если передано только одно, возвращается INVALID_ARGUMENT. Явная пара никогда не дополняется из конфигурации по умолчанию или окружения, а пустые строки не считаются пропуском. Недействительные учётные данные возвращают LICENSE_INVALID без перехода на коммерческую лицензию по умолчанию.
Необязательная поддержка PDF
Установите пакет расширения PDF и импортируйте его точку входа до настройки авторизации:
pnpm add @univerjs-pro/exchange-node @univerjs-pro/exchange-pdf-node-bindingimport '@univerjs-pro/exchange-node/pdf'import { configureExchange, getExportQuota } from '@univerjs-pro/exchange-node'await configureExchange({ license: '<license content>', licenseKey: '<licenseKey content>',})const quota = await getExportQuota()Эта точка входа регистрирует поддержку PDF; нативные компоненты загружаются при использовании. Для PDF применяются те же API importBuffer, importFile, exportToBuffer, exportToFile и соответствующие API Snapshot с UniverInstanceType.UNIVER_PDF и ExchangeFormat.PDF. Приложению, работающему только с PDF, не нужно загружать нативный компонент Office. Настройка через окружение действует и для PDF.
Запрос оставшейся квоты
getExportQuota({ license, licenseKey }) возвращает Promise<ExportQuota> с квотой, общей для Office и PDF в рамках авторизации. Без учётных данных запрашивается конфигурация по умолчанию. Метод не принимает тип Unit и не проверяет право на экспорт конкретного типа; эта проверка выполняется при экспорте.
Запросы не расходуют и не резервируют квоту и не проверяют версию SDK, дату активации или право на тип экспорта. При нулевом остатке запрос всё равно успешно возвращает снимок. Другие запросы могут израсходовать квоту позже, поэтому обрабатывайте и ошибки самого экспорта.
До начала авторизации запрос с ограниченной квотой возвращает первый месяц авторизации с periodStart в будущем. Успешный запрос или состояние valid не дают права на экспорт. Версия, активация, право на тип, доступная квота и параллельность проверяются при экспорте.
| Поле | Тип | Значение |
|---|---|---|
licenseStatus | 'not_configured' | 'expired' | 'valid' | Подписка на экспорт не настроена, истекла или не истекла. valid не означает, что проверки допуска к экспорту пройдены. Недействительные учётные данные возвращают ошибку. |
expiresAt | string | null | Окончание подписки на экспорт, метка времени ISO в UTC; null, если не настроена или срок не ограничен. |
observedAt | string | Метка времени ISO в UTC для этого снимка. |
limit | number | null | Текущий месячный лимит экспортов; null без ограничений. |
used | number | null | Успешные экспорты за текущий месяц; null без ограничений. |
reserved | number | null | Выполняющиеся экспорты, занимающие квоту текущего месяца; null без ограничений. |
remaining | number | null | Доступные экспорты: max(0, limit - used - reserved); null без ограничений. |
periodStart | string | null | Начало (включительно) запрошенного месячного периода квоты, ISO в UTC; до активации первый период начинается в будущем. null без ограничений. |
periodEnd | string | null | Конец (не включительно) запрошенного месячного периода квоты, ISO в UTC; null без ограничений. |
periodEnd отмечает начало следующего месячного периода квоты; expiresAt — окончание подписки на экспорт. Действующая подписка всегда использует коммерческую квоту. Её исчерпание никогда не переключает на Free, а новый период коммерческой квоты начинается в следующем месяце. Только истечение подписки переключает на оставшуюся квоту Free, без её сброса или повторной выдачи.
Пример снимка с ограниченной квотой:
{ "licenseStatus": "valid", "expiresAt": "2027-10-19T23:59:59Z", "observedAt": "2026-10-21T09:00:00Z", "limit": 500, "used": 20, "reserved": 1, "remaining": 479, "periodStart": "2026-10-19T00:00:00Z", "periodEnd": "2026-11-19T00:00:00Z"}Расход квоты экспорта
Free допускает 10 успешных экспортов за месяц авторизации. Квота экспорта, параллельность и диапазон версий коммерческой лицензии зависят от приобретённой лицензии. Ни Free, ни коммерческие лицензии не ограничивают размер файла или число ячеек. Текущий период и оставшуюся квоту узнавайте из ответа на запрос. Неиспользованная месячная квота не переносится.
Импорт не требует авторизации экспорта и не расходует квоту экспорта. Экспорты Office и PDF с одной коммерческой лицензией в рамках одного развёртывания используют общую квоту. Форматы конвертации Exchange описаны в разделе Импорт и экспорт файлов Office.
Каждая успешная конвертация расходует один экспорт. Возврат Buffer считается успехом. Последующая ошибка записи, загрузки или скачивания файла не возвращает этот экспорт; новая успешная конвертация расходует ещё один. Когда в текущем периоде квота закончилась, новые экспорты отклоняются. Дождитесь следующего периода авторизации или используйте действующую лицензию с большей квотой; исчерпанная действующая коммерческая лицензия не использует квоту Free.
Обработка ошибок
Определяйте ошибки по структурированному code, а не разбирая текст message. Интерфейс может сопоставлять коды ошибок с локализованными сообщениями. Сохраняйте диагностическую информацию для технической поддержки.
import { UniverInstanceType } from '@univerjs/core'import { ExchangeError, ExchangeFormat, exportToBuffer } from '@univerjs-pro/exchange-node'try { const output = await exportToBuffer(workbook, { type: UniverInstanceType.UNIVER_SHEET, format: ExchangeFormat.XLSX, })} catch (error) { if (error instanceof ExchangeError) { // Покажите сообщение для error.code, например LICENSE_EXPORT_QUOTA_EXCEEDED, когда квота исчерпана console.error(error.code) } else { throw error }}В таблице различаются запросы квоты (getExportQuota) и фактические экспорты. Оба API возвращают Promise; обрабатывайте ошибки с помощью await и try/catch.
| Код | Операция | Значение и действия |
|---|---|---|
LICENSE_EXPORT_QUOTA_EXCEEDED | Только экспорт | Недостаточно квоты экспорта в текущем периоде. Запросите квоту или обратитесь в отдел продаж, чтобы изменить лицензию. |
LICENSE_CONCURRENCY_TIMEOUT | Только экспорт | Истекло время ожидания свободного места для параллельного экспорта. Уменьшите число одновременных экспортов и отправьте снова. |
LICENSE_UNIT_TYPE_REJECTED | Только экспорт | Этот тип экспорта не лицензирован или право на него истекло. Используйте действующую лицензию, покрывающую этот тип. |
LICENSE_INVALID | Запрос, экспорт | Лицензия недействительна. Проверьте полноту учётных данных или запросите обновление у поставщика лицензии. |
LICENSE_POLICY_INVALID | Запрос, экспорт | Конфигурация авторизации не соответствует требованиям SDK. Запросите обновление у поставщика лицензии. |
LICENSE_NOT_YET_EFFECTIVE | Только экспорт | Авторизация ещё не началась. Используйте её после даты вступления в силу. |
LICENSE_VERSION_NOT_ALLOWED | Только экспорт | Текущая версия SDK вне лицензированного диапазона. Используйте подходящую версию или обновите лицензию. |
UNSUPPORTED_FORMAT | Только экспорт | Формат не поддерживается или не соответствует типу Unit. Проверьте параметры экспорта. |
INVALID_FILE | Только экспорт | Входные данные конвертации недействительны. Проверьте их содержимое. |
INCOMPLETE_SNAPSHOT | Только экспорт | Данные экспорта неполные. Передайте полные данные или полный Snapshot. |
CONVERSION_FAILED | Только экспорт | Конвертация не удалась. Сохраните ошибку и проверьте входные данные. |
IO_ERROR | Только экспорт | Ошибка файлового ввода-вывода. Ошибка записи после успешной конвертации уже израсходовала один экспорт. |
INVALID_ARGUMENT | Запрос, экспорт | Неполные аргументы или учётные данные. Проверьте конфигурацию. |
NATIVE_LOAD_FAILED | Запрос, экспорт | Не удалось загрузить нативный компонент SDK. Проверьте совместимость пакета и среды выполнения. |
LICENSE_USAGE_STATE_INVALID | Запрос, экспорт | Невозможно проверить состояние использования лицензии. Сохраните ошибку и обратитесь в техническую поддержку. |
LICENSE_USAGE_STORAGE_ERROR | Запрос, экспорт | Не удалось обработать использование лицензии. Сохраните ошибку, обратитесь в техническую поддержку и избегайте автоматической повторной отправки. |
Приложения могут формировать напоминания об окончании срока по licenseStatus и expiresAt; SDK не возвращает отдельный список уведомлений.
После ошибки обработки использования лицензии не делайте выводов об учёте только по ошибке. Сохраните полную ошибку и обратитесь в техническую поддержку.
Насколько полезно это руководство?