@coopenomics/extension-kit 2026.9.22 → 2026.9.24-3
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/dist/index.cjs +308 -89
- package/dist/index.d.cts +172 -14
- package/dist/index.d.mts +172 -14
- package/dist/index.d.ts +172 -14
- package/dist/index.mjs +295 -89
- package/dist/sync/index.cjs +3 -2
- package/dist/sync/index.d.cts +8 -0
- package/dist/sync/index.d.mts +8 -0
- package/dist/sync/index.d.ts +8 -0
- package/dist/sync/index.mjs +3 -2
- package/package.json +6 -4
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,7 @@ import { Reflector } from '@nestjs/core';
|
|
|
5
5
|
import { Observable } from 'rxjs';
|
|
6
6
|
import { ZodObject } from 'zod';
|
|
7
7
|
import { Cooperative } from 'cooptypes';
|
|
8
|
+
import { MigrationInterface, ObjectLiteral, Repository } from 'typeorm';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Пути внутри объекта, по которым пайщик признаётся «своим» для поля.
|
|
@@ -747,6 +748,15 @@ interface IRegistryExtension {
|
|
|
747
748
|
* расширения, которое своих таблиц не держит, — нормальное состояние.
|
|
748
749
|
*/
|
|
749
750
|
entities?: ReadonlyArray<new (...args: any[]) => any>;
|
|
751
|
+
/**
|
|
752
|
+
* Миграции таблиц расширения — классы миграций TypeORM.
|
|
753
|
+
*
|
|
754
|
+
* Схему базы меняют только миграции: добавил или поменял колонку в сущности
|
|
755
|
+
* из `entities` — положи рядом миграцию (`pnpm schema:generate`). Порядок
|
|
756
|
+
* задаёт метка времени в имени класса, общая лента с миграциями ядра.
|
|
757
|
+
* Не путать с `migrations` ниже — те переводят конфиг расширения.
|
|
758
|
+
*/
|
|
759
|
+
databaseMigrations?: ReadonlyArray<new () => MigrationInterface>;
|
|
750
760
|
/**
|
|
751
761
|
* Миграции схемы конфига расширения — в порядке применения.
|
|
752
762
|
*
|
|
@@ -935,6 +945,46 @@ declare function extensionEntities(): ReadonlyArray<ExtensionEntityClass>;
|
|
|
935
945
|
/** Сбросить состав. Только для тестов, которые поднимают граф модулей заново. */
|
|
936
946
|
declare function resetExtensionEntities(): void;
|
|
937
947
|
|
|
948
|
+
/**
|
|
949
|
+
* Миграции таблиц установленных расширений — то, что контроллер отдаёт TypeORM
|
|
950
|
+
* вместе с миграциями ядра.
|
|
951
|
+
*
|
|
952
|
+
* Схему базы меняют только миграции: `synchronize` выключен, потому что он молча
|
|
953
|
+
* удаляет колонки, которых нет в сущности, и превращает переименование в потерю
|
|
954
|
+
* данных. Таблицы расширения описывает оно само — списком `databaseMigrations`
|
|
955
|
+
* в записи реестра, — и файлы миграций лежат в его каталоге: расширение,
|
|
956
|
+
* вынесенное из монолита, уносит историю своих таблиц с собой.
|
|
957
|
+
*
|
|
958
|
+
* Порядок применения задаёт метка времени в имени класса (так TypeORM сортирует
|
|
959
|
+
* миграции), поэтому миграции ядра и расширений идут одной лентой.
|
|
960
|
+
*
|
|
961
|
+
* Список задаётся один раз, до инициализации подключения, — как и состав
|
|
962
|
+
* сущностей (`registerExtensionEntities`).
|
|
963
|
+
*/
|
|
964
|
+
type ExtensionDatabaseMigrationClass = new () => MigrationInterface;
|
|
965
|
+
/** Объявить миграции таблиц установленных расширений. Вызывает composition root. */
|
|
966
|
+
declare function registerExtensionDatabaseMigrations(list: ReadonlyArray<ExtensionDatabaseMigrationClass>): void;
|
|
967
|
+
/**
|
|
968
|
+
* Прочитать миграции таблиц расширений.
|
|
969
|
+
*
|
|
970
|
+
* До объявления возвращает пустой список: подключение к базе поднимается и в
|
|
971
|
+
* контурах без единого расширения.
|
|
972
|
+
*/
|
|
973
|
+
declare function extensionDatabaseMigrations(): ReadonlyArray<ExtensionDatabaseMigrationClass>;
|
|
974
|
+
/** Сбросить список. Только для тестов, которые поднимают граф модулей заново. */
|
|
975
|
+
declare function resetExtensionDatabaseMigrations(): void;
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Допустимое поле сортировки: имя из латиницы, цифр и подчёркивания и, по
|
|
979
|
+
* желанию, направление через двоеточие (`created_at:desc` — так сортирует
|
|
980
|
+
* реестр пайщиков, репозиторий пользователей разбирает пару сам). Поле уходит
|
|
981
|
+
* в `ORDER BY` строкой, и любой другой символ открывал бы подстановку SQL.
|
|
982
|
+
* Какая именно колонка разрешена, решает репозиторий по своему списку или
|
|
983
|
+
* метаданным сущности (`resolveSortColumn`); здесь отсекается всё, что именем
|
|
984
|
+
* колонки быть не может. Пустая строка — «без сортировки»: её отдаёт таблица
|
|
985
|
+
* со снятой сортировкой, и репозитории берут порядок по умолчанию.
|
|
986
|
+
*/
|
|
987
|
+
declare const SORT_FIELD_PATTERN: RegExp;
|
|
938
988
|
/**
|
|
939
989
|
* Входные параметры для пагинации и сортировки
|
|
940
990
|
*/
|
|
@@ -1060,14 +1110,6 @@ interface PlatformBlockchainSettings {
|
|
|
1060
1110
|
rootSymbol: string;
|
|
1061
1111
|
/** Точность системного токена — знаков после запятой. */
|
|
1062
1112
|
rootPrecision: number;
|
|
1063
|
-
/**
|
|
1064
|
-
* Пауза перед чтением таблиц цепи сразу после успешной мутации, мс.
|
|
1065
|
-
*
|
|
1066
|
-
* На узле-последователе строка появляется в состоянии с задержкой
|
|
1067
|
-
* относительно ответа RPC, и величина этой задержки зависит от узла контура,
|
|
1068
|
-
* а не от расширения.
|
|
1069
|
-
*/
|
|
1070
|
-
postTransactChainReadDelayMs: number;
|
|
1071
1113
|
/**
|
|
1072
1114
|
* Идентификатор цепи контура. Входит в подписываемую транзакцию, поэтому
|
|
1073
1115
|
* подпись, собранная для одной цепи, в другой недействительна — расширение
|
|
@@ -1274,6 +1316,16 @@ declare class DomainToBlockchainUtils {
|
|
|
1274
1316
|
static getEmptyHash(): string;
|
|
1275
1317
|
}
|
|
1276
1318
|
|
|
1319
|
+
/** sha256 текста в UTF-8; пустой текст остаётся пустой строкой. */
|
|
1320
|
+
declare function chainTextDigest(text: string | null | undefined): string;
|
|
1321
|
+
/** Значение из цепи — хеш текста, а не сам текст. */
|
|
1322
|
+
declare function isChainTextDigest(value: string | null | undefined): value is string;
|
|
1323
|
+
/**
|
|
1324
|
+
* Значение поля из цепи для записи в базу: хеш текст в базе не заменяет.
|
|
1325
|
+
* Строки, записанные до выноса текстов, несут сам текст и копируются как раньше.
|
|
1326
|
+
*/
|
|
1327
|
+
declare function resolveChainText(chainValue: string, current: string | null | undefined): string;
|
|
1328
|
+
|
|
1277
1329
|
/**
|
|
1278
1330
|
* Утилиты для работы с ассетами в формате "AMOUNT SYMBOL" (например, "100.0000 RUB")
|
|
1279
1331
|
*/
|
|
@@ -1444,11 +1496,27 @@ declare class DateUtils {
|
|
|
1444
1496
|
static formatDurationHumanizeRu(minutes: number): string;
|
|
1445
1497
|
}
|
|
1446
1498
|
|
|
1499
|
+
/** Источник событий: подписка и отписка (EventEmitter2, EventEmitter). */
|
|
1500
|
+
interface EventSource {
|
|
1501
|
+
on(event: string, listener: (...args: any[]) => void): unknown;
|
|
1502
|
+
off(event: string, listener: (...args: any[]) => void): unknown;
|
|
1503
|
+
}
|
|
1504
|
+
interface EventWait<T> {
|
|
1505
|
+
/** Событие, прошедшее отбор, либо `null` по пределу или отмене. */
|
|
1506
|
+
promise: Promise<T | null>;
|
|
1507
|
+
/** Снять ожидание досрочно (факт уже виден без события). */
|
|
1508
|
+
cancel(): void;
|
|
1509
|
+
}
|
|
1447
1510
|
/**
|
|
1448
|
-
*
|
|
1449
|
-
*
|
|
1511
|
+
* Дождаться события, а не опрашивать базу. Для случаев, когда ответ зависит
|
|
1512
|
+
* от чужого факта — робот совета решил, обратный вызов перевёл сагу: свой
|
|
1513
|
+
* блок транзакция дожидается сама, а чужое действие приходит событием.
|
|
1514
|
+
*
|
|
1515
|
+
* Порядок у вызывающего: сначала `waitForEvent`, потом одно чтение текущего
|
|
1516
|
+
* состояния — если факт уже случился, `cancel()` и ответ сразу; так событие
|
|
1517
|
+
* между чтением и подпиской не теряется. Подписка снимается при любом исходе.
|
|
1450
1518
|
*/
|
|
1451
|
-
declare function
|
|
1519
|
+
declare function waitForEvent<T>(source: EventSource, event: string, match: (payload: T) => boolean, timeoutMs: number): EventWait<T>;
|
|
1452
1520
|
|
|
1453
1521
|
/**
|
|
1454
1522
|
* Форма ответа, из которой берётся номер блока. Описана здесь, а не взята из
|
|
@@ -1528,7 +1596,7 @@ declare class CurrencyValidationUtil {
|
|
|
1528
1596
|
/**
|
|
1529
1597
|
* Форматирует сумму с правильным символом валюты
|
|
1530
1598
|
* @param value Числовое значение
|
|
1531
|
-
* @param precision Количество знаков после запятой (по умолчанию из
|
|
1599
|
+
* @param precision Количество знаков после запятой (по умолчанию из настроек платформы)
|
|
1532
1600
|
* @returns string - отформатированная сумма
|
|
1533
1601
|
*/
|
|
1534
1602
|
static formatAmount(value: number, precision?: number): string;
|
|
@@ -1549,6 +1617,20 @@ declare class CurrencyValidationUtil {
|
|
|
1549
1617
|
*/
|
|
1550
1618
|
declare function sanitizeUserText<T extends string | null | undefined>(value: T): T;
|
|
1551
1619
|
|
|
1620
|
+
/**
|
|
1621
|
+
* Имя поля сортировки приходит от клиента и подставляется в `ORDER BY` строкой:
|
|
1622
|
+
* TypeORM вставляет его в SQL как есть, без параметров и экранирования. Поэтому
|
|
1623
|
+
* произвольную строку туда пускать нельзя. Разрешённый набор берём из
|
|
1624
|
+
* метаданных сущности: колонка, которой нет в таблице, молча заменяется на
|
|
1625
|
+
* умолчание — список не должен падать из-за устаревшей ссылки в клиенте.
|
|
1626
|
+
*
|
|
1627
|
+
* @param repository — репозиторий сущности, по чьим колонкам сортируем.
|
|
1628
|
+
* @param sortBy — имя поля от клиента.
|
|
1629
|
+
* @param fallback — колонка по умолчанию.
|
|
1630
|
+
* @returns Имя существующей колонки сущности.
|
|
1631
|
+
*/
|
|
1632
|
+
declare function resolveSortColumn<T extends ObjectLiteral>(repository: Repository<T>, sortBy: string | undefined, fallback: string): string;
|
|
1633
|
+
|
|
1552
1634
|
/**
|
|
1553
1635
|
* Ошибка API с кодом состояния HTTP.
|
|
1554
1636
|
*
|
|
@@ -1565,6 +1647,21 @@ declare class HttpApiError extends HttpException {
|
|
|
1565
1647
|
constructor(statusCode: HttpStatus, message: string, isOperational?: boolean, stack?: string, subcode?: any);
|
|
1566
1648
|
}
|
|
1567
1649
|
|
|
1650
|
+
/**
|
|
1651
|
+
* Разбор отказа контракта. Контракт пишет причину как `КОД: текст`
|
|
1652
|
+
* (`GATEWAY_OUTCOME_NOT_FOUND: Объект возврата не существует…`); старые
|
|
1653
|
+
* отказы — одним текстом, без кода.
|
|
1654
|
+
*/
|
|
1655
|
+
declare function parseChainAssert(message: string): {
|
|
1656
|
+
code?: string;
|
|
1657
|
+
text: string;
|
|
1658
|
+
};
|
|
1659
|
+
/**
|
|
1660
|
+
* Код отказа контракта — из DomainError, в который отказ уже превращён,
|
|
1661
|
+
* или из сырой ошибки цепи. Отказ без кода — undefined. Сравнивать отказы
|
|
1662
|
+
* контракта — по этому коду, а не по тексту: текст переводится и правится.
|
|
1663
|
+
*/
|
|
1664
|
+
declare function chainErrorCode(error: unknown): string | undefined;
|
|
1568
1665
|
/**
|
|
1569
1666
|
* Пробросить отказ цепи человеку.
|
|
1570
1667
|
*
|
|
@@ -1572,8 +1669,69 @@ declare class HttpApiError extends HttpException {
|
|
|
1572
1669
|
* message: ...`; пайщику нужна причина, а не обёртка виртуальной машины.
|
|
1573
1670
|
* Живёт в каркасе, потому что в цепь ходит не одно расширение: вторая копия
|
|
1574
1671
|
* этой чистки разошлась бы с первой на первом же новом формате ошибки.
|
|
1672
|
+
*
|
|
1673
|
+
* Отказ с кодом (`КОД: текст`) уходит с этим кодом, текст — из словаря,
|
|
1674
|
+
* а без записи в словаре — текст контракта. Отказ без кода — `CHAIN_ASSERT`,
|
|
1675
|
+
* прочий сбой цепи — `CHAIN_ERROR`, текст — параметром `message`.
|
|
1575
1676
|
*/
|
|
1576
1677
|
declare function rethrowChainError(error: unknown): never;
|
|
1577
1678
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1679
|
+
type DomainErrorParams = Record<string, string | number | boolean | null | undefined>;
|
|
1680
|
+
interface Branded {
|
|
1681
|
+
code: string;
|
|
1682
|
+
params: DomainErrorParams;
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Текст отказа на языке текущего запроса. Кода нет в словаре, но есть
|
|
1686
|
+
* исходный текст (`params.message` — так приходит отказ контракта с кодом,
|
|
1687
|
+
* ещё не заведённым в словарь) — показывается он, а не ключ.
|
|
1688
|
+
*/
|
|
1689
|
+
declare function domainErrorMessage(code: string, params?: DomainErrorParams): string;
|
|
1690
|
+
/**
|
|
1691
|
+
* Отказ, который видит пайщик: код + параметры, текст — из словаря.
|
|
1692
|
+
*
|
|
1693
|
+
* Код — `SCREAMING_SNAKE` с префиксом области (`CAPITAL_ISSUE_NOT_FOUND`),
|
|
1694
|
+
* сообщение — по ключу `errors.<КОД>` в словаре ядра или расширения.
|
|
1695
|
+
* `message` переводится при создании на язык текущего запроса (для журнала и
|
|
1696
|
+
* старого кода, читающего `error.message`); ответ клиенту фильтр ошибок
|
|
1697
|
+
* переводит заново на язык запроса и кладёт код в `extensions.code`,
|
|
1698
|
+
* параметры — в `extensions.params`.
|
|
1699
|
+
*
|
|
1700
|
+
* Бросать через фабрики по смыслу отказа:
|
|
1701
|
+
* throw DomainError.notFound('FREE_DECISION_DOCUMENT_NOT_FOUND');
|
|
1702
|
+
* throw DomainError.badRequest('WALLET_AMOUNT_TOO_SMALL', { min: '100,00 RUB' });
|
|
1703
|
+
*/
|
|
1704
|
+
declare class DomainError extends HttpException implements Branded {
|
|
1705
|
+
code: string;
|
|
1706
|
+
params: DomainErrorParams;
|
|
1707
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
1708
|
+
constructor(code: string, params?: DomainErrorParams, status?: HttpStatus);
|
|
1709
|
+
/** Ключ сообщения в словаре. */
|
|
1710
|
+
get messageKey(): string;
|
|
1711
|
+
static badRequest(code: string, params?: DomainErrorParams): DomainError;
|
|
1712
|
+
static unauthorized(code: string, params?: DomainErrorParams): DomainError;
|
|
1713
|
+
static forbidden(code: string, params?: DomainErrorParams): DomainError;
|
|
1714
|
+
static notFound(code: string, params?: DomainErrorParams): DomainError;
|
|
1715
|
+
static conflict(code: string, params?: DomainErrorParams): DomainError;
|
|
1716
|
+
static unprocessable(code: string, params?: DomainErrorParams): DomainError;
|
|
1717
|
+
static tooManyRequests(code: string, params?: DomainErrorParams): DomainError;
|
|
1718
|
+
static internal(code: string, params?: DomainErrorParams): DomainError;
|
|
1719
|
+
static badGateway(code: string, params?: DomainErrorParams): DomainError;
|
|
1720
|
+
static serviceUnavailable(code: string, params?: DomainErrorParams): DomainError;
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* Сообщение для class-validator по ключу словаря. Переводится в момент
|
|
1724
|
+
* проверки — на язык запроса, а не при загрузке модуля:
|
|
1725
|
+
*
|
|
1726
|
+
* @IsNotEmpty({ message: validationMessage('validation.required') })
|
|
1727
|
+
*
|
|
1728
|
+
* В параметры сообщения попадают `property` (имя поля) и `value`.
|
|
1729
|
+
*/
|
|
1730
|
+
declare function validationMessage(key: string, params?: DomainErrorParams): (args: {
|
|
1731
|
+
property: string;
|
|
1732
|
+
value?: unknown;
|
|
1733
|
+
constraints?: unknown[];
|
|
1734
|
+
}) => string;
|
|
1735
|
+
|
|
1736
|
+
export { ActiveUserStatusGuard, AmountFormatterUtils, AssetUtils, AuthRoles, BaseExtensionModule, BucketRegistry, CandidateFilterInputDTO, CandidateOutputDTO, CandidateStatus, CurrencyValidationUtil, CurrentUser, DEFAULT_DOCUMENT_VERSION, DateUtils, DocumentAggregateDTO, DomainError, DomainToBlockchainUtils, EMPTY_HASH, EXTENSION_APP_TERMINATE_EVENT, EXTENSION_REPOSITORY, EXTENSION_SECRET_SET, EXTENSION_SECRET_UNSET, ExpenseProposalStatementGenerateDocumentInputDTO, ExpenseProposalStatementSignedDocumentInputDTO, ExpenseProposalStatementSignedMetaDocumentInputDTO, ExtensionAvailability, ExtensionConfigSuppliedBy, ExtensionDomainEntity, GenerateDocumentInputDTO, GenerateDocumentOptionsInputDTO, GenerateMetaDocumentInputDTO, GeneratedDocumentDTO, GqlJwtAuthGuard, HttpApiError, HttpJwtAuthGuard, IPNProvider, InjectBucket, LOG_EXTENSION_REPOSITORY, LangType, LogExtensionDomainEntity, MetaDocumentInputDTO, ONBOARDING_EXPIRY_DAYS, ONBOARDING_EXPIRY_MS, OptionalCurrentUser, OptionalGqlJwtAuthGuard, PaginationInputDTO, PaginationResult, PaginationUtils, PaymentProvider, PollingProvider, QuantityUtils, ROLES_ANY_STATUS_KEY, ROLES_DENY_SELF_KEY, RolesGuard, SORT_FIELD_PATTERN, SignatureInfoDTO, SignatureInfoInputDTO, SignedDigitalDocumentDTO, SignedDigitalDocumentInputDTO, TransactionDTO, UseBucket, bucketProvidersFor, bucketTokenFor, buildPaginationResult, chainErrorCode, chainTextDigest, checkPaymentAmount, checkPaymentSymbol, computeOnboardingExpiresAt, configureExtensionAuth, configurePlatformSettings, createPaginationResult, domainErrorMessage, extensionDatabaseMigrations, extensionEntities, generateHashFromString, generateRandomHash, generateUniqueHash, getAmountPlusFee, getAppliedBlockNum, hasServerSecret, isChainTextDigest, isExtensionAvailable, mergeSecretConfig, paginationInputToOffset, parseChainAssert, platformSettings, providerSuppliedPaths, redactSecretConfig, registerExtensionDatabaseMigrations, registerExtensionEntities, resetExtensionDatabaseMigrations, resetExtensionEntities, resolveChainText, resolveSortColumn, rethrowChainError, sanitizeUserText, validationMessage, verifySignedDocumentAgainstStoredDraft, waitForEvent };
|
|
1737
|
+
export type { AuthRolesOptions, BucketSource, BucketSpec, DeserializedDescriptionOfExtension, DomainErrorParams, EventSource, EventWait, ExcludeCommonProps, ExtensionAppTerminatePayload, ExtensionAuthOptions, ExtensionConfigFieldPolicy, ExtensionConfigPolicy, ExtensionDatabaseMigrationClass, ExtensionDomainInterface, ExtensionDomainRepository, ExtensionEntityClass, ExtensionSchemaMigrationAfterContext, GeneratedDocumentDomainInterface, GeneratedDocumentDraft, IDesktopConfig, IExtensionSchemaMigration, IRegistryExtension, IResolvedRegistryExtension, LoadGeneratedDocumentByDocHash, LogExtensionDomainInterface, LogExtensionDomainRepository, LogExtensionFilter, LogExtensionPaginationOptions, LogExtensionPaginationResult, PaymentDetails, PlatformBlockchainSettings, PlatformSettings, RegisteredBucket, RequireFields, SignedDocumentMetaCompareMode, SignedDocumentMetaVerification, SignedDocumentToVerify, TransactResultWithResponse };
|
package/dist/index.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ import { Reflector } from '@nestjs/core';
|
|
|
5
5
|
import { Observable } from 'rxjs';
|
|
6
6
|
import { ZodObject } from 'zod';
|
|
7
7
|
import { Cooperative } from 'cooptypes';
|
|
8
|
+
import { MigrationInterface, ObjectLiteral, Repository } from 'typeorm';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Пути внутри объекта, по которым пайщик признаётся «своим» для поля.
|
|
@@ -747,6 +748,15 @@ interface IRegistryExtension {
|
|
|
747
748
|
* расширения, которое своих таблиц не держит, — нормальное состояние.
|
|
748
749
|
*/
|
|
749
750
|
entities?: ReadonlyArray<new (...args: any[]) => any>;
|
|
751
|
+
/**
|
|
752
|
+
* Миграции таблиц расширения — классы миграций TypeORM.
|
|
753
|
+
*
|
|
754
|
+
* Схему базы меняют только миграции: добавил или поменял колонку в сущности
|
|
755
|
+
* из `entities` — положи рядом миграцию (`pnpm schema:generate`). Порядок
|
|
756
|
+
* задаёт метка времени в имени класса, общая лента с миграциями ядра.
|
|
757
|
+
* Не путать с `migrations` ниже — те переводят конфиг расширения.
|
|
758
|
+
*/
|
|
759
|
+
databaseMigrations?: ReadonlyArray<new () => MigrationInterface>;
|
|
750
760
|
/**
|
|
751
761
|
* Миграции схемы конфига расширения — в порядке применения.
|
|
752
762
|
*
|
|
@@ -935,6 +945,46 @@ declare function extensionEntities(): ReadonlyArray<ExtensionEntityClass>;
|
|
|
935
945
|
/** Сбросить состав. Только для тестов, которые поднимают граф модулей заново. */
|
|
936
946
|
declare function resetExtensionEntities(): void;
|
|
937
947
|
|
|
948
|
+
/**
|
|
949
|
+
* Миграции таблиц установленных расширений — то, что контроллер отдаёт TypeORM
|
|
950
|
+
* вместе с миграциями ядра.
|
|
951
|
+
*
|
|
952
|
+
* Схему базы меняют только миграции: `synchronize` выключен, потому что он молча
|
|
953
|
+
* удаляет колонки, которых нет в сущности, и превращает переименование в потерю
|
|
954
|
+
* данных. Таблицы расширения описывает оно само — списком `databaseMigrations`
|
|
955
|
+
* в записи реестра, — и файлы миграций лежат в его каталоге: расширение,
|
|
956
|
+
* вынесенное из монолита, уносит историю своих таблиц с собой.
|
|
957
|
+
*
|
|
958
|
+
* Порядок применения задаёт метка времени в имени класса (так TypeORM сортирует
|
|
959
|
+
* миграции), поэтому миграции ядра и расширений идут одной лентой.
|
|
960
|
+
*
|
|
961
|
+
* Список задаётся один раз, до инициализации подключения, — как и состав
|
|
962
|
+
* сущностей (`registerExtensionEntities`).
|
|
963
|
+
*/
|
|
964
|
+
type ExtensionDatabaseMigrationClass = new () => MigrationInterface;
|
|
965
|
+
/** Объявить миграции таблиц установленных расширений. Вызывает composition root. */
|
|
966
|
+
declare function registerExtensionDatabaseMigrations(list: ReadonlyArray<ExtensionDatabaseMigrationClass>): void;
|
|
967
|
+
/**
|
|
968
|
+
* Прочитать миграции таблиц расширений.
|
|
969
|
+
*
|
|
970
|
+
* До объявления возвращает пустой список: подключение к базе поднимается и в
|
|
971
|
+
* контурах без единого расширения.
|
|
972
|
+
*/
|
|
973
|
+
declare function extensionDatabaseMigrations(): ReadonlyArray<ExtensionDatabaseMigrationClass>;
|
|
974
|
+
/** Сбросить список. Только для тестов, которые поднимают граф модулей заново. */
|
|
975
|
+
declare function resetExtensionDatabaseMigrations(): void;
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Допустимое поле сортировки: имя из латиницы, цифр и подчёркивания и, по
|
|
979
|
+
* желанию, направление через двоеточие (`created_at:desc` — так сортирует
|
|
980
|
+
* реестр пайщиков, репозиторий пользователей разбирает пару сам). Поле уходит
|
|
981
|
+
* в `ORDER BY` строкой, и любой другой символ открывал бы подстановку SQL.
|
|
982
|
+
* Какая именно колонка разрешена, решает репозиторий по своему списку или
|
|
983
|
+
* метаданным сущности (`resolveSortColumn`); здесь отсекается всё, что именем
|
|
984
|
+
* колонки быть не может. Пустая строка — «без сортировки»: её отдаёт таблица
|
|
985
|
+
* со снятой сортировкой, и репозитории берут порядок по умолчанию.
|
|
986
|
+
*/
|
|
987
|
+
declare const SORT_FIELD_PATTERN: RegExp;
|
|
938
988
|
/**
|
|
939
989
|
* Входные параметры для пагинации и сортировки
|
|
940
990
|
*/
|
|
@@ -1060,14 +1110,6 @@ interface PlatformBlockchainSettings {
|
|
|
1060
1110
|
rootSymbol: string;
|
|
1061
1111
|
/** Точность системного токена — знаков после запятой. */
|
|
1062
1112
|
rootPrecision: number;
|
|
1063
|
-
/**
|
|
1064
|
-
* Пауза перед чтением таблиц цепи сразу после успешной мутации, мс.
|
|
1065
|
-
*
|
|
1066
|
-
* На узле-последователе строка появляется в состоянии с задержкой
|
|
1067
|
-
* относительно ответа RPC, и величина этой задержки зависит от узла контура,
|
|
1068
|
-
* а не от расширения.
|
|
1069
|
-
*/
|
|
1070
|
-
postTransactChainReadDelayMs: number;
|
|
1071
1113
|
/**
|
|
1072
1114
|
* Идентификатор цепи контура. Входит в подписываемую транзакцию, поэтому
|
|
1073
1115
|
* подпись, собранная для одной цепи, в другой недействительна — расширение
|
|
@@ -1274,6 +1316,16 @@ declare class DomainToBlockchainUtils {
|
|
|
1274
1316
|
static getEmptyHash(): string;
|
|
1275
1317
|
}
|
|
1276
1318
|
|
|
1319
|
+
/** sha256 текста в UTF-8; пустой текст остаётся пустой строкой. */
|
|
1320
|
+
declare function chainTextDigest(text: string | null | undefined): string;
|
|
1321
|
+
/** Значение из цепи — хеш текста, а не сам текст. */
|
|
1322
|
+
declare function isChainTextDigest(value: string | null | undefined): value is string;
|
|
1323
|
+
/**
|
|
1324
|
+
* Значение поля из цепи для записи в базу: хеш текст в базе не заменяет.
|
|
1325
|
+
* Строки, записанные до выноса текстов, несут сам текст и копируются как раньше.
|
|
1326
|
+
*/
|
|
1327
|
+
declare function resolveChainText(chainValue: string, current: string | null | undefined): string;
|
|
1328
|
+
|
|
1277
1329
|
/**
|
|
1278
1330
|
* Утилиты для работы с ассетами в формате "AMOUNT SYMBOL" (например, "100.0000 RUB")
|
|
1279
1331
|
*/
|
|
@@ -1444,11 +1496,27 @@ declare class DateUtils {
|
|
|
1444
1496
|
static formatDurationHumanizeRu(minutes: number): string;
|
|
1445
1497
|
}
|
|
1446
1498
|
|
|
1499
|
+
/** Источник событий: подписка и отписка (EventEmitter2, EventEmitter). */
|
|
1500
|
+
interface EventSource {
|
|
1501
|
+
on(event: string, listener: (...args: any[]) => void): unknown;
|
|
1502
|
+
off(event: string, listener: (...args: any[]) => void): unknown;
|
|
1503
|
+
}
|
|
1504
|
+
interface EventWait<T> {
|
|
1505
|
+
/** Событие, прошедшее отбор, либо `null` по пределу или отмене. */
|
|
1506
|
+
promise: Promise<T | null>;
|
|
1507
|
+
/** Снять ожидание досрочно (факт уже виден без события). */
|
|
1508
|
+
cancel(): void;
|
|
1509
|
+
}
|
|
1447
1510
|
/**
|
|
1448
|
-
*
|
|
1449
|
-
*
|
|
1511
|
+
* Дождаться события, а не опрашивать базу. Для случаев, когда ответ зависит
|
|
1512
|
+
* от чужого факта — робот совета решил, обратный вызов перевёл сагу: свой
|
|
1513
|
+
* блок транзакция дожидается сама, а чужое действие приходит событием.
|
|
1514
|
+
*
|
|
1515
|
+
* Порядок у вызывающего: сначала `waitForEvent`, потом одно чтение текущего
|
|
1516
|
+
* состояния — если факт уже случился, `cancel()` и ответ сразу; так событие
|
|
1517
|
+
* между чтением и подпиской не теряется. Подписка снимается при любом исходе.
|
|
1450
1518
|
*/
|
|
1451
|
-
declare function
|
|
1519
|
+
declare function waitForEvent<T>(source: EventSource, event: string, match: (payload: T) => boolean, timeoutMs: number): EventWait<T>;
|
|
1452
1520
|
|
|
1453
1521
|
/**
|
|
1454
1522
|
* Форма ответа, из которой берётся номер блока. Описана здесь, а не взята из
|
|
@@ -1528,7 +1596,7 @@ declare class CurrencyValidationUtil {
|
|
|
1528
1596
|
/**
|
|
1529
1597
|
* Форматирует сумму с правильным символом валюты
|
|
1530
1598
|
* @param value Числовое значение
|
|
1531
|
-
* @param precision Количество знаков после запятой (по умолчанию из
|
|
1599
|
+
* @param precision Количество знаков после запятой (по умолчанию из настроек платформы)
|
|
1532
1600
|
* @returns string - отформатированная сумма
|
|
1533
1601
|
*/
|
|
1534
1602
|
static formatAmount(value: number, precision?: number): string;
|
|
@@ -1549,6 +1617,20 @@ declare class CurrencyValidationUtil {
|
|
|
1549
1617
|
*/
|
|
1550
1618
|
declare function sanitizeUserText<T extends string | null | undefined>(value: T): T;
|
|
1551
1619
|
|
|
1620
|
+
/**
|
|
1621
|
+
* Имя поля сортировки приходит от клиента и подставляется в `ORDER BY` строкой:
|
|
1622
|
+
* TypeORM вставляет его в SQL как есть, без параметров и экранирования. Поэтому
|
|
1623
|
+
* произвольную строку туда пускать нельзя. Разрешённый набор берём из
|
|
1624
|
+
* метаданных сущности: колонка, которой нет в таблице, молча заменяется на
|
|
1625
|
+
* умолчание — список не должен падать из-за устаревшей ссылки в клиенте.
|
|
1626
|
+
*
|
|
1627
|
+
* @param repository — репозиторий сущности, по чьим колонкам сортируем.
|
|
1628
|
+
* @param sortBy — имя поля от клиента.
|
|
1629
|
+
* @param fallback — колонка по умолчанию.
|
|
1630
|
+
* @returns Имя существующей колонки сущности.
|
|
1631
|
+
*/
|
|
1632
|
+
declare function resolveSortColumn<T extends ObjectLiteral>(repository: Repository<T>, sortBy: string | undefined, fallback: string): string;
|
|
1633
|
+
|
|
1552
1634
|
/**
|
|
1553
1635
|
* Ошибка API с кодом состояния HTTP.
|
|
1554
1636
|
*
|
|
@@ -1565,6 +1647,21 @@ declare class HttpApiError extends HttpException {
|
|
|
1565
1647
|
constructor(statusCode: HttpStatus, message: string, isOperational?: boolean, stack?: string, subcode?: any);
|
|
1566
1648
|
}
|
|
1567
1649
|
|
|
1650
|
+
/**
|
|
1651
|
+
* Разбор отказа контракта. Контракт пишет причину как `КОД: текст`
|
|
1652
|
+
* (`GATEWAY_OUTCOME_NOT_FOUND: Объект возврата не существует…`); старые
|
|
1653
|
+
* отказы — одним текстом, без кода.
|
|
1654
|
+
*/
|
|
1655
|
+
declare function parseChainAssert(message: string): {
|
|
1656
|
+
code?: string;
|
|
1657
|
+
text: string;
|
|
1658
|
+
};
|
|
1659
|
+
/**
|
|
1660
|
+
* Код отказа контракта — из DomainError, в который отказ уже превращён,
|
|
1661
|
+
* или из сырой ошибки цепи. Отказ без кода — undefined. Сравнивать отказы
|
|
1662
|
+
* контракта — по этому коду, а не по тексту: текст переводится и правится.
|
|
1663
|
+
*/
|
|
1664
|
+
declare function chainErrorCode(error: unknown): string | undefined;
|
|
1568
1665
|
/**
|
|
1569
1666
|
* Пробросить отказ цепи человеку.
|
|
1570
1667
|
*
|
|
@@ -1572,8 +1669,69 @@ declare class HttpApiError extends HttpException {
|
|
|
1572
1669
|
* message: ...`; пайщику нужна причина, а не обёртка виртуальной машины.
|
|
1573
1670
|
* Живёт в каркасе, потому что в цепь ходит не одно расширение: вторая копия
|
|
1574
1671
|
* этой чистки разошлась бы с первой на первом же новом формате ошибки.
|
|
1672
|
+
*
|
|
1673
|
+
* Отказ с кодом (`КОД: текст`) уходит с этим кодом, текст — из словаря,
|
|
1674
|
+
* а без записи в словаре — текст контракта. Отказ без кода — `CHAIN_ASSERT`,
|
|
1675
|
+
* прочий сбой цепи — `CHAIN_ERROR`, текст — параметром `message`.
|
|
1575
1676
|
*/
|
|
1576
1677
|
declare function rethrowChainError(error: unknown): never;
|
|
1577
1678
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1679
|
+
type DomainErrorParams = Record<string, string | number | boolean | null | undefined>;
|
|
1680
|
+
interface Branded {
|
|
1681
|
+
code: string;
|
|
1682
|
+
params: DomainErrorParams;
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Текст отказа на языке текущего запроса. Кода нет в словаре, но есть
|
|
1686
|
+
* исходный текст (`params.message` — так приходит отказ контракта с кодом,
|
|
1687
|
+
* ещё не заведённым в словарь) — показывается он, а не ключ.
|
|
1688
|
+
*/
|
|
1689
|
+
declare function domainErrorMessage(code: string, params?: DomainErrorParams): string;
|
|
1690
|
+
/**
|
|
1691
|
+
* Отказ, который видит пайщик: код + параметры, текст — из словаря.
|
|
1692
|
+
*
|
|
1693
|
+
* Код — `SCREAMING_SNAKE` с префиксом области (`CAPITAL_ISSUE_NOT_FOUND`),
|
|
1694
|
+
* сообщение — по ключу `errors.<КОД>` в словаре ядра или расширения.
|
|
1695
|
+
* `message` переводится при создании на язык текущего запроса (для журнала и
|
|
1696
|
+
* старого кода, читающего `error.message`); ответ клиенту фильтр ошибок
|
|
1697
|
+
* переводит заново на язык запроса и кладёт код в `extensions.code`,
|
|
1698
|
+
* параметры — в `extensions.params`.
|
|
1699
|
+
*
|
|
1700
|
+
* Бросать через фабрики по смыслу отказа:
|
|
1701
|
+
* throw DomainError.notFound('FREE_DECISION_DOCUMENT_NOT_FOUND');
|
|
1702
|
+
* throw DomainError.badRequest('WALLET_AMOUNT_TOO_SMALL', { min: '100,00 RUB' });
|
|
1703
|
+
*/
|
|
1704
|
+
declare class DomainError extends HttpException implements Branded {
|
|
1705
|
+
code: string;
|
|
1706
|
+
params: DomainErrorParams;
|
|
1707
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
1708
|
+
constructor(code: string, params?: DomainErrorParams, status?: HttpStatus);
|
|
1709
|
+
/** Ключ сообщения в словаре. */
|
|
1710
|
+
get messageKey(): string;
|
|
1711
|
+
static badRequest(code: string, params?: DomainErrorParams): DomainError;
|
|
1712
|
+
static unauthorized(code: string, params?: DomainErrorParams): DomainError;
|
|
1713
|
+
static forbidden(code: string, params?: DomainErrorParams): DomainError;
|
|
1714
|
+
static notFound(code: string, params?: DomainErrorParams): DomainError;
|
|
1715
|
+
static conflict(code: string, params?: DomainErrorParams): DomainError;
|
|
1716
|
+
static unprocessable(code: string, params?: DomainErrorParams): DomainError;
|
|
1717
|
+
static tooManyRequests(code: string, params?: DomainErrorParams): DomainError;
|
|
1718
|
+
static internal(code: string, params?: DomainErrorParams): DomainError;
|
|
1719
|
+
static badGateway(code: string, params?: DomainErrorParams): DomainError;
|
|
1720
|
+
static serviceUnavailable(code: string, params?: DomainErrorParams): DomainError;
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* Сообщение для class-validator по ключу словаря. Переводится в момент
|
|
1724
|
+
* проверки — на язык запроса, а не при загрузке модуля:
|
|
1725
|
+
*
|
|
1726
|
+
* @IsNotEmpty({ message: validationMessage('validation.required') })
|
|
1727
|
+
*
|
|
1728
|
+
* В параметры сообщения попадают `property` (имя поля) и `value`.
|
|
1729
|
+
*/
|
|
1730
|
+
declare function validationMessage(key: string, params?: DomainErrorParams): (args: {
|
|
1731
|
+
property: string;
|
|
1732
|
+
value?: unknown;
|
|
1733
|
+
constraints?: unknown[];
|
|
1734
|
+
}) => string;
|
|
1735
|
+
|
|
1736
|
+
export { ActiveUserStatusGuard, AmountFormatterUtils, AssetUtils, AuthRoles, BaseExtensionModule, BucketRegistry, CandidateFilterInputDTO, CandidateOutputDTO, CandidateStatus, CurrencyValidationUtil, CurrentUser, DEFAULT_DOCUMENT_VERSION, DateUtils, DocumentAggregateDTO, DomainError, DomainToBlockchainUtils, EMPTY_HASH, EXTENSION_APP_TERMINATE_EVENT, EXTENSION_REPOSITORY, EXTENSION_SECRET_SET, EXTENSION_SECRET_UNSET, ExpenseProposalStatementGenerateDocumentInputDTO, ExpenseProposalStatementSignedDocumentInputDTO, ExpenseProposalStatementSignedMetaDocumentInputDTO, ExtensionAvailability, ExtensionConfigSuppliedBy, ExtensionDomainEntity, GenerateDocumentInputDTO, GenerateDocumentOptionsInputDTO, GenerateMetaDocumentInputDTO, GeneratedDocumentDTO, GqlJwtAuthGuard, HttpApiError, HttpJwtAuthGuard, IPNProvider, InjectBucket, LOG_EXTENSION_REPOSITORY, LangType, LogExtensionDomainEntity, MetaDocumentInputDTO, ONBOARDING_EXPIRY_DAYS, ONBOARDING_EXPIRY_MS, OptionalCurrentUser, OptionalGqlJwtAuthGuard, PaginationInputDTO, PaginationResult, PaginationUtils, PaymentProvider, PollingProvider, QuantityUtils, ROLES_ANY_STATUS_KEY, ROLES_DENY_SELF_KEY, RolesGuard, SORT_FIELD_PATTERN, SignatureInfoDTO, SignatureInfoInputDTO, SignedDigitalDocumentDTO, SignedDigitalDocumentInputDTO, TransactionDTO, UseBucket, bucketProvidersFor, bucketTokenFor, buildPaginationResult, chainErrorCode, chainTextDigest, checkPaymentAmount, checkPaymentSymbol, computeOnboardingExpiresAt, configureExtensionAuth, configurePlatformSettings, createPaginationResult, domainErrorMessage, extensionDatabaseMigrations, extensionEntities, generateHashFromString, generateRandomHash, generateUniqueHash, getAmountPlusFee, getAppliedBlockNum, hasServerSecret, isChainTextDigest, isExtensionAvailable, mergeSecretConfig, paginationInputToOffset, parseChainAssert, platformSettings, providerSuppliedPaths, redactSecretConfig, registerExtensionDatabaseMigrations, registerExtensionEntities, resetExtensionDatabaseMigrations, resetExtensionEntities, resolveChainText, resolveSortColumn, rethrowChainError, sanitizeUserText, validationMessage, verifySignedDocumentAgainstStoredDraft, waitForEvent };
|
|
1737
|
+
export type { AuthRolesOptions, BucketSource, BucketSpec, DeserializedDescriptionOfExtension, DomainErrorParams, EventSource, EventWait, ExcludeCommonProps, ExtensionAppTerminatePayload, ExtensionAuthOptions, ExtensionConfigFieldPolicy, ExtensionConfigPolicy, ExtensionDatabaseMigrationClass, ExtensionDomainInterface, ExtensionDomainRepository, ExtensionEntityClass, ExtensionSchemaMigrationAfterContext, GeneratedDocumentDomainInterface, GeneratedDocumentDraft, IDesktopConfig, IExtensionSchemaMigration, IRegistryExtension, IResolvedRegistryExtension, LoadGeneratedDocumentByDocHash, LogExtensionDomainInterface, LogExtensionDomainRepository, LogExtensionFilter, LogExtensionPaginationOptions, LogExtensionPaginationResult, PaymentDetails, PlatformBlockchainSettings, PlatformSettings, RegisteredBucket, RequireFields, SignedDocumentMetaCompareMode, SignedDocumentMetaVerification, SignedDocumentToVerify, TransactResultWithResponse };
|