eimzo-ts 0.1.0 → 0.1.2
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/CHANGELOG.md +16 -1
- package/README.md +1 -1
- package/dist/index.cjs +3 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +3 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.1.2]
|
|
9
|
+
|
|
10
|
+
### Исправлено
|
|
11
|
+
|
|
12
|
+
- Неверный пароль в E-IMZO 6.3 (`status -9999`, «Sequence tag error» / «Password is not ASCII»)
|
|
13
|
+
теперь даёт `WRONG_PASSWORD`, а не `EIMZO_ERROR`.
|
|
14
|
+
|
|
15
|
+
## [0.1.1]
|
|
16
|
+
|
|
17
|
+
### Исправлено
|
|
18
|
+
|
|
19
|
+
- «Отмена» в окне пароля E-IMZO (`status -5000`) теперь даёт `CANCELLED`, а не `EIMZO_ERROR`.
|
|
20
|
+
|
|
8
21
|
## [0.1.0]
|
|
9
22
|
|
|
10
23
|
Первая версия.
|
|
@@ -22,5 +35,7 @@
|
|
|
22
35
|
- Сборки ESM, CJS и IIFE (`EimzoClient`) с типами.
|
|
23
36
|
- Демо с режимом без E-IMZO и просмотром содержимого PKCS#7.
|
|
24
37
|
|
|
25
|
-
[Unreleased]: https://github.com/abduazimkhuja/eimzo-ts/compare/v0.1.
|
|
38
|
+
[Unreleased]: https://github.com/abduazimkhuja/eimzo-ts/compare/v0.1.2...HEAD
|
|
39
|
+
[0.1.2]: https://github.com/abduazimkhuja/eimzo-ts/compare/v0.1.1...v0.1.2
|
|
40
|
+
[0.1.1]: https://github.com/abduazimkhuja/eimzo-ts/compare/v0.1.0...v0.1.1
|
|
26
41
|
[0.1.0]: https://github.com/abduazimkhuja/eimzo-ts/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm install eimzo-ts
|
|
|
26
26
|
Без сборщика:
|
|
27
27
|
|
|
28
28
|
```html
|
|
29
|
-
<script src="https://unpkg.com/eimzo-ts@0.1.
|
|
29
|
+
<script src="https://unpkg.com/eimzo-ts@0.1.2/dist/index.global.js"></script>
|
|
30
30
|
<script>
|
|
31
31
|
const eimzo = EimzoClient.createEimzo({ apiKeys: EimzoClient.DEV_API_KEYS });
|
|
32
32
|
</script>
|
package/dist/index.cjs
CHANGED
|
@@ -151,11 +151,12 @@ function notInstalledError(wsCode, cause) {
|
|
|
151
151
|
return new EimzoError("NOT_INSTALLED", {}, { wsCode, cause });
|
|
152
152
|
}
|
|
153
153
|
var STATUS_KEY_NOT_FOUND = [-1010, -1014];
|
|
154
|
-
var STATUS_CANCELLED = [];
|
|
154
|
+
var STATUS_CANCELLED = [-5e3];
|
|
155
|
+
var WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;
|
|
155
156
|
function errorFromResponse(res) {
|
|
156
157
|
const { status, reason } = res;
|
|
157
158
|
const details = { reason, status };
|
|
158
|
-
if (reason &&
|
|
159
|
+
if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError("WRONG_PASSWORD", {}, details);
|
|
159
160
|
if (status !== void 0 && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {
|
|
160
161
|
return new EimzoError("KEY_NOT_FOUND", {}, details);
|
|
161
162
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export {\n Eimzo,\n createEimzo,\n DEV_API_KEYS,\n DEFAULT_MAX_FILE_SIZE,\n type SignFileOptions,\n type ApiKeys,\n type DeviceType,\n type EimzoOptions,\n type EimzoVersion,\n type LoadKeyOptions,\n type SignOptions,\n type SignableData,\n} from './eimzo';\nexport { createFetchBackend, type EimzoBackend, type FetchBackendOptions } from './backend';\nexport {\n parseCertificateInfo,\n parseX500,\n type CertificateInfo,\n type EimzoKey,\n type PfxKey,\n type TokenKey,\n} from './certificate';\nexport {\n EimzoError,\n isEimzoError,\n type EimzoErrorCode,\n type EimzoErrorDetails,\n type EimzoErrorParams,\n type EimzoMessages,\n} from './errors';\nexport {\n builtinMessages,\n DEFAULT_LOCALE,\n formatEimzoError,\n type BuiltinLocale,\n type EimzoLocale,\n type MessageOverrides,\n} from './i18n';\nexport { en } from './locales/en';\nexport { kaa } from './locales/kaa';\nexport { ru } from './locales/ru';\nexport { uzLatn } from './locales/uz-Latn';\nexport { uzCyrl } from './locales/uz-Cyrl';\nexport {\n createCapiwsTransport,\n createDefaultTransport,\n createWebSocketTransport,\n defaultEimzoUrl,\n type CapiwsLike,\n type EimzoRequest,\n type EimzoResponse,\n type Transport,\n type WebSocketTransportOptions,\n} from './transport';\n","export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\nconst STATUS_CANCELLED: number[] = [];\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && reason.indexOf('BadPaddingException') !== -1) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export {\n Eimzo,\n createEimzo,\n DEV_API_KEYS,\n DEFAULT_MAX_FILE_SIZE,\n type SignFileOptions,\n type ApiKeys,\n type DeviceType,\n type EimzoOptions,\n type EimzoVersion,\n type LoadKeyOptions,\n type SignOptions,\n type SignableData,\n} from './eimzo';\nexport { createFetchBackend, type EimzoBackend, type FetchBackendOptions } from './backend';\nexport {\n parseCertificateInfo,\n parseX500,\n type CertificateInfo,\n type EimzoKey,\n type PfxKey,\n type TokenKey,\n} from './certificate';\nexport {\n EimzoError,\n isEimzoError,\n type EimzoErrorCode,\n type EimzoErrorDetails,\n type EimzoErrorParams,\n type EimzoMessages,\n} from './errors';\nexport {\n builtinMessages,\n DEFAULT_LOCALE,\n formatEimzoError,\n type BuiltinLocale,\n type EimzoLocale,\n type MessageOverrides,\n} from './i18n';\nexport { en } from './locales/en';\nexport { kaa } from './locales/kaa';\nexport { ru } from './locales/ru';\nexport { uzLatn } from './locales/uz-Latn';\nexport { uzCyrl } from './locales/uz-Cyrl';\nexport {\n createCapiwsTransport,\n createDefaultTransport,\n createWebSocketTransport,\n defaultEimzoUrl,\n type CapiwsLike,\n type EimzoRequest,\n type EimzoResponse,\n type Transport,\n type WebSocketTransportOptions,\n} from './transport';\n","export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\n// -5000 «Ввод пароля отменен»: кнопка «Отмена» в окне пароля.\nconst STATUS_CANCELLED = [-5000];\n// Неверный пароль PFX. Старые версии: BadPaddingException. E-IMZO 6.3 — status -9999 с текстом\n// «Sequence tag error» или «getSecretKey failed: Password is not ASCII» (пароль в другой раскладке).\n// -9999 бывает и у других ошибок, поэтому сверяем текст.\nconst WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
package/dist/index.global.js
CHANGED
|
@@ -151,11 +151,12 @@ var EimzoClient = (() => {
|
|
|
151
151
|
return new EimzoError("NOT_INSTALLED", {}, { wsCode, cause });
|
|
152
152
|
}
|
|
153
153
|
var STATUS_KEY_NOT_FOUND = [-1010, -1014];
|
|
154
|
-
var STATUS_CANCELLED = [];
|
|
154
|
+
var STATUS_CANCELLED = [-5e3];
|
|
155
|
+
var WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;
|
|
155
156
|
function errorFromResponse(res) {
|
|
156
157
|
const { status, reason } = res;
|
|
157
158
|
const details = { reason, status };
|
|
158
|
-
if (reason &&
|
|
159
|
+
if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError("WRONG_PASSWORD", {}, details);
|
|
159
160
|
if (status !== void 0 && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {
|
|
160
161
|
return new EimzoError("KEY_NOT_FOUND", {}, details);
|
|
161
162
|
}
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export {\n Eimzo,\n createEimzo,\n DEV_API_KEYS,\n DEFAULT_MAX_FILE_SIZE,\n type SignFileOptions,\n type ApiKeys,\n type DeviceType,\n type EimzoOptions,\n type EimzoVersion,\n type LoadKeyOptions,\n type SignOptions,\n type SignableData,\n} from './eimzo';\nexport { createFetchBackend, type EimzoBackend, type FetchBackendOptions } from './backend';\nexport {\n parseCertificateInfo,\n parseX500,\n type CertificateInfo,\n type EimzoKey,\n type PfxKey,\n type TokenKey,\n} from './certificate';\nexport {\n EimzoError,\n isEimzoError,\n type EimzoErrorCode,\n type EimzoErrorDetails,\n type EimzoErrorParams,\n type EimzoMessages,\n} from './errors';\nexport {\n builtinMessages,\n DEFAULT_LOCALE,\n formatEimzoError,\n type BuiltinLocale,\n type EimzoLocale,\n type MessageOverrides,\n} from './i18n';\nexport { en } from './locales/en';\nexport { kaa } from './locales/kaa';\nexport { ru } from './locales/ru';\nexport { uzLatn } from './locales/uz-Latn';\nexport { uzCyrl } from './locales/uz-Cyrl';\nexport {\n createCapiwsTransport,\n createDefaultTransport,\n createWebSocketTransport,\n defaultEimzoUrl,\n type CapiwsLike,\n type EimzoRequest,\n type EimzoResponse,\n type Transport,\n type WebSocketTransportOptions,\n} from './transport';\n","export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\nconst STATUS_CANCELLED: number[] = [];\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && reason.indexOf('BadPaddingException') !== -1) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export {\n Eimzo,\n createEimzo,\n DEV_API_KEYS,\n DEFAULT_MAX_FILE_SIZE,\n type SignFileOptions,\n type ApiKeys,\n type DeviceType,\n type EimzoOptions,\n type EimzoVersion,\n type LoadKeyOptions,\n type SignOptions,\n type SignableData,\n} from './eimzo';\nexport { createFetchBackend, type EimzoBackend, type FetchBackendOptions } from './backend';\nexport {\n parseCertificateInfo,\n parseX500,\n type CertificateInfo,\n type EimzoKey,\n type PfxKey,\n type TokenKey,\n} from './certificate';\nexport {\n EimzoError,\n isEimzoError,\n type EimzoErrorCode,\n type EimzoErrorDetails,\n type EimzoErrorParams,\n type EimzoMessages,\n} from './errors';\nexport {\n builtinMessages,\n DEFAULT_LOCALE,\n formatEimzoError,\n type BuiltinLocale,\n type EimzoLocale,\n type MessageOverrides,\n} from './i18n';\nexport { en } from './locales/en';\nexport { kaa } from './locales/kaa';\nexport { ru } from './locales/ru';\nexport { uzLatn } from './locales/uz-Latn';\nexport { uzCyrl } from './locales/uz-Cyrl';\nexport {\n createCapiwsTransport,\n createDefaultTransport,\n createWebSocketTransport,\n defaultEimzoUrl,\n type CapiwsLike,\n type EimzoRequest,\n type EimzoResponse,\n type Transport,\n type WebSocketTransportOptions,\n} from './transport';\n","export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\n// -5000 «Ввод пароля отменен»: кнопка «Отмена» в окне пароля.\nconst STATUS_CANCELLED = [-5000];\n// Неверный пароль PFX. Старые версии: BadPaddingException. E-IMZO 6.3 — status -9999 с текстом\n// «Sequence tag error» или «getSecretKey failed: Password is not ASCII» (пароль в другой раскладке).\n// -9999 бывает и у других ошибок, поэтому сверяем текст.\nconst WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
package/dist/index.js
CHANGED
|
@@ -105,11 +105,12 @@ function notInstalledError(wsCode, cause) {
|
|
|
105
105
|
return new EimzoError("NOT_INSTALLED", {}, { wsCode, cause });
|
|
106
106
|
}
|
|
107
107
|
var STATUS_KEY_NOT_FOUND = [-1010, -1014];
|
|
108
|
-
var STATUS_CANCELLED = [];
|
|
108
|
+
var STATUS_CANCELLED = [-5e3];
|
|
109
|
+
var WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;
|
|
109
110
|
function errorFromResponse(res) {
|
|
110
111
|
const { status, reason } = res;
|
|
111
112
|
const details = { reason, status };
|
|
112
|
-
if (reason &&
|
|
113
|
+
if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError("WRONG_PASSWORD", {}, details);
|
|
113
114
|
if (status !== void 0 && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {
|
|
114
115
|
return new EimzoError("KEY_NOT_FOUND", {}, details);
|
|
115
116
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\nconst STATUS_CANCELLED: number[] = [];\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && reason.indexOf('BadPaddingException') !== -1) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
|
1
|
+
{"version":3,"sources":["../src/base64.ts","../src/certificate.ts","../src/locales/format.ts","../src/locales/ru.ts","../src/errors.ts","../src/locales/en.ts","../src/locales/kaa.ts","../src/locales/uz-Latn.ts","../src/locales/uz-Cyrl.ts","../src/i18n.ts","../src/transport.ts","../src/eimzo.ts","../src/backend.ts"],"sourcesContent":["export function bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)));\n }\n return btoa(binary);\n}\n\nexport function utf8ToBase64(text: string): string {\n return bytesToBase64(new TextEncoder().encode(text));\n}\n","export interface CertificateInfo {\n serialNumber: string;\n /** ФИО владельца. */\n CN: string;\n /** ИНН; для физлиц без ИНН — UID, как в e-imzo-client.js. */\n TIN: string;\n PINFL: string;\n UID: string;\n /** Организация. */\n O: string;\n /** Должность. */\n T: string;\n validFrom: Date | null;\n validTo: Date | null;\n /** Срок действия истёк на момент получения списка. */\n expired: boolean;\n}\n\nexport interface PfxKey extends CertificateInfo {\n type: 'pfx';\n disk: string;\n path: string;\n name: string;\n alias: string;\n}\n\n/** Токен, найденный плагином `ftjc` (только E-IMZO старше 4.12). */\nexport interface TokenKey extends CertificateInfo {\n type: 'ftjc';\n cardUID: string;\n statusInfo: string;\n ownerName: string;\n info: string;\n}\n\nexport type EimzoKey = PfxKey | TokenKey;\n\nconst OID_ALIASES: Record<string, string> = {\n '1.2.860.3.16.1.1': 'INN',\n '1.2.860.3.16.1.2': 'PINFL',\n};\n\n// Атрибут начинается в начале строки или после запятой: `cn=...,1.2.860.3.16.1.2=...`\nconst ATTRIBUTE_START = /(?:^|,)\\s*([A-Za-z][A-Za-z0-9]*|\\d+(?:\\.\\d+)+)=/g;\n\n/**\n * Разбирает строку вида `cn=Иванов,uid=123,validto=2024.09.24 23:59:59` в словарь\n * с ключами в верхнем регистре. Значения могут содержать запятые.\n */\nexport function parseX500(source: string): Record<string, string> {\n const matches: { key: string; start: number; end: number }[] = [];\n ATTRIBUTE_START.lastIndex = 0;\n for (let m = ATTRIBUTE_START.exec(source); m; m = ATTRIBUTE_START.exec(source)) {\n matches.push({ key: m[1], start: m.index, end: m.index + m[0].length });\n }\n const result: Record<string, string> = {};\n matches.forEach((m, i) => {\n const key = OID_ALIASES[m.key] ?? m.key.toUpperCase();\n const value = source.slice(m.end, i + 1 < matches.length ? matches[i + 1].start : source.length);\n if (!(key in result)) result[key] = value;\n });\n return result;\n}\n\n/** PFX отдаёт даты как `2022.09.24 17:29:21`, токены — в формате, понятном `Date`. */\nexport function parseEimzoDate(value: string | undefined): Date | null {\n if (!value) return null;\n const normalized = /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)\n ? value.replace(/\\./g, '-').replace(' ', 'T')\n : value;\n const date = new Date(normalized);\n return isNaN(date.getTime()) ? null : date;\n}\n\n/** Возвращает `null` для сертификатов без ИНН и ПИНФЛ — e-imzo-client.js их пропускает. */\nexport function parseCertificateInfo(x500: string, now: Date = new Date()): CertificateInfo | null {\n const a = parseX500(x500);\n const TIN = a.INN || a.UID || '';\n const PINFL = a.PINFL || '';\n if (!TIN && !PINFL) return null;\n const validTo = parseEimzoDate(a.VALIDTO);\n // E-IMZO отдаёт alias в нижнем регистре; как и e-imzo-client.js, показываем имена заглавными.\n const upper = (value: string | undefined) => (value || '').toUpperCase();\n return {\n serialNumber: a.SERIALNUMBER || '',\n CN: upper(a.CN),\n TIN,\n PINFL,\n UID: a.UID || '',\n O: upper(a.O),\n T: upper(a.T),\n validFrom: parseEimzoDate(a.VALIDFROM),\n validTo,\n expired: validTo !== null && validTo.getTime() < now.getTime(),\n };\n}\n","/** Размер в байтах → \"12.3 MB\" (одинаково для всех языков). */\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const ru: EimzoMessages = {\n NOT_INSTALLED: () => 'Нет соединения с E-IMZO. Убедитесь, что приложение E-IMZO установлено и запущено.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер не поддерживает WebSocket. Обновите браузер.',\n TIMEOUT: () => 'E-IMZO не ответил вовремя. Попробуйте ещё раз.',\n OUTDATED_VERSION: (p) =>\n `Установлена устаревшая версия E-IMZO (${p.installed}). Установите версию ${p.min} или новее: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO отклонил API-ключ для этого сайта.',\n WRONG_PASSWORD: () => 'Неверный пароль.',\n CANCELLED: () => 'Операция отменена.',\n KEY_NOT_FOUND: () => 'Ключ не найден в E-IMZO. Выберите ключ заново.',\n FILE_TOO_LARGE: (p) => `Файл слишком большой (${formatSize(p.size)}). Максимум — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Ключ не выбран.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend не настроен: нет методов ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Ошибка сервера: ${p.detail}` : p.status ? `Ошибка сервера (HTTP ${p.status}).` : 'Ошибка сервера.',\n EIMZO_ERROR: (p) => (p.reason ? `Ошибка E-IMZO: ${p.reason}` : 'Неизвестная ошибка E-IMZO.'),\n};\n","import { ru } from './locales/ru';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype NoParams = {};\n\n/** Параметры, которые подставляются в текст ошибки, по каждому коду. */\nexport interface EimzoErrorParams {\n /** E-IMZO.exe не запущен или не установлен (WebSocket не открылся). */\n NOT_INSTALLED: NoParams;\n /** Браузер не поддерживает WebSocket. */\n WEBSOCKET_UNSUPPORTED: NoParams;\n /** E-IMZO не ответил за `timeoutMs`. */\n TIMEOUT: NoParams;\n /** Установленная версия E-IMZO ниже `minVersion`. */\n OUTDATED_VERSION: { installed: string; min: string };\n /** E-IMZO отклонил API-KEY для домена страницы. */\n API_KEY_REJECTED: NoParams;\n /** Неверный пароль PFX-ключа. */\n WRONG_PASSWORD: NoParams;\n /** Пользователь закрыл окно пароля/PIN. Обычно это не ошибка, показывать не нужно. */\n CANCELLED: NoParams;\n /** E-IMZO не знает этот `keyId`: прошло 24 часа, ключ выгружен или E-IMZO перезапущен. */\n KEY_NOT_FOUND: NoParams;\n /** Файл больше `maxSize` в `signFile()`. Размеры в байтах. */\n FILE_TOO_LARGE: { size: number; max: number };\n /** `sign()` вызван до `loadKey()`. */\n KEY_NOT_LOADED: NoParams;\n /** В `options.backend` нет нужных методов — ошибка в коде приложения. */\n BACKEND_NOT_CONFIGURED: { methods: string };\n /** Backend ответил ошибкой или некорректными данными. */\n BACKEND_ERROR: { status?: number; detail?: string };\n /** Прочие ошибки E-IMZO; исходный текст — в `reason`. */\n EIMZO_ERROR: { reason?: string };\n}\n\nexport type EimzoErrorCode = keyof EimzoErrorParams;\n\n/** Словарь сообщений: функция на каждый код ошибки. */\nexport type EimzoMessages = {\n [C in EimzoErrorCode]: (params: EimzoErrorParams[C]) => string;\n};\n\nexport interface EimzoErrorDetails {\n /** Текст ошибки от E-IMZO (`data.reason`), не переводится. */\n reason?: string;\n /** Числовой `status` из ответа E-IMZO. */\n status?: number;\n /** Код закрытия WebSocket. */\n wsCode?: number;\n /** HTTP-статус ответа backend. */\n httpStatus?: number;\n cause?: unknown;\n}\n\ntype ParamsArg<C extends EimzoErrorCode> = keyof EimzoErrorParams[C] extends never\n ? [params?: EimzoErrorParams[C], details?: EimzoErrorDetails]\n : [params: EimzoErrorParams[C], details?: EimzoErrorDetails];\n\n/**\n * Ошибка библиотеки. Для логики используйте `code` и `params`.\n * `message` — текст на языке экземпляра `Eimzo` (по умолчанию на русском);\n * чтобы перевести на другой язык, используйте `eimzo.t(error)` или `formatEimzoError()`.\n */\nexport class EimzoError<C extends EimzoErrorCode = EimzoErrorCode> extends Error {\n readonly code: C;\n readonly params: EimzoErrorParams[C];\n readonly reason?: string;\n readonly status?: number;\n readonly wsCode?: number;\n readonly httpStatus?: number;\n\n constructor(code: C, ...[params, details = {}]: ParamsArg<C>) {\n const p = (params ?? {}) as EimzoErrorParams[C];\n super(ru[code](p));\n this.name = 'EimzoError';\n this.code = code;\n this.params = p;\n this.reason = details.reason;\n this.status = details.status;\n this.wsCode = details.wsCode;\n this.httpStatus = details.httpStatus;\n if (details.cause !== undefined) (this as { cause?: unknown }).cause = details.cause;\n }\n}\n\nexport function isEimzoError<C extends EimzoErrorCode>(error: unknown, code?: C): error is EimzoError<C> {\n return error instanceof EimzoError && (code === undefined || error.code === code);\n}\n\nexport function notInstalledError(wsCode?: number, cause?: unknown): EimzoError<'NOT_INSTALLED'> {\n return new EimzoError('NOT_INSTALLED', {}, { wsCode, cause });\n}\n\n// Коды `status` E-IMZO, проверенные на E-IMZO 6.3.5.\nconst STATUS_KEY_NOT_FOUND = [-1010, -1014];\n// -5000 «Ввод пароля отменен»: кнопка «Отмена» в окне пароля.\nconst STATUS_CANCELLED = [-5000];\n// Неверный пароль PFX. Старые версии: BadPaddingException. E-IMZO 6.3 — status -9999 с текстом\n// «Sequence tag error» или «getSecretKey failed: Password is not ASCII» (пароль в другой раскладке).\n// -9999 бывает и у других ошибок, поэтому сверяем текст.\nconst WRONG_PASSWORD_REASONS = /BadPaddingException|Sequence tag error|getSecretKey failed/;\n\n/** Превращает неуспешный ответ E-IMZO (`status`, `reason`) в типизированную ошибку. */\nexport function errorFromResponse(res: { status?: number; reason?: string }): EimzoError {\n const { status, reason } = res;\n const details = { reason, status };\n if (reason && WRONG_PASSWORD_REASONS.test(reason)) return new EimzoError('WRONG_PASSWORD', {}, details);\n if (status !== undefined && STATUS_KEY_NOT_FOUND.indexOf(status) !== -1) {\n return new EimzoError('KEY_NOT_FOUND', {}, details);\n }\n if (status !== undefined && STATUS_CANCELLED.indexOf(status) !== -1) return new EimzoError('CANCELLED', {}, details);\n return new EimzoError('EIMZO_ERROR', { reason }, details);\n}\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\nexport const en: EimzoMessages = {\n NOT_INSTALLED: () => 'Cannot connect to E-IMZO. Make sure the E-IMZO application is installed and running.',\n WEBSOCKET_UNSUPPORTED: () => 'Your browser does not support WebSocket. Please update your browser.',\n TIMEOUT: () => 'E-IMZO did not respond in time. Please try again.',\n OUTDATED_VERSION: (p) =>\n `An outdated version of E-IMZO is installed (${p.installed}). Install version ${p.min} or newer: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO rejected the API key for this site.',\n WRONG_PASSWORD: () => 'Wrong password.',\n CANCELLED: () => 'Operation cancelled.',\n KEY_NOT_FOUND: () => 'Key not found in E-IMZO. Please select the key again.',\n FILE_TOO_LARGE: (p) => `File is too large (${formatSize(p.size)}). Maximum is ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'No key selected.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend is not configured: missing methods ${p.methods}.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server error: ${p.detail}` : p.status ? `Server error (HTTP ${p.status}).` : 'Server error.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO error: ${p.reason}` : 'Unknown E-IMZO error.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Qaraqalpaqsha (latın). */\nexport const kaa: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO menen baylanıs joq. E-IMZO baǵdarlaması ornatılǵanın hám iske túsirilgenin tekseriń.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasın qollap-quwatlamaydı. Brauzerdi jańalań.',\n TIMEOUT: () => 'E-IMZO óz waqtında juwap bermedi. Qaytadan urınıp kóriń.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO baǵdarlamasınıń eski versiyası ornatılǵan (${p.installed}). ${p.min} yamasa onnan jańa versiyanı ornatıń: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO usı sayt ushın API-giltti qabıl etpedi.',\n WRONG_PASSWORD: () => 'Parol qáte.',\n CANCELLED: () => 'Ámel biykar etildi.',\n KEY_NOT_FOUND: () => 'Gilt E-IMZO-da tabılmadı. Giltti qaytadan tańlań.',\n FILE_TOO_LARGE: (p) => `Fayl júdá úlken (${formatSize(p.size)}). Eń kóbi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Gilt tańlanbaǵan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sazlanbaǵan: ${p.methods} metodları joq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server qátesi: ${p.detail}` : p.status ? `Server qátesi (HTTP ${p.status}).` : 'Server qátesi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO qátesi: ${p.reason}` : 'E-IMZO-da belgisiz qátelik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Oʻzbekcha (lotin). */\nexport const uzLatn: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO bilan aloqa yoʻq. E-IMZO dasturi oʻrnatilgan va ishga tushirilganiga ishonch hosil qiling.',\n WEBSOCKET_UNSUPPORTED: () => 'Brauzer WebSocket texnologiyasini qoʻllab-quvvatlamaydi. Brauzerni yangilang.',\n TIMEOUT: () => 'E-IMZO oʻz vaqtida javob bermadi. Qaytadan urinib koʻring.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO dasturining eskirgan versiyasi oʻrnatilgan (${p.installed}). ${p.min} yoki undan yangi versiyani oʻrnating: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ushbu sayt uchun API-kalitni rad etdi.',\n WRONG_PASSWORD: () => 'Parol notoʻgʻri.',\n CANCELLED: () => 'Amal bekor qilindi.',\n KEY_NOT_FOUND: () => 'Kalit E-IMZO da topilmadi. Kalitni qaytadan tanlang.',\n FILE_TOO_LARGE: (p) => `Fayl juda katta (${formatSize(p.size)}). Eng koʻpi — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Kalit tanlanmagan.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend sozlanmagan: ${p.methods} metodlari yoʻq.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Server xatosi: ${p.detail}` : p.status ? `Server xatosi (HTTP ${p.status}).` : 'Server xatosi.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO xatosi: ${p.reason}` : 'E-IMZO da nomaʼlum xatolik.'),\n};\n","import type { EimzoMessages } from '../errors';\nimport { formatSize } from './format';\n\nconst DOWNLOAD_URL = 'https://e-imzo.uz/main/downloads/';\n\n/** Ўзбекча (кирилл). */\nexport const uzCyrl: EimzoMessages = {\n NOT_INSTALLED: () =>\n 'E-IMZO билан алоқа йўқ. E-IMZO дастури ўрнатилган ва ишга туширилганига ишонч ҳосил қилинг.',\n WEBSOCKET_UNSUPPORTED: () => 'Браузер WebSocket технологиясини қўллаб-қувватламайди. Браузерни янгиланг.',\n TIMEOUT: () => 'E-IMZO ўз вақтида жавоб бермади. Қайтадан уриниб кўринг.',\n OUTDATED_VERSION: (p) =>\n `E-IMZO дастурининг эскирган версияси ўрнатилган (${p.installed}). ${p.min} ёки ундан янги версияни ўрнатинг: ${DOWNLOAD_URL}`,\n API_KEY_REJECTED: () => 'E-IMZO ушбу сайт учун API-калитни рад этди.',\n WRONG_PASSWORD: () => 'Парол нотўғри.',\n CANCELLED: () => 'Амал бекор қилинди.',\n KEY_NOT_FOUND: () => 'Калит E-IMZO да топилмади. Калитни қайтадан танланг.',\n FILE_TOO_LARGE: (p) => `Файл жуда катта (${formatSize(p.size)}). Энг кўпи — ${formatSize(p.max)}.`,\n KEY_NOT_LOADED: () => 'Калит танланмаган.',\n BACKEND_NOT_CONFIGURED: (p) => `Backend созланмаган: ${p.methods} методлари йўқ.`,\n BACKEND_ERROR: (p) =>\n p.detail ? `Сервер хатоси: ${p.detail}` : p.status ? `Сервер хатоси (HTTP ${p.status}).` : 'Сервер хатоси.',\n EIMZO_ERROR: (p) => (p.reason ? `E-IMZO хатоси: ${p.reason}` : 'E-IMZO да номаълум хатолик.'),\n};\n","import { EimzoError, type EimzoErrorCode, type EimzoMessages } from './errors';\nimport { en } from './locales/en';\nimport { kaa } from './locales/kaa';\nimport { ru } from './locales/ru';\nimport { uzLatn } from './locales/uz-Latn';\nimport { uzCyrl } from './locales/uz-Cyrl';\n\n/** Встроенные языки. Можно передать и любой свой код языка вместе с `messages`. */\nexport type BuiltinLocale = 'ru' | 'uz-Latn' | 'uz-Cyrl' | 'kaa' | 'en';\nexport type EimzoLocale = BuiltinLocale | (string & {});\n\nexport const DEFAULT_LOCALE: BuiltinLocale = 'ru';\n\nexport const builtinMessages: Record<BuiltinLocale, EimzoMessages> = {\n ru,\n 'uz-Latn': uzLatn,\n 'uz-Cyrl': uzCyrl,\n kaa,\n en,\n};\n\n/** Свои тексты: новый язык целиком или замена отдельных сообщений встроенного. */\nexport type MessageOverrides = Record<string, Partial<EimzoMessages>>;\n\n/**\n * Текст ошибки на нужном языке. Порядок поиска: `overrides[locale]` → встроенный `locale`\n * → русский. Для не-`EimzoError` возвращает `error.message`.\n */\nexport function formatEimzoError(\n error: unknown,\n locale: EimzoLocale = DEFAULT_LOCALE,\n overrides: MessageOverrides = {},\n): string {\n if (!(error instanceof EimzoError)) {\n return error instanceof Error ? error.message : String(error);\n }\n const code = error.code as EimzoErrorCode;\n const format = (overrides[locale]?.[code] ??\n builtinMessages[locale as BuiltinLocale]?.[code] ??\n ru[code]) as (params: unknown) => string;\n return format(error.params);\n}\n","import { EimzoError, notInstalledError } from './errors';\n\nexport interface EimzoRequest {\n plugin?: string;\n name: string;\n arguments?: unknown[];\n}\n\nexport interface EimzoResponse {\n success: boolean;\n reason?: string;\n [key: string]: any;\n}\n\n/** Один вызов функции E-IMZO. Подменяется в тестах или для нестандартного окружения. */\nexport type Transport = (request: EimzoRequest) => Promise<EimzoResponse>;\n\nexport interface WebSocketTransportOptions {\n /** По умолчанию выбирается по протоколу страницы, см. `defaultEimzoUrl()`. */\n url?: string;\n /**\n * Таймаут одного вызова, мс. По умолчанию не ограничен: `create_pkcs7`\n * ждёт, пока пользователь введёт пароль.\n */\n timeoutMs?: number;\n /** Реализация WebSocket, если глобальной нет. */\n WebSocketImpl?: typeof WebSocket;\n}\n\n/** Совместимый с `CAPIWS` объект; так устроено браузерное расширение `EIMZOEXT`. */\nexport interface CapiwsLike {\n callFunction(def: EimzoRequest, onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n version(onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n apikey(keys: unknown[], onSuccess: (event: unknown, data: EimzoResponse) => void, onError: (code?: number) => void): void;\n}\n\nexport function defaultEimzoUrl(): string {\n const https = typeof location !== 'undefined' && location.protocol.toLowerCase() === 'https:';\n return (https ? 'wss://127.0.0.1:64443' : 'ws://127.0.0.1:64646') + '/service/cryptapi';\n}\n\n/** Как `CAPIWS` в e-imzo.js: одно WebSocket-соединение на каждый вызов. */\nexport function createWebSocketTransport(options: WebSocketTransportOptions = {}): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const WS = options.WebSocketImpl ?? (globalThis as { WebSocket?: typeof WebSocket }).WebSocket;\n if (!WS) {\n reject(new EimzoError('WEBSOCKET_UNSUPPORTED'));\n return;\n }\n\n let socket: WebSocket;\n try {\n socket = new WS(options.url ?? defaultEimzoUrl());\n } catch (e) {\n reject(notInstalledError(undefined, e));\n return;\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n fn();\n };\n\n if (options.timeoutMs) {\n timer = setTimeout(() => {\n settle(() => reject(new EimzoError('TIMEOUT')));\n socket.close();\n }, options.timeoutMs);\n }\n\n socket.onopen = () => socket.send(JSON.stringify(request));\n socket.onmessage = (event) => {\n settle(() => {\n try {\n resolve(JSON.parse(event.data as string) as EimzoResponse);\n } catch (e) {\n reject(new EimzoError('EIMZO_ERROR', { reason: 'invalid JSON response' }, { cause: e }));\n }\n });\n socket.close();\n };\n // Закрытие до ответа — значит E-IMZO недоступен.\n socket.onclose = (event) => settle(() => reject(notInstalledError(event.code)));\n });\n}\n\nexport function createCapiwsTransport(capiws: CapiwsLike): Transport {\n return (request) =>\n new Promise<EimzoResponse>((resolve, reject) => {\n const ok = (_event: unknown, data: EimzoResponse) => resolve(data);\n const fail = (code?: number) => reject(notInstalledError(code));\n if (!request.plugin && request.name === 'version') capiws.version(ok, fail);\n else if (!request.plugin && request.name === 'apikey') capiws.apikey(request.arguments ?? [], ok, fail);\n else capiws.callFunction(request, ok, fail);\n });\n}\n\n/**\n * Через расширение `EIMZOEXT`, если оно есть на странице, иначе через WebSocket.\n * Проверка на каждом вызове: расширение может внедриться после загрузки скрипта.\n */\nexport function createDefaultTransport(options: WebSocketTransportOptions = {}): Transport {\n const ws = createWebSocketTransport(options);\n return (request) => {\n const ext = (globalThis as { EIMZOEXT?: CapiwsLike }).EIMZOEXT;\n return ext ? createCapiwsTransport(ext)(request) : ws(request);\n };\n}\n","import { bytesToBase64, utf8ToBase64 } from './base64';\nimport type { EimzoBackend } from './backend';\nimport { parseCertificateInfo, type EimzoKey, type PfxKey, type TokenKey } from './certificate';\nimport { EimzoError, errorFromResponse, isEimzoError } from './errors';\nimport { DEFAULT_LOCALE, formatEimzoError, type EimzoLocale, type MessageOverrides } from './i18n';\nimport { createDefaultTransport, type EimzoResponse, type Transport, type WebSocketTransportOptions } from './transport';\n\n/** Пары «домен → API-KEY» или плоский массив `[домен, ключ, домен, ключ, ...]`, как в демо. */\nexport type ApiKeys = Record<string, string> | string[];\n\n/** Аппаратные носители: подписывают без `load_key`, `id` передаётся в `create_pkcs7` напрямую. */\nexport type DeviceType = 'idcard' | 'baikey' | 'ckc';\n\nexport interface EimzoVersion {\n major: number;\n minor: number;\n}\n\nexport interface EimzoOptions<TLogin = unknown> extends WebSocketTransportOptions {\n /**\n * API-ключи доменов. Пусто — `apikey` не вызывается (E-IMZO v6 подбирает ключ по домену сам).\n * Для localhost используйте `DEV_API_KEYS`.\n */\n apiKeys?: ApiKeys;\n /** Минимальная версия E-IMZO, `\"major.minor\"`. По умолчанию `\"4.86\"`. */\n minVersion?: string;\n backend?: EimzoBackend<TLogin>;\n /** Своя реализация вызовов E-IMZO, например для тестов. */\n transport?: Transport;\n /**\n * Язык сообщений об ошибках: `'ru'` (по умолчанию), `'uz-Latn'`, `'uz-Cyrl'`, `'kaa'`, `'en'`\n * или свой код вместе с `messages`.\n */\n locale?: EimzoLocale;\n /**\n * Свои тексты: `{ ru: { WRONG_PASSWORD: () => '...' } }` заменяет одно сообщение,\n * `{ kk: { ... } }` добавляет язык. Недостающие сообщения берутся из русского.\n */\n messages?: MessageOverrides;\n /**\n * Если E-IMZO забыл `keyId` (24 часа, перезапуск E-IMZO), `sign()` сам загрузит\n * тот же ключ заново и повторит подпись. E-IMZO при этом снова спросит пароль.\n * По умолчанию `true`.\n */\n autoReloadKey?: boolean;\n}\n\nexport interface LoadKeyOptions {\n /**\n * Сразу спросить пароль/PIN (`verify_password` / `verify_pin`).\n * Внимание: `verify_password` не показывает флажок «Запомнить на 6 час.»\n * и сокращает уже запомненный пароль до 1 минуты.\n */\n verifyPassword?: boolean;\n}\n\nexport interface SignOptions {\n /** PKCS#7 без вложенных данных (detached). По умолчанию — с данными (attached). */\n detached?: boolean;\n /** Строка `data` уже в base64 (например, содержимое файла). */\n base64?: boolean;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport type SignableData = string | Uint8Array | ArrayBuffer;\n\nexport interface SignFileOptions {\n /** По умолчанию `true`: файл хранится у вас, класть его копию в подпись незачем. */\n detached?: boolean;\n /** Максимальный размер файла в байтах. По умолчанию 10 МБ. */\n maxSize?: number;\n /** Подписать другим ключом, а не загруженным через `loadKey()`. */\n keyId?: string;\n}\n\nexport const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n/** Публичные ключи E-IMZO для локальной разработки (из официального примера). */\nexport const DEV_API_KEYS: Record<string, string> = {\n localhost:\n '96D0C1491615C82B9A54D9989779DF825B690748224C2B04F500F370D51827CE2644D8D4A82C18184D73AB8530BB8ED537269603F61DB0D03D2104ABF789970B',\n '127.0.0.1':\n 'A7BCFA5D490B351BE0754130DF03A068F855DB4333D43921125B9CF2670EF6A40370C646B90401955E1F7BC9CDBF59CE0B2C5467D820BE189C845D0B79CFC96F',\n};\n\nconst DEFAULT_MIN_VERSION = '4.86';\n// Пороги из e-imzo-client.js (NEW_API2 / NEW_API3).\nconst VERSION_PFX_ONLY = 412;\nconst VERSION_BAIK_CKC = 486;\n\nconst versionNumber = (v: EimzoVersion) => v.major * 100 + v.minor;\n\nfunction parseVersion(value: string): EimzoVersion {\n const [major, minor] = value.split('.').map((part) => parseInt(part, 10));\n if (isNaN(major) || isNaN(minor)) throw new Error(`Invalid E-IMZO version: \"${value}\"`);\n return { major, minor };\n}\n\nfunction flattenApiKeys(keys: ApiKeys | undefined): string[] {\n if (!keys) return [];\n if (Array.isArray(keys)) return keys;\n return Object.keys(keys).reduce<string[]>((acc, domain) => acc.concat(domain, keys[domain]), []);\n}\n\nfunction toBase64(data: SignableData, alreadyBase64: boolean): string {\n if (typeof data === 'string') return alreadyBase64 ? data : utf8ToBase64(data);\n return bytesToBase64(data instanceof Uint8Array ? data : new Uint8Array(data));\n}\n\nexport class Eimzo<TLogin = unknown> {\n private readonly transport: Transport;\n private readonly minVersion: EimzoVersion;\n private ready: Promise<EimzoVersion> | null = null;\n private currentKeyId: string | null = null;\n /** Ключ, из которого получен `currentKeyId`, — чтобы загрузить его заново. */\n private currentKey: EimzoKey | DeviceType | null = null;\n private currentLocale: EimzoLocale;\n /** Хвост очереди операций, которые могут открыть окно пароля. */\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(private readonly options: EimzoOptions<TLogin> = {}) {\n this.transport = options.transport ?? createDefaultTransport(options);\n this.minVersion = parseVersion(options.minVersion ?? DEFAULT_MIN_VERSION);\n this.currentLocale = options.locale ?? DEFAULT_LOCALE;\n }\n\n /** `keyId` последнего `loadKey()`. Держите его, чтобы работало запоминание пароля на 6 часов. */\n get keyId(): string | null {\n return this.currentKeyId;\n }\n\n get locale(): EimzoLocale {\n return this.currentLocale;\n }\n\n /** Сменить язык. Влияет на `t()` и на `message` следующих ошибок. */\n setLocale(locale: EimzoLocale): void {\n this.currentLocale = locale;\n }\n\n /**\n * Текст ошибки на текущем (или указанном) языке. Используйте при показе, а не\n * `error.message`: так после смены языка старая ошибка тоже покажется на новом.\n */\n t(error: unknown, locale: EimzoLocale = this.currentLocale): string {\n return formatEimzoError(error, locale, this.options.messages);\n }\n\n /** Все публичные методы проходят через guard: `message` ошибки — на текущем языке. */\n private guard<T>(work: () => Promise<T>): Promise<T> {\n return work().catch((error: unknown) => {\n if (error instanceof EimzoError) error.message = this.t(error);\n throw error;\n });\n }\n\n /**\n * Операции, которые могут открыть окно пароля, выполняются строго по одной:\n * двойной клик по «Подписать» не откроет два окна, второй вызов дождётся первого.\n */\n private exclusive<T>(work: () => Promise<T>): Promise<T> {\n const run = this.queue.then(work, work);\n this.queue = run.catch(() => undefined);\n return this.guard(() => run);\n }\n\n /**\n * Проверяет версию и устанавливает API-ключи. Вызывается автоматически перед любой\n * операцией; результат кешируется, после ошибки следующий вызов пробует заново.\n */\n init(): Promise<EimzoVersion> {\n if (!this.ready) {\n this.ready = this.doInit().catch((error) => {\n this.ready = null;\n throw error;\n });\n }\n const ready = this.ready;\n return this.guard(() => ready);\n }\n\n private async doInit(): Promise<EimzoVersion> {\n const version = await this.readVersion();\n if (versionNumber(version) < versionNumber(this.minVersion)) {\n throw new EimzoError('OUTDATED_VERSION', {\n installed: `${version.major}.${version.minor}`,\n min: `${this.minVersion.major}.${this.minVersion.minor}`,\n });\n }\n const apiKeys = flattenApiKeys(this.options.apiKeys);\n if (apiKeys.length > 0) {\n const res = await this.transport({ name: 'apikey', arguments: apiKeys });\n if (!res.success) throw new EimzoError('API_KEY_REJECTED', {}, { reason: res.reason });\n }\n return version;\n }\n\n /** Версия установленного E-IMZO. Не требует API-ключа. */\n getVersion(): Promise<EimzoVersion> {\n return this.guard(() => this.readVersion());\n }\n\n private async readVersion(): Promise<EimzoVersion> {\n const res = await this.transport({ name: 'version' });\n if (!res.success) throw errorFromResponse(res);\n const major = parseInt(res.major, 10);\n const minor = parseInt(res.minor, 10);\n if (isNaN(major) || isNaN(minor)) throw new EimzoError('EIMZO_ERROR', { reason: 'version is undefined' });\n return { major, minor };\n }\n\n /** Прямой вызов функции плагина E-IMZO (см. http://127.0.0.1:64646/apidoc.html). */\n call(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n return this.guard(() => this.invoke(plugin, name, args));\n }\n\n private async invoke(plugin: string, name: string, args: unknown[] = []): Promise<EimzoResponse> {\n await this.init();\n const res = await this.transport({ plugin, name, arguments: args });\n if (!res.success) throw errorFromResponse(res);\n return res;\n }\n\n /** PFX-ключи (и токены `ftjc` для E-IMZO старше 4.12). Ключи без ИНН и ПИНФЛ пропускаются. */\n listKeys(): Promise<EimzoKey[]> {\n return this.guard(async () => {\n const version = await this.init();\n const sources: Promise<EimzoKey[]>[] = [this.listPfx()];\n if (versionNumber(version) < VERSION_PFX_ONLY) sources.push(this.listTokens());\n\n const results = await Promise.allSettled(sources);\n const keys: EimzoKey[] = [];\n let firstError: unknown;\n for (const r of results) {\n if (r.status === 'fulfilled') keys.push(...r.value);\n else if (firstError === undefined) firstError = r.reason;\n }\n // Как в оригинале: ошибка, только если ничего не нашлось.\n if (keys.length === 0 && firstError !== undefined) throw firstError;\n return keys;\n });\n }\n\n private async listPfx(): Promise<PfxKey[]> {\n const res = await this.invoke('pfx', 'list_all_certificates');\n const now = new Date();\n const keys: PfxKey[] = [];\n for (const el of res.certificates ?? []) {\n const info = parseCertificateInfo(el.alias, now);\n if (info) keys.push({ ...info, type: 'pfx', disk: el.disk, path: el.path, name: el.name, alias: el.alias });\n }\n return keys;\n }\n\n private async listTokens(): Promise<TokenKey[]> {\n const res = await this.invoke('ftjc', 'list_all_keys', ['']);\n const now = new Date();\n const keys: TokenKey[] = [];\n for (const el of res.tokens ?? []) {\n const info = parseCertificateInfo(el.info, now);\n if (info) {\n keys.push({\n ...info,\n type: 'ftjc',\n cardUID: el.cardUID,\n statusInfo: el.statusInfo,\n ownerName: el.ownerName,\n info: el.info,\n });\n }\n }\n return keys;\n }\n\n /** Какие аппаратные носители подключены. Носители, которые версия E-IMZO не поддерживает, — `false`. */\n listDevices(): Promise<Record<DeviceType, boolean>> {\n return this.guard(async () => {\n const v = versionNumber(await this.init());\n const check = async (enabled: boolean, plugin: string, name: string, field: string) => {\n if (!enabled) return false;\n try {\n const res = await this.invoke(plugin, name);\n return Array.isArray(res[field]) && res[field].length > 0;\n } catch (error) {\n // Ошибка плагина = носителя нет; ошибки связи пробрасываем.\n if (error instanceof EimzoError && error.code === 'EIMZO_ERROR') return false;\n throw error;\n }\n };\n const [idcard, baikey, ckc] = await Promise.all([\n check(v >= VERSION_PFX_ONLY, 'idcard', 'list_readers', 'readers'),\n check(v >= VERSION_BAIK_CKC, 'baikey', 'list_tokens', 'tokens'),\n check(v >= VERSION_BAIK_CKC, 'ckc', 'list_ckc', 'devices'),\n ]);\n return { idcard, baikey, ckc };\n });\n }\n\n /**\n * Загружает ключ и запоминает его `keyId` для `sign()`.\n * Для аппаратного носителя (`'idcard' | 'baikey' | 'ckc'`) E-IMZO не вызывается.\n * Каждый вызов для PFX создаёт новую сессию, и E-IMZO снова спросит пароль.\n * Предыдущий загруженный PFX-ключ выгружается из E-IMZO.\n */\n loadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions = {}): Promise<string> {\n return this.exclusive(() => this.doLoadKey(key, options));\n }\n\n private async doLoadKey(key: EimzoKey | DeviceType, options: LoadKeyOptions): Promise<string> {\n await this.releaseCurrentKey();\n let keyId: string;\n if (typeof key === 'string') {\n keyId = key;\n } else if (key.type === 'pfx') {\n keyId = (await this.invoke('pfx', 'load_key', [key.disk, key.path, key.name, key.alias])).keyId;\n if (options.verifyPassword) await this.invoke('pfx', 'verify_password', [keyId]);\n } else {\n keyId = (await this.invoke('ftjc', 'load_key', [key.cardUID])).keyId;\n if (options.verifyPassword) await this.invoke('ftjc', 'verify_pin', [keyId, '1']);\n }\n this.currentKey = key;\n this.currentKeyId = keyId;\n return keyId;\n }\n\n /**\n * Выгрузить ключ из E-IMZO и забыть его. Вызывайте при выходе пользователя:\n * иначе пароль, запомненный на 6 часов, останется в E-IMZO на этом компьютере.\n */\n unloadKey(): Promise<void> {\n return this.exclusive(() => this.releaseCurrentKey());\n }\n\n private async releaseCurrentKey(): Promise<void> {\n const key = this.currentKey;\n const keyId = this.currentKeyId;\n this.currentKey = null;\n this.currentKeyId = null;\n if (!keyId || !key || typeof key === 'string' || key.type !== 'pfx') return;\n try {\n await this.invoke('pfx', 'unload_key', [keyId]);\n } catch (error) {\n // Уже выгружен или E-IMZO перезапущен — цель достигнута.\n if (!isEimzoError(error, 'KEY_NOT_FOUND')) throw error;\n }\n }\n\n /** Создаёт PKCS#7 (base64). Пароль спрашивает окно E-IMZO, сайт его не видит. */\n sign(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(() => this.doSign(data, options));\n }\n\n /**\n * Подписывает файл (`File` из `<input type=\"file\">` или `Blob`). По умолчанию detached.\n * Метку времени добавьте отдельно: `signDocument(await file.arrayBuffer(), { detached: true })`.\n */\n signFile(file: Blob, options: SignFileOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const max = options.maxSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > max) throw new EimzoError('FILE_TOO_LARGE', { size: file.size, max });\n const bytes = new Uint8Array(await file.arrayBuffer());\n return this.doSign(bytes, { detached: options.detached ?? true, keyId: options.keyId });\n });\n }\n\n private async doSign(data: SignableData, options: SignOptions): Promise<string> {\n const keyId = options.keyId ?? this.currentKeyId;\n if (!keyId) throw new EimzoError('KEY_NOT_LOADED');\n const data64 = toBase64(data, options.base64 === true);\n const create = (id: string) =>\n this.invoke('pkcs7', 'create_pkcs7', [data64, id, options.detached ? 'yes' : 'no']).then((res) => res.pkcs7_64);\n try {\n return await create(keyId);\n } catch (error) {\n // E-IMZO забыл keyId (24 часа или перезапуск): загружаем тот же ключ и пробуем ещё раз.\n const key = this.currentKey;\n const canReload =\n this.options.autoReloadKey !== false &&\n options.keyId === undefined &&\n isEimzoError(error, 'KEY_NOT_FOUND') &&\n key !== null &&\n typeof key !== 'string';\n if (!canReload) throw error;\n this.currentKeyId = null; // старый keyId уже недействителен, выгружать нечего\n return create(await this.doLoadKey(key, {}));\n }\n }\n\n /**\n * Вход по ЭЦП: challenge с backend → `loadKey` → подпись challenge → `backend.login`.\n * Возвращает то, что вернул `backend.login` (сессия, JWT и т.п.).\n */\n login(key: EimzoKey | DeviceType): Promise<TLogin> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('getChallenge', 'login');\n const challenge = await backend.getChallenge!();\n await this.doLoadKey(key, {});\n const pkcs7 = await this.doSign(challenge, {});\n return backend.login!(pkcs7);\n });\n }\n\n /** Подпись документа загруженным ключом + метка времени через backend. */\n signDocument(data: SignableData, options: SignOptions = {}): Promise<string> {\n return this.exclusive(async () => {\n const backend = this.requireBackend('timestamp');\n const pkcs7 = await this.doSign(data, options);\n return backend.timestamp!(pkcs7);\n });\n }\n\n private requireBackend(...methods: (keyof EimzoBackend)[]): EimzoBackend<TLogin> {\n const backend = this.options.backend;\n const missing = methods.filter((m) => typeof backend?.[m] !== 'function');\n if (!backend || missing.length > 0) {\n throw new EimzoError('BACKEND_NOT_CONFIGURED', { methods: missing.join(', ') });\n }\n return backend;\n }\n}\n\nexport function createEimzo<TLogin = unknown>(options: EimzoOptions<TLogin> = {}): Eimzo<TLogin> {\n return new Eimzo<TLogin>(options);\n}\n","import { EimzoError } from './errors';\n\n/**\n * Связь с вашим backend. Библиотека не знает ваших адресов и формата ответа,\n * поэтому каждый шаг задаётся функцией. Нужны только те методы, которые вы вызываете:\n * `login()` требует `getChallenge` и `login`, `signDocument()` — `timestamp`.\n */\nexport interface EimzoBackend<TLogin = unknown> {\n /** Одноразовый challenge от e-imzo-server (`/frontend/challenge`). */\n getChallenge?(): Promise<string>;\n /** Отправить PKCS#7 с подписанным challenge; backend проверяет его через `/backend/auth`. */\n login?(pkcs7: string): Promise<TLogin>;\n /** Прикрепить метку времени (`/frontend/timestamp/pkcs7`); вернуть PKCS#7 с меткой. */\n timestamp?(pkcs7: string): Promise<string>;\n}\n\nexport interface FetchBackendOptions {\n /** GET, ответ `{ challenge, status }`. */\n challengeUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ возвращается из `login()` как есть. */\n loginUrl?: string;\n /** POST, тело — PKCS#7 в base64 (text/plain). Ответ `{ pkcs7b64, status }`. */\n timestampUrl?: string;\n /** Общие параметры запросов: заголовки (CSRF, Authorization), `credentials` и т.п. */\n init?: RequestInit;\n fetch?: typeof fetch;\n}\n\n/**\n * Backend на `fetch`. Форматы ответов совпадают с e-imzo-server, поэтому backend\n * может просто проксировать `/frontend/challenge` и `/frontend/timestamp/pkcs7`.\n */\nexport function createFetchBackend<TLogin = unknown>(options: FetchBackendOptions): EimzoBackend<TLogin> {\n const doFetch = options.fetch ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init));\n const base = options.init ?? {};\n\n const request = async (url: string, init: RequestInit): Promise<any> => {\n const response = await doFetch(url, {\n ...base,\n ...init,\n headers: { ...headersToObject(base.headers), ...headersToObject(init.headers) },\n });\n const text = await response.text();\n let body: any = text;\n try {\n body = text ? JSON.parse(text) : null;\n } catch {\n // не JSON — вернём текст\n }\n if (!response.ok) {\n const detail = body && typeof body === 'object' && body.message ? String(body.message) : undefined;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n if (body && typeof body === 'object' && 'status' in body && body.status !== 1) {\n const detail = body.message ? String(body.message) : `status ${body.status}`;\n throw new EimzoError('BACKEND_ERROR', { status: response.status, detail }, { httpStatus: response.status });\n }\n return body;\n };\n\n const postPkcs7 = (url: string, pkcs7: string) =>\n request(url, { method: 'POST', body: pkcs7, headers: { 'Content-Type': 'text/plain' } });\n\n const backend: EimzoBackend<TLogin> = {};\n if (options.challengeUrl) {\n const url = options.challengeUrl;\n backend.getChallenge = async () => {\n const body = await request(url, { method: 'GET', cache: 'no-store' });\n if (!body || typeof body.challenge !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"challenge\" field in response' });\n }\n return body.challenge;\n };\n }\n if (options.loginUrl) {\n const url = options.loginUrl;\n backend.login = (pkcs7) => postPkcs7(url, pkcs7);\n }\n if (options.timestampUrl) {\n const url = options.timestampUrl;\n backend.timestamp = async (pkcs7) => {\n const body = await postPkcs7(url, pkcs7);\n if (!body || typeof body.pkcs7b64 !== 'string') {\n throw new EimzoError('BACKEND_ERROR', { detail: 'no \"pkcs7b64\" field in response' });\n }\n return body.pkcs7b64;\n };\n }\n return backend;\n}\n\nfunction headersToObject(headers: HeadersInit | undefined): Record<string, string> {\n if (!headers) return {};\n if (typeof Headers !== 'undefined' && headers instanceof Headers) {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n return result;\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers);\n return headers as Record<string, string>;\n}\n"],"mappings":"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","names":["DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL","DOWNLOAD_URL"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eimzo-ts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Unofficial framework-agnostic TypeScript client for E-IMZO (Uzbekistan digital signature): key listing, PKCS#7 signing, login by EDS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Abduazimkhoja",
|