@bitrix24/b24jssdk 0.1.7 → 0.2.1

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @version @bitrix24/b24jssdk v0.1.7
2
+ * @version @bitrix24/b24jssdk v0.2.1
3
3
  * @copyright (c) 2025 Bitrix24
4
4
  * @licence MIT
5
5
  * @links https://github.com/bitrix24/b24jssdk - GitHub
@@ -504,6 +504,24 @@ class TypeManager {
504
504
  }
505
505
  const Type = new TypeManager();
506
506
 
507
+ function pick(data, keys) {
508
+ const result = {};
509
+ for (const key of keys) {
510
+ result[key] = data[key];
511
+ }
512
+ return result;
513
+ }
514
+ function omit(data, keys) {
515
+ const result = { ...data };
516
+ for (const key of keys) {
517
+ delete result[key];
518
+ }
519
+ return result;
520
+ }
521
+ function isArrayOfArray(item) {
522
+ return Array.isArray(item[0]);
523
+ }
524
+
507
525
  const _state = {};
508
526
  let getRandomValues;
509
527
  const randoms8 = new Uint8Array(16);
@@ -679,7 +697,6 @@ class TextManager {
679
697
  return str;
680
698
  }
681
699
  const matches = str.match(
682
- // eslint-disable-next-line
683
700
  /[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g
684
701
  );
685
702
  if (!matches) {
@@ -1048,75 +1065,42 @@ var RpcMethod = /* @__PURE__ */ ((RpcMethod2) => {
1048
1065
  })(RpcMethod || {});
1049
1066
 
1050
1067
  class Result {
1051
- _errorCollection;
1068
+ _errors;
1052
1069
  _data;
1053
- constructor() {
1054
- this._errorCollection = /* @__PURE__ */ new Set();
1055
- this._data = null;
1070
+ constructor(data) {
1071
+ this._errors = /* @__PURE__ */ new Map();
1072
+ this._data = data ?? null;
1056
1073
  }
1057
- /**
1058
- * Getter for the `isSuccess` property.
1059
- * Checks if the `_errorCollection` is empty to determine success.
1060
- *
1061
- * @returns Whether the operation resulted in success (no errors).
1062
- */
1063
1074
  get isSuccess() {
1064
- return this._errorCollection.size === 0;
1075
+ return this._errors.size === 0;
1076
+ }
1077
+ get errors() {
1078
+ return this._errors;
1065
1079
  }
1066
- /**
1067
- * Sets the data associated with the result.
1068
- *
1069
- * @param data The data to be stored in the result.
1070
- * @returns The current Result object for chaining methods.
1071
- */
1072
1080
  setData(data) {
1073
1081
  this._data = data;
1074
1082
  return this;
1075
1083
  }
1076
- /**
1077
- * Retrieves the data associated with the result.
1078
- *
1079
- * @returns The data stored in the result, if any.
1080
- */
1081
1084
  getData() {
1082
1085
  return this._data;
1083
1086
  }
1084
- /**
1085
- * Adds an error message or Error object to the result.
1086
- *
1087
- * @param error The error message or Error object to be added.
1088
- * @returns The current Result object for chaining methods.
1089
- */
1090
- addError(error) {
1091
- if (error instanceof Error) {
1092
- this._errorCollection.add(error);
1093
- } else {
1094
- this._errorCollection.add(new Error(error.toString()));
1095
- }
1087
+ addError(error, key) {
1088
+ const errorKey = key ?? Text.getUuidRfc4122();
1089
+ const errorObj = typeof error === "string" ? new Error(error) : error;
1090
+ this._errors.set(errorKey, errorObj);
1096
1091
  return this;
1097
1092
  }
1098
- /**
1099
- * Adds multiple errors to the result in a single call.
1100
- *
1101
- * @param errors An array of errors or strings that will be converted to errors.
1102
- * @returns The current Result object for chaining methods.
1103
- */
1104
1093
  addErrors(errors) {
1105
1094
  for (const error of errors) {
1106
- if (error instanceof Error) {
1107
- this._errorCollection.add(error);
1108
- } else {
1109
- this._errorCollection.add(new Error(error.toString()));
1110
- }
1095
+ this.addError(error);
1111
1096
  }
1112
1097
  return this;
1113
1098
  }
1114
- /**
1115
- * Retrieves an iterator for the errors collected in the result.
1116
- * @returns An iterator over the stored Error objects.
1117
- */
1118
1099
  getErrors() {
1119
- return this._errorCollection.values();
1100
+ return this._errors.values();
1101
+ }
1102
+ hasError(key) {
1103
+ return this._errors.has(key);
1120
1104
  }
1121
1105
  /**
1122
1106
  * Retrieves an array of error messages from the collected errors.
@@ -1125,7 +1109,7 @@ class Result {
1125
1109
  * contains the message of a corresponding error object.
1126
1110
  */
1127
1111
  getErrorMessages() {
1128
- return [...this.getErrors()].map((error) => error.message);
1112
+ return Array.from(this._errors.values(), (e) => e.message);
1129
1113
  }
1130
1114
  /**
1131
1115
  * Converts the Result object to a string.
@@ -1133,36 +1117,168 @@ class Result {
1133
1117
  * @returns {string} Returns a string representation of the result operation
1134
1118
  */
1135
1119
  toString() {
1136
- if (this.isSuccess) {
1137
- return `Result (success): data: ${JSON.stringify(this._data)}`;
1120
+ const status = this.isSuccess ? "success" : "failure";
1121
+ const data = this.safeStringify(this._data);
1122
+ return this.isSuccess ? `Result(${status}): ${data}` : `Result(${status}): ${data}
1123
+ Errors: ${this.getErrorMessages().join(", ")}`;
1124
+ }
1125
+ safeStringify(data) {
1126
+ try {
1127
+ return JSON.stringify(data, this.replacer, 2);
1128
+ } catch {
1129
+ return "[Unable to serialize data]";
1130
+ }
1131
+ }
1132
+ replacer(_, value) {
1133
+ if (value instanceof Error) {
1134
+ return {
1135
+ name: value.name,
1136
+ message: value.message,
1137
+ stack: value.stack
1138
+ };
1138
1139
  }
1139
- return `Result (failure): errors: ${this.getErrorMessages().join(", ")}`;
1140
+ return value;
1141
+ }
1142
+ // Static constructors
1143
+ static ok(data) {
1144
+ return new Result(data);
1145
+ }
1146
+ static fail(error, key) {
1147
+ return new Result().addError(error, key);
1140
1148
  }
1141
1149
  }
1142
1150
 
1143
1151
  class AjaxError extends Error {
1144
- cause;
1152
+ code;
1145
1153
  _status;
1146
- _answerError;
1147
- constructor(params) {
1148
- const message = `${params.answerError.error}${params.answerError.errorDescription ? ": " + params.answerError.errorDescription : ""}`;
1154
+ requestInfo;
1155
+ timestamp;
1156
+ originalError;
1157
+ // override cause: null | Error
1158
+ // private _status: number
1159
+ // private _answerError: AnswerError
1160
+ constructor(details) {
1161
+ const message = AjaxError.formatErrorMessage(details);
1149
1162
  super(message);
1150
- this.cause = params.cause || null;
1151
- this.name = this.constructor.name;
1152
- this._status = params.status;
1153
- this._answerError = params.answerError;
1154
- }
1163
+ this.name = "AjaxError";
1164
+ this.code = details.code;
1165
+ this._status = details.status;
1166
+ this.requestInfo = details.requestInfo;
1167
+ this.originalError = details.originalError;
1168
+ this.timestamp = /* @__PURE__ */ new Date();
1169
+ this.cleanErrorStack();
1170
+ }
1171
+ // constructor(params: AjaxErrorParams) {
1172
+ // const message = `${ params.answerError.error }${
1173
+ // params.answerError.errorDescription
1174
+ // ? ': ' + params.answerError.errorDescription
1175
+ // : ''
1176
+ // }`
1177
+ //
1178
+ // super(message)
1179
+ // this.cause = params.cause || null
1180
+ // this.name = this.constructor.name
1181
+ //
1182
+ // this._status = params.status
1183
+ // this._answerError = params.answerError
1184
+ // }
1185
+ /**
1186
+ * @deprecated
1187
+ */
1155
1188
  get answerError() {
1156
- return this._answerError;
1189
+ return {
1190
+ error: this.message,
1191
+ errorDescription: ""
1192
+ };
1157
1193
  }
1158
1194
  get status() {
1159
1195
  return this._status;
1160
1196
  }
1197
+ /**
1198
+ * @deprecated
1199
+ */
1161
1200
  set status(status) {
1162
1201
  this._status = status;
1163
1202
  }
1203
+ /**
1204
+ * Creates AjaxError from HTTP response
1205
+ */
1206
+ static fromResponse(response) {
1207
+ return new AjaxError({
1208
+ code: response.data?.error || "unknown_error",
1209
+ description: response.data?.error_description,
1210
+ status: response.status,
1211
+ requestInfo: {
1212
+ method: response.config?.method?.toUpperCase(),
1213
+ url: response.config?.url,
1214
+ params: response.config?.params
1215
+ }
1216
+ });
1217
+ }
1218
+ /**
1219
+ * Creates AjaxError from exception
1220
+ */
1221
+ static fromException(error, context) {
1222
+ if (error instanceof AjaxError) return error;
1223
+ return new AjaxError({
1224
+ code: context?.code || "internal_error",
1225
+ status: context?.status || 500,
1226
+ description: error instanceof Error ? error.message : String(error),
1227
+ requestInfo: context?.requestInfo,
1228
+ originalError: error
1229
+ });
1230
+ }
1231
+ /**
1232
+ * Serializes error for logging and debugging
1233
+ */
1234
+ toJSON() {
1235
+ return {
1236
+ name: this.name,
1237
+ code: this.code,
1238
+ message: this.message,
1239
+ status: this._status,
1240
+ timestamp: this.timestamp.toISOString(),
1241
+ requestInfo: this.requestInfo,
1242
+ stack: this.stack
1243
+ };
1244
+ }
1245
+ // override toString(): string {
1246
+ // return `${ this.answerError.error }${
1247
+ // this.answerError.errorDescription
1248
+ // ? ': ' + this.answerError.errorDescription
1249
+ // : ''
1250
+ // } (${ this.status })`
1251
+ // }
1252
+ /**
1253
+ * Formats error information for human-readable output
1254
+ */
1164
1255
  toString() {
1165
- return `${this.answerError.error}${this.answerError.errorDescription ? ": " + this.answerError.errorDescription : ""} (${this.status})`;
1256
+ let output = `[${this.name}] ${this.code} (${this._status}): ${this.message}`;
1257
+ if (this.requestInfo) {
1258
+ output += `
1259
+ Request: ${this.requestInfo.method} ${this.requestInfo.url}`;
1260
+ }
1261
+ if (this.stack) {
1262
+ output += `
1263
+ Stack trace:
1264
+ ${this.stack}`;
1265
+ }
1266
+ return output;
1267
+ }
1268
+ static formatErrorMessage(details) {
1269
+ const parts = [details.code];
1270
+ if (details.description) {
1271
+ parts.push(`- ${details.description}`);
1272
+ }
1273
+ if (details.requestInfo?.method && details.requestInfo.url) {
1274
+ parts.push(`(on ${details.requestInfo.method} ${details.requestInfo.url})`);
1275
+ }
1276
+ return parts.join(" ");
1277
+ }
1278
+ cleanErrorStack() {
1279
+ if (typeof this.stack === "string") {
1280
+ this.stack = this.stack.split("\n").filter((line) => !line.includes("AjaxError.constructor")).join("\n");
1281
+ }
1166
1282
  }
1167
1283
  }
1168
1284
 
@@ -1170,31 +1286,48 @@ class AjaxResult extends Result {
1170
1286
  _status;
1171
1287
  _query;
1172
1288
  _data;
1173
- constructor(answer, query, status) {
1289
+ constructor(options) {
1174
1290
  super();
1175
- this._data = answer;
1176
- this._query = structuredClone(query);
1177
- this._status = status;
1178
- if (typeof this._data.error !== "undefined") {
1179
- const error = typeof this._data.error === "string" ? this._data : this._data.error;
1180
- this.addError(
1181
- new AjaxError({
1182
- status: this._status,
1183
- answerError: {
1184
- error: error.error || "",
1185
- errorDescription: error.error_description || ""
1186
- }
1187
- })
1188
- );
1189
- }
1190
- }
1191
- // @ts-ignore
1192
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1193
- setData(data) {
1194
- throw new Error("AjaxResult not support setData()");
1291
+ this._data = Object.freeze(options.answer);
1292
+ this._query = Object.freeze(structuredClone(options.query));
1293
+ this._status = options.status;
1294
+ this.#processErrors();
1295
+ }
1296
+ #processErrors() {
1297
+ const { error } = this._data;
1298
+ if (!error) return;
1299
+ const errorParams = this.#normalizeError(error);
1300
+ this.addError(this.#createAjaxError(errorParams), "base-error");
1301
+ }
1302
+ #normalizeError(error) {
1303
+ return typeof error === "string" ? { code: error, description: this._data.error_description || "" } : { code: error.error, description: error.error_description || "" };
1304
+ }
1305
+ #createAjaxError(params) {
1306
+ return new AjaxError({
1307
+ code: String(this._status),
1308
+ description: params.description,
1309
+ status: this._status,
1310
+ requestInfo: {
1311
+ method: this._query.method,
1312
+ // url: '?',
1313
+ params: this._query.params
1314
+ }
1315
+ // request:
1316
+ });
1195
1317
  }
1196
1318
  getData() {
1197
- return this._data;
1319
+ return Object.freeze({
1320
+ result: this._data.result,
1321
+ next: this._data.next,
1322
+ total: this._data.total,
1323
+ time: this._data.time
1324
+ });
1325
+ }
1326
+ /**
1327
+ * Alias for isMore
1328
+ */
1329
+ hasMore() {
1330
+ return this.isMore();
1198
1331
  }
1199
1332
  isMore() {
1200
1333
  return Type.isNumber(this._data?.next);
@@ -1208,16 +1341,35 @@ class AjaxResult extends Result {
1208
1341
  getQuery() {
1209
1342
  return this._query;
1210
1343
  }
1211
- async getNext(http) {
1212
- if (this.isMore() && this.isSuccess) {
1213
- this._query.start = Number.parseInt(this._data?.next);
1214
- return http.call(
1215
- this._query.method,
1216
- this._query.params,
1217
- this._query.start
1218
- );
1344
+ /**
1345
+ * Alias for getNext
1346
+ * @param http
1347
+ */
1348
+ async fetchNext(http) {
1349
+ const data = await this.getNext(http);
1350
+ if (data === false) {
1351
+ return null;
1219
1352
  }
1220
- return Promise.resolve(false);
1353
+ return data;
1354
+ }
1355
+ async getNext(http) {
1356
+ if (!this.isMore() || !this.isSuccess) return false;
1357
+ const nextPageQuery = this.#buildNextPageQuery();
1358
+ return http.call(
1359
+ nextPageQuery.method,
1360
+ nextPageQuery.params,
1361
+ nextPageQuery.start
1362
+ );
1363
+ }
1364
+ #buildNextPageQuery() {
1365
+ return {
1366
+ ...this._query,
1367
+ start: Text.toInteger(this._data.next)
1368
+ };
1369
+ }
1370
+ // Immutable API
1371
+ setData() {
1372
+ throw new ReferenceError("AjaxResult does not allow data modification");
1221
1373
  }
1222
1374
  }
1223
1375
 
@@ -1404,33 +1556,37 @@ class Http {
1404
1556
  // endregion ////
1405
1557
  // region Actions Call ////
1406
1558
  async batch(calls, isHaltOnError = true) {
1407
- const isArrayMode = Array.isArray(calls);
1408
- const cmd = isArrayMode ? [] : {};
1559
+ if (Array.isArray(calls)) {
1560
+ return this.#batchAsArray(
1561
+ calls,
1562
+ isHaltOnError
1563
+ );
1564
+ }
1565
+ return this.#batchAsObject(
1566
+ calls,
1567
+ isHaltOnError
1568
+ );
1569
+ }
1570
+ async #batchAsObject(calls, isHaltOnError = true) {
1571
+ const cmd = {};
1409
1572
  let cnt = 0;
1410
1573
  const processRow = (row, index) => {
1411
1574
  let method = null;
1412
1575
  let params = null;
1413
- if (Array.isArray(row)) {
1414
- method = row[0];
1415
- params = row[1];
1416
- } else if (row.method) {
1417
- method = row.method;
1418
- params = row.params;
1576
+ if (row.method) {
1577
+ method = row.method ?? null;
1578
+ params = row?.params ?? null;
1579
+ } else if (Array.isArray(row) && row.length > 0) {
1580
+ method = row[0] ?? null;
1581
+ params = row[1] ?? null;
1419
1582
  }
1420
1583
  if (method) {
1421
1584
  cnt++;
1422
- const data = method + "?" + qs__namespace.stringify(params);
1423
- if (isArrayMode || Array.isArray(cmd)) {
1424
- cmd.push(data);
1425
- } else {
1426
- cmd[index] = data;
1427
- }
1585
+ cmd[index] = method + "?" + qs__namespace.stringify(params);
1428
1586
  }
1429
1587
  };
1430
- if (isArrayMode) {
1431
- for (const [index, item] of calls.entries()) processRow(item, index);
1432
- } else {
1433
- for (const [index, item] of Object.entries(calls)) processRow(item, index);
1588
+ for (const [index, row] of Object.entries(calls)) {
1589
+ processRow(row, index);
1434
1590
  }
1435
1591
  if (cnt < 1) {
1436
1592
  return Promise.resolve(new Result());
@@ -1440,7 +1596,7 @@ class Http {
1440
1596
  cmd
1441
1597
  }).then((response) => {
1442
1598
  const responseResult = response.getData().result;
1443
- const results = isArrayMode ? [] : {};
1599
+ const results = {};
1444
1600
  const processResponse = (row, index) => {
1445
1601
  if (
1446
1602
  // @ts-ignore
@@ -1448,8 +1604,8 @@ class Http {
1448
1604
  typeof responseResult.result_error[index] !== "undefined"
1449
1605
  ) {
1450
1606
  const q = row.split("?");
1451
- const data = new AjaxResult(
1452
- {
1607
+ results[index] = new AjaxResult({
1608
+ answer: {
1453
1609
  // @ts-ignore
1454
1610
  result: Type.isUndefined(responseResult.result[index]) ? (
1455
1611
  // @ts-ignore
@@ -1463,67 +1619,154 @@ class Http {
1463
1619
  // @ts-ignore
1464
1620
  total: responseResult.result_total[index],
1465
1621
  // @ts-ignore
1466
- next: responseResult.result_next[index]
1622
+ next: responseResult.result_next[index],
1623
+ // @todo test this ////
1624
+ // @ts-ignore
1625
+ time: responseResult.result_time[index]
1467
1626
  },
1468
- {
1627
+ query: {
1469
1628
  method: q[0] || "",
1470
1629
  params: qs__namespace.parse(q[1] || ""),
1471
1630
  start: 0
1472
1631
  },
1473
- response.getStatus()
1474
- );
1475
- if (isArrayMode || Array.isArray(results)) {
1476
- results.push(data);
1477
- } else {
1478
- results[index] = data;
1479
- }
1632
+ status: response.getStatus()
1633
+ });
1480
1634
  }
1481
1635
  };
1482
- if (Array.isArray(cmd)) {
1483
- for (const [index, item] of cmd.entries()) processResponse(item, index);
1484
- } else {
1485
- for (const [index, item] of Object.entries(cmd))
1486
- processResponse(item, index);
1636
+ for (const [index, row] of Object.entries(cmd)) {
1637
+ processResponse(row, index);
1487
1638
  }
1488
- let dataResult;
1639
+ const dataResult = {};
1489
1640
  const initError = (result2) => {
1641
+ if (result2.hasError("base-error")) {
1642
+ return result2.errors.get("base-error");
1643
+ }
1490
1644
  return new AjaxError({
1645
+ code: "0",
1646
+ description: result2.getErrorMessages().join("; "),
1491
1647
  status: 0,
1492
- answerError: {
1493
- error: result2.getErrorMessages().join("; "),
1494
- errorDescription: `batch ${result2.getQuery().method}: ${qs__namespace.stringify(result2.getQuery().params, { encode: false })}`
1648
+ requestInfo: {
1649
+ method: result2.getQuery().method,
1650
+ params: result2.getQuery().params
1495
1651
  },
1496
- cause: result2.getErrors().next().value
1652
+ originalError: result2.getErrors().next().value
1497
1653
  });
1498
1654
  };
1499
1655
  const result = new Result();
1500
- if (isArrayMode || Array.isArray(results)) {
1501
- dataResult = [];
1502
- for (const data of results) {
1503
- if (data.getStatus() !== 200 || !data.isSuccess) {
1504
- const error = initError(data);
1505
- if (!isHaltOnError && !data.isSuccess) {
1506
- result.addError(error);
1507
- continue;
1508
- }
1509
- return Promise.reject(error);
1656
+ for (const key of Object.keys(results)) {
1657
+ const data = results[key];
1658
+ if (data.getStatus() !== 200 || !data.isSuccess) {
1659
+ const error = initError(data);
1660
+ if (!isHaltOnError && !data.isSuccess) {
1661
+ result.addError(error, key);
1662
+ continue;
1510
1663
  }
1511
- dataResult.push(data.getData().result);
1664
+ return Promise.reject(error);
1512
1665
  }
1513
- } else {
1514
- dataResult = {};
1515
- for (const key of Object.keys(results)) {
1516
- const data = results[key];
1517
- if (data.getStatus() !== 200 || !data.isSuccess) {
1518
- const error = initError(data);
1519
- if (!isHaltOnError && !data.isSuccess) {
1520
- result.addError(error);
1521
- continue;
1522
- }
1523
- return Promise.reject(error);
1666
+ dataResult[key] = data.getData().result;
1667
+ }
1668
+ result.setData(dataResult);
1669
+ return Promise.resolve(result);
1670
+ });
1671
+ }
1672
+ async #batchAsArray(calls, isHaltOnError = true) {
1673
+ const cmd = [];
1674
+ let cnt = 0;
1675
+ const processRow = (row) => {
1676
+ let method = null;
1677
+ let params = null;
1678
+ if (row.method) {
1679
+ method = row.method ?? null;
1680
+ params = row?.params ?? null;
1681
+ } else if (Array.isArray(row) && row.length > 0) {
1682
+ method = row[0] ?? null;
1683
+ params = row[1] ?? null;
1684
+ }
1685
+ if (method) {
1686
+ cnt++;
1687
+ const data = method + "?" + qs__namespace.stringify(params);
1688
+ cmd.push(data);
1689
+ }
1690
+ };
1691
+ for (const [_, row] of calls.entries()) {
1692
+ processRow(row);
1693
+ }
1694
+ if (cnt < 1) {
1695
+ return Promise.resolve(new Result());
1696
+ }
1697
+ return this.call("batch", {
1698
+ halt: isHaltOnError ? 1 : 0,
1699
+ cmd
1700
+ }).then((response) => {
1701
+ const responseResult = response.getData().result;
1702
+ const results = [];
1703
+ const processResponse = (row, index) => {
1704
+ if (
1705
+ // @ts-ignore
1706
+ typeof responseResult.result[index] !== "undefined" || // @ts-ignore
1707
+ typeof responseResult.result_error[index] !== "undefined"
1708
+ ) {
1709
+ const q = row.split("?");
1710
+ const data = new AjaxResult({
1711
+ answer: {
1712
+ // @ts-ignore
1713
+ result: Type.isUndefined(responseResult.result[index]) ? (
1714
+ // @ts-ignore
1715
+ {}
1716
+ ) : (
1717
+ // @ts-ignore
1718
+ responseResult.result[index]
1719
+ ),
1720
+ // @ts-ignore
1721
+ error: responseResult?.result_error[index] || void 0,
1722
+ // @ts-ignore
1723
+ total: responseResult.result_total[index],
1724
+ // @ts-ignore
1725
+ next: responseResult.result_next[index],
1726
+ // @todo test this ////
1727
+ // @ts-ignore
1728
+ time: responseResult.result_time[index]
1729
+ },
1730
+ query: {
1731
+ method: q[0] || "",
1732
+ params: qs__namespace.parse(q[1] || ""),
1733
+ start: 0
1734
+ },
1735
+ status: response.getStatus()
1736
+ });
1737
+ results.push(data);
1738
+ }
1739
+ };
1740
+ for (const [index, row] of cmd.entries()) {
1741
+ processResponse(row, index);
1742
+ }
1743
+ const dataResult = [];
1744
+ const initError = (result2) => {
1745
+ if (result2.hasError("base-error")) {
1746
+ return result2.errors.get("base-error");
1747
+ }
1748
+ return new AjaxError({
1749
+ code: "0",
1750
+ description: result2.getErrorMessages().join("; "),
1751
+ status: 0,
1752
+ requestInfo: {
1753
+ method: result2.getQuery().method,
1754
+ params: result2.getQuery().params
1755
+ },
1756
+ originalError: result2.getErrors().next().value
1757
+ });
1758
+ };
1759
+ const result = new Result();
1760
+ for (const data of results) {
1761
+ if (data.getStatus() !== 200 || !data.isSuccess) {
1762
+ const error = initError(data);
1763
+ if (!isHaltOnError && !data.isSuccess) {
1764
+ result.addError(error);
1765
+ continue;
1524
1766
  }
1525
- dataResult[key] = data.getData().result;
1767
+ return Promise.reject(error);
1526
1768
  }
1769
+ dataResult.push(data.getData().result);
1527
1770
  }
1528
1771
  result.setData(dataResult);
1529
1772
  return Promise.resolve(result);
@@ -1571,9 +1814,14 @@ class Http {
1571
1814
  };
1572
1815
  }
1573
1816
  const problemError = new AjaxError({
1817
+ code: String(answerError.error),
1818
+ description: answerError.errorDescription,
1574
1819
  status: error_.response?.status || 0,
1575
- answerError,
1576
- cause: error_
1820
+ requestInfo: {
1821
+ method,
1822
+ params
1823
+ },
1824
+ originalError: error_
1577
1825
  });
1578
1826
  if (problemError.status === 401 && ["expired_token", "invalid_token"].includes(
1579
1827
  problemError.answerError.error
@@ -1607,9 +1855,14 @@ class Http {
1607
1855
  };
1608
1856
  }
1609
1857
  const problemError2 = new AjaxError({
1610
- status: error__.response?.status || 0,
1611
- answerError: answerError2,
1612
- cause: error__
1858
+ code: String(answerError2.error),
1859
+ description: answerError2.errorDescription,
1860
+ status: error_.response?.status || 0,
1861
+ requestInfo: {
1862
+ method,
1863
+ params
1864
+ },
1865
+ originalError: error__
1613
1866
  });
1614
1867
  return Promise.reject(problemError2);
1615
1868
  }
@@ -1618,15 +1871,15 @@ class Http {
1618
1871
  return Promise.reject(problemError);
1619
1872
  }
1620
1873
  ).then((response) => {
1621
- const result = new AjaxResult(
1622
- response.payload,
1623
- {
1874
+ const result = new AjaxResult({
1875
+ answer: response.payload,
1876
+ query: {
1624
1877
  method,
1625
1878
  params,
1626
1879
  start
1627
1880
  },
1628
- response.status
1629
- );
1881
+ status: response.status
1882
+ });
1630
1883
  return Promise.resolve(result);
1631
1884
  });
1632
1885
  }
@@ -1647,7 +1900,7 @@ class Http {
1647
1900
  result.logTag = this.#logTag;
1648
1901
  }
1649
1902
  result[this.#requestIdGenerator.getQueryStringParameterName()] = this.#requestIdGenerator.getRequestId();
1650
- result[this.#requestIdGenerator.getQueryStringSdkParameterName()] = "0.1.7";
1903
+ result[this.#requestIdGenerator.getQueryStringSdkParameterName()] = "0.2.1";
1651
1904
  if (!!result.data && !!result.data.start) {
1652
1905
  delete result.data.start;
1653
1906
  }
@@ -2809,11 +3062,13 @@ var MessageCommands = /* @__PURE__ */ ((MessageCommands2) => {
2809
3062
  class MessageManager {
2810
3063
  #appFrame;
2811
3064
  #callbackPromises;
3065
+ #callbackSingletone;
2812
3066
  _logger = null;
2813
3067
  runCallbackHandler;
2814
3068
  constructor(appFrame) {
2815
3069
  this.#appFrame = appFrame;
2816
3070
  this.#callbackPromises = /* @__PURE__ */ new Map();
3071
+ this.#callbackSingletone = /* @__PURE__ */ new Map();
2817
3072
  this.runCallbackHandler = this._runCallback.bind(this);
2818
3073
  }
2819
3074
  setLogger(logger) {
@@ -2863,17 +3118,22 @@ class MessageManager {
2863
3118
  timeoutId: null
2864
3119
  };
2865
3120
  const keyPromise = this.#setCallbackPromise(promiseHandler);
3121
+ const paramsSend = omit(params || {}, ["callBack", "isSafely", "safelyTime"]);
3122
+ const { callBack } = params || {};
3123
+ if (callBack) {
3124
+ this.#callbackSingletone.set(keyPromise, callBack);
3125
+ }
2866
3126
  if (command.toString().includes(":")) {
2867
3127
  cmd = {
2868
3128
  method: command.toString(),
2869
- params: params ?? "",
3129
+ params: paramsSend ?? "",
2870
3130
  callback: keyPromise,
2871
3131
  appSid: this.#appFrame.getAppSid()
2872
3132
  };
2873
3133
  } else {
2874
3134
  cmd = command.toString();
2875
3135
  const listParams = [
2876
- params ? JSON.stringify(params) : null,
3136
+ params ? JSON.stringify(paramsSend) : null,
2877
3137
  keyPromise,
2878
3138
  this.#appFrame.getAppSid()
2879
3139
  ];
@@ -2928,6 +3188,11 @@ class MessageManager {
2928
3188
  }
2929
3189
  this.#callbackPromises.delete(cmd.id);
2930
3190
  promise.resolve(cmd.args);
3191
+ } else if (this.#callbackSingletone.has(cmd.id)) {
3192
+ const callBack = this.#callbackSingletone.get(cmd.id);
3193
+ if (callBack) {
3194
+ callBack.apply(globalThis, [cmd.args]);
3195
+ }
2931
3196
  }
2932
3197
  }
2933
3198
  }
@@ -3654,15 +3919,17 @@ class PlacementManager {
3654
3919
  /**
3655
3920
  * Set Up the Interface Event Handler
3656
3921
  * @param {string} eventName
3922
+ * @param {(...args: any[]) => void} callBack
3657
3923
  * @return {Promise<any>}
3658
3924
  *
3659
3925
  * @link https://apidocs.bitrix24.com/api-reference/widgets/ui-interaction/bx24-placement-bind-event.html
3660
3926
  */
3661
- async bindEvent(eventName) {
3927
+ async bindEvent(eventName, callBack) {
3662
3928
  return this.#messageManager.send(
3663
- MessageCommands.getInterface,
3929
+ MessageCommands.placementBindEvent,
3664
3930
  {
3665
3931
  event: eventName,
3932
+ callBack,
3666
3933
  isSafely: true
3667
3934
  }
3668
3935
  );
@@ -11619,7 +11886,7 @@ class PullClient {
11619
11886
  }
11620
11887
  if (message.extra.server_time_unix) {
11621
11888
  message.extra.server_time_ago = (Date.now() - message.extra.server_time_unix * 1e3) / 1e3 - (this._config?.server.timeShift || 0);
11622
- message.extra.server_time_ago = message.extra.server_time_ago > 0 ? message.extra.server_time_ago : 0;
11889
+ message.extra.server_time_ago = Math.max(message.extra.server_time_ago, 0);
11623
11890
  }
11624
11891
  this.logMessage(message);
11625
11892
  try {
@@ -12685,7 +12952,7 @@ Data string: ${pullEvent}
12685
12952
  }
12686
12953
  trimDuplicates() {
12687
12954
  if (this._session.lastMessageIds.length > MAX_IDS_TO_STORE) {
12688
- this._session.lastMessageIds = this._session.lastMessageIds.slice(-MAX_IDS_TO_STORE);
12955
+ this._session.lastMessageIds = this._session.lastMessageIds.slice(-10);
12689
12956
  }
12690
12957
  }
12691
12958
  // endregion ////
@@ -12763,19 +13030,19 @@ Data string: ${pullEvent}
12763
13030
  * @deprecated
12764
13031
  */
12765
13032
  /*/
12766
- getRestClientOptions()
12767
- {
12768
- let result = {};
13033
+ getRestClientOptions()
13034
+ {
13035
+ let result = {};
12769
13036
 
12770
- if (this.guestMode && this.guestUserId !== 0)
12771
- {
12772
- result.queryParams = {
12773
- pull_guest_id: this.guestUserId
12774
- }
12775
- }
12776
- return result;
12777
- }
12778
- //*/
13037
+ if (this.guestMode && this.guestUserId !== 0)
13038
+ {
13039
+ result.queryParams = {
13040
+ pull_guest_id: this.guestUserId
13041
+ }
13042
+ }
13043
+ return result;
13044
+ }
13045
+ //*/
12779
13046
  // endregion ////
12780
13047
  }
12781
13048
 
@@ -13341,6 +13608,9 @@ exports.Type = Type;
13341
13608
  exports.TypeOption = TypeOption;
13342
13609
  exports.TypeSpecificUrl = TypeSpecificUrl;
13343
13610
  exports.initializeB24Frame = initializeB24Frame;
13611
+ exports.isArrayOfArray = isArrayOfArray;
13612
+ exports.omit = omit;
13613
+ exports.pick = pick;
13344
13614
  exports.useB24Helper = useB24Helper;
13345
13615
  exports.useFormatter = useFormatter;
13346
13616
  //# sourceMappingURL=index.cjs.map