@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.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const common = require('@nestjs/common');
|
|
4
4
|
const graphql = require('@nestjs/graphql');
|
|
5
|
+
const server = require('@coopenomics/i18n/server');
|
|
5
6
|
const core = require('@nestjs/core');
|
|
6
7
|
const passport = require('@nestjs/passport');
|
|
7
8
|
const node_crypto = require('node:crypto');
|
|
@@ -12,16 +13,160 @@ const graphqlTypeJson = require('graphql-type-json');
|
|
|
12
13
|
const sdk = require('@coopenomics/sdk');
|
|
13
14
|
const antelope = require('@wharfkit/antelope');
|
|
14
15
|
const moment = require('moment');
|
|
16
|
+
const crypto = require('crypto');
|
|
15
17
|
const moment$1 = require('moment-timezone');
|
|
16
18
|
require('moment/locale/ru');
|
|
17
|
-
const crypto = require('crypto');
|
|
18
19
|
const cooptypes = require('cooptypes');
|
|
19
20
|
|
|
20
21
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
21
22
|
|
|
22
23
|
const moment__default = /*#__PURE__*/_interopDefaultCompat(moment);
|
|
23
|
-
const moment__default$1 = /*#__PURE__*/_interopDefaultCompat(moment$1);
|
|
24
24
|
const crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
|
|
25
|
+
const moment__default$1 = /*#__PURE__*/_interopDefaultCompat(moment$1);
|
|
26
|
+
|
|
27
|
+
const DOMAIN_ERROR = Symbol.for("@coopenomics/extension-kit/DomainError");
|
|
28
|
+
function domainErrorMessage(code, params = {}) {
|
|
29
|
+
const key = `errors.${code}`;
|
|
30
|
+
if (!server.te(key) && typeof params.message === "string")
|
|
31
|
+
return params.message;
|
|
32
|
+
return server.t(key, params);
|
|
33
|
+
}
|
|
34
|
+
function body(code, params, status) {
|
|
35
|
+
return { statusCode: status, code, params, message: domainErrorMessage(code, params) };
|
|
36
|
+
}
|
|
37
|
+
function brand(target, code, params) {
|
|
38
|
+
target.code = code;
|
|
39
|
+
target.params = params;
|
|
40
|
+
target[DOMAIN_ERROR] = true;
|
|
41
|
+
target.name = "DomainError";
|
|
42
|
+
}
|
|
43
|
+
class DomainError extends common.HttpException {
|
|
44
|
+
static [Symbol.hasInstance](value) {
|
|
45
|
+
return !!value && value[DOMAIN_ERROR] === true;
|
|
46
|
+
}
|
|
47
|
+
constructor(code, params = {}, status = common.HttpStatus.BAD_REQUEST) {
|
|
48
|
+
super(body(code, params, status), status);
|
|
49
|
+
brand(this, code, params);
|
|
50
|
+
}
|
|
51
|
+
/** Ключ сообщения в словаре. */
|
|
52
|
+
get messageKey() {
|
|
53
|
+
return `errors.${this.code}`;
|
|
54
|
+
}
|
|
55
|
+
static badRequest(code, params = {}) {
|
|
56
|
+
return new DomainBadRequest(code, params);
|
|
57
|
+
}
|
|
58
|
+
static unauthorized(code, params = {}) {
|
|
59
|
+
return new DomainUnauthorized(code, params);
|
|
60
|
+
}
|
|
61
|
+
static forbidden(code, params = {}) {
|
|
62
|
+
return new DomainForbidden(code, params);
|
|
63
|
+
}
|
|
64
|
+
static notFound(code, params = {}) {
|
|
65
|
+
return new DomainNotFound(code, params);
|
|
66
|
+
}
|
|
67
|
+
static conflict(code, params = {}) {
|
|
68
|
+
return new DomainConflict(code, params);
|
|
69
|
+
}
|
|
70
|
+
static unprocessable(code, params = {}) {
|
|
71
|
+
return new DomainUnprocessable(code, params);
|
|
72
|
+
}
|
|
73
|
+
static tooManyRequests(code, params = {}) {
|
|
74
|
+
return new DomainError(code, params, common.HttpStatus.TOO_MANY_REQUESTS);
|
|
75
|
+
}
|
|
76
|
+
static internal(code, params = {}) {
|
|
77
|
+
return new DomainInternal(code, params);
|
|
78
|
+
}
|
|
79
|
+
static badGateway(code, params = {}) {
|
|
80
|
+
return new DomainBadGateway(code, params);
|
|
81
|
+
}
|
|
82
|
+
static serviceUnavailable(code, params = {}) {
|
|
83
|
+
return new DomainServiceUnavailable(code, params);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
class DomainBadGateway extends common.BadGatewayException {
|
|
87
|
+
constructor(code, params) {
|
|
88
|
+
super(body(code, params, common.HttpStatus.BAD_GATEWAY));
|
|
89
|
+
brand(this, code, params);
|
|
90
|
+
}
|
|
91
|
+
get messageKey() {
|
|
92
|
+
return `errors.${this.code}`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
class DomainServiceUnavailable extends common.ServiceUnavailableException {
|
|
96
|
+
constructor(code, params) {
|
|
97
|
+
super(body(code, params, common.HttpStatus.SERVICE_UNAVAILABLE));
|
|
98
|
+
brand(this, code, params);
|
|
99
|
+
}
|
|
100
|
+
get messageKey() {
|
|
101
|
+
return `errors.${this.code}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
class DomainBadRequest extends common.BadRequestException {
|
|
105
|
+
constructor(code, params) {
|
|
106
|
+
super(body(code, params, common.HttpStatus.BAD_REQUEST));
|
|
107
|
+
brand(this, code, params);
|
|
108
|
+
}
|
|
109
|
+
get messageKey() {
|
|
110
|
+
return `errors.${this.code}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
class DomainUnauthorized extends common.UnauthorizedException {
|
|
114
|
+
constructor(code, params) {
|
|
115
|
+
super(body(code, params, common.HttpStatus.UNAUTHORIZED));
|
|
116
|
+
brand(this, code, params);
|
|
117
|
+
}
|
|
118
|
+
get messageKey() {
|
|
119
|
+
return `errors.${this.code}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
class DomainForbidden extends common.ForbiddenException {
|
|
123
|
+
constructor(code, params) {
|
|
124
|
+
super(body(code, params, common.HttpStatus.FORBIDDEN));
|
|
125
|
+
brand(this, code, params);
|
|
126
|
+
}
|
|
127
|
+
get messageKey() {
|
|
128
|
+
return `errors.${this.code}`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
class DomainNotFound extends common.NotFoundException {
|
|
132
|
+
constructor(code, params) {
|
|
133
|
+
super(body(code, params, common.HttpStatus.NOT_FOUND));
|
|
134
|
+
brand(this, code, params);
|
|
135
|
+
}
|
|
136
|
+
get messageKey() {
|
|
137
|
+
return `errors.${this.code}`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
class DomainConflict extends common.ConflictException {
|
|
141
|
+
constructor(code, params) {
|
|
142
|
+
super(body(code, params, common.HttpStatus.CONFLICT));
|
|
143
|
+
brand(this, code, params);
|
|
144
|
+
}
|
|
145
|
+
get messageKey() {
|
|
146
|
+
return `errors.${this.code}`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
class DomainUnprocessable extends common.UnprocessableEntityException {
|
|
150
|
+
constructor(code, params) {
|
|
151
|
+
super(body(code, params, common.HttpStatus.UNPROCESSABLE_ENTITY));
|
|
152
|
+
brand(this, code, params);
|
|
153
|
+
}
|
|
154
|
+
get messageKey() {
|
|
155
|
+
return `errors.${this.code}`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
class DomainInternal extends common.InternalServerErrorException {
|
|
159
|
+
constructor(code, params) {
|
|
160
|
+
super(body(code, params, common.HttpStatus.INTERNAL_SERVER_ERROR));
|
|
161
|
+
brand(this, code, params);
|
|
162
|
+
}
|
|
163
|
+
get messageKey() {
|
|
164
|
+
return `errors.${this.code}`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function validationMessage(key, params = {}) {
|
|
168
|
+
return (args) => server.t(key, { property: args.property, value: String(args.value ?? ""), ...params });
|
|
169
|
+
}
|
|
25
170
|
|
|
26
171
|
const ROLES_DENY_SELF_KEY = "roles_deny_self";
|
|
27
172
|
const ROLES_ANY_STATUS_KEY = "roles_any_status";
|
|
@@ -39,7 +184,7 @@ const CurrentUser = common.createParamDecorator((data, context) => {
|
|
|
39
184
|
const ctx = graphql.GqlExecutionContext.create(context);
|
|
40
185
|
const request = ctx.getContext().req;
|
|
41
186
|
if (!request?.user) {
|
|
42
|
-
throw
|
|
187
|
+
throw DomainError.unauthorized("KIT_USER_NOT_AUTHORIZED");
|
|
43
188
|
}
|
|
44
189
|
return request?.user;
|
|
45
190
|
});
|
|
@@ -122,7 +267,7 @@ exports.OptionalGqlJwtAuthGuard = class OptionalGqlJwtAuthGuard extends passport
|
|
|
122
267
|
if (err instanceof Error) {
|
|
123
268
|
throw err;
|
|
124
269
|
}
|
|
125
|
-
throw
|
|
270
|
+
throw DomainError.unauthorized("KIT_SESSION_ENDED");
|
|
126
271
|
}
|
|
127
272
|
};
|
|
128
273
|
exports.OptionalGqlJwtAuthGuard = __decorateClass$g([
|
|
@@ -172,11 +317,11 @@ exports.RolesGuard = class RolesGuard {
|
|
|
172
317
|
if (allowedRoles.includes(user.role)) {
|
|
173
318
|
const anyStatus = this.reflector.get(ROLES_ANY_STATUS_KEY, context.getHandler()) === true;
|
|
174
319
|
if (user.role === PARTICIPANT_ROLE && !anyStatus && user.status !== ACTIVE_USER_STATUS) {
|
|
175
|
-
throw
|
|
320
|
+
throw DomainError.forbidden("KIT_MEMBERS_ONLY");
|
|
176
321
|
}
|
|
177
322
|
return true;
|
|
178
323
|
}
|
|
179
|
-
throw
|
|
324
|
+
throw DomainError.unauthorized("KIT_INSUFFICIENT_RIGHTS");
|
|
180
325
|
}
|
|
181
326
|
};
|
|
182
327
|
exports.RolesGuard = __decorateClass$g([
|
|
@@ -192,12 +337,10 @@ exports.ActiveUserStatusGuard = class ActiveUserStatusGuard {
|
|
|
192
337
|
}
|
|
193
338
|
const user = request.user;
|
|
194
339
|
if (!user?.status) {
|
|
195
|
-
throw
|
|
340
|
+
throw DomainError.forbidden("KIT_AUTHORIZED_USER_REQUIRED");
|
|
196
341
|
}
|
|
197
342
|
if (user.status !== ACTIVE_USER_STATUS) {
|
|
198
|
-
throw
|
|
199
|
-
"\u0414\u043E\u0441\u0442\u0443\u043F \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u043F\u0430\u0439\u0449\u0438\u043A\u043E\u0432 \u0432 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \xABactive\xBB"
|
|
200
|
-
);
|
|
343
|
+
throw DomainError.forbidden("KIT_ACTIVE_MEMBERS_ONLY");
|
|
201
344
|
}
|
|
202
345
|
return true;
|
|
203
346
|
}
|
|
@@ -262,6 +405,7 @@ const BucketRegistry = {
|
|
|
262
405
|
const existing = REGISTERED.get(cls);
|
|
263
406
|
if (existing && existing.name !== spec.name) {
|
|
264
407
|
throw new Error(
|
|
408
|
+
// i18n-ignore: ошибка регистрации бакета при старте, до пайщика не доходит
|
|
265
409
|
`BucketRegistry: \u043A\u043B\u0430\u0441\u0441 ${cls.name} \u0443\u0436\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043E\u0432\u0430\u043D \u043F\u043E\u0434 \u0431\u0430\u043A\u0435\u0442\u043E\u043C '${existing.name}', \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u0430\u044F \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u043F\u043E\u0434 '${spec.name}' \u0437\u0430\u043F\u0440\u0435\u0449\u0435\u043D\u0430`
|
|
266
410
|
);
|
|
267
411
|
}
|
|
@@ -298,6 +442,7 @@ function bucketProvidersFor(fileStoragePortToken, consumers) {
|
|
|
298
442
|
const spec = BucketRegistry.get(cls);
|
|
299
443
|
if (!spec) {
|
|
300
444
|
throw new Error(
|
|
445
|
+
// i18n-ignore: ошибка объявления хранилища при старте, до пайщика не доходит
|
|
301
446
|
`bucketProvidersFor: \u043A\u043B\u0430\u0441\u0441 ${cls.name} \u043D\u0435 \u043F\u043E\u043C\u0435\u0447\u0435\u043D @UseBucket \u2014 \u043E\u0431\u044A\u044F\u0432\u0438\u0442\u0435 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0435 \u0440\u044F\u0434\u043E\u043C \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043E\u043C`
|
|
302
447
|
);
|
|
303
448
|
}
|
|
@@ -655,7 +800,7 @@ __decorateClass$a([
|
|
|
655
800
|
graphql.Field(() => String, { description: "\u0421\u0440\u043E\u043A \u0438\u0441\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F (\xAB\u0432 \u0441\u0440\u043E\u043A \u0434\u043E\xBB), \u0444\u043E\u0440\u043C\u0430\u0442 DD.MM.YYYY" }),
|
|
656
801
|
classValidator.IsString(),
|
|
657
802
|
classValidator.Matches(/^\d{2}\.\d{2}\.\d{4}$/, {
|
|
658
|
-
message: "
|
|
803
|
+
message: validationMessage("kit.expenseStatement.dueDateFormat")
|
|
659
804
|
})
|
|
660
805
|
], ExpenseProposalHeaderInputDTO.prototype, "deadline", 2);
|
|
661
806
|
__decorateClass$a([
|
|
@@ -882,6 +1027,7 @@ let entities;
|
|
|
882
1027
|
function registerExtensionEntities(list) {
|
|
883
1028
|
if (entities) {
|
|
884
1029
|
throw new Error(
|
|
1030
|
+
// i18n-ignore: ошибка сборки приложения при старте, до пайщика не доходит
|
|
885
1031
|
"\u0421\u043E\u0441\u0442\u0430\u0432 \u0442\u0430\u0431\u043B\u0438\u0446 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0439 \u0443\u0436\u0435 \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D: registerExtensionEntities() \u0432\u044B\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u043E\u0434\u0438\u043D \u0440\u0430\u0437 \u043F\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435"
|
|
886
1032
|
);
|
|
887
1033
|
}
|
|
@@ -894,6 +1040,23 @@ function resetExtensionEntities() {
|
|
|
894
1040
|
entities = void 0;
|
|
895
1041
|
}
|
|
896
1042
|
|
|
1043
|
+
let migrations;
|
|
1044
|
+
function registerExtensionDatabaseMigrations(list) {
|
|
1045
|
+
if (migrations) {
|
|
1046
|
+
throw new Error(
|
|
1047
|
+
// i18n-ignore: ошибка сборки composition root для разработчика, до пайщика не доходит
|
|
1048
|
+
"\u041C\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0442\u0430\u0431\u043B\u0438\u0446 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0439 \u0443\u0436\u0435 \u043E\u0431\u044A\u044F\u0432\u043B\u0435\u043D\u044B: registerExtensionDatabaseMigrations() \u0432\u044B\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F \u043E\u0434\u0438\u043D \u0440\u0430\u0437 \u043F\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435"
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
migrations = [...list];
|
|
1052
|
+
}
|
|
1053
|
+
function extensionDatabaseMigrations() {
|
|
1054
|
+
return migrations ?? [];
|
|
1055
|
+
}
|
|
1056
|
+
function resetExtensionDatabaseMigrations() {
|
|
1057
|
+
migrations = void 0;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
897
1060
|
var __defProp$7 = Object.defineProperty;
|
|
898
1061
|
var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
|
|
899
1062
|
var __decorateClass$7 = (decorators, target, key, kind) => {
|
|
@@ -905,6 +1068,7 @@ var __decorateClass$7 = (decorators, target, key, kind) => {
|
|
|
905
1068
|
__defProp$7(target, key, result);
|
|
906
1069
|
return result;
|
|
907
1070
|
};
|
|
1071
|
+
const SORT_FIELD_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*(:(asc|desc))?)?$/i;
|
|
908
1072
|
exports.PaginationInputDTO = class PaginationInputDTO {
|
|
909
1073
|
};
|
|
910
1074
|
__decorateClass$7([
|
|
@@ -914,7 +1078,9 @@ __decorateClass$7([
|
|
|
914
1078
|
graphql.Field(() => graphql.Int, { description: "\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u043D\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435", defaultValue: 10 })
|
|
915
1079
|
], exports.PaginationInputDTO.prototype, "limit", 2);
|
|
916
1080
|
__decorateClass$7([
|
|
917
|
-
graphql.Field(() => String, { nullable: true, description: '\u041A\u043B\u044E\u0447 \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0438 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, "name")' })
|
|
1081
|
+
graphql.Field(() => String, { nullable: true, description: '\u041A\u043B\u044E\u0447 \u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u043A\u0438 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, "name")' }),
|
|
1082
|
+
classValidator.IsOptional(),
|
|
1083
|
+
classValidator.Matches(SORT_FIELD_PATTERN, { message: validationMessage("kit.pagination.invalidSortField") })
|
|
918
1084
|
], exports.PaginationInputDTO.prototype, "sortBy", 2);
|
|
919
1085
|
__decorateClass$7([
|
|
920
1086
|
graphql.Field(() => String, {
|
|
@@ -988,13 +1154,16 @@ class PaginationUtils {
|
|
|
988
1154
|
static validatePaginationOptions(options) {
|
|
989
1155
|
const { page = 1, limit = 10, sortBy, sortOrder = "ASC" } = options;
|
|
990
1156
|
if (page < 1) {
|
|
991
|
-
throw
|
|
1157
|
+
throw DomainError.internal("KIT_PAGE_NUMBER_INVALID");
|
|
992
1158
|
}
|
|
993
1159
|
if (limit < 1 || limit > 1e3) {
|
|
994
|
-
throw
|
|
1160
|
+
throw DomainError.internal("KIT_PAGE_LIMIT_INVALID");
|
|
995
1161
|
}
|
|
996
1162
|
if (sortOrder !== "ASC" && sortOrder !== "DESC") {
|
|
997
|
-
throw
|
|
1163
|
+
throw DomainError.internal("KIT_SORT_ORDER_INVALID");
|
|
1164
|
+
}
|
|
1165
|
+
if (sortBy !== void 0 && sortBy !== null && !SORT_FIELD_PATTERN.test(sortBy)) {
|
|
1166
|
+
throw DomainError.internal("KIT_SORT_FIELD_INVALID");
|
|
998
1167
|
}
|
|
999
1168
|
return {
|
|
1000
1169
|
page,
|
|
@@ -1124,6 +1293,7 @@ function configurePlatformSettings(value) {
|
|
|
1124
1293
|
function platformSettings() {
|
|
1125
1294
|
if (!settings) {
|
|
1126
1295
|
throw new Error(
|
|
1296
|
+
// i18n-ignore: ошибка сборки приложения при старте, до пайщика не доходит
|
|
1127
1297
|
"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u043A\u043E\u043D\u0442\u0443\u0440\u0430 \u043D\u0435 \u0437\u0430\u0434\u0430\u043D\u044B: composition root \u043E\u0431\u044F\u0437\u0430\u043D \u0432\u044B\u0437\u0432\u0430\u0442\u044C configurePlatformSettings() \u043F\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435"
|
|
1128
1298
|
);
|
|
1129
1299
|
}
|
|
@@ -1341,19 +1511,6 @@ exports.DocumentAggregateDTO = __decorateClass$1([
|
|
|
1341
1511
|
graphql.ObjectType("DocumentAggregate")
|
|
1342
1512
|
], exports.DocumentAggregateDTO);
|
|
1343
1513
|
|
|
1344
|
-
class HttpApiError extends common.HttpException {
|
|
1345
|
-
constructor(statusCode, message, isOperational = true, stack, subcode) {
|
|
1346
|
-
super(message, statusCode);
|
|
1347
|
-
this.isOperational = isOperational;
|
|
1348
|
-
this.subcode = subcode;
|
|
1349
|
-
if (stack) {
|
|
1350
|
-
this.stack = stack;
|
|
1351
|
-
} else {
|
|
1352
|
-
Error.captureStackTrace(this, this.constructor);
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
1514
|
class CurrencyValidationUtil {
|
|
1358
1515
|
/**
|
|
1359
1516
|
* Проверяет, что сумма содержит правильный символ валюты
|
|
@@ -1373,10 +1530,10 @@ class CurrencyValidationUtil {
|
|
|
1373
1530
|
* @param fieldName Название поля для сообщения об ошибке (по умолчанию "сумма")
|
|
1374
1531
|
* @throws Error если символ валюты неправильный
|
|
1375
1532
|
*/
|
|
1376
|
-
static validateCurrencySymbol(amount, fieldName = "
|
|
1533
|
+
static validateCurrencySymbol(amount, fieldName = server.t("kit.currency.defaultFieldName")) {
|
|
1377
1534
|
if (!this.hasValidCurrencySymbol(amount)) {
|
|
1378
1535
|
const expectedSymbol = platformSettings().blockchain.rootGovernSymbol;
|
|
1379
|
-
throw
|
|
1536
|
+
throw DomainError.internal("KIT_CURRENCY_SYMBOL_INVALID", { fieldName, expectedSymbol });
|
|
1380
1537
|
}
|
|
1381
1538
|
}
|
|
1382
1539
|
/**
|
|
@@ -1407,12 +1564,13 @@ class CurrencyValidationUtil {
|
|
|
1407
1564
|
/**
|
|
1408
1565
|
* Форматирует сумму с правильным символом валюты
|
|
1409
1566
|
* @param value Числовое значение
|
|
1410
|
-
* @param precision Количество знаков после запятой (по умолчанию из
|
|
1567
|
+
* @param precision Количество знаков после запятой (по умолчанию из настроек платформы)
|
|
1411
1568
|
* @returns string - отформатированная сумма
|
|
1412
1569
|
*/
|
|
1413
1570
|
static formatAmount(value, precision) {
|
|
1414
|
-
const
|
|
1415
|
-
const
|
|
1571
|
+
const { rootGovernPrecision, rootGovernSymbol } = platformSettings().blockchain;
|
|
1572
|
+
const actualPrecision = precision ?? rootGovernPrecision;
|
|
1573
|
+
const symbol = rootGovernSymbol;
|
|
1416
1574
|
return `${value.toFixed(actualPrecision)} ${symbol}`;
|
|
1417
1575
|
}
|
|
1418
1576
|
}
|
|
@@ -1420,18 +1578,12 @@ class CurrencyValidationUtil {
|
|
|
1420
1578
|
async function verifySignedDocumentAgainstStoredDraft(loadGeneratedByDocHash, signed, metaVerifications) {
|
|
1421
1579
|
const generated = await loadGeneratedByDocHash(signed.doc_hash);
|
|
1422
1580
|
if (!generated) {
|
|
1423
|
-
throw
|
|
1424
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1425
|
-
`\u0421\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u0441 \u0445\u0435\u0448\u0435\u043C ${signed.doc_hash} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442.`
|
|
1426
|
-
);
|
|
1581
|
+
throw DomainError.badRequest("KIT_GENERATED_DOCUMENT_NOT_FOUND", { docHash: signed.doc_hash });
|
|
1427
1582
|
}
|
|
1428
1583
|
const comparison = await sdk.Classes.Document.compareDocuments(signed, generated);
|
|
1429
1584
|
if (!comparison.isValid) {
|
|
1430
|
-
const differences = Object.entries(comparison.differences).map(([field, values]) =>
|
|
1431
|
-
throw
|
|
1432
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1433
|
-
`\u0421\u0432\u0435\u0440\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u0430\u043D\u043D\u043E\u0433\u043E \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 \u0441 \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A\u043E\u043C \u043D\u0435 \u043F\u0440\u043E\u0448\u043B\u0430: ${differences}. \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u0430 \u043F\u043E\u0434\u043C\u0435\u043D\u0430 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430.`
|
|
1434
|
-
);
|
|
1585
|
+
const differences = Object.entries(comparison.differences).map(([field, values]) => server.t("kit.documentVerification.fieldDifference", { field, expected: values.expected, actual: values.actual })).join("; ");
|
|
1586
|
+
throw DomainError.badRequest("KIT_DOCUMENT_DRAFT_MISMATCH", { differences });
|
|
1435
1587
|
}
|
|
1436
1588
|
if (!metaVerifications || metaVerifications.length === 0) {
|
|
1437
1589
|
return;
|
|
@@ -1441,10 +1593,7 @@ async function verifySignedDocumentAgainstStoredDraft(loadGeneratedByDocHash, si
|
|
|
1441
1593
|
const raw = meta[field];
|
|
1442
1594
|
const actualStr = typeof raw === "string" ? raw.trim() : raw !== void 0 && raw !== null ? String(raw).trim() : "";
|
|
1443
1595
|
if (!actualStr) {
|
|
1444
|
-
throw
|
|
1445
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1446
|
-
`\u0412 \u043C\u0435\u0442\u0430\u0434\u0430\u043D\u043D\u044B\u0445 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043F\u043E\u043B\u0435 \xAB${field}\xBB, \u0442\u0440\u0435\u0431\u0443\u0435\u043C\u043E\u0435 \u0434\u043B\u044F \u0441\u0432\u0435\u0440\u043A\u0438.`
|
|
1447
|
-
);
|
|
1596
|
+
throw DomainError.badRequest("KIT_DOCUMENT_META_FIELD_MISSING", { field });
|
|
1448
1597
|
}
|
|
1449
1598
|
const expectedTrimmed = expected.trim();
|
|
1450
1599
|
switch (mode) {
|
|
@@ -1452,39 +1601,27 @@ async function verifySignedDocumentAgainstStoredDraft(loadGeneratedByDocHash, si
|
|
|
1452
1601
|
const parsedExpected = CurrencyValidationUtil.extractAmountValue(expectedTrimmed);
|
|
1453
1602
|
const parsedActual = CurrencyValidationUtil.extractAmountValue(actualStr);
|
|
1454
1603
|
if (Number.isNaN(parsedExpected) || Number.isNaN(parsedActual)) {
|
|
1455
|
-
throw
|
|
1456
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1457
|
-
`\u041D\u0435\u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D\u044B\u0439 \u0444\u043E\u0440\u043C\u0430\u0442 \u0441\u0443\u043C\u043C\u044B \u0432 \u043F\u043E\u043B\u0435 \xAB${field}\xBB \u0438\u043B\u0438 \u0432 \u043E\u0436\u0438\u0434\u0430\u0435\u043C\u043E\u043C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0438.`
|
|
1458
|
-
);
|
|
1604
|
+
throw DomainError.badRequest("KIT_DOCUMENT_AMOUNT_FORMAT_INVALID", { field });
|
|
1459
1605
|
}
|
|
1460
1606
|
if (CurrencyValidationUtil.formatAmount(parsedExpected) !== CurrencyValidationUtil.formatAmount(parsedActual)) {
|
|
1461
|
-
throw
|
|
1462
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1463
|
-
`\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u044F \xAB${field}\xBB \u0432 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0435 (${actualStr}) \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442 \u0441 \u043E\u0436\u0438\u0434\u0430\u0435\u043C\u044B\u043C (${expectedTrimmed}). \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u0430 \u043F\u043E\u0434\u043C\u0435\u043D\u0430 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430.`
|
|
1464
|
-
);
|
|
1607
|
+
throw DomainError.badRequest("KIT_DOCUMENT_FIELD_MISMATCH", { field, actual: actualStr, expected: expectedTrimmed });
|
|
1465
1608
|
}
|
|
1466
1609
|
break;
|
|
1467
1610
|
}
|
|
1468
1611
|
case "string_trim": {
|
|
1469
1612
|
if (actualStr !== expectedTrimmed) {
|
|
1470
|
-
throw
|
|
1471
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1472
|
-
`\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u044F \xAB${field}\xBB \u0432 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0435 (${actualStr}) \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442 \u0441 \u043E\u0436\u0438\u0434\u0430\u0435\u043C\u044B\u043C (${expectedTrimmed}). \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u0430 \u043F\u043E\u0434\u043C\u0435\u043D\u0430 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430.`
|
|
1473
|
-
);
|
|
1613
|
+
throw DomainError.badRequest("KIT_DOCUMENT_FIELD_MISMATCH", { field, actual: actualStr, expected: expectedTrimmed });
|
|
1474
1614
|
}
|
|
1475
1615
|
break;
|
|
1476
1616
|
}
|
|
1477
1617
|
case "hex_case_insensitive": {
|
|
1478
1618
|
if (actualStr.toLowerCase() !== expectedTrimmed.toLowerCase()) {
|
|
1479
|
-
throw
|
|
1480
|
-
common.HttpStatus.BAD_REQUEST,
|
|
1481
|
-
`\u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u044F \xAB${field}\xBB \u0432 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0435 (${actualStr}) \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442 \u0441 \u043E\u0436\u0438\u0434\u0430\u0435\u043C\u044B\u043C (${expectedTrimmed}). \u0412\u043E\u0437\u043C\u043E\u0436\u043D\u0430 \u043F\u043E\u0434\u043C\u0435\u043D\u0430 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430.`
|
|
1482
|
-
);
|
|
1619
|
+
throw DomainError.badRequest("KIT_DOCUMENT_FIELD_MISMATCH", { field, actual: actualStr, expected: expectedTrimmed });
|
|
1483
1620
|
}
|
|
1484
1621
|
break;
|
|
1485
1622
|
}
|
|
1486
1623
|
default:
|
|
1487
|
-
throw
|
|
1624
|
+
throw DomainError.internal("KIT_DOCUMENT_COMPARE_MODE_UNKNOWN", { mode: String(mode) });
|
|
1488
1625
|
}
|
|
1489
1626
|
}
|
|
1490
1627
|
}
|
|
@@ -1541,12 +1678,12 @@ exports.DomainToBlockchainUtils = class DomainToBlockchainUtils {
|
|
|
1541
1678
|
formatQuantityWithPrecision(quantity) {
|
|
1542
1679
|
const parts = quantity.split(" ");
|
|
1543
1680
|
if (parts.length !== 2) {
|
|
1544
|
-
throw
|
|
1681
|
+
throw DomainError.internal("KIT_QUANTITY_FORMAT_INVALID", { quantity });
|
|
1545
1682
|
}
|
|
1546
1683
|
const [amount, symbol] = parts;
|
|
1547
1684
|
const numericAmount = parseFloat(amount);
|
|
1548
1685
|
if (isNaN(numericAmount)) {
|
|
1549
|
-
throw
|
|
1686
|
+
throw DomainError.internal("KIT_QUANTITY_AMOUNT_INVALID", { amount });
|
|
1550
1687
|
}
|
|
1551
1688
|
const { rootSymbol, rootPrecision, rootGovernSymbol, rootGovernPrecision } = platformSettings().blockchain;
|
|
1552
1689
|
let precision;
|
|
@@ -1555,7 +1692,7 @@ exports.DomainToBlockchainUtils = class DomainToBlockchainUtils {
|
|
|
1555
1692
|
} else if (symbol === rootGovernSymbol) {
|
|
1556
1693
|
precision = rootGovernPrecision;
|
|
1557
1694
|
} else {
|
|
1558
|
-
throw
|
|
1695
|
+
throw DomainError.internal("KIT_SYMBOL_UNSUPPORTED", { symbol, rootSymbol, rootGovernSymbol });
|
|
1559
1696
|
}
|
|
1560
1697
|
return `${numericAmount.toFixed(precision)} ${symbol}`;
|
|
1561
1698
|
}
|
|
@@ -1563,10 +1700,10 @@ exports.DomainToBlockchainUtils = class DomainToBlockchainUtils {
|
|
|
1563
1700
|
formatNumericStringToAssetString(numericString, precision, symbol) {
|
|
1564
1701
|
const numericValue = parseFloat(numericString);
|
|
1565
1702
|
if (isNaN(numericValue)) {
|
|
1566
|
-
throw
|
|
1703
|
+
throw DomainError.internal("KIT_NUMBER_INVALID", { value: numericString });
|
|
1567
1704
|
}
|
|
1568
1705
|
if (numericValue < 0) {
|
|
1569
|
-
throw
|
|
1706
|
+
throw DomainError.internal("KIT_NUMBER_NEGATIVE", { value: numericString });
|
|
1570
1707
|
}
|
|
1571
1708
|
return `${numericValue.toFixed(precision)} ${symbol}`;
|
|
1572
1709
|
}
|
|
@@ -1597,6 +1734,19 @@ exports.DomainToBlockchainUtils = __decorateClass([
|
|
|
1597
1734
|
common.Injectable()
|
|
1598
1735
|
], exports.DomainToBlockchainUtils);
|
|
1599
1736
|
|
|
1737
|
+
const DIGEST_RE = /^[0-9a-f]{64}$/;
|
|
1738
|
+
function chainTextDigest(text) {
|
|
1739
|
+
if (!text)
|
|
1740
|
+
return "";
|
|
1741
|
+
return crypto.createHash("sha256").update(text, "utf8").digest("hex");
|
|
1742
|
+
}
|
|
1743
|
+
function isChainTextDigest(value) {
|
|
1744
|
+
return typeof value === "string" && DIGEST_RE.test(value);
|
|
1745
|
+
}
|
|
1746
|
+
function resolveChainText(chainValue, current) {
|
|
1747
|
+
return isChainTextDigest(chainValue) ? current ?? "" : chainValue;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1600
1750
|
class AssetUtils {
|
|
1601
1751
|
/**
|
|
1602
1752
|
* Парсит строку ассета и возвращает числовое значение и символ
|
|
@@ -1683,17 +1833,17 @@ class AmountFormatterUtils {
|
|
|
1683
1833
|
*/
|
|
1684
1834
|
static formatAmount(amountStr) {
|
|
1685
1835
|
if (!amountStr || typeof amountStr !== "string") {
|
|
1686
|
-
throw
|
|
1836
|
+
throw DomainError.internal("KIT_AMOUNT_FORMAT_INVALID", { amount: amountStr });
|
|
1687
1837
|
}
|
|
1688
1838
|
const parts = amountStr.trim().split(/\s+/);
|
|
1689
1839
|
if (parts.length < 1 || !parts[0]) {
|
|
1690
|
-
throw
|
|
1840
|
+
throw DomainError.internal("KIT_AMOUNT_FORMAT_INVALID", { amount: amountStr });
|
|
1691
1841
|
}
|
|
1692
1842
|
const amountPart = parts[0].replace(",", ".");
|
|
1693
1843
|
const currency = parts.length >= 2 ? parts.slice(1).join(" ") : "";
|
|
1694
1844
|
const amount = parseFloat(amountPart);
|
|
1695
1845
|
if (isNaN(amount)) {
|
|
1696
|
-
throw
|
|
1846
|
+
throw DomainError.internal("KIT_AMOUNT_NUMBER_INVALID", { value: parts[0] });
|
|
1697
1847
|
}
|
|
1698
1848
|
const formattedAmount = amount.toLocaleString("ru-RU", {
|
|
1699
1849
|
minimumFractionDigits: 2,
|
|
@@ -1738,7 +1888,7 @@ function checkPaymentAmount(incomeAmount, expectedAmount, tolerancePercentage) {
|
|
|
1738
1888
|
if (incomeAmount < expectedAmount - tolerance) {
|
|
1739
1889
|
return {
|
|
1740
1890
|
status: "error",
|
|
1741
|
-
message:
|
|
1891
|
+
message: server.t("kit.payments.insufficientFunds", { income: incomeAmount, expected: expectedAmount })
|
|
1742
1892
|
};
|
|
1743
1893
|
}
|
|
1744
1894
|
return {
|
|
@@ -1769,7 +1919,7 @@ class QuantityUtils {
|
|
|
1769
1919
|
} else if (symbol === rootGovernSymbol) {
|
|
1770
1920
|
return rootGovernPrecision;
|
|
1771
1921
|
} else {
|
|
1772
|
-
throw
|
|
1922
|
+
throw DomainError.internal("KIT_SYMBOL_UNSUPPORTED", { symbol, rootSymbol, rootGovernSymbol });
|
|
1773
1923
|
}
|
|
1774
1924
|
}
|
|
1775
1925
|
/**
|
|
@@ -1779,7 +1929,7 @@ class QuantityUtils {
|
|
|
1779
1929
|
static validateSymbol(symbol) {
|
|
1780
1930
|
if (!this.isSupportedSymbol(symbol)) {
|
|
1781
1931
|
const { rootSymbol, rootGovernSymbol } = platformSettings().blockchain;
|
|
1782
|
-
throw
|
|
1932
|
+
throw DomainError.internal("KIT_SYMBOL_UNSUPPORTED", { symbol, rootSymbol, rootGovernSymbol });
|
|
1783
1933
|
}
|
|
1784
1934
|
}
|
|
1785
1935
|
/**
|
|
@@ -1791,7 +1941,7 @@ class QuantityUtils {
|
|
|
1791
1941
|
static formatQuantityForBlockchain(amount, symbol) {
|
|
1792
1942
|
this.validateSymbol(symbol);
|
|
1793
1943
|
if (isNaN(amount) || amount < 0) {
|
|
1794
|
-
throw
|
|
1944
|
+
throw DomainError.internal("KIT_NUMBER_INVALID", { value: amount });
|
|
1795
1945
|
}
|
|
1796
1946
|
const precision = this.getPrecisionForSymbol(symbol);
|
|
1797
1947
|
const formattedAmount = amount.toFixed(precision);
|
|
@@ -1806,7 +1956,7 @@ class QuantityUtils {
|
|
|
1806
1956
|
static combineQuantityAndSymbol(amount, symbol) {
|
|
1807
1957
|
this.validateSymbol(symbol);
|
|
1808
1958
|
if (isNaN(amount) || amount < 0) {
|
|
1809
|
-
throw
|
|
1959
|
+
throw DomainError.internal("KIT_NUMBER_INVALID", { value: amount });
|
|
1810
1960
|
}
|
|
1811
1961
|
return `${amount} ${symbol}`;
|
|
1812
1962
|
}
|
|
@@ -1818,12 +1968,12 @@ class QuantityUtils {
|
|
|
1818
1968
|
static parseQuantityString(quantity) {
|
|
1819
1969
|
const parts = quantity.split(" ");
|
|
1820
1970
|
if (parts.length !== 2) {
|
|
1821
|
-
throw
|
|
1971
|
+
throw DomainError.internal("KIT_QUANTITY_FORMAT_INVALID", { quantity });
|
|
1822
1972
|
}
|
|
1823
1973
|
const [amountStr, symbol] = parts;
|
|
1824
1974
|
const amount = parseFloat(amountStr);
|
|
1825
1975
|
if (isNaN(amount)) {
|
|
1826
|
-
throw
|
|
1976
|
+
throw DomainError.internal("KIT_QUANTITY_AMOUNT_INVALID", { amount: amountStr });
|
|
1827
1977
|
}
|
|
1828
1978
|
this.validateSymbol(symbol);
|
|
1829
1979
|
return { amount, symbol };
|
|
@@ -1886,14 +2036,29 @@ class DateUtils {
|
|
|
1886
2036
|
}
|
|
1887
2037
|
}
|
|
1888
2038
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
}
|
|
1894
|
-
await new Promise((resolve) => {
|
|
1895
|
-
setTimeout(resolve, ms);
|
|
2039
|
+
function waitForEvent(source, event, match, timeoutMs) {
|
|
2040
|
+
let settle;
|
|
2041
|
+
const promise = new Promise((resolve) => {
|
|
2042
|
+
settle = resolve;
|
|
1896
2043
|
});
|
|
2044
|
+
let done = false;
|
|
2045
|
+
let timer;
|
|
2046
|
+
const listener = (payload) => {
|
|
2047
|
+
if (match(payload))
|
|
2048
|
+
finish(payload);
|
|
2049
|
+
};
|
|
2050
|
+
function finish(value) {
|
|
2051
|
+
if (done)
|
|
2052
|
+
return;
|
|
2053
|
+
done = true;
|
|
2054
|
+
if (timer)
|
|
2055
|
+
clearTimeout(timer);
|
|
2056
|
+
source.off(event, listener);
|
|
2057
|
+
settle(value);
|
|
2058
|
+
}
|
|
2059
|
+
source.on(event, listener);
|
|
2060
|
+
timer = setTimeout(() => finish(null), timeoutMs);
|
|
2061
|
+
return { promise, cancel: () => finish(null) };
|
|
1897
2062
|
}
|
|
1898
2063
|
|
|
1899
2064
|
function getAppliedBlockNum(transactResult) {
|
|
@@ -1920,11 +2085,52 @@ function sanitizeUserText(value) {
|
|
|
1920
2085
|
return cooptypes._Common.Text.sanitizeEditorMarkdown(value);
|
|
1921
2086
|
}
|
|
1922
2087
|
|
|
2088
|
+
function resolveSortColumn(repository, sortBy, fallback) {
|
|
2089
|
+
if (!sortBy)
|
|
2090
|
+
return fallback;
|
|
2091
|
+
const isKnownColumn = repository.metadata.columns.some(
|
|
2092
|
+
(column) => column.propertyName === sortBy || column.databaseName === sortBy
|
|
2093
|
+
);
|
|
2094
|
+
return isKnownColumn ? sortBy : fallback;
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
class HttpApiError extends common.HttpException {
|
|
2098
|
+
constructor(statusCode, message, isOperational = true, stack, subcode) {
|
|
2099
|
+
super(message, statusCode);
|
|
2100
|
+
this.isOperational = isOperational;
|
|
2101
|
+
this.subcode = subcode;
|
|
2102
|
+
if (stack) {
|
|
2103
|
+
this.stack = stack;
|
|
2104
|
+
} else {
|
|
2105
|
+
Error.captureStackTrace(this, this.constructor);
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
const ASSERT_PREFIX = /assertion failure with message: (.+?)(?:\n|$)/;
|
|
2111
|
+
const CODED = /^([A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+):\s*(.*)$/s;
|
|
2112
|
+
function parseChainAssert(message) {
|
|
2113
|
+
const assert = message.match(ASSERT_PREFIX);
|
|
2114
|
+
const body = (assert ? assert[1] : message).trim();
|
|
2115
|
+
const coded = body.match(CODED);
|
|
2116
|
+
return coded ? { code: coded[1], text: coded[2].trim() } : { text: body };
|
|
2117
|
+
}
|
|
2118
|
+
function chainErrorCode(error) {
|
|
2119
|
+
if (error instanceof DomainError) {
|
|
2120
|
+
if (error.code !== "CHAIN_ASSERT" && error.code !== "CHAIN_ERROR")
|
|
2121
|
+
return error.code;
|
|
2122
|
+
return typeof error.params.message === "string" ? parseChainAssert(error.params.message).code : void 0;
|
|
2123
|
+
}
|
|
2124
|
+
const raw = error?.message ?? String(error);
|
|
2125
|
+
return parseChainAssert(raw).code;
|
|
2126
|
+
}
|
|
1923
2127
|
function rethrowChainError(error) {
|
|
1924
2128
|
const raw = error?.message ?? String(error);
|
|
1925
|
-
const match = raw.match(
|
|
1926
|
-
|
|
1927
|
-
|
|
2129
|
+
const match = raw.match(ASSERT_PREFIX);
|
|
2130
|
+
if (!match)
|
|
2131
|
+
throw DomainError.badRequest("CHAIN_ERROR", { message: raw });
|
|
2132
|
+
const { code, text } = parseChainAssert(raw);
|
|
2133
|
+
throw DomainError.badRequest(code ?? "CHAIN_ASSERT", { message: text });
|
|
1928
2134
|
}
|
|
1929
2135
|
|
|
1930
2136
|
exports.AmountFormatterUtils = AmountFormatterUtils;
|
|
@@ -1936,6 +2142,7 @@ exports.CurrencyValidationUtil = CurrencyValidationUtil;
|
|
|
1936
2142
|
exports.CurrentUser = CurrentUser;
|
|
1937
2143
|
exports.DEFAULT_DOCUMENT_VERSION = DEFAULT_DOCUMENT_VERSION;
|
|
1938
2144
|
exports.DateUtils = DateUtils;
|
|
2145
|
+
exports.DomainError = DomainError;
|
|
1939
2146
|
exports.EMPTY_HASH = EMPTY_HASH;
|
|
1940
2147
|
exports.EXTENSION_APP_TERMINATE_EVENT = EXTENSION_APP_TERMINATE_EVENT;
|
|
1941
2148
|
exports.EXTENSION_REPOSITORY = EXTENSION_REPOSITORY;
|
|
@@ -1957,16 +2164,21 @@ exports.PaginationUtils = PaginationUtils;
|
|
|
1957
2164
|
exports.QuantityUtils = QuantityUtils;
|
|
1958
2165
|
exports.ROLES_ANY_STATUS_KEY = ROLES_ANY_STATUS_KEY;
|
|
1959
2166
|
exports.ROLES_DENY_SELF_KEY = ROLES_DENY_SELF_KEY;
|
|
2167
|
+
exports.SORT_FIELD_PATTERN = SORT_FIELD_PATTERN;
|
|
1960
2168
|
exports.UseBucket = UseBucket;
|
|
1961
2169
|
exports.bucketProvidersFor = bucketProvidersFor;
|
|
1962
2170
|
exports.bucketTokenFor = bucketTokenFor;
|
|
1963
2171
|
exports.buildPaginationResult = buildPaginationResult;
|
|
2172
|
+
exports.chainErrorCode = chainErrorCode;
|
|
2173
|
+
exports.chainTextDigest = chainTextDigest;
|
|
1964
2174
|
exports.checkPaymentAmount = checkPaymentAmount;
|
|
1965
2175
|
exports.checkPaymentSymbol = checkPaymentSymbol;
|
|
1966
2176
|
exports.computeOnboardingExpiresAt = computeOnboardingExpiresAt;
|
|
1967
2177
|
exports.configureExtensionAuth = configureExtensionAuth;
|
|
1968
2178
|
exports.configurePlatformSettings = configurePlatformSettings;
|
|
1969
2179
|
exports.createPaginationResult = createPaginationResult;
|
|
2180
|
+
exports.domainErrorMessage = domainErrorMessage;
|
|
2181
|
+
exports.extensionDatabaseMigrations = extensionDatabaseMigrations;
|
|
1970
2182
|
exports.extensionEntities = extensionEntities;
|
|
1971
2183
|
exports.generateHashFromString = generateHashFromString;
|
|
1972
2184
|
exports.generateRandomHash = generateRandomHash;
|
|
@@ -1974,15 +2186,22 @@ exports.generateUniqueHash = generateUniqueHash;
|
|
|
1974
2186
|
exports.getAmountPlusFee = getAmountPlusFee;
|
|
1975
2187
|
exports.getAppliedBlockNum = getAppliedBlockNum;
|
|
1976
2188
|
exports.hasServerSecret = hasServerSecret;
|
|
2189
|
+
exports.isChainTextDigest = isChainTextDigest;
|
|
1977
2190
|
exports.isExtensionAvailable = isExtensionAvailable;
|
|
1978
2191
|
exports.mergeSecretConfig = mergeSecretConfig;
|
|
1979
2192
|
exports.paginationInputToOffset = paginationInputToOffset;
|
|
2193
|
+
exports.parseChainAssert = parseChainAssert;
|
|
1980
2194
|
exports.platformSettings = platformSettings;
|
|
1981
2195
|
exports.providerSuppliedPaths = providerSuppliedPaths;
|
|
1982
2196
|
exports.redactSecretConfig = redactSecretConfig;
|
|
2197
|
+
exports.registerExtensionDatabaseMigrations = registerExtensionDatabaseMigrations;
|
|
1983
2198
|
exports.registerExtensionEntities = registerExtensionEntities;
|
|
2199
|
+
exports.resetExtensionDatabaseMigrations = resetExtensionDatabaseMigrations;
|
|
1984
2200
|
exports.resetExtensionEntities = resetExtensionEntities;
|
|
2201
|
+
exports.resolveChainText = resolveChainText;
|
|
2202
|
+
exports.resolveSortColumn = resolveSortColumn;
|
|
1985
2203
|
exports.rethrowChainError = rethrowChainError;
|
|
1986
2204
|
exports.sanitizeUserText = sanitizeUserText;
|
|
2205
|
+
exports.validationMessage = validationMessage;
|
|
1987
2206
|
exports.verifySignedDocumentAgainstStoredDraft = verifySignedDocumentAgainstStoredDraft;
|
|
1988
|
-
exports.
|
|
2207
|
+
exports.waitForEvent = waitForEvent;
|