Лицензия

Настройка авторизации экспорта Exchange, запрос оставшейся квоты и обработка ошибок лицензии.

Exchange читает лицензию в серверном процессе, где работает @univerjs-pro/exchange-node. Конвертация описана в разделе Импорт и экспорт файлов Office.

Настройка авторизации

Передайте лицензию через переменные окружения UNIVER_LICENSE и UNIVER_LICENSE_KEY. Вызывать configureExchange необязательно: SDK один раз читает окружение при первом экспорте или запросе квоты и затем использует эту конфигурацию. Без учётных данных в окружении действует Free. Переданные, но недействительные учётные данные возвращают ошибку и не могут использоваться для экспорта.

Для явной настройки configureExchange({ license, licenseKey }) возвращает Promise<void> и полностью игнорирует окружение. Дождитесь его завершения, прежде чем запускать экспорты с новыми учётными данными.

TypeScript
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, чтобы авторизовать только эту операцию, не меняя конфигурацию по умолчанию. Например, запросите квоту и выполните экспорт с одними и теми же учётными данными:

TypeScript
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 и импортируйте его точку входа до настройки авторизации:

Shell
pnpm add @univerjs-pro/exchange-node @univerjs-pro/exchange-pdf-node-binding
TypeScript
import '@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 не означает, что проверки допуска к экспорту пройдены. Недействительные учётные данные возвращают ошибку.
expiresAtstring | nullОкончание подписки на экспорт, метка времени ISO в UTC; null, если не настроена или срок не ограничен.
observedAtstringМетка времени ISO в UTC для этого снимка.
limitnumber | nullТекущий месячный лимит экспортов; null без ограничений.
usednumber | nullУспешные экспорты за текущий месяц; null без ограничений.
reservednumber | nullВыполняющиеся экспорты, занимающие квоту текущего месяца; null без ограничений.
remainingnumber | nullДоступные экспорты: max(0, limit - used - reserved); null без ограничений.
periodStartstring | nullНачало (включительно) запрошенного месячного периода квоты, ISO в UTC; до активации первый период начинается в будущем. null без ограничений.
periodEndstring | nullКонец (не включительно) запрошенного месячного периода квоты, ISO в UTC; null без ограничений.

periodEnd отмечает начало следующего месячного периода квоты; expiresAt — окончание подписки на экспорт. Действующая подписка всегда использует коммерческую квоту. Её исчерпание никогда не переключает на Free, а новый период коммерческой квоты начинается в следующем месяце. Только истечение подписки переключает на оставшуюся квоту Free, без её сброса или повторной выдачи.

Пример снимка с ограниченной квотой:

JSON
{  "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. Интерфейс может сопоставлять коды ошибок с локализованными сообщениями. Сохраняйте диагностическую информацию для технической поддержки.

TypeScript
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 не возвращает отдельный список уведомлений.

После ошибки обработки использования лицензии не делайте выводов об учёте только по ошибке. Сохраните полную ошибку и обратитесь в техническую поддержку.

Насколько полезно это руководство?

© 2026 DreamNum Co., Ltd.