bx-rest 1.6.0 → 1.7.0

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.
Files changed (172) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.en.md +96 -4
  3. package/README.md +96 -4
  4. package/consts/part-name-methods.d.ts +1 -0
  5. package/esm2022/consts/part-name-methods.mjs +2 -1
  6. package/esm2022/map/pull/application/config.mjs +25 -29
  7. package/esm2022/map/pull.mjs +8 -13
  8. package/esm2022/public-api.mjs +2 -1
  9. package/esm2022/request-navvy/booking/v1/resource.mjs +2 -2
  10. package/esm2022/request-navvy/booking/v1/resourcetype.mjs +2 -2
  11. package/esm2022/request-navvy/catalog/catalog.mjs +2 -2
  12. package/esm2022/request-navvy/catalog/document/element.mjs +2 -2
  13. package/esm2022/request-navvy/catalog/document.mjs +2 -2
  14. package/esm2022/request-navvy/catalog/documentcontractor.mjs +2 -2
  15. package/esm2022/request-navvy/catalog/extra.mjs +2 -2
  16. package/esm2022/request-navvy/catalog/measure.mjs +2 -2
  17. package/esm2022/request-navvy/catalog/price.mjs +2 -2
  18. package/esm2022/request-navvy/catalog/pricetype.mjs +2 -2
  19. package/esm2022/request-navvy/catalog/pricetypegroup.mjs +2 -2
  20. package/esm2022/request-navvy/catalog/pricetypelang.mjs +2 -2
  21. package/esm2022/request-navvy/catalog/product/offer.mjs +2 -2
  22. package/esm2022/request-navvy/catalog/product/service.mjs +2 -2
  23. package/esm2022/request-navvy/catalog/product/sku.mjs +2 -2
  24. package/esm2022/request-navvy/catalog/product.mjs +2 -2
  25. package/esm2022/request-navvy/catalog/productproperty.mjs +2 -2
  26. package/esm2022/request-navvy/catalog/productpropertyenum.mjs +2 -2
  27. package/esm2022/request-navvy/catalog/productpropertyfeature.mjs +2 -2
  28. package/esm2022/request-navvy/catalog/productpropertysection.mjs +2 -2
  29. package/esm2022/request-navvy/catalog/ratio.mjs +2 -2
  30. package/esm2022/request-navvy/catalog/roundingrule.mjs +2 -2
  31. package/esm2022/request-navvy/catalog/section.mjs +2 -2
  32. package/esm2022/request-navvy/catalog/store.mjs +2 -2
  33. package/esm2022/request-navvy/catalog/storeproduct.mjs +2 -2
  34. package/esm2022/request-navvy/catalog/userfield/document.mjs +2 -2
  35. package/esm2022/request-navvy/catalog/vat.mjs +2 -2
  36. package/esm2022/request-navvy/crm/activity.mjs +2 -2
  37. package/esm2022/request-navvy/crm/deal/recurring.mjs +2 -2
  38. package/esm2022/request-navvy/crm/item/product/row.mjs +2 -2
  39. package/esm2022/request-navvy/crm/orderentity.mjs +2 -2
  40. package/esm2022/request-navvy/crm/requisite/link.mjs +2 -2
  41. package/esm2022/request-navvy/crm/stagehistory.mjs +2 -2
  42. package/esm2022/request-navvy/crm/timeline/bindings.mjs +2 -2
  43. package/esm2022/request-navvy/documentgenerator/document.mjs +2 -2
  44. package/esm2022/request-navvy/documentgenerator/numerator.mjs +2 -2
  45. package/esm2022/request-navvy/documentgenerator/role.mjs +2 -2
  46. package/esm2022/request-navvy/documentgenerator/template.mjs +2 -2
  47. package/esm2022/request-navvy/pull/application/config.mjs +10 -4
  48. package/esm2022/request-navvy/pull/application/event.mjs +23 -0
  49. package/esm2022/request-navvy/pull/application/push.mjs +23 -0
  50. package/esm2022/request-navvy/pull/channel/public.mjs +4 -4
  51. package/esm2022/request-navvy/pull/config.mjs +8 -4
  52. package/esm2022/request-navvy/pull.mjs +12 -1
  53. package/esm2022/request-navvy/sale/basketitem.mjs +2 -2
  54. package/esm2022/request-navvy/sale/basketproperties.mjs +2 -2
  55. package/esm2022/request-navvy/sale/businessvaluepersondomain.mjs +2 -2
  56. package/esm2022/request-navvy/sale/order.mjs +2 -2
  57. package/esm2022/request-navvy/sale/payment.mjs +2 -2
  58. package/esm2022/request-navvy/sale/paymentitembasket.mjs +2 -2
  59. package/esm2022/request-navvy/sale/paymentitemshipment.mjs +2 -2
  60. package/esm2022/request-navvy/sale/persontype.mjs +2 -2
  61. package/esm2022/request-navvy/sale/property.mjs +2 -2
  62. package/esm2022/request-navvy/sale/propertyrelation.mjs +2 -2
  63. package/esm2022/request-navvy/sale/propertyvalue.mjs +2 -2
  64. package/esm2022/request-navvy/sale/propertyvariant.mjs +2 -2
  65. package/esm2022/request-navvy/sale/shipment.mjs +2 -2
  66. package/esm2022/request-navvy/sale/shipmentitem.mjs +2 -2
  67. package/esm2022/request-navvy/sale/shipmentproperty.mjs +2 -2
  68. package/esm2022/request-navvy/sale/shipmentpropertyvalue.mjs +2 -2
  69. package/esm2022/request-navvy/sale/status.mjs +2 -2
  70. package/esm2022/request-navvy/sale/statuslang.mjs +2 -2
  71. package/esm2022/request-navvy/sale/tradebinding.mjs +2 -2
  72. package/esm2022/request-navvy/sale/tradeplatform.mjs +2 -2
  73. package/esm2022/request-navvy/task/operation/elapseditem.mjs +44 -21
  74. package/esm2022/request-navvy/userfieldtype.mjs +2 -2
  75. package/esm2022/services/http/HttpBX.mjs +9 -6
  76. package/esm2022/services/http/fetch.mjs +45 -0
  77. package/esm2022/services/http/http.mjs +12 -3
  78. package/esm2022/services/http/middleware.mjs +56 -2
  79. package/esm2022/services/navvy/navvy-pag-nav-keyed.mjs +31 -0
  80. package/esm2022/services/navvy.mjs +20 -6
  81. package/esm2022/typification/rest/crm/requisite.mjs +1 -1
  82. package/esm2022/typification/rest/crm/timeline/bindings.mjs +1 -1
  83. package/esm2022/typification/rest/pull/application/config/get.mjs +1 -1
  84. package/esm2022/typification/rest/pull/application/event/add.mjs +2 -0
  85. package/esm2022/typification/rest/pull/application/push/add.mjs +2 -0
  86. package/esm2022/typification/rest/pull/config/get.mjs +1 -1
  87. package/esm2022/typification/rest/pull.mjs +3 -1
  88. package/esm2022/typification/settings.mjs +1 -1
  89. package/fesm2022/bx-rest.mjs +365 -140
  90. package/fesm2022/bx-rest.mjs.map +1 -1
  91. package/map/pull/application/config.d.ts +3 -0
  92. package/package.json +1 -1
  93. package/public-api.d.ts +2 -1
  94. package/request-navvy/booking/v1/resource.d.ts +1 -1
  95. package/request-navvy/booking/v1/resourcetype.d.ts +1 -1
  96. package/request-navvy/catalog/catalog.d.ts +1 -1
  97. package/request-navvy/catalog/document/element.d.ts +1 -1
  98. package/request-navvy/catalog/document.d.ts +1 -1
  99. package/request-navvy/catalog/documentcontractor.d.ts +1 -1
  100. package/request-navvy/catalog/extra.d.ts +1 -1
  101. package/request-navvy/catalog/measure.d.ts +1 -1
  102. package/request-navvy/catalog/price.d.ts +1 -1
  103. package/request-navvy/catalog/pricetype.d.ts +1 -1
  104. package/request-navvy/catalog/pricetypegroup.d.ts +1 -1
  105. package/request-navvy/catalog/pricetypelang.d.ts +1 -1
  106. package/request-navvy/catalog/product/offer.d.ts +1 -1
  107. package/request-navvy/catalog/product/service.d.ts +1 -1
  108. package/request-navvy/catalog/product/sku.d.ts +1 -1
  109. package/request-navvy/catalog/product.d.ts +1 -1
  110. package/request-navvy/catalog/productproperty.d.ts +1 -1
  111. package/request-navvy/catalog/productpropertyenum.d.ts +1 -1
  112. package/request-navvy/catalog/productpropertyfeature.d.ts +1 -1
  113. package/request-navvy/catalog/productpropertysection.d.ts +1 -1
  114. package/request-navvy/catalog/ratio.d.ts +1 -1
  115. package/request-navvy/catalog/roundingrule.d.ts +1 -1
  116. package/request-navvy/catalog/section.d.ts +1 -1
  117. package/request-navvy/catalog/store.d.ts +1 -1
  118. package/request-navvy/catalog/storeproduct.d.ts +1 -1
  119. package/request-navvy/catalog/userfield/document.d.ts +1 -1
  120. package/request-navvy/catalog/vat.d.ts +1 -1
  121. package/request-navvy/crm/activity.d.ts +1 -1
  122. package/request-navvy/crm/deal/recurring.d.ts +1 -1
  123. package/request-navvy/crm/item/product/row.d.ts +5 -1
  124. package/request-navvy/crm/orderentity.d.ts +5 -1
  125. package/request-navvy/crm/requisite/link.d.ts +1 -1
  126. package/request-navvy/crm/stagehistory.d.ts +5 -1
  127. package/request-navvy/crm/timeline/bindings.d.ts +1 -1
  128. package/request-navvy/documentgenerator/document.d.ts +1 -1
  129. package/request-navvy/documentgenerator/numerator.d.ts +1 -1
  130. package/request-navvy/documentgenerator/role.d.ts +1 -1
  131. package/request-navvy/documentgenerator/template.d.ts +1 -1
  132. package/request-navvy/pull/application/config.d.ts +9 -3
  133. package/request-navvy/pull/application/event.d.ts +17 -0
  134. package/request-navvy/pull/application/push.d.ts +17 -0
  135. package/request-navvy/pull/config.d.ts +7 -3
  136. package/request-navvy/pull.d.ts +11 -0
  137. package/request-navvy/sale/basketitem.d.ts +1 -1
  138. package/request-navvy/sale/basketproperties.d.ts +1 -1
  139. package/request-navvy/sale/businessvaluepersondomain.d.ts +1 -1
  140. package/request-navvy/sale/order.d.ts +1 -1
  141. package/request-navvy/sale/payment.d.ts +1 -1
  142. package/request-navvy/sale/paymentitembasket.d.ts +1 -1
  143. package/request-navvy/sale/paymentitemshipment.d.ts +1 -1
  144. package/request-navvy/sale/persontype.d.ts +1 -1
  145. package/request-navvy/sale/property.d.ts +1 -1
  146. package/request-navvy/sale/propertyrelation.d.ts +1 -1
  147. package/request-navvy/sale/propertyvalue.d.ts +1 -1
  148. package/request-navvy/sale/propertyvariant.d.ts +1 -1
  149. package/request-navvy/sale/shipment.d.ts +1 -1
  150. package/request-navvy/sale/shipmentitem.d.ts +1 -1
  151. package/request-navvy/sale/shipmentproperty.d.ts +1 -1
  152. package/request-navvy/sale/shipmentpropertyvalue.d.ts +1 -1
  153. package/request-navvy/sale/status.d.ts +1 -1
  154. package/request-navvy/sale/statuslang.d.ts +1 -1
  155. package/request-navvy/sale/tradebinding.d.ts +1 -1
  156. package/request-navvy/sale/tradeplatform.d.ts +1 -1
  157. package/request-navvy/task/operation/elapseditem.d.ts +15 -10
  158. package/request-navvy/userfieldtype.d.ts +1 -1
  159. package/services/http/HttpBX.d.ts +5 -4
  160. package/services/http/fetch.d.ts +22 -0
  161. package/services/http/http.d.ts +8 -0
  162. package/services/http/middleware.d.ts +2 -1
  163. package/services/navvy/navvy-pag-nav-keyed.d.ts +18 -0
  164. package/services/navvy.d.ts +16 -0
  165. package/typification/rest/crm/requisite.d.ts +1 -1
  166. package/typification/rest/crm/timeline/bindings.d.ts +2 -1
  167. package/typification/rest/pull/application/config/get.d.ts +1 -1
  168. package/typification/rest/pull/application/event/add.d.ts +24 -0
  169. package/typification/rest/pull/application/push/add.d.ts +16 -0
  170. package/typification/rest/pull/config/get.d.ts +28 -3
  171. package/typification/rest/pull.d.ts +2 -0
  172. package/typification/settings.d.ts +35 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,75 @@
7
7
  История до версии 1.0.0 здесь не восстанавливалась — смотрите `git log` для
8
8
  более ранних изменений.
9
9
 
10
+ ## [1.7.0] - 2026-11-11
11
+
12
+ ### Added
13
+
14
+ - `.resAll()` у 59 списочных методов, которые листаются через `start`:
15
+ `catalog.*.list` (25 методов), `sale.*.list` (20),
16
+ `documentgenerator.{document,numerator,role,template}.list`,
17
+ `booking.v1.resource.list`, `booking.v1.resourcetype.list`,
18
+ `crm.activity.list`, `crm.item.productrow.list`, `crm.orderentity.list`,
19
+ `crm.stagehistory.list`, `crm.timeline.bindings.list`,
20
+ `crm.requisite.link.list`, `crm.deal.recurring.list` и `userfieldtype.list`.
21
+ Список сверен с документацией Bitrix24. `.res()` у этих методов не
22
+ изменился. Если `result` метода — объект со списком под ключом, как у
23
+ `catalog.product.list` (`{ products: [...] }`), `.resAll()` отдаёт такой же
24
+ объект, где под ключом собраны записи всех страниц. Подробнее — в разделе
25
+ README «Режимы результата».
26
+ - `Navvy.pagNavKeyed()` и класс `NavvyPagNavKeyed` — пагинация для своих
27
+ методов, у которых `result` — объект со списком под ключом.
28
+ - `pull.application.event.add()` — событие в канал приложения, и
29
+ `pull.application.push.add()` — push-уведомление в мобильное приложение.
30
+ Типы параметров: `iBXRestParamPullApplicationEventAdd`,
31
+ `iBXRestParamPullApplicationPushAdd`.
32
+ - `pull.application.config.get()` и `pull.config.get()` принимают
33
+ необязательные параметры `CACHE` и `REOPEN` (тип `iBXRestParamPullConfigGet`).
34
+ В типах ответа появились поля `exp`, `clientId` и `jwt`. Подробнее — в
35
+ разделе README «Push & Pull».
36
+ - Настройка `logRequests` — журнал запросов: функция получает запись о каждом
37
+ HTTP-запросе (метод, адрес, длительность, статус, код ошибки Bitrix). Тип
38
+ записи `BXRestRequestLogEntry`. Адрес в записи не маскируется. Подробнее — в
39
+ разделе README «Журнал запросов».
40
+ - Настройка `transport: 'fetch'` — отправка запросов через глобальный `fetch`
41
+ вместо axios. Ответ не 2xx приходит ошибкой `BXRestHttpError` с полем
42
+ `response: { status, data }`. Подробнее — в разделе README «Транспорт fetch».
43
+ - `new Navvy(settings)` и `new BXRestRequest(settings)` — свои настройки, как у
44
+ `new BXRestNavvy(settings)`. Без аргумента оба работают с глобальными
45
+ `BXRestSettings`, как раньше.
46
+
47
+ ### Changed
48
+
49
+ - Тип результата `.res()` у `crm.item.productrow.list`, `crm.orderentity.list`
50
+ и `crm.stagehistory.list` исправлен на объект: `{ productRows }`,
51
+ `{ orderEntity }` и `{ items }`. Раньше тип обещал массив, хотя портал
52
+ отдаёт объект, и само значение не изменилось. Код, который работал с
53
+ результатом как с массивом, перестанет компилироваться: во время выполнения
54
+ он и раньше не работал.
55
+ - Тип результата `userfieldtype.list().res()` исправлен на массив: портал
56
+ отдаёт массив.
57
+ - Типы параметров `crm.timeline.bindings.list` и `crm.requisite.link.list`
58
+ принимают `start`.
59
+ - В сырых типах ответа `iBXRestPullConfigGetHttp` и
60
+ `iBXRestPullApplicationConfigGetHttp` поле `publicChannels` может быть
61
+ `false`: так портал отвечает при версии сервера Push & Pull ниже 4. После
62
+ маппера `.res()` такое значение становится пустым объектом.
63
+
64
+ ### Fixed
65
+
66
+ - `task.elapsedItem.operation.getListByIDTask()` загружает все записи каждой
67
+ задачи. Раньше метод запрашивал одну страницу с `nPageSize: 99999`, а по
68
+ документации портал отдаёт не больше 50 записей на страницу, поэтому у
69
+ задачи с большим числом записей часть могла пропасть без ошибки. Теперь
70
+ первые страницы всех задач уходят одним batch, как раньше, а остальные
71
+ страницы догружаются только для задач, где записей больше 50.
72
+ - Публичное поле `pull.channel.public.url.get` указывало на `log.blogpost.add`.
73
+ Теперь там `pull.channel.public.get`, сам запрос и раньше шёл на этот метод.
74
+ - Мапперы `pull.application.config.get()` и `pull.config.get()` больше не
75
+ падают с `TypeError`, если в ответе нет `publicChannels` или одного из
76
+ каналов, и с `Wrong date format`, если в ответе `pull.config.get` нет
77
+ `serverTime`.
78
+
10
79
  ## [1.6.0] - 2026-11-10
11
80
 
12
81
  ### Added
package/README.en.md CHANGED
@@ -26,6 +26,8 @@ Also known as: Bitrix24 REST client, BX24 REST SDK, Bitrix24 API client, Bitrix
26
26
  - [Recipe: through a backend proxy](#recipe-through-a-backend-proxy)
27
27
  - [Several portals](#several-portals)
28
28
  - [Retry, timeout and request queue](#retry-timeout-and-request-queue)
29
+ - [Request log](#request-log)
30
+ - [The fetch transport](#the-fetch-transport)
29
31
  - [Your own middleware](#your-own-middleware)
30
32
  - [Working in an iframe without BX24.js](#working-in-an-iframe-without-bx24js)
31
33
  - [Usage in Angular](#usage-in-angular)
@@ -39,6 +41,7 @@ Also known as: Bitrix24 REST client, BX24 REST SDK, Bitrix24 API client, Bitrix
39
41
  - [A paginated custom method with `pagNav()`](#a-paginated-custom-method-with-pagnav)
40
42
  - [Specific methods](#specific-methods)
41
43
  - [`tasks.task.list`](#taskstasklist)
44
+ - [Push & Pull](#push--pull)
42
45
  - [Date parsing](#date-parsing)
43
46
  - [Future features](#future-features)
44
47
  - [License](#license)
@@ -101,7 +104,7 @@ REST calls are lazy: the request starts when the returned `Observable` is subscr
101
104
  | Method | Result |
102
105
  | --- | --- |
103
106
  | `.res(options?)` | Unwraps the Bitrix response and applies the configured mapper. For paginated methods it returns the current page. |
104
- | `.resAll()` | Loads and combines every page. Available on paginated Navvy helpers. |
107
+ | `.resAll()` | Loads and combines every page. Available on paged list methods, see below. |
105
108
  | `.resVanilla()` | Returns the raw Bitrix response, including fields such as `result`, `total` and `next`. |
106
109
  | `.mapForVanilla()` | Keeps the raw response envelope but applies the mapper to its `result`. |
107
110
 
@@ -111,6 +114,13 @@ REST calls are lazy: the request starts when the returned `Observable` is subscr
111
114
  | --- | --- | --- |
112
115
  | `throwOnApiError` | `false` | When `true`, a Bitrix-level API error makes the returned `Observable` error out with a `BXRestApiError` instead of resolving with `undefined`. See [Error handling](#error-handling). |
113
116
 
117
+ `.resAll()` exists on list methods that page through `start`. It requests the first page itself and the rest in packs through `batch`. The result has the same shape as `.res()`:
118
+
119
+ - if the method returns an array (`crm.deal.list`, `crm.activity.list`), `.resAll()` returns an array of all records;
120
+ - if `result` is an object with the list under a key, as with `catalog.product.list` (`{ products: [...] }`) or `sale.order.list` (`{ orders: [...] }`), `.resAll()` returns the same object with the records of all pages under that key.
121
+
122
+ Methods that return the whole list in one response or page in another way (`OFFSET`/`LIMIT`, a page number, the REST v3 `pagination` object) have no `.resAll()`. They are listed with reasons in [list-pagination.spec.ts](https://github.com/Aricatofuka/bx-rest/blob/main/projects/bx-rest/src/rest/list-pagination.spec.ts).
123
+
114
124
  ## Authentication and OAuth2
115
125
 
116
126
  `auth.source` controls where credentials are read from. `auth.key` controls the request parameter name, except for the special `OAuth2` cookie-credentials mode.
@@ -454,7 +464,7 @@ const deals = await firstValueFrom(
454
464
  - **Another portal or other headers** — create a new client, it takes a fraction of a millisecond.
455
465
  - **Authorization refresh** is per client: a client's `auth.refresh` is called only for its own requests.
456
466
  - **`auth.source: 'cookies'` and `'localStorage'`** read the shared browser storage, so two clients with the same key get the same token. For several portals, set `source` to a function.
457
- - **Objects created directly** — `new Navvy()`, `new BXRestRequest()`, `new SessionKeyServices()` — use the global `BXRestSettings`. Only `BXRestNavvy` and everything created through it get the client's own settings.
467
+ - **Objects created directly** — `new Navvy()` and `new BXRestRequest()` — use the global `BXRestSettings` when called without an argument. They also accept their own settings: `new Navvy(settings)`, `new BXRestRequest(settings)`. Such an object has its own `throttle` queue and authorization refresh, even if a `BXRestNavvy` client has the same settings. `new SessionKeyServices()` always uses the global settings.
458
468
 
459
469
  ## Retry, timeout and request queue
460
470
 
@@ -476,13 +486,49 @@ BXRestSettings.update({
476
486
 
477
487
  An object may set only some fields: `retryOnQueryLimit: { attempts: 5 }` keeps `delay: 1000`.
478
488
 
479
- - **Order:** retry, queue, timeout, [your own middleware](#your-own-middleware), axios. Every retry attempt queues again and gets its own `timeout`. Waiting in the queue and pauses before a retry do not count towards `timeout`.
489
+ - **Order:** retry, queue, timeout, [log](#request-log), [your own middleware](#your-own-middleware), [transport](#the-fetch-transport). Every retry attempt queues again and gets its own `timeout`. Waiting in the queue and pauses before a retry do not count towards `timeout`.
480
490
  - **The queue** belongs to each `new BXRestNavvy(settings)` client and is shared by everything that uses the global `BXRestSettings`. Every request goes through it, including every batch request of `.resAll()`.
481
491
  - **`throttle` is stricter than the portal.** Bitrix24 lets short bursts above the limit through, while `throttle` spreads all requests evenly. If short bursts of requests need to be fast, `retryOnQueryLimit` alone is enough.
482
492
  - **Unsubscribing** stops both the wait in the queue and the pause before a retry: such a request is never sent.
483
493
  - **Settings are read at subscribe time**, like the rest.
484
494
  - **An invalid value** — for example `throttle: { perSecond: 0 }` or a negative `timeout` — fails the request with a `TypeError` that describes it; nothing is sent to the portal.
485
495
 
496
+ ### Request log
497
+
498
+ `logRequests` is a function that receives an entry for every HTTP request once it finishes. It is set the same way, globally or per client:
499
+
500
+ ```typescript
501
+ BXRestSettings.update({
502
+ logRequests: entry => console.debug(entry.method, entry.url, `${entry.duration} ms`, entry.failed ? entry.error : 'ok'),
503
+ })
504
+ ```
505
+
506
+ | Field | What it holds |
507
+ | --- | --- |
508
+ | `method` | `'GET'` or `'POST'`. |
509
+ | `url` | The full request address. |
510
+ | `duration` | Time from sending to the response or error, ms. |
511
+ | `failed` | `true` if the request failed: a non-2xx response, a network failure, a timeout or a cancel. |
512
+ | `status` | The HTTP status of a failed response. The transport does not report the status of a successful one. |
513
+ | `error` | The Bitrix error code from the response body, such as `QUERY_LIMIT_EXCEEDED`, including one from a 2xx response. If the portal sent no code, the error message. |
514
+
515
+ - **One entry per HTTP request:** every `retryOnQueryLimit` attempt and every batch request of `.resAll()` is its own entry. Waiting in the `throttle` queue does not count towards `duration`.
516
+ - **The address is as is.** The request body is not in the entry, but a webhook keeps its secret in the address, and a GET request keeps the token there. If the log goes to a third-party system, remove them yourself.
517
+ - **An exception from the function** does not affect the request.
518
+
519
+ ### The fetch transport
520
+
521
+ By default axios sends the requests. With `transport: 'fetch'` the global `fetch` of the browser or Node 18+ sends them:
522
+
523
+ ```typescript
524
+ const portal = new BXRestNavvy({ ...settings, transport: 'fetch' })
525
+ ```
526
+
527
+ The result is the same as with axios; only transport errors differ:
528
+
529
+ - on a non-2xx response `.resVanilla()` fails with a `BXRestHttpError` that has `response: { status, data }`, like `AxiosError`; in `.res()` it is in the `cause` of `BXRestApiError`;
530
+ - a network failure comes as the error of `fetch` itself (usually a `TypeError`), without the `request` field axios has.
531
+
486
532
  ### Your own middleware
487
533
 
488
534
  A middleware is a function every request passes through before it is sent: logging, metrics, changing headers, your own transport instead of axios. Set it in `middleware`, globally or per client in the same way:
@@ -503,7 +549,7 @@ BXRestSettings.update({ middleware: [logDuration] })
503
549
  ```
504
550
 
505
551
  - **`config`** is the request: `method` (`'GET'` or `'POST'`), `url` (with the parameters for GET), `data` (the POST body), `headers`, `withCredentials`, `signal`. `next(config)` sends it on and returns the response body.
506
- - **Order:** the first in the list is the outermost one: it sees the request first and the response last. All your middleware run after `retryOnQueryLimit`, `throttle` and `timeout`, so they see every retry attempt. The retry after `auth.refresh` wraps all the steps: on an authorization refresh the request passes through them again.
552
+ - **Order:** the first in the list is the outermost one: it sees the request first and the response last. All your middleware run after `retryOnQueryLimit`, `throttle`, `timeout` and `logRequests`, so they see every retry attempt. The retry after `auth.refresh` wraps all the steps: on an authorization refresh the request passes through them again.
507
553
  - **To change the request**, pass a new object on: `next({ ...config, headers: { ...config.headers, 'X-Trace': id } })`.
508
554
  - **Your own transport** is a middleware that does not call `next`: it sends the request itself and returns the response body. For a non-2xx response it must reject with an error that has a `response: { status, data }` field, as axios does. The library uses that field to recognize Bitrix errors (`BXRestApiError`) and authorization errors (`auth.refresh`).
509
555
  - **Pass `config.signal`** to your transport: it aborts the request on unsubscribe and on `timeout`.
@@ -888,6 +934,18 @@ export class BXRestNavvyCustomApiBlogList {
888
934
 
889
935
  The returned helper additionally supports `.resAll()` for loading and combining all pages.
890
936
 
937
+ If the method's `result` is an object with the list under a key, such as `{ items: [...] }`, use `pagNavKeyed()`: its third argument is the list key. `.res()` returns the object as is, `.resAll()` the same object with the records of all pages under the key:
938
+
939
+ ```typescript
940
+ type BlogItems = { items?: iBXRestCustomBlogGetHttp[] }
941
+
942
+ this.navvy.pagNavKeyed<BlogItems, BlogItems, iBXRestCustomParamBlogList>(
943
+ ['blog', 'item', PNM.$list],
944
+ param,
945
+ 'items'
946
+ )
947
+ ```
948
+
891
949
  ## Specific methods
892
950
 
893
951
  ### `tasks.task.list`
@@ -939,6 +997,40 @@ const tasks$ = bxRest.tasks.task.list<
939
997
  }).res()
940
998
  ```
941
999
 
1000
+ ### Push & Pull
1001
+
1002
+ The `pull` section returns the settings for connecting to the Push & Pull server and sends application events. The library has no websocket client: connect with your own client following the [protocol description](https://apidocs.bitrix24.com/settings/interactivity/custom-push-and-pull-client.html) or with `PullClient` from [b24jssdk](https://github.com/bitrix24/b24jssdk).
1003
+
1004
+ ```typescript
1005
+ import { firstValueFrom } from 'rxjs'
1006
+ import { BXRestNavvy } from 'bx-rest'
1007
+
1008
+ const bxRest = new BXRestNavvy()
1009
+
1010
+ // Server addresses and channels for the client to connect
1011
+ const config = await firstValueFrom(bxRest.pull.application.config.get().res())
1012
+ console.log(config?.server.websocket_secure, config?.channels.private.id, config?.exp)
1013
+
1014
+ // An event in the shared channel of the application: every subscribed client gets it
1015
+ await firstValueFrom(bxRest.pull.application.event.add({
1016
+ COMMAND: 'grid:update',
1017
+ PARAMS: { grid_id: 15 },
1018
+ }).res())
1019
+ ```
1020
+
1021
+ | Method | What it does |
1022
+ | --- | --- |
1023
+ | `pull.application.config.get(param?)` | Connection settings for the application: server addresses, the `shared` and `private` channels, public channels, `exp`, and with the right server version `clientId` or `jwt`. Channel dates are `Date`. |
1024
+ | `pull.application.event.add(param)` | An event in the application channel: without `USER_ID` in the shared `shared` channel, with it in the users' personal channels. |
1025
+ | `pull.application.push.add(param)` | A push notification to the Bitrix24 mobile app. For portal administrators only. |
1026
+ | `pull.config.get(param?)` | Connection settings for a user. The method is not in the Bitrix24 documentation, so it is marked `@experimental`. |
1027
+ | `pull.channel.public.get()` | A public Push & Pull channel. |
1028
+
1029
+ - **`pull.application.*` methods** work only in an application context, with its OAuth token. Through a webhook the portal answers `WRONG_AUTH_TYPE`.
1030
+ - **`true` in the response** of `event.add` and `push.add` means "accepted for sending", not "delivered".
1031
+ - **`USER_ID` for a non-administrator.** They can send an event only to themselves, and `USER_ID` must then be a string: `'577'`. The portal rejects a number or an array with `USER_ID_ACCESS_ERROR`.
1032
+ - **The settings are personal:** the `private` channel belongs to the user whose token makes the request. Request them again when `exp` or the channels' `end` expires.
1033
+
942
1034
  ## Date parsing
943
1035
 
944
1036
  Some Bitrix24 REST fields (notably `calendar.section.get`, `calendar.event.get` and `crm.calllist.*`) return dates as plain strings formatted according to the portal's own date/time settings (Settings → date and time format) — not a fixed ISO format. Because that format is a per-portal setting, `bx-rest` can't know it in advance, so `BXBaseServices.toDate()` (used internally by these mappers) resolves an ambiguous string in three steps, in order:
package/README.md CHANGED
@@ -26,6 +26,8 @@
26
26
  - [Рецепт: через бэкенд-прокси](#рецепт-через-бэкенд-прокси)
27
27
  - [Несколько порталов](#несколько-порталов)
28
28
  - [Повтор, таймаут и очередь запросов](#повтор-таймаут-и-очередь-запросов)
29
+ - [Журнал запросов](#журнал-запросов)
30
+ - [Транспорт fetch](#транспорт-fetch)
29
31
  - [Свои middleware](#свои-middleware)
30
32
  - [Работа в iframe без BX24.js](#работа-в-iframe-без-bx24js)
31
33
  - [Использование в Angular](#использование-в-angular)
@@ -39,6 +41,7 @@
39
41
  - [Пагинированный кастомный метод с `pagNav()`](#пагинированный-кастомный-метод-с-pagnav)
40
42
  - [Специфичные методы](#специфичные-методы)
41
43
  - [`tasks.task.list`](#taskstasklist)
44
+ - [Push & Pull](#push--pull)
42
45
  - [Парсинг дат](#парсинг-дат)
43
46
  - [Планы на будущее](#планы-на-будущее)
44
47
  - [Лицензия](#лицензия)
@@ -111,7 +114,7 @@ REST-вызовы ленивые: запрос начинается, когда
111
114
  | Метод | Результат |
112
115
  | --- | --- |
113
116
  | `.res(options?)` | Разворачивает ответ Bitrix и применяет настроенный маппер. Для пагинированных методов возвращает текущую страницу. |
114
- | `.resAll()` | Загружает и объединяет все страницы. Доступен для пагинированных Navvy-хелперов. |
117
+ | `.resAll()` | Загружает и объединяет все страницы. Доступен у списочных методов с постраничной навигацией, подробнее ниже. |
115
118
  | `.resVanilla()` | Возвращает сырой ответ Bitrix, включая такие поля, как `result`, `total` и `next`. |
116
119
  | `.mapForVanilla()` | Сохраняет исходную обёртку ответа, но применяет маппер к её `result`. |
117
120
 
@@ -121,6 +124,13 @@ REST-вызовы ленивые: запрос начинается, когда
121
124
  | --- | --- | --- |
122
125
  | `throwOnApiError` | `false` | При `true` ошибка API-уровня Bitrix приводит к тому, что возвращённый `Observable` завершается ошибкой `BXRestApiError` вместо резолва в `undefined`. См. [Обработка ошибок](#обработка-ошибок). |
123
126
 
127
+ `.resAll()` есть у списочных методов, которые листаются через `start`. Первую страницу он запрашивает сам, остальные — пакетами через `batch`. Результат такой же формы, как у `.res()`:
128
+
129
+ - если метод отдаёт массив (`crm.deal.list`, `crm.activity.list`), `.resAll()` отдаёт массив всех записей;
130
+ - если `result` — объект со списком под ключом, как у `catalog.product.list` (`{ products: [...] }`) или `sale.order.list` (`{ orders: [...] }`), `.resAll()` отдаёт такой же объект, где под ключом собраны записи всех страниц.
131
+
132
+ У методов, которые отдают весь список одним ответом или листаются иначе (`OFFSET`/`LIMIT`, номер страницы, объект `pagination` в REST v3), `.resAll()` нет. Они перечислены с причинами в [list-pagination.spec.ts](https://github.com/Aricatofuka/bx-rest/blob/main/projects/bx-rest/src/rest/list-pagination.spec.ts).
133
+
124
134
  ## Аутентификация и OAuth2
125
135
 
126
136
  `auth.source` определяет, откуда читаются учётные данные. `auth.key` определяет имя параметра запроса, за исключением специального режима учётных данных через куки `OAuth2`.
@@ -464,7 +474,7 @@ const deals = await firstValueFrom(
464
474
  - **Другой портал или другие заголовки** — создайте новый клиент, это занимает доли миллисекунды.
465
475
  - **Продление авторизации** у каждого клиента своё: `auth.refresh` клиента вызывается только для его запросов.
466
476
  - **`auth.source: 'cookies'` и `'localStorage'`** читают общее хранилище браузера, поэтому два клиента с одним ключом получат один и тот же токен. Для нескольких порталов задавайте `source` функцией.
467
- - **Объекты, созданные напрямую**, — `new Navvy()`, `new BXRestRequest()`, `new SessionKeyServices()` — работают с глобальными `BXRestSettings`. Свои настройки получает только `BXRestNavvy` и всё, что создаётся через него.
477
+ - **Объекты, созданные напрямую**, — `new Navvy()` и `new BXRestRequest()` — без аргумента работают с глобальными `BXRestSettings`. Им тоже можно передать свои настройки: `new Navvy(settings)`, `new BXRestRequest(settings)`. Очередь `throttle` и продление авторизации у такого объекта свои, даже если у клиента `BXRestNavvy` те же настройки. `new SessionKeyServices()` всегда работает с глобальными.
468
478
 
469
479
  ## Повтор, таймаут и очередь запросов
470
480
 
@@ -486,13 +496,49 @@ BXRestSettings.update({
486
496
 
487
497
  В объекте можно задать только часть полей: `retryOnQueryLimit: { attempts: 5 }` оставит `delay: 1000`.
488
498
 
489
- - **Порядок:** повтор, очередь, таймаут, [свои middleware](#свои-middleware), axios. Каждая попытка повтора заново встаёт в очередь и получает своё время `timeout`. Ожидание в очереди и паузы перед повтором в `timeout` не входят.
499
+ - **Порядок:** повтор, очередь, таймаут, [журнал](#журнал-запросов), [свои middleware](#свои-middleware), [транспорт](#транспорт-fetch). Каждая попытка повтора заново встаёт в очередь и получает своё время `timeout`. Ожидание в очереди и паузы перед повтором в `timeout` не входят.
490
500
  - **Очередь** своя у каждого клиента `new BXRestNavvy(settings)` и общая у всех, кто работает с глобальными `BXRestSettings`. Через неё проходит каждый запрос, в том числе каждый batch-запрос `.resAll()`.
491
501
  - **`throttle` строже портала.** Bitrix24 пропускает короткие всплески сверх лимита, а `throttle` равномерно распределяет все запросы. Если важна скорость коротких пачек запросов, хватит одного `retryOnQueryLimit`.
492
502
  - **Отписка** прерывает и ожидание в очереди, и паузу перед повтором: такой запрос уже не уйдёт.
493
503
  - **Настройки читаются в момент подписки**, как и остальные.
494
504
  - **Неверное значение** — например, `throttle: { perSecond: 0 }` или отрицательный `timeout` — завершает запрос ошибкой `TypeError` с описанием, на портал ничего не уходит.
495
505
 
506
+ ### Журнал запросов
507
+
508
+ `logRequests` — функция, которая получает запись о каждом HTTP-запросе после его завершения. Задаётся так же, глобально или у клиента:
509
+
510
+ ```typescript
511
+ BXRestSettings.update({
512
+ logRequests: entry => console.debug(entry.method, entry.url, `${entry.duration} ms`, entry.failed ? entry.error : 'ok'),
513
+ })
514
+ ```
515
+
516
+ | Поле | Что в нём |
517
+ | --- | --- |
518
+ | `method` | `'GET'` или `'POST'`. |
519
+ | `url` | Полный адрес запроса. |
520
+ | `duration` | Время от отправки до ответа или ошибки, мс. |
521
+ | `failed` | `true`, если запрос завершился ошибкой: ответ не 2xx, сбой сети, таймаут или отмена. |
522
+ | `status` | HTTP-статус ответа с ошибкой. У успешного ответа транспорт статус не сообщает. |
523
+ | `error` | Код ошибки Bitrix из тела ответа, например `QUERY_LIMIT_EXCEEDED`, в том числе из ответа 2xx. Если портал кода не прислал — текст ошибки. |
524
+
525
+ - **Запись на каждый HTTP-запрос:** каждая попытка `retryOnQueryLimit` и каждый batch-запрос `.resAll()` — отдельная запись. Ожидание в очереди `throttle` в `duration` не входит.
526
+ - **Адрес — как есть.** Тела запроса в записи нет, но у вебхука секрет лежит в адресе, а у GET-запроса в адресе токен. Если журнал уходит в стороннюю систему, уберите их сами.
527
+ - **Исключение из функции** на запрос не влияет.
528
+
529
+ ### Транспорт fetch
530
+
531
+ По умолчанию запросы отправляет axios. С `transport: 'fetch'` их отправляет глобальный `fetch` браузера или Node 18+:
532
+
533
+ ```typescript
534
+ const portal = new BXRestNavvy({ ...settings, transport: 'fetch' })
535
+ ```
536
+
537
+ Результат тот же, что с axios, разница только в ошибках транспорта:
538
+
539
+ - на ответ не 2xx `.resVanilla()` завершается ошибкой `BXRestHttpError` с полем `response: { status, data }`, как у `AxiosError`; в `.res()` она лежит в `cause` у `BXRestApiError`;
540
+ - сбой сети приходит ошибкой самого `fetch` (обычно `TypeError`), поля `request`, как у axios, у неё нет.
541
+
496
542
  ### Свои middleware
497
543
 
498
544
  Middleware — функция, через которую проходит каждый запрос перед отправкой: логирование, метрики, подмена заголовков, свой транспорт вместо axios. Задаётся в `middleware` — так же глобально или у клиента:
@@ -513,7 +559,7 @@ BXRestSettings.update({ middleware: [logDuration] })
513
559
  ```
514
560
 
515
561
  - **`config`** — запрос: `method` (`'GET'` или `'POST'`), `url` (у GET вместе с параметрами), `data` (тело POST), `headers`, `withCredentials`, `signal`. `next(config)` отправляет его дальше и возвращает тело ответа.
516
- - **Порядок:** первый в списке — внешний, он первым видит запрос и последним — ответ. Все свои middleware идут после `retryOnQueryLimit`, `throttle` и `timeout`, поэтому видят каждую попытку повтора. Повтор после `auth.refresh` идёт снаружи всех шагов: при продлении авторизации запрос пройдёт через них ещё раз.
562
+ - **Порядок:** первый в списке — внешний, он первым видит запрос и последним — ответ. Все свои middleware идут после `retryOnQueryLimit`, `throttle`, `timeout` и `logRequests`, поэтому видят каждую попытку повтора. Повтор после `auth.refresh` идёт снаружи всех шагов: при продлении авторизации запрос пройдёт через них ещё раз.
517
563
  - **Изменить запрос** — передать дальше новый объект: `next({ ...config, headers: { ...config.headers, 'X-Trace': id } })`.
518
564
  - **Свой транспорт** — middleware, который не зовёт `next`: он сам отправляет запрос и возвращает тело ответа. На ответ не 2xx он должен отклонить промис ошибкой с полем `response: { status, data }`, как это делает axios. По этому полю библиотека узнаёт ошибки Bitrix (`BXRestApiError`) и ошибки авторизации (`auth.refresh`).
519
565
  - **`config.signal`** передавайте в свой транспорт: по нему запрос отменяется при отписке и по `timeout`.
@@ -899,6 +945,18 @@ export class BXRestNavvyCustomApiBlogList {
899
945
 
900
946
  Возвращённый хелпер дополнительно поддерживает `.resAll()` для загрузки и объединения всех страниц.
901
947
 
948
+ Если `result` метода — объект со списком под ключом, например `{ items: [...] }`, используйте `pagNavKeyed()`: третий аргумент — ключ списка. `.res()` отдаёт объект как есть, `.resAll()` — такой же объект с записями всех страниц под ключом:
949
+
950
+ ```typescript
951
+ type BlogItems = { items?: iBXRestCustomBlogGetHttp[] }
952
+
953
+ this.navvy.pagNavKeyed<BlogItems, BlogItems, iBXRestCustomParamBlogList>(
954
+ ['blog', 'item', PNM.$list],
955
+ param,
956
+ 'items'
957
+ )
958
+ ```
959
+
902
960
  ## Специфичные методы
903
961
 
904
962
  ### `tasks.task.list`
@@ -950,6 +1008,40 @@ const tasks$ = bxRest.tasks.task.list<
950
1008
  }).res()
951
1009
  ```
952
1010
 
1011
+ ### Push & Pull
1012
+
1013
+ Раздел `pull` отдаёт настройки подключения к серверу Push & Pull и отправляет события приложения. Клиента веб-сокета в библиотеке нет: подключайтесь своим клиентом по [описанию протокола](https://apidocs.bitrix24.com/settings/interactivity/custom-push-and-pull-client.html) или клиентом `PullClient` из [b24jssdk](https://github.com/bitrix24/b24jssdk).
1014
+
1015
+ ```typescript
1016
+ import { firstValueFrom } from 'rxjs'
1017
+ import { BXRestNavvy } from 'bx-rest'
1018
+
1019
+ const bxRest = new BXRestNavvy()
1020
+
1021
+ // Адреса сервера и каналы для подключения клиента
1022
+ const config = await firstValueFrom(bxRest.pull.application.config.get().res())
1023
+ console.log(config?.server.websocket_secure, config?.channels.private.id, config?.exp)
1024
+
1025
+ // Событие в общий канал приложения: его получат все подписанные клиенты
1026
+ await firstValueFrom(bxRest.pull.application.event.add({
1027
+ COMMAND: 'grid:update',
1028
+ PARAMS: { grid_id: 15 },
1029
+ }).res())
1030
+ ```
1031
+
1032
+ | Метод | Что делает |
1033
+ | --- | --- |
1034
+ | `pull.application.config.get(param?)` | Настройки подключения для приложения: адреса сервера, каналы `shared` и `private`, публичные каналы, `exp`, при нужной версии сервера — `clientId` или `jwt`. Даты каналов — `Date`. |
1035
+ | `pull.application.event.add(param)` | Событие в канал приложения: без `USER_ID` — в общий канал `shared`, с ним — в личные каналы пользователей. |
1036
+ | `pull.application.push.add(param)` | Push-уведомление в мобильное приложение Bitrix24. Только для администратора портала. |
1037
+ | `pull.config.get(param?)` | Настройки подключения для пользователя. Метода нет в документации Bitrix24, поэтому он помечен `@experimental`. |
1038
+ | `pull.channel.public.get()` | Публичный канал Push & Pull. |
1039
+
1040
+ - **Методы `pull.application.*`** работают только в контексте приложения, с его OAuth-токеном. Через вебхук портал отвечает `WRONG_AUTH_TYPE`.
1041
+ - **`true` в ответе** `event.add` и `push.add` значит «принято к отправке», а не «доставлено».
1042
+ - **`USER_ID` у не администратора.** Отправить событие можно только себе, и `USER_ID` при этом — строка: `'577'`. Число или массив портал отклонит с ошибкой `USER_ID_ACCESS_ERROR`.
1043
+ - **Настройки личные:** канал `private` принадлежит пользователю, с чьим токеном идёт запрос. Запрашивайте их заново, когда истекут `exp` или `end` каналов.
1044
+
953
1045
  ## Парсинг дат
954
1046
 
955
1047
  Некоторые REST-поля Bitrix24 (в частности `calendar.section.get`, `calendar.event.get` и `crm.calllist.*`) возвращают даты в виде обычных строк, отформатированных согласно собственным настройкам даты/времени портала (Настройки → формат даты и времени), а не в фиксированном формате ISO. Поскольку этот формат — настройка конкретного портала, `bx-rest` не может знать его заранее, поэтому `BXBaseServices.toDate()` (используется этими мапперами внутренне) разрешает неоднозначную строку в три шага, по порядку:
@@ -105,6 +105,7 @@ export declare const $pull = "pull";
105
105
  export declare const $channel = "channel";
106
106
  export declare const $public = "public";
107
107
  export declare const $application = "application";
108
+ export declare const $push = "push";
108
109
  export declare const $dialog = "dialog";
109
110
  export declare const $users = "users";
110
111
  export declare const $messages = "messages";