@bitrix24/b24jssdk 1.2.0 → 2.0.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 (447) hide show
  1. package/README-AI.md +6 -5
  2. package/README.md +2 -0
  3. package/dist/cjs/_virtual/_commonjsHelpers.cjs +19 -0
  4. package/dist/cjs/_virtual/_commonjsHelpers.cjs.map +1 -0
  5. package/dist/cjs/_virtual/protobuf.cjs +20 -0
  6. package/dist/cjs/_virtual/protobuf.cjs.map +1 -0
  7. package/dist/cjs/_virtual/protobuf2.cjs +14 -0
  8. package/dist/cjs/_virtual/protobuf2.cjs.map +1 -0
  9. package/dist/cjs/core/abstract-b24.cjs +357 -0
  10. package/dist/cjs/core/abstract-b24.cjs.map +1 -0
  11. package/dist/cjs/core/actions/abstract-action.cjs +26 -0
  12. package/dist/cjs/core/actions/abstract-action.cjs.map +1 -0
  13. package/dist/cjs/core/actions/abstract-batch.cjs +97 -0
  14. package/dist/cjs/core/actions/abstract-batch.cjs.map +1 -0
  15. package/dist/cjs/core/actions/manager.cjs +55 -0
  16. package/dist/cjs/core/actions/manager.cjs.map +1 -0
  17. package/dist/cjs/core/actions/v2/batch-by-chunk.cjs +95 -0
  18. package/dist/cjs/core/actions/v2/batch-by-chunk.cjs.map +1 -0
  19. package/dist/cjs/core/actions/v2/batch.cjs +128 -0
  20. package/dist/cjs/core/actions/v2/batch.cjs.map +1 -0
  21. package/dist/cjs/core/actions/v2/call-list.cjs +144 -0
  22. package/dist/cjs/core/actions/v2/call-list.cjs.map +1 -0
  23. package/dist/cjs/core/actions/v2/call.cjs +56 -0
  24. package/dist/cjs/core/actions/v2/call.cjs.map +1 -0
  25. package/dist/cjs/core/actions/v2/fetch-list.cjs +145 -0
  26. package/dist/cjs/core/actions/v2/fetch-list.cjs.map +1 -0
  27. package/dist/cjs/core/actions/v2/manager-v2.cjs +76 -0
  28. package/dist/cjs/core/actions/v2/manager-v2.cjs.map +1 -0
  29. package/dist/cjs/core/actions/v3/_keyset-paginate.cjs +69 -0
  30. package/dist/cjs/core/actions/v3/_keyset-paginate.cjs.map +1 -0
  31. package/dist/cjs/core/actions/v3/aggregate.cjs +96 -0
  32. package/dist/cjs/core/actions/v3/aggregate.cjs.map +1 -0
  33. package/dist/cjs/core/actions/v3/batch-by-chunk.cjs +93 -0
  34. package/dist/cjs/core/actions/v3/batch-by-chunk.cjs.map +1 -0
  35. package/dist/cjs/core/actions/v3/batch.cjs +122 -0
  36. package/dist/cjs/core/actions/v3/batch.cjs.map +1 -0
  37. package/dist/cjs/core/actions/v3/call-list.cjs +126 -0
  38. package/dist/cjs/core/actions/v3/call-list.cjs.map +1 -0
  39. package/dist/cjs/core/actions/v3/call-tail.cjs +118 -0
  40. package/dist/cjs/core/actions/v3/call-tail.cjs.map +1 -0
  41. package/dist/cjs/core/actions/v3/call.cjs +51 -0
  42. package/dist/cjs/core/actions/v3/call.cjs.map +1 -0
  43. package/dist/cjs/core/actions/v3/fetch-list.cjs +122 -0
  44. package/dist/cjs/core/actions/v3/fetch-list.cjs.map +1 -0
  45. package/dist/cjs/core/actions/v3/fetch-tail.cjs +112 -0
  46. package/dist/cjs/core/actions/v3/fetch-tail.cjs.map +1 -0
  47. package/dist/cjs/core/actions/v3/manager-v3.cjs +100 -0
  48. package/dist/cjs/core/actions/v3/manager-v3.cjs.map +1 -0
  49. package/dist/cjs/core/http/abstract-http.cjs +641 -0
  50. package/dist/cjs/core/http/abstract-http.cjs.map +1 -0
  51. package/dist/cjs/core/http/ajax-error.cjs +113 -0
  52. package/dist/cjs/core/http/ajax-error.cjs.map +1 -0
  53. package/dist/cjs/core/http/ajax-result.cjs +219 -0
  54. package/dist/cjs/core/http/ajax-result.cjs.map +1 -0
  55. package/dist/cjs/core/http/limiters/adaptive-delayer.cjs +137 -0
  56. package/dist/cjs/core/http/limiters/adaptive-delayer.cjs.map +1 -0
  57. package/dist/cjs/core/http/limiters/manager.cjs +373 -0
  58. package/dist/cjs/core/http/limiters/manager.cjs.map +1 -0
  59. package/dist/cjs/core/http/limiters/operating-limiter.cjs +173 -0
  60. package/dist/cjs/core/http/limiters/operating-limiter.cjs.map +1 -0
  61. package/dist/cjs/core/http/limiters/params-factory.cjs +124 -0
  62. package/dist/cjs/core/http/limiters/params-factory.cjs.map +1 -0
  63. package/dist/cjs/core/http/limiters/rate-limiter.cjs +404 -0
  64. package/dist/cjs/core/http/limiters/rate-limiter.cjs.map +1 -0
  65. package/dist/cjs/core/http/redact.cjs +85 -0
  66. package/dist/cjs/core/http/redact.cjs.map +1 -0
  67. package/dist/cjs/core/http/v2.cjs +85 -0
  68. package/dist/cjs/core/http/v2.cjs.map +1 -0
  69. package/dist/cjs/core/http/v3.cjs +82 -0
  70. package/dist/cjs/core/http/v3.cjs.map +1 -0
  71. package/dist/cjs/core/interaction/batch/abstract-interaction-batch.cjs +71 -0
  72. package/dist/cjs/core/interaction/batch/abstract-interaction-batch.cjs.map +1 -0
  73. package/dist/cjs/core/interaction/batch/parse-row.cjs +69 -0
  74. package/dist/cjs/core/interaction/batch/parse-row.cjs.map +1 -0
  75. package/dist/cjs/core/interaction/batch/processing/interface-strategy.cjs +87 -0
  76. package/dist/cjs/core/interaction/batch/processing/interface-strategy.cjs.map +1 -0
  77. package/dist/cjs/core/interaction/batch/processing/v2/abstract-processing.cjs +138 -0
  78. package/dist/cjs/core/interaction/batch/processing/v2/abstract-processing.cjs.map +1 -0
  79. package/dist/cjs/core/interaction/batch/processing/v2/as-array.cjs +34 -0
  80. package/dist/cjs/core/interaction/batch/processing/v2/as-array.cjs.map +1 -0
  81. package/dist/cjs/core/interaction/batch/processing/v2/as-object.cjs +34 -0
  82. package/dist/cjs/core/interaction/batch/processing/v2/as-object.cjs.map +1 -0
  83. package/dist/cjs/core/interaction/batch/processing/v3/abstract-processing.cjs +115 -0
  84. package/dist/cjs/core/interaction/batch/processing/v3/abstract-processing.cjs.map +1 -0
  85. package/dist/cjs/core/interaction/batch/processing/v3/as-array.cjs +34 -0
  86. package/dist/cjs/core/interaction/batch/processing/v3/as-array.cjs.map +1 -0
  87. package/dist/cjs/core/interaction/batch/processing/v3/as-object.cjs +34 -0
  88. package/dist/cjs/core/interaction/batch/processing/v3/as-object.cjs.map +1 -0
  89. package/dist/cjs/core/interaction/batch/v2.cjs +47 -0
  90. package/dist/cjs/core/interaction/batch/v2.cjs.map +1 -0
  91. package/dist/cjs/core/interaction/batch/v3.cjs +45 -0
  92. package/dist/cjs/core/interaction/batch/v3.cjs.map +1 -0
  93. package/dist/cjs/core/language/list.cjs +59 -0
  94. package/dist/cjs/core/language/list.cjs.map +1 -0
  95. package/dist/cjs/core/request-id-generator.cjs +44 -0
  96. package/dist/cjs/core/request-id-generator.cjs.map +1 -0
  97. package/dist/cjs/core/result.cjs +137 -0
  98. package/dist/cjs/core/result.cjs.map +1 -0
  99. package/dist/cjs/core/sdk-error.cjs +85 -0
  100. package/dist/cjs/core/sdk-error.cjs.map +1 -0
  101. package/dist/cjs/core/tools/abstract-tool.cjs +26 -0
  102. package/dist/cjs/core/tools/abstract-tool.cjs.map +1 -0
  103. package/dist/cjs/core/tools/healthcheck.cjs +50 -0
  104. package/dist/cjs/core/tools/healthcheck.cjs.map +1 -0
  105. package/dist/cjs/core/tools/manager.cjs +52 -0
  106. package/dist/cjs/core/tools/manager.cjs.map +1 -0
  107. package/dist/cjs/core/tools/ping.cjs +58 -0
  108. package/dist/cjs/core/tools/ping.cjs.map +1 -0
  109. package/dist/cjs/core/version-manager.cjs +57 -0
  110. package/dist/cjs/core/version-manager.cjs.map +1 -0
  111. package/dist/cjs/frame/auth.cjs +100 -0
  112. package/dist/cjs/frame/auth.cjs.map +1 -0
  113. package/dist/cjs/frame/b24.cjs +178 -0
  114. package/dist/cjs/frame/b24.cjs.map +1 -0
  115. package/dist/cjs/frame/dialog.cjs +120 -0
  116. package/dist/cjs/frame/dialog.cjs.map +1 -0
  117. package/dist/cjs/frame/frame.cjs +103 -0
  118. package/dist/cjs/frame/frame.cjs.map +1 -0
  119. package/dist/cjs/frame/message/commands.cjs +39 -0
  120. package/dist/cjs/frame/message/commands.cjs.map +1 -0
  121. package/dist/cjs/frame/message/controller.cjs +191 -0
  122. package/dist/cjs/frame/message/controller.cjs.map +1 -0
  123. package/dist/cjs/frame/options.cjs +108 -0
  124. package/dist/cjs/frame/options.cjs.map +1 -0
  125. package/dist/cjs/frame/parent.cjs +259 -0
  126. package/dist/cjs/frame/parent.cjs.map +1 -0
  127. package/dist/cjs/frame/placement.cjs +156 -0
  128. package/dist/cjs/frame/placement.cjs.map +1 -0
  129. package/dist/cjs/frame/slider.cjs +162 -0
  130. package/dist/cjs/frame/slider.cjs.map +1 -0
  131. package/dist/cjs/helper/abstract-helper.cjs +55 -0
  132. package/dist/cjs/helper/abstract-helper.cjs.map +1 -0
  133. package/dist/cjs/helper/app-manager.cjs +39 -0
  134. package/dist/cjs/helper/app-manager.cjs.map +1 -0
  135. package/dist/cjs/helper/currency-manager.cjs +215 -0
  136. package/dist/cjs/helper/currency-manager.cjs.map +1 -0
  137. package/dist/cjs/helper/helper-manager.cjs +397 -0
  138. package/dist/cjs/helper/helper-manager.cjs.map +1 -0
  139. package/dist/cjs/helper/license-manager.cjs +52 -0
  140. package/dist/cjs/helper/license-manager.cjs.map +1 -0
  141. package/dist/cjs/helper/options-manager.cjs +205 -0
  142. package/dist/cjs/helper/options-manager.cjs.map +1 -0
  143. package/dist/cjs/helper/payment-manager.cjs +35 -0
  144. package/dist/cjs/helper/payment-manager.cjs.map +1 -0
  145. package/dist/cjs/helper/profile-manager.cjs +35 -0
  146. package/dist/cjs/helper/profile-manager.cjs.map +1 -0
  147. package/dist/cjs/helper/use-b24-helper.cjs +85 -0
  148. package/dist/cjs/helper/use-b24-helper.cjs.map +1 -0
  149. package/dist/cjs/hook/auth.cjs +79 -0
  150. package/dist/cjs/hook/auth.cjs.map +1 -0
  151. package/dist/cjs/hook/b24.cjs +117 -0
  152. package/dist/cjs/hook/b24.cjs.map +1 -0
  153. package/dist/cjs/index.cjs +176 -0
  154. package/dist/cjs/index.cjs.map +1 -0
  155. package/dist/cjs/index.d.cts +6415 -0
  156. package/dist/cjs/index.d.mts +6415 -0
  157. package/dist/cjs/index.d.ts +6415 -0
  158. package/dist/cjs/loader-b24frame.cjs +103 -0
  159. package/dist/cjs/loader-b24frame.cjs.map +1 -0
  160. package/dist/cjs/logger/abstract-logger.cjs +71 -0
  161. package/dist/cjs/logger/abstract-logger.cjs.map +1 -0
  162. package/dist/cjs/logger/browser.cjs +165 -0
  163. package/dist/cjs/logger/browser.cjs.map +1 -0
  164. package/dist/cjs/logger/formatter/abstract-formatter.cjs +36 -0
  165. package/dist/cjs/logger/formatter/abstract-formatter.cjs.map +1 -0
  166. package/dist/cjs/logger/formatter/json-formatter.cjs +36 -0
  167. package/dist/cjs/logger/formatter/json-formatter.cjs.map +1 -0
  168. package/dist/cjs/logger/formatter/line-formatter.cjs +43 -0
  169. package/dist/cjs/logger/formatter/line-formatter.cjs.map +1 -0
  170. package/dist/cjs/logger/formatter/telegram-formatter.cjs +105 -0
  171. package/dist/cjs/logger/formatter/telegram-formatter.cjs.map +1 -0
  172. package/dist/cjs/logger/handler/abstract-handler.cjs +41 -0
  173. package/dist/cjs/logger/handler/abstract-handler.cjs.map +1 -0
  174. package/dist/cjs/logger/handler/consola-adapter.cjs +64 -0
  175. package/dist/cjs/logger/handler/consola-adapter.cjs.map +1 -0
  176. package/dist/cjs/logger/handler/console-handler.cjs +100 -0
  177. package/dist/cjs/logger/handler/console-handler.cjs.map +1 -0
  178. package/dist/cjs/logger/handler/console-v2-handler.cjs +53 -0
  179. package/dist/cjs/logger/handler/console-v2-handler.cjs.map +1 -0
  180. package/dist/cjs/logger/handler/memory-handler.cjs +50 -0
  181. package/dist/cjs/logger/handler/memory-handler.cjs.map +1 -0
  182. package/dist/cjs/logger/handler/stream-handler.cjs +75 -0
  183. package/dist/cjs/logger/handler/stream-handler.cjs.map +1 -0
  184. package/dist/cjs/logger/handler/telegram-handler.cjs +159 -0
  185. package/dist/cjs/logger/handler/telegram-handler.cjs.map +1 -0
  186. package/dist/cjs/logger/handler/winston-adapter.cjs +59 -0
  187. package/dist/cjs/logger/handler/winston-adapter.cjs.map +1 -0
  188. package/dist/cjs/logger/logger-factory.cjs +69 -0
  189. package/dist/cjs/logger/logger-factory.cjs.map +1 -0
  190. package/dist/cjs/logger/logger.cjs +78 -0
  191. package/dist/cjs/logger/logger.cjs.map +1 -0
  192. package/dist/cjs/logger/null-logger.cjs +34 -0
  193. package/dist/cjs/logger/null-logger.cjs.map +1 -0
  194. package/dist/cjs/logger/processor/memory-usage-processor.cjs +22 -0
  195. package/dist/cjs/logger/processor/memory-usage-processor.cjs.map +1 -0
  196. package/dist/cjs/logger/processor/pid-processor.cjs +22 -0
  197. package/dist/cjs/logger/processor/pid-processor.cjs.map +1 -0
  198. package/dist/cjs/oauth/auth.cjs +214 -0
  199. package/dist/cjs/oauth/auth.cjs.map +1 -0
  200. package/dist/cjs/oauth/b24.cjs +119 -0
  201. package/dist/cjs/oauth/b24.cjs.map +1 -0
  202. package/dist/cjs/oauth/refresh-token-error.cjs +22 -0
  203. package/dist/cjs/oauth/refresh-token-error.cjs.map +1 -0
  204. package/dist/cjs/pullClient/abstract-connector.cjs +80 -0
  205. package/dist/cjs/pullClient/abstract-connector.cjs.map +1 -0
  206. package/dist/cjs/pullClient/channel-manager.cjs +91 -0
  207. package/dist/cjs/pullClient/channel-manager.cjs.map +1 -0
  208. package/dist/cjs/pullClient/client.cjs +2177 -0
  209. package/dist/cjs/pullClient/client.cjs.map +1 -0
  210. package/dist/cjs/pullClient/errors.cjs +34 -0
  211. package/dist/cjs/pullClient/errors.cjs.map +1 -0
  212. package/dist/cjs/pullClient/json-rpc.cjs +213 -0
  213. package/dist/cjs/pullClient/json-rpc.cjs.map +1 -0
  214. package/dist/cjs/pullClient/long-polling-connector.cjs +159 -0
  215. package/dist/cjs/pullClient/long-polling-connector.cjs.map +1 -0
  216. package/dist/cjs/pullClient/protobuf/index.cjs +22 -0
  217. package/dist/cjs/pullClient/protobuf/index.cjs.map +1 -0
  218. package/dist/cjs/pullClient/protobuf/model.cjs +1060 -0
  219. package/dist/cjs/pullClient/protobuf/model.cjs.map +1 -0
  220. package/dist/cjs/pullClient/protobuf/protobuf.cjs +4655 -0
  221. package/dist/cjs/pullClient/protobuf/protobuf.cjs.map +1 -0
  222. package/dist/cjs/pullClient/shared-config.cjs +135 -0
  223. package/dist/cjs/pullClient/shared-config.cjs.map +1 -0
  224. package/dist/cjs/pullClient/storage-manager.cjs +74 -0
  225. package/dist/cjs/pullClient/storage-manager.cjs.map +1 -0
  226. package/dist/cjs/pullClient/web-socket-connector.cjs +131 -0
  227. package/dist/cjs/pullClient/web-socket-connector.cjs.map +1 -0
  228. package/dist/cjs/tools/batch-ref-v3.cjs +54 -0
  229. package/dist/cjs/tools/batch-ref-v3.cjs.map +1 -0
  230. package/dist/cjs/tools/browser.cjs +156 -0
  231. package/dist/cjs/tools/browser.cjs.map +1 -0
  232. package/dist/cjs/tools/environment.cjs +32 -0
  233. package/dist/cjs/tools/environment.cjs.map +1 -0
  234. package/dist/cjs/tools/filter-v3.cjs +139 -0
  235. package/dist/cjs/tools/filter-v3.cjs.map +1 -0
  236. package/dist/cjs/tools/formatters/iban.cjs +307 -0
  237. package/dist/cjs/tools/formatters/iban.cjs.map +1 -0
  238. package/dist/cjs/tools/formatters/numbers.cjs +68 -0
  239. package/dist/cjs/tools/formatters/numbers.cjs.map +1 -0
  240. package/dist/cjs/tools/index.cjs +42 -0
  241. package/dist/cjs/tools/index.cjs.map +1 -0
  242. package/dist/cjs/tools/scroll-size.cjs +29 -0
  243. package/dist/cjs/tools/scroll-size.cjs.map +1 -0
  244. package/dist/cjs/tools/text.cjs +210 -0
  245. package/dist/cjs/tools/text.cjs.map +1 -0
  246. package/dist/cjs/tools/type.cjs +339 -0
  247. package/dist/cjs/tools/type.cjs.map +1 -0
  248. package/dist/cjs/tools/use-formatters.cjs +462 -0
  249. package/dist/cjs/tools/use-formatters.cjs.map +1 -0
  250. package/dist/cjs/tools/uuidv7.cjs +58 -0
  251. package/dist/cjs/tools/uuidv7.cjs.map +1 -0
  252. package/dist/cjs/types/b24-helper.cjs +62 -0
  253. package/dist/cjs/types/b24-helper.cjs.map +1 -0
  254. package/dist/cjs/types/b24.cjs +18 -0
  255. package/dist/cjs/types/b24.cjs.map +1 -0
  256. package/dist/cjs/types/bizproc/index.cjs +195 -0
  257. package/dist/cjs/types/bizproc/index.cjs.map +1 -0
  258. package/dist/cjs/types/catalog/index.cjs +39 -0
  259. package/dist/cjs/types/catalog/index.cjs.map +1 -0
  260. package/dist/cjs/types/common.cjs +33 -0
  261. package/dist/cjs/types/common.cjs.map +1 -0
  262. package/dist/cjs/types/crm/entity-type.cjs +62 -0
  263. package/dist/cjs/types/crm/entity-type.cjs.map +1 -0
  264. package/dist/cjs/types/crm/productrow.cjs +19 -0
  265. package/dist/cjs/types/crm/productrow.cjs.map +1 -0
  266. package/dist/cjs/types/logger.cjs +24 -0
  267. package/dist/cjs/types/logger.cjs.map +1 -0
  268. package/dist/cjs/types/pull.cjs +94 -0
  269. package/dist/cjs/types/pull.cjs.map +1 -0
  270. package/dist/esm/_virtual/_commonjsHelpers.mjs +1 -1
  271. package/dist/esm/_virtual/protobuf.mjs +1 -1
  272. package/dist/esm/_virtual/protobuf2.mjs +1 -1
  273. package/dist/esm/core/abstract-b24.mjs +1 -1
  274. package/dist/esm/core/actions/abstract-action.mjs +1 -1
  275. package/dist/esm/core/actions/abstract-batch.mjs +1 -1
  276. package/dist/esm/core/actions/manager.mjs +1 -1
  277. package/dist/esm/core/actions/v2/batch-by-chunk.mjs +1 -1
  278. package/dist/esm/core/actions/v2/batch.mjs +1 -1
  279. package/dist/esm/core/actions/v2/call-list.mjs +17 -10
  280. package/dist/esm/core/actions/v2/call-list.mjs.map +1 -1
  281. package/dist/esm/core/actions/v2/call.mjs +1 -15
  282. package/dist/esm/core/actions/v2/call.mjs.map +1 -1
  283. package/dist/esm/core/actions/v2/fetch-list.mjs +17 -10
  284. package/dist/esm/core/actions/v2/fetch-list.mjs.map +1 -1
  285. package/dist/esm/core/actions/v2/manager-v2.mjs +6 -6
  286. package/dist/esm/core/actions/v2/manager-v2.mjs.map +1 -1
  287. package/dist/esm/core/actions/v3/_keyset-paginate.mjs +66 -0
  288. package/dist/esm/core/actions/v3/_keyset-paginate.mjs.map +1 -0
  289. package/dist/esm/core/actions/v3/aggregate.mjs +94 -0
  290. package/dist/esm/core/actions/v3/aggregate.mjs.map +1 -0
  291. package/dist/esm/core/actions/v3/batch-by-chunk.mjs +1 -1
  292. package/dist/esm/core/actions/v3/batch.mjs +1 -10
  293. package/dist/esm/core/actions/v3/batch.mjs.map +1 -1
  294. package/dist/esm/core/actions/v3/call-list.mjs +40 -47
  295. package/dist/esm/core/actions/v3/call-list.mjs.map +1 -1
  296. package/dist/esm/core/actions/v3/call-tail.mjs +116 -0
  297. package/dist/esm/core/actions/v3/call-tail.mjs.map +1 -0
  298. package/dist/esm/core/actions/v3/call.mjs +1 -10
  299. package/dist/esm/core/actions/v3/call.mjs.map +1 -1
  300. package/dist/esm/core/actions/v3/fetch-list.mjs +34 -44
  301. package/dist/esm/core/actions/v3/fetch-list.mjs.map +1 -1
  302. package/dist/esm/core/actions/v3/fetch-tail.mjs +110 -0
  303. package/dist/esm/core/actions/v3/fetch-tail.mjs.map +1 -0
  304. package/dist/esm/core/actions/v3/manager-v3.mjs +30 -6
  305. package/dist/esm/core/actions/v3/manager-v3.mjs.map +1 -1
  306. package/dist/esm/core/http/abstract-http.mjs +96 -21
  307. package/dist/esm/core/http/abstract-http.mjs.map +1 -1
  308. package/dist/esm/core/http/ajax-error.mjs +1 -1
  309. package/dist/esm/core/http/ajax-result.mjs +9 -8
  310. package/dist/esm/core/http/ajax-result.mjs.map +1 -1
  311. package/dist/esm/core/http/limiters/adaptive-delayer.mjs +1 -1
  312. package/dist/esm/core/http/limiters/manager.mjs +2 -1
  313. package/dist/esm/core/http/limiters/manager.mjs.map +1 -1
  314. package/dist/esm/core/http/limiters/operating-limiter.mjs +1 -1
  315. package/dist/esm/core/http/limiters/params-factory.mjs +1 -1
  316. package/dist/esm/core/http/limiters/rate-limiter.mjs +1 -1
  317. package/dist/esm/core/http/redact.mjs +41 -13
  318. package/dist/esm/core/http/redact.mjs.map +1 -1
  319. package/dist/esm/core/http/v2.mjs +1 -18
  320. package/dist/esm/core/http/v2.mjs.map +1 -1
  321. package/dist/esm/core/http/v3.mjs +1 -15
  322. package/dist/esm/core/http/v3.mjs.map +1 -1
  323. package/dist/esm/core/interaction/batch/abstract-interaction-batch.mjs +1 -1
  324. package/dist/esm/core/interaction/batch/parse-row.mjs +1 -1
  325. package/dist/esm/core/interaction/batch/processing/interface-strategy.mjs +44 -1
  326. package/dist/esm/core/interaction/batch/processing/interface-strategy.mjs.map +1 -1
  327. package/dist/esm/core/interaction/batch/processing/v2/abstract-processing.mjs +7 -6
  328. package/dist/esm/core/interaction/batch/processing/v2/abstract-processing.mjs.map +1 -1
  329. package/dist/esm/core/interaction/batch/processing/v2/as-array.mjs +3 -3
  330. package/dist/esm/core/interaction/batch/processing/v2/as-array.mjs.map +1 -1
  331. package/dist/esm/core/interaction/batch/processing/v2/as-object.mjs +1 -1
  332. package/dist/esm/core/interaction/batch/processing/v3/abstract-processing.mjs +7 -19
  333. package/dist/esm/core/interaction/batch/processing/v3/abstract-processing.mjs.map +1 -1
  334. package/dist/esm/core/interaction/batch/processing/v3/as-array.mjs +3 -3
  335. package/dist/esm/core/interaction/batch/processing/v3/as-array.mjs.map +1 -1
  336. package/dist/esm/core/interaction/batch/processing/v3/as-object.mjs +1 -1
  337. package/dist/esm/core/interaction/batch/v2.mjs +1 -1
  338. package/dist/esm/core/interaction/batch/v3.mjs +1 -1
  339. package/dist/esm/core/language/list.mjs +1 -1
  340. package/dist/esm/core/request-id-generator.mjs +1 -1
  341. package/dist/esm/core/result.mjs +35 -1
  342. package/dist/esm/core/result.mjs.map +1 -1
  343. package/dist/esm/core/sdk-error.mjs +1 -1
  344. package/dist/esm/core/tools/abstract-tool.mjs +1 -1
  345. package/dist/esm/core/tools/healthcheck.mjs +1 -1
  346. package/dist/esm/core/tools/manager.mjs +3 -3
  347. package/dist/esm/core/tools/manager.mjs.map +1 -1
  348. package/dist/esm/core/tools/ping.mjs +1 -1
  349. package/dist/esm/core/version-manager.mjs +19 -80
  350. package/dist/esm/core/version-manager.mjs.map +1 -1
  351. package/dist/esm/frame/auth.mjs +1 -1
  352. package/dist/esm/frame/b24.mjs +8 -2
  353. package/dist/esm/frame/b24.mjs.map +1 -1
  354. package/dist/esm/frame/dialog.mjs +1 -1
  355. package/dist/esm/frame/frame.mjs +1 -1
  356. package/dist/esm/frame/message/commands.mjs +1 -1
  357. package/dist/esm/frame/message/controller.mjs +17 -6
  358. package/dist/esm/frame/message/controller.mjs.map +1 -1
  359. package/dist/esm/frame/options.mjs +1 -1
  360. package/dist/esm/frame/parent.mjs +6 -2
  361. package/dist/esm/frame/parent.mjs.map +1 -1
  362. package/dist/esm/frame/placement.mjs +1 -1
  363. package/dist/esm/frame/slider.mjs +5 -1
  364. package/dist/esm/frame/slider.mjs.map +1 -1
  365. package/dist/esm/helper/abstract-helper.mjs +1 -1
  366. package/dist/esm/helper/app-manager.mjs +1 -1
  367. package/dist/esm/helper/currency-manager.mjs +1 -1
  368. package/dist/esm/helper/helper-manager.mjs +1 -1
  369. package/dist/esm/helper/license-manager.mjs +1 -1
  370. package/dist/esm/helper/options-manager.mjs +1 -1
  371. package/dist/esm/helper/payment-manager.mjs +1 -1
  372. package/dist/esm/helper/profile-manager.mjs +1 -1
  373. package/dist/esm/helper/use-b24-helper.mjs +1 -1
  374. package/dist/esm/hook/auth.mjs +1 -1
  375. package/dist/esm/hook/b24.mjs +3 -3
  376. package/dist/esm/hook/b24.mjs.map +1 -1
  377. package/dist/esm/index.d.mts +501 -49
  378. package/dist/esm/index.d.ts +501 -49
  379. package/dist/esm/index.mjs +3 -1
  380. package/dist/esm/index.mjs.map +1 -1
  381. package/dist/esm/loader-b24frame.mjs +1 -1
  382. package/dist/esm/logger/abstract-logger.mjs +1 -1
  383. package/dist/esm/logger/browser.mjs +1 -1
  384. package/dist/esm/logger/formatter/abstract-formatter.mjs +1 -1
  385. package/dist/esm/logger/formatter/json-formatter.mjs +1 -1
  386. package/dist/esm/logger/formatter/line-formatter.mjs +1 -1
  387. package/dist/esm/logger/formatter/telegram-formatter.mjs +1 -1
  388. package/dist/esm/logger/handler/abstract-handler.mjs +1 -1
  389. package/dist/esm/logger/handler/consola-adapter.mjs +1 -1
  390. package/dist/esm/logger/handler/console-handler.mjs +1 -1
  391. package/dist/esm/logger/handler/console-v2-handler.mjs +1 -1
  392. package/dist/esm/logger/handler/memory-handler.mjs +1 -1
  393. package/dist/esm/logger/handler/stream-handler.mjs +1 -1
  394. package/dist/esm/logger/handler/telegram-handler.mjs +1 -1
  395. package/dist/esm/logger/handler/winston-adapter.mjs +1 -1
  396. package/dist/esm/logger/logger-factory.mjs +1 -1
  397. package/dist/esm/logger/logger.mjs +1 -1
  398. package/dist/esm/logger/null-logger.mjs +1 -1
  399. package/dist/esm/logger/processor/memory-usage-processor.mjs +1 -1
  400. package/dist/esm/logger/processor/pid-processor.mjs +1 -1
  401. package/dist/esm/oauth/auth.mjs +13 -16
  402. package/dist/esm/oauth/auth.mjs.map +1 -1
  403. package/dist/esm/oauth/b24.mjs +1 -1
  404. package/dist/esm/oauth/refresh-token-error.mjs +1 -1
  405. package/dist/esm/pullClient/abstract-connector.mjs +1 -1
  406. package/dist/esm/pullClient/channel-manager.mjs +1 -1
  407. package/dist/esm/pullClient/client.mjs +141 -30
  408. package/dist/esm/pullClient/client.mjs.map +1 -1
  409. package/dist/esm/pullClient/errors.mjs +1 -1
  410. package/dist/esm/pullClient/json-rpc.mjs +5 -4
  411. package/dist/esm/pullClient/json-rpc.mjs.map +1 -1
  412. package/dist/esm/pullClient/long-polling-connector.mjs +1 -1
  413. package/dist/esm/pullClient/protobuf/index.mjs +1 -1
  414. package/dist/esm/pullClient/protobuf/model.mjs +1 -1
  415. package/dist/esm/pullClient/protobuf/protobuf.mjs +1 -1
  416. package/dist/esm/pullClient/shared-config.mjs +1 -1
  417. package/dist/esm/pullClient/storage-manager.mjs +1 -1
  418. package/dist/esm/pullClient/web-socket-connector.mjs +1 -1
  419. package/dist/esm/tools/batch-ref-v3.mjs +52 -0
  420. package/dist/esm/tools/batch-ref-v3.mjs.map +1 -0
  421. package/dist/esm/tools/browser.mjs +1 -1
  422. package/dist/esm/tools/environment.mjs +1 -1
  423. package/dist/esm/tools/filter-v3.mjs +137 -0
  424. package/dist/esm/tools/filter-v3.mjs.map +1 -0
  425. package/dist/esm/tools/formatters/iban.mjs +1 -1
  426. package/dist/esm/tools/formatters/numbers.mjs +1 -1
  427. package/dist/esm/tools/index.mjs +1 -1
  428. package/dist/esm/tools/scroll-size.mjs +1 -1
  429. package/dist/esm/tools/text.mjs +1 -1
  430. package/dist/esm/tools/type.mjs +1 -1
  431. package/dist/esm/tools/use-formatters.mjs +1 -1
  432. package/dist/esm/tools/uuidv7.mjs +1 -1
  433. package/dist/esm/types/b24-helper.mjs +1 -1
  434. package/dist/esm/types/b24.mjs +1 -1
  435. package/dist/esm/types/bizproc/index.mjs +1 -1
  436. package/dist/esm/types/catalog/index.mjs +1 -1
  437. package/dist/esm/types/common.mjs +1 -1
  438. package/dist/esm/types/crm/entity-type.mjs +1 -1
  439. package/dist/esm/types/crm/productrow.mjs +1 -1
  440. package/dist/esm/types/logger.mjs +1 -1
  441. package/dist/esm/types/pull.mjs +1 -1
  442. package/dist/umd/index.js +1384 -680
  443. package/dist/umd/index.js.map +1 -1
  444. package/dist/umd/index.min.js +26 -26
  445. package/dist/umd/index.min.js.map +1 -1
  446. package/dist/umd/package.json +3 -0
  447. package/package.json +12 -4
@@ -0,0 +1,2177 @@
1
+ /**
2
+ * @package @bitrix24/b24jssdk
3
+ * @version 2.0.0
4
+ * @copyright (c) 2026 Bitrix24
5
+ * @license MIT
6
+ * @see https://github.com/bitrix24/b24jssdk
7
+ * @see https://bitrix24.github.io/b24jssdk/
8
+ */
9
+ 'use strict';
10
+
11
+ const type = require('../tools/type.cjs');
12
+ const text = require('../tools/text.cjs');
13
+ const browser = require('../tools/browser.cjs');
14
+ const redact = require('../core/http/redact.cjs');
15
+ const storageManager = require('./storage-manager.cjs');
16
+ const jsonRpc = require('./json-rpc.cjs');
17
+ const sharedConfig = require('./shared-config.cjs');
18
+ const channelManager = require('./channel-manager.cjs');
19
+ const index = require('./protobuf/index.cjs');
20
+ const pull = require('../types/pull.cjs');
21
+ const webSocketConnector = require('./web-socket-connector.cjs');
22
+ const longPollingConnector = require('./long-polling-connector.cjs');
23
+ const loggerFactory = require('../logger/logger-factory.cjs');
24
+
25
+ var __defProp = Object.defineProperty;
26
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
27
+ const REVISION = 19;
28
+ const RESTORE_WEBSOCKET_TIMEOUT = 30 * 60;
29
+ const OFFLINE_STATUS_DELAY = 5e3;
30
+ const CONFIG_CHECK_INTERVAL = 60 * 1e3;
31
+ const MAX_IDS_TO_STORE = 10;
32
+ const PING_TIMEOUT = 10;
33
+ const JSON_RPC_PING = "ping";
34
+ const JSON_RPC_PONG = "pong";
35
+ const LS_SESSION = "bx-pull-session";
36
+ const LS_SESSION_CACHE_TIME = 20;
37
+ const EmptyConfig = {
38
+ api: {},
39
+ channels: {},
40
+ publicChannels: {},
41
+ server: { timeShift: 0 },
42
+ clientId: null,
43
+ jwt: null,
44
+ exp: 0
45
+ };
46
+ class PullClient {
47
+ static {
48
+ __name(this, "PullClient");
49
+ }
50
+ // region Params ////
51
+ _logger;
52
+ _restClient;
53
+ _status;
54
+ _context;
55
+ _guestMode;
56
+ _guestUserId;
57
+ _userId;
58
+ _configGetMethod;
59
+ _getPublicListMethod;
60
+ _siteId;
61
+ _enabled;
62
+ _unloading = false;
63
+ _starting = false;
64
+ _debug = false;
65
+ _connectionAttempt = 0;
66
+ _connectionType = pull.ConnectionType.WebSocket;
67
+ _skipStorageInit;
68
+ _skipCheckRevision;
69
+ _subscribers = {};
70
+ _watchTagsQueue = /* @__PURE__ */ new Map();
71
+ _watchUpdateInterval = 174e4;
72
+ _watchForceUpdateInterval = 5e3;
73
+ _configTimestamp = 0;
74
+ _session = {
75
+ mid: null,
76
+ tag: null,
77
+ time: null,
78
+ history: {},
79
+ lastMessageIds: [],
80
+ messageCount: 0
81
+ };
82
+ _connectors = {
83
+ [pull.ConnectionType.Undefined]: null,
84
+ [pull.ConnectionType.WebSocket]: null,
85
+ [pull.ConnectionType.LongPolling]: null
86
+ };
87
+ _isSecure;
88
+ _config = null;
89
+ _storage = null;
90
+ _sharedConfig;
91
+ _channelManager;
92
+ _jsonRpcAdapter = null;
93
+ /**
94
+ * @depricate
95
+ */
96
+ // private _notificationPopup: null = null
97
+ // timers ////
98
+ _reconnectTimeout = null;
99
+ _restartTimeout = null;
100
+ _restoreWebSocketTimeout = null;
101
+ _checkInterval = null;
102
+ _offlineTimeout = null;
103
+ _watchUpdateTimeout = null;
104
+ _pingWaitTimeout = null;
105
+ // manual stop workaround ////
106
+ _isManualDisconnect = false;
107
+ // set once destroy() has run; gates reconnect / watch / online so a torn-down
108
+ // client never schedules new work (#141) ////
109
+ _disposed = false;
110
+ _loggingEnabled = false;
111
+ // bound event handlers, stored so they can be removed in destroy() (#141) ////
112
+ _onPingTimeoutHandler;
113
+ _onBeforeUnloadHandler;
114
+ _onOfflineHandler;
115
+ _onOnlineHandler;
116
+ // [userId] => array of callbacks
117
+ _userStatusCallbacks = {};
118
+ _connectPromise = null;
119
+ _startingPromise = null;
120
+ // endregion ////
121
+ // region Init ////
122
+ /**
123
+ * @param params
124
+ */
125
+ constructor(params) {
126
+ this._logger = loggerFactory.LoggerFactory.createNullLogger();
127
+ this._restClient = params.b24;
128
+ this._status = pull.PullStatus.Offline;
129
+ this._context = "master";
130
+ if (params.restApplication) {
131
+ if (typeof params.configGetMethod === "undefined") {
132
+ params.configGetMethod = "pull.application.config.get";
133
+ }
134
+ if (typeof params.skipCheckRevision === "undefined") {
135
+ params.skipCheckRevision = true;
136
+ }
137
+ if (type.Type.isStringFilled(params.restApplication)) {
138
+ params.siteId = params.restApplication;
139
+ }
140
+ params.serverEnabled = true;
141
+ }
142
+ this._guestMode = params.guestMode ? text.Text.toBoolean(params.guestMode) : false;
143
+ this._guestUserId = params.guestUserId ? text.Text.toInteger(params.guestUserId) : 0;
144
+ if (this._guestMode && this._guestUserId > 0) {
145
+ this._userId = this._guestUserId;
146
+ } else {
147
+ this._guestMode = false;
148
+ this._userId = params.userId ? text.Text.toInteger(params.userId) : 0;
149
+ }
150
+ this._siteId = params.siteId ?? "none";
151
+ this._enabled = !type.Type.isUndefined(params.serverEnabled) ? params.serverEnabled === true : true;
152
+ this._configGetMethod = !type.Type.isStringFilled(params.configGetMethod) ? "pull.config.get" : params.configGetMethod || "";
153
+ this._getPublicListMethod = !type.Type.isStringFilled(params.getPublicListMethod) ? "pull.channel.public.list" : params.getPublicListMethod || "";
154
+ this._skipStorageInit = params.skipStorageInit === true;
155
+ this._skipCheckRevision = params.skipCheckRevision === true;
156
+ if (!type.Type.isUndefined(params.configTimestamp)) {
157
+ this._configTimestamp = text.Text.toInteger(params.configTimestamp);
158
+ }
159
+ this._isSecure = document?.location.href.indexOf("https") === 0;
160
+ if (this._userId && !this._skipStorageInit) {
161
+ this._storage = new storageManager.StorageManager({
162
+ userId: this._userId,
163
+ siteId: this._siteId
164
+ });
165
+ }
166
+ this._sharedConfig = new sharedConfig.SharedConfig({
167
+ onWebSocketBlockChanged: this.onWebSocketBlockChanged.bind(this),
168
+ storage: this._storage
169
+ });
170
+ this._channelManager = new channelManager.ChannelManager({
171
+ b24: this._restClient,
172
+ getPublicListMethod: this._getPublicListMethod
173
+ });
174
+ this._loggingEnabled = this._sharedConfig.isLoggingEnabled();
175
+ this._onPingTimeoutHandler = this.onPingTimeout.bind(this);
176
+ this._onBeforeUnloadHandler = this.onBeforeUnload.bind(this);
177
+ this._onOfflineHandler = this.onOffline.bind(this);
178
+ this._onOnlineHandler = this.onOnline.bind(this);
179
+ }
180
+ setLogger(logger) {
181
+ this._logger = logger;
182
+ this._jsonRpcAdapter?.setLogger(this.getLogger());
183
+ this._storage?.setLogger(this.getLogger());
184
+ this._sharedConfig.setLogger(this.getLogger());
185
+ this._channelManager.setLogger(this.getLogger());
186
+ this._connectors.webSocket?.setLogger(this.getLogger());
187
+ this._connectors.longPolling?.setLogger(this.getLogger());
188
+ }
189
+ getLogger() {
190
+ return this._logger;
191
+ }
192
+ /**
193
+ * Terminal teardown: removes the window listeners, cancels every pending timer,
194
+ * persists the session for a quick re-init, and disconnects. Irreversible — a
195
+ * destroyed client schedules no further work and `start()` rejects with
196
+ * `PULL_DISPOSED`; create a new instance to reconnect.
197
+ */
198
+ destroy() {
199
+ this._disposed = true;
200
+ this.stop(pull.CloseReasons.NORMAL_CLOSURE, "manual stop");
201
+ if (typeof window !== "undefined") {
202
+ window.removeEventListener("beforeunload", this._onBeforeUnloadHandler);
203
+ window.removeEventListener("offline", this._onOfflineHandler);
204
+ window.removeEventListener("online", this._onOnlineHandler);
205
+ }
206
+ if (this._storage) {
207
+ this._storage.remove(pull.LsKeys.PullConfig);
208
+ }
209
+ this.persistSession();
210
+ }
211
+ init() {
212
+ if (this._disposed) {
213
+ return;
214
+ }
215
+ this._connectors.webSocket = new webSocketConnector.WebSocketConnector({
216
+ parent: this,
217
+ onOpen: this.onWebSocketOpen.bind(this),
218
+ onMessage: this.onIncomingMessage.bind(this),
219
+ onDisconnect: this.onWebSocketDisconnect.bind(this),
220
+ onError: this.onWebSocketError.bind(this)
221
+ });
222
+ this._connectors.longPolling = new longPollingConnector.LongPollingConnector({
223
+ parent: this,
224
+ onOpen: this.onLongPollingOpen.bind(this),
225
+ onMessage: this.onIncomingMessage.bind(this),
226
+ onDisconnect: this.onLongPollingDisconnect.bind(this),
227
+ onError: this.onLongPollingError.bind(this)
228
+ });
229
+ this._connectionType = this.isWebSocketAllowed() ? pull.ConnectionType.WebSocket : pull.ConnectionType.LongPolling;
230
+ if (typeof window !== "undefined") {
231
+ window.addEventListener("beforeunload", this._onBeforeUnloadHandler);
232
+ window.addEventListener("offline", this._onOfflineHandler);
233
+ window.addEventListener("online", this._onOnlineHandler);
234
+ }
235
+ this._jsonRpcAdapter = new jsonRpc.JsonRpc({
236
+ connector: this._connectors.webSocket,
237
+ handlers: {
238
+ "incoming.message": this.handleRpcIncomingMessage.bind(this)
239
+ }
240
+ });
241
+ }
242
+ // endregion ////
243
+ // region Get-Set ////
244
+ get connector() {
245
+ return this._connectors[this._connectionType];
246
+ }
247
+ get status() {
248
+ return this._status;
249
+ }
250
+ /**
251
+ * @param status
252
+ */
253
+ set status(status) {
254
+ if (this._status === status) {
255
+ return;
256
+ }
257
+ this._status = status;
258
+ if (this._offlineTimeout) {
259
+ clearTimeout(this._offlineTimeout);
260
+ this._offlineTimeout = null;
261
+ }
262
+ if (status === pull.PullStatus.Offline) {
263
+ this.sendPullStatusDelayed(status, OFFLINE_STATUS_DELAY);
264
+ } else {
265
+ this.sendPullStatus(status);
266
+ }
267
+ }
268
+ get session() {
269
+ return this._session;
270
+ }
271
+ // endregion ////
272
+ // region Public /////
273
+ /**
274
+ * Creates a subscription to incoming messages.
275
+ *
276
+ * @param {TypeSubscriptionOptions | TypeSubscriptionCommandHandler} params
277
+ * @returns { () => void } - Unsubscribe callback function
278
+ */
279
+ subscribe(params) {
280
+ if (!type.Type.isPlainObject(params)) {
281
+ return this.attachCommandHandler(params);
282
+ }
283
+ params = params;
284
+ params.type = params.type || pull.SubscriptionType.Server;
285
+ params.command = params.command || null;
286
+ if (params.type == pull.SubscriptionType.Server || params.type == pull.SubscriptionType.Client) {
287
+ if (typeof params.moduleId === "undefined") {
288
+ throw new TypeError(
289
+ `${text.Text.getDateForLog()}: Pull.subscribe: parameter moduleId is not specified`
290
+ );
291
+ }
292
+ if (typeof this._subscribers[params.type] === "undefined") {
293
+ this._subscribers[params.type] = {};
294
+ }
295
+ if (typeof this._subscribers[params.type][params.moduleId] === "undefined") {
296
+ this._subscribers[params.type][params.moduleId] = {
297
+ callbacks: [],
298
+ commands: {}
299
+ };
300
+ }
301
+ if (params.command) {
302
+ if (typeof this._subscribers[params.type][params.moduleId]["commands"][params.command] === "undefined") {
303
+ this._subscribers[params.type][params.moduleId]["commands"][params.command] = [];
304
+ }
305
+ this._subscribers[params.type][params.moduleId]["commands"][params.command].push(params.callback);
306
+ return () => {
307
+ if (typeof params.type === "undefined" || typeof params.moduleId === "undefined" || typeof params.command === "undefined" || null === params.command) {
308
+ return;
309
+ }
310
+ this._subscribers[params.type][params.moduleId]["commands"][params.command] = this._subscribers[params.type][params.moduleId]["commands"][params.command].filter((element) => {
311
+ return element !== params.callback;
312
+ });
313
+ };
314
+ } else {
315
+ this._subscribers[params.type][params.moduleId]["callbacks"].push(
316
+ params.callback
317
+ );
318
+ return () => {
319
+ if (typeof params.type === "undefined" || typeof params.moduleId === "undefined") {
320
+ return;
321
+ }
322
+ this._subscribers[params.type][params.moduleId]["callbacks"] = this._subscribers[params.type][params.moduleId]["callbacks"].filter(
323
+ (element) => {
324
+ return element !== params.callback;
325
+ }
326
+ );
327
+ };
328
+ }
329
+ } else {
330
+ if (typeof this._subscribers[params.type] === "undefined") {
331
+ this._subscribers[params.type] = [];
332
+ }
333
+ this._subscribers[params.type].push(params.callback);
334
+ return () => {
335
+ if (typeof params.type === "undefined") {
336
+ return;
337
+ }
338
+ this._subscribers[params.type] = this._subscribers[params.type].filter(
339
+ (element) => {
340
+ return element !== params.callback;
341
+ }
342
+ );
343
+ };
344
+ }
345
+ }
346
+ /**
347
+ * @param {TypeSubscriptionCommandHandler} handler
348
+ * @returns {() => void} - Unsubscribe callback function
349
+ */
350
+ attachCommandHandler(handler) {
351
+ if (typeof handler.getModuleId !== "function" || typeof handler.getModuleId() !== "string") {
352
+ this.getLogger().error(`${text.Text.getDateForLog()}: Pull.attachCommandHandler: result of handler.getModuleId() is not a string.`);
353
+ return () => {
354
+ };
355
+ }
356
+ let type = pull.SubscriptionType.Server;
357
+ if (typeof handler.getSubscriptionType === "function") {
358
+ type = handler.getSubscriptionType();
359
+ }
360
+ return this.subscribe({
361
+ type,
362
+ moduleId: handler.getModuleId(),
363
+ callback: /* @__PURE__ */ __name((data) => {
364
+ let method = null;
365
+ if (typeof handler.getMap === "function") {
366
+ const mapping = handler.getMap();
367
+ if (mapping && typeof mapping === "object") {
368
+ const rowMapping = mapping[data.command];
369
+ if (typeof rowMapping === "function") {
370
+ method = rowMapping.bind(handler);
371
+ } else if (typeof rowMapping === "string" && typeof handler[rowMapping] === "function") {
372
+ method = handler[rowMapping].bind(handler);
373
+ }
374
+ }
375
+ }
376
+ if (!method) {
377
+ const methodName = `handle${text.Text.capitalize(data.command)}`;
378
+ if (typeof handler[methodName] === "function") {
379
+ method = handler[methodName].bind(handler);
380
+ }
381
+ }
382
+ if (method) {
383
+ if (this._debug && this._context !== "master") {
384
+ this.getLogger().warning(
385
+ `${text.Text.getDateForLog()}: Pull.attachCommandHandler: result of handler.getModuleId() is not a string`,
386
+ // data.params / data.extra are app-defined and may carry a credential key (#43)
387
+ redact.redactSensitiveParams({ data })
388
+ );
389
+ }
390
+ method(data.params, data.extra, data.command);
391
+ }
392
+ }, "callback")
393
+ });
394
+ }
395
+ /**
396
+ * Connects the client and begins receiving events.
397
+ *
398
+ * @param config
399
+ * @throws Rejects with `{ ex: { error: 'PULL_DISPOSED' } }` when called after
400
+ * `destroy()` — a destroyed client cannot be restarted; create a new instance.
401
+ */
402
+ async start(config = null) {
403
+ if (this._disposed) {
404
+ return Promise.reject({
405
+ ex: {
406
+ error: "PULL_DISPOSED",
407
+ error_description: "PullClient has been destroyed; create a new instance"
408
+ }
409
+ });
410
+ }
411
+ let allowConfigCaching = true;
412
+ if (this.isConnected()) {
413
+ return Promise.resolve(true);
414
+ }
415
+ if (this._starting && this._startingPromise) {
416
+ return this._startingPromise;
417
+ }
418
+ if (!this._userId) {
419
+ throw new Error("Not set userId");
420
+ }
421
+ if (this._siteId === "none") {
422
+ throw new Error("Not set siteId");
423
+ }
424
+ let skipReconnectToLastSession = false;
425
+ if (!!config && type.Type.isPlainObject(config)) {
426
+ if (typeof config?.skipReconnectToLastSession !== "undefined") {
427
+ skipReconnectToLastSession = config.skipReconnectToLastSession;
428
+ delete config.skipReconnectToLastSession;
429
+ }
430
+ this._config = config;
431
+ allowConfigCaching = false;
432
+ }
433
+ if (!this._enabled) {
434
+ return Promise.reject({
435
+ ex: {
436
+ error: "PULL_DISABLED",
437
+ error_description: "Push & Pull server is disabled"
438
+ }
439
+ });
440
+ }
441
+ const now = Date.now();
442
+ let oldSession;
443
+ if (!skipReconnectToLastSession && this._storage) {
444
+ oldSession = this._storage.get(LS_SESSION, null);
445
+ }
446
+ if (type.Type.isPlainObject(oldSession) && Object.prototype.hasOwnProperty.call(oldSession, "ttl") && oldSession["ttl"] >= now) {
447
+ this._session.mid = oldSession["mid"];
448
+ }
449
+ this._starting = true;
450
+ return this._startingPromise = new Promise((resolve, reject) => {
451
+ this.loadConfig("client_start").then((config2) => {
452
+ this.setConfig(config2, allowConfigCaching);
453
+ this.init();
454
+ this.updateWatch(true);
455
+ this.startCheckConfig();
456
+ this.connect().then(
457
+ () => resolve(true),
458
+ (error) => reject(error)
459
+ );
460
+ }).catch((error) => {
461
+ this._starting = false;
462
+ this.status = pull.PullStatus.Offline;
463
+ this.stopCheckConfig();
464
+ this.getLogger().error(
465
+ `${text.Text.getDateForLog()}: Pull: could not read push-server config`,
466
+ { error }
467
+ );
468
+ reject(error);
469
+ });
470
+ });
471
+ }
472
+ /**
473
+ * @param disconnectCode
474
+ * @param disconnectReason
475
+ */
476
+ restart(disconnectCode = pull.CloseReasons.NORMAL_CLOSURE, disconnectReason = "manual restart") {
477
+ if (this._disposed) {
478
+ return;
479
+ }
480
+ if (this._restartTimeout) {
481
+ clearTimeout(this._restartTimeout);
482
+ this._restartTimeout = null;
483
+ }
484
+ this.getLogger().debug(
485
+ `${text.Text.getDateForLog()}: Pull: restarting with code ${disconnectCode}`
486
+ );
487
+ this.disconnect(disconnectCode, disconnectReason);
488
+ if (this._storage) {
489
+ this._storage.remove(pull.LsKeys.PullConfig);
490
+ }
491
+ this._config = null;
492
+ const loadConfigReason = `${disconnectCode}_${disconnectReason.replaceAll(" ", "_")}`;
493
+ this.loadConfig(loadConfigReason).then(
494
+ (config) => {
495
+ this.setConfig(config, true);
496
+ this.updateWatch();
497
+ this.startCheckConfig();
498
+ this.connect().catch((error) => {
499
+ this.getLogger().error("restart error", { error });
500
+ });
501
+ },
502
+ (error) => {
503
+ this.getLogger().error(
504
+ `${text.Text.getDateForLog()}: Pull: could not read push-server config `,
505
+ { error }
506
+ );
507
+ this.status = pull.PullStatus.Offline;
508
+ if (this._reconnectTimeout) {
509
+ clearTimeout(this._reconnectTimeout);
510
+ this._reconnectTimeout = null;
511
+ }
512
+ if (error?.status == 401 || error?.status == 403) {
513
+ this.stopCheckConfig();
514
+ this.onCustomEvent("onPullError", ["AUTHORIZE_ERROR"]);
515
+ }
516
+ }
517
+ );
518
+ }
519
+ stop(disconnectCode = pull.CloseReasons.NORMAL_CLOSURE, disconnectReason = "manual stop") {
520
+ this.disconnect(disconnectCode, disconnectReason);
521
+ this.stopCheckConfig();
522
+ this.clearAllTimers();
523
+ }
524
+ // Cancel every pending timer so a stopped/destroyed client leaves nothing
525
+ // running. Previously only _checkInterval was cleared, so the other six timers
526
+ // (including the self-rescheduling watch-extend) survived teardown (#141).
527
+ clearAllTimers() {
528
+ for (const timer of [
529
+ this._reconnectTimeout,
530
+ this._restartTimeout,
531
+ this._restoreWebSocketTimeout,
532
+ this._offlineTimeout,
533
+ this._watchUpdateTimeout,
534
+ this._pingWaitTimeout
535
+ ]) {
536
+ if (timer) {
537
+ clearTimeout(timer);
538
+ }
539
+ }
540
+ if (this._checkInterval) {
541
+ clearInterval(this._checkInterval);
542
+ }
543
+ this._reconnectTimeout = null;
544
+ this._restartTimeout = null;
545
+ this._restoreWebSocketTimeout = null;
546
+ this._offlineTimeout = null;
547
+ this._watchUpdateTimeout = null;
548
+ this._pingWaitTimeout = null;
549
+ this._checkInterval = null;
550
+ }
551
+ reconnect(disconnectCode, disconnectReason, delay = 1) {
552
+ this.disconnect(disconnectCode, disconnectReason);
553
+ this.scheduleReconnect(delay);
554
+ }
555
+ /**
556
+ * @param lastMessageId
557
+ */
558
+ setLastMessageId(lastMessageId) {
559
+ this._session.mid = lastMessageId;
560
+ }
561
+ /**
562
+ * Send a single message to the specified users.
563
+ *
564
+ * @param users User ids of the message receivers.
565
+ * @param moduleId Name of the module to receive a message,
566
+ * @param command Command name.
567
+ * @param {object} params Command parameters.
568
+ * @param [expiry] Message expiry time in seconds.
569
+ * @return {Promise}
570
+ */
571
+ async sendMessage(users, moduleId, command, params, expiry) {
572
+ const message = {
573
+ userList: users,
574
+ body: {
575
+ module_id: moduleId,
576
+ command,
577
+ params
578
+ },
579
+ expiry
580
+ };
581
+ if (this.isJsonRpc()) {
582
+ return this._jsonRpcAdapter?.executeOutgoingRpcCommand(
583
+ pull.RpcMethod.Publish,
584
+ message
585
+ );
586
+ } else {
587
+ return this.sendMessageBatch([message]);
588
+ }
589
+ }
590
+ /**
591
+ * Send a single message to the specified public channels.
592
+ *
593
+ * @param publicChannels Public ids of the channels to receive a message.
594
+ * @param moduleId Name of the module to receive a message,
595
+ * @param command Command name.
596
+ * @param {object} params Command parameters.
597
+ * @param [expiry] Message expiry time in seconds.
598
+ * @return {Promise}
599
+ */
600
+ async sendMessageToChannels(publicChannels, moduleId, command, params, expiry) {
601
+ const message = {
602
+ channelList: publicChannels,
603
+ body: {
604
+ module_id: moduleId,
605
+ command,
606
+ params
607
+ },
608
+ expiry
609
+ };
610
+ if (this.isJsonRpc()) {
611
+ return this._jsonRpcAdapter?.executeOutgoingRpcCommand(
612
+ pull.RpcMethod.Publish,
613
+ message
614
+ );
615
+ } else {
616
+ return this.sendMessageBatch([message]);
617
+ }
618
+ }
619
+ /**
620
+ * @param debugFlag
621
+ */
622
+ capturePullEvent(debugFlag = true) {
623
+ this._debug = debugFlag;
624
+ }
625
+ /**
626
+ * @param loggingFlag
627
+ */
628
+ enableLogging(loggingFlag = true) {
629
+ this._sharedConfig.setLoggingEnabled(loggingFlag);
630
+ this._loggingEnabled = loggingFlag;
631
+ }
632
+ /**
633
+ * Returns list channels that the connection is subscribed to.
634
+ *
635
+ * @returns {Promise}
636
+ */
637
+ async listChannels() {
638
+ return this._jsonRpcAdapter?.executeOutgoingRpcCommand(
639
+ pull.RpcMethod.ListChannels,
640
+ {}
641
+ ) || Promise.reject(new Error("jsonRpcAdapter not init"));
642
+ }
643
+ /**
644
+ * Returns "last seen" time in seconds for the users.
645
+ * Result format: Object{userId: int}
646
+ * If the user is currently connected - will return 0.
647
+ * If the user is offline - will return the diff between the current timestamp and the last seen timestamp in seconds.
648
+ * If the user was never online - the record for the user will be missing from the result object.
649
+ *
650
+ * @param {integer[]} userList List of user ids.
651
+ * @returns {Promise}
652
+ */
653
+ async getUsersLastSeen(userList) {
654
+ if (!type.Type.isArray(userList) || !userList.every((item) => typeof item === "number")) {
655
+ throw new Error("userList must be an array of numbers");
656
+ }
657
+ const result = {};
658
+ return new Promise((resolve, reject) => {
659
+ this._jsonRpcAdapter?.executeOutgoingRpcCommand(pull.RpcMethod.GetUsersLastSeen, {
660
+ userList
661
+ }).then((response) => {
662
+ const unresolved = [];
663
+ for (let i = 0; i < userList.length; i++) {
664
+ if (!Object.prototype.hasOwnProperty.call(response, userList[i])) {
665
+ unresolved.push(userList[i]);
666
+ }
667
+ }
668
+ if (unresolved.length === 0) {
669
+ return resolve(result);
670
+ }
671
+ const params = {
672
+ userIds: unresolved,
673
+ sendToQueueSever: true
674
+ };
675
+ this._restClient.actions.v2.call.make({
676
+ method: "pull.api.user.getLastSeen",
677
+ params
678
+ }).then((response2) => {
679
+ const data = response2.getData().result;
680
+ for (const userId in data) {
681
+ result[Number(userId)] = Number(data[userId]);
682
+ }
683
+ return resolve(result);
684
+ }).catch((error) => {
685
+ this.getLogger().error("getUsersLastSeen", { error });
686
+ reject(error);
687
+ });
688
+ }).catch((error) => {
689
+ this.getLogger().error("getUsersLastSeen", { error });
690
+ reject(error);
691
+ });
692
+ });
693
+ }
694
+ /**
695
+ * Pings server.
696
+ * In case of success promise will be resolved, otherwise - rejected.
697
+ *
698
+ * @param {number} timeout Request timeout in seconds
699
+ * @returns {Promise}
700
+ */
701
+ async ping(timeout = 5) {
702
+ return this._jsonRpcAdapter?.executeOutgoingRpcCommand(
703
+ pull.RpcMethod.Ping,
704
+ {},
705
+ timeout
706
+ );
707
+ }
708
+ /**
709
+ * @param userId {number}
710
+ * @param callback {UserStatusCallback}
711
+ * @returns {Promise}
712
+ */
713
+ async subscribeUserStatusChange(userId, callback) {
714
+ return new Promise((resolve, reject) => {
715
+ this._jsonRpcAdapter?.executeOutgoingRpcCommand(pull.RpcMethod.SubscribeStatusChange, {
716
+ userId
717
+ }).then(() => {
718
+ if (!this._userStatusCallbacks[userId]) {
719
+ this._userStatusCallbacks[userId] = [];
720
+ }
721
+ if (type.Type.isFunction(callback)) {
722
+ this._userStatusCallbacks[userId].push(callback);
723
+ }
724
+ return resolve();
725
+ }).catch((error) => reject(error));
726
+ });
727
+ }
728
+ /**
729
+ * @param {number} userId
730
+ * @param {UserStatusCallback} callback
731
+ * @returns {Promise}
732
+ */
733
+ async unsubscribeUserStatusChange(userId, callback) {
734
+ if (this._userStatusCallbacks[userId]) {
735
+ this._userStatusCallbacks[userId] = this._userStatusCallbacks[userId].filter((cb) => cb !== callback);
736
+ if (this._userStatusCallbacks[userId].length === 0) {
737
+ return this._jsonRpcAdapter?.executeOutgoingRpcCommand(
738
+ pull.RpcMethod.UnsubscribeStatusChange,
739
+ {
740
+ userId
741
+ }
742
+ );
743
+ }
744
+ }
745
+ return Promise.resolve();
746
+ }
747
+ // endregion ////
748
+ // region Get ////
749
+ getRevision() {
750
+ return this._config && this._config.api ? this._config.api.revision_web : null;
751
+ }
752
+ getServerVersion() {
753
+ return this._config && this._config.server ? this._config.server.version : 0;
754
+ }
755
+ getServerMode() {
756
+ return this._config && this._config.server ? this._config.server.mode : null;
757
+ }
758
+ getConfig() {
759
+ return this._config;
760
+ }
761
+ getDebugInfo() {
762
+ if (!JSON || !JSON.stringify) {
763
+ return {};
764
+ }
765
+ let configDump;
766
+ if (this._config && this._config.channels) {
767
+ configDump = {
768
+ // The private channel id is a subscription secret — mask it here too, not
769
+ // just in `Path` below, so the debug dump never surfaces it (#148). Expiry
770
+ // timestamps are non-sensitive and kept for diagnostics.
771
+ ChannelID: this._config.channels.private?.id ? redact.REDACTED_PLACEHOLDER : "n/a",
772
+ ChannelDie: this._config.channels.private?.end || "n/a",
773
+ ChannelDieShared: this._config.channels.shared?.end || "n/a"
774
+ };
775
+ } else {
776
+ configDump = {
777
+ ConfigError: "config is not loaded"
778
+ };
779
+ }
780
+ let websocketMode = "-";
781
+ if (this._connectors.webSocket && this._connectors.webSocket?.socket) {
782
+ if (this.isJsonRpc()) {
783
+ websocketMode = "json-rpc";
784
+ } else {
785
+ websocketMode = this._connectors.webSocket?.socket?.url.search("binaryMode=true") != -1 ? "protobuf" : "text";
786
+ }
787
+ }
788
+ const connectionPath = this.connector?.connectionPath;
789
+ return {
790
+ "UserId": this._userId + (this._userId > 0 ? "" : "(guest)"),
791
+ "Guest userId": this._guestMode && this._guestUserId !== 0 ? this._guestUserId : "-",
792
+ "Browser online": navigator.onLine ? "Y" : "N",
793
+ "Connect": this.isConnected() ? "Y" : "N",
794
+ "Server type": this.isSharedMode() ? "cloud" : "local",
795
+ "WebSocket supported": this.isWebSocketSupported() ? "Y" : "N",
796
+ "WebSocket connected": this._connectors.webSocket && this._connectors.webSocket.connected ? "Y" : "N",
797
+ "WebSocket mode": websocketMode,
798
+ "Try connect": this._reconnectTimeout ? "Y" : "N",
799
+ "Try number": this._connectionAttempt,
800
+ // Mask the push JWT (`token`) and private `CHANNEL_ID`s before exposing
801
+ // the connection path through this developer-facing debug dump (#148).
802
+ "Path": connectionPath ? redact.redactSensitiveUrl(connectionPath, ["CHANNEL_ID"]) : "-",
803
+ ...configDump,
804
+ "Last message": this._session.mid || "-",
805
+ "Session history": this._session.history,
806
+ "Watch tags": this._watchTagsQueue.entries()
807
+ };
808
+ }
809
+ /**
810
+ * @process
811
+ * @param connectionType
812
+ */
813
+ getConnectionPath(connectionType) {
814
+ let path;
815
+ const params = {};
816
+ switch (connectionType) {
817
+ case pull.ConnectionType.WebSocket:
818
+ path = this._isSecure ? this._config?.server.websocket_secure : this._config?.server.websocket;
819
+ break;
820
+ case pull.ConnectionType.LongPolling:
821
+ path = this._isSecure ? this._config?.server.long_pooling_secure : this._config?.server.long_polling;
822
+ break;
823
+ default:
824
+ throw new Error(`Unknown connection type ${connectionType}`);
825
+ }
826
+ if (!type.Type.isStringFilled(path)) {
827
+ throw new Error(`Empty path`);
828
+ }
829
+ if (typeof this._config?.jwt === "string" && this._config?.jwt !== "") {
830
+ params["token"] = this._config?.jwt;
831
+ } else {
832
+ const channels = [];
833
+ if (this._config?.channels?.private?.id) {
834
+ channels.push(this._config.channels.private.id);
835
+ }
836
+ if (this._config?.channels?.shared?.id) {
837
+ channels.push(this._config.channels.shared.id);
838
+ }
839
+ if (channels.length === 0) {
840
+ throw new Error(`Empty channels`);
841
+ }
842
+ params["CHANNEL_ID"] = channels.join("/");
843
+ }
844
+ if (this.isJsonRpc()) {
845
+ params.jsonRpc = "true";
846
+ } else if (this.isProtobufSupported()) {
847
+ params.binaryMode = "true";
848
+ }
849
+ if (this.isSharedMode()) {
850
+ if (!this._config?.clientId) {
851
+ throw new Error(
852
+ "Push-server is in shared mode, but clientId is not set"
853
+ );
854
+ }
855
+ params.clientId = this._config.clientId;
856
+ }
857
+ if (this._session.mid) {
858
+ params.mid = this._session.mid;
859
+ }
860
+ if (this._session.tag) {
861
+ params.tag = this._session.tag;
862
+ }
863
+ if (this._session.time) {
864
+ params.time = this._session.time;
865
+ }
866
+ params.revision = REVISION;
867
+ return `${path}?${text.Text.buildQueryString(params)}`;
868
+ }
869
+ /**
870
+ * @process
871
+ */
872
+ getPublicationPath() {
873
+ const path = this._isSecure ? this._config?.server.publish_secure : this._config?.server.publish;
874
+ if (!path) {
875
+ return "";
876
+ }
877
+ const channels = [];
878
+ if (this._config?.channels.private?.id) {
879
+ channels.push(this._config.channels.private.id);
880
+ }
881
+ if (this._config?.channels.shared?.id) {
882
+ channels.push(this._config.channels.shared.id);
883
+ }
884
+ const params = {
885
+ CHANNEL_ID: channels.join("/")
886
+ };
887
+ return path + "?" + text.Text.buildQueryString(params);
888
+ }
889
+ // endregion ////
890
+ // region Is* ////
891
+ isConnected() {
892
+ return this.connector ? this.connector.connected : false;
893
+ }
894
+ isWebSocketSupported() {
895
+ return typeof window.WebSocket !== "undefined";
896
+ }
897
+ isWebSocketAllowed() {
898
+ if (this._sharedConfig.isWebSocketBlocked()) {
899
+ return false;
900
+ }
901
+ return this.isWebSocketEnabled();
902
+ }
903
+ isWebSocketEnabled() {
904
+ if (!this.isWebSocketSupported()) {
905
+ return false;
906
+ }
907
+ if (!this._config) {
908
+ return false;
909
+ }
910
+ if (!this._config.server) {
911
+ return false;
912
+ }
913
+ return this._config.server.websocket_enabled;
914
+ }
915
+ isPublishingSupported() {
916
+ return this.getServerVersion() > 3;
917
+ }
918
+ isPublishingEnabled() {
919
+ if (!this.isPublishingSupported()) {
920
+ return false;
921
+ }
922
+ return this._config?.server.publish_enabled === true;
923
+ }
924
+ isProtobufSupported() {
925
+ return this.getServerVersion() == 4 && !browser.Browser.isIE();
926
+ }
927
+ isJsonRpc() {
928
+ return this.getServerVersion() >= 5;
929
+ }
930
+ isSharedMode() {
931
+ return this.getServerMode() === pull.ServerMode.Shared;
932
+ }
933
+ // endregion ////
934
+ // region Events ////
935
+ /**
936
+ * @param {TypePullClientEmitConfig} params
937
+ * @returns {boolean}
938
+ */
939
+ emit(params) {
940
+ if (params.type == pull.SubscriptionType.Server || params.type == pull.SubscriptionType.Client) {
941
+ if (typeof this._subscribers[params.type] === "undefined") {
942
+ this._subscribers[params.type] = {};
943
+ }
944
+ if (typeof params.moduleId === "undefined") {
945
+ throw new TypeError(
946
+ `${text.Text.getDateForLog()}: Pull.emit: parameter moduleId is not specified`
947
+ );
948
+ }
949
+ if (typeof this._subscribers[params.type][params.moduleId] === "undefined") {
950
+ this._subscribers[params.type][params.moduleId] = {
951
+ callbacks: [],
952
+ commands: {}
953
+ };
954
+ }
955
+ if (this._subscribers[params.type][params.moduleId]["callbacks"].length > 0) {
956
+ this._subscribers[params.type][params.moduleId]["callbacks"].forEach(
957
+ (callback) => {
958
+ callback(params.data, {
959
+ type: params.type,
960
+ moduleId: params.moduleId ?? "?"
961
+ });
962
+ }
963
+ );
964
+ }
965
+ if (!(typeof params.data === "undefined") && !(typeof params.data["command"] === "undefined") && this._subscribers[params.type][params.moduleId]["commands"][params.data["command"]] && this._subscribers[params.type][params.moduleId]["commands"][params.data["command"]].length > 0) {
966
+ this._subscribers[params.type][params.moduleId]["commands"][params.data["command"]].forEach((callback) => {
967
+ if (typeof params.data === "undefined") {
968
+ return;
969
+ }
970
+ callback(
971
+ params.data["params"],
972
+ params.data["extra"],
973
+ params.data["command"],
974
+ {
975
+ type: params.type,
976
+ moduleId: params.moduleId
977
+ }
978
+ );
979
+ });
980
+ }
981
+ return true;
982
+ } else {
983
+ if (typeof this._subscribers[params.type] === "undefined") {
984
+ this._subscribers[params.type] = [];
985
+ }
986
+ if (this._subscribers[params.type].length <= 0) {
987
+ return true;
988
+ }
989
+ this._subscribers[params.type].forEach(
990
+ (callback) => {
991
+ callback(params.data, {
992
+ type: params.type
993
+ });
994
+ }
995
+ );
996
+ return true;
997
+ }
998
+ }
999
+ /**
1000
+ * @process
1001
+ *
1002
+ * @param message
1003
+ */
1004
+ broadcastMessage(message) {
1005
+ const moduleId = message.module_id = message.module_id.toLowerCase();
1006
+ const command = message.command;
1007
+ if (!message.extra) {
1008
+ message.extra = {};
1009
+ }
1010
+ if (message.extra.server_time_unix) {
1011
+ message.extra.server_time_ago = (Date.now() - message.extra.server_time_unix * 1e3) / 1e3 - (this._config?.server.timeShift || 0);
1012
+ message.extra.server_time_ago = Math.max(message.extra.server_time_ago, 0);
1013
+ }
1014
+ this.logMessage(message);
1015
+ try {
1016
+ if (message.extra.sender && message.extra.sender.type === pull.SenderType.Client) {
1017
+ this.onCustomEvent(
1018
+ "onPullClientEvent-" + moduleId,
1019
+ [command, message.params, message.extra],
1020
+ true
1021
+ );
1022
+ this.onCustomEvent(
1023
+ "onPullClientEvent",
1024
+ [moduleId, command, message.params, message.extra],
1025
+ true
1026
+ );
1027
+ this.emit({
1028
+ type: pull.SubscriptionType.Client,
1029
+ moduleId,
1030
+ data: {
1031
+ command,
1032
+ params: type.Type.clone(message.params),
1033
+ extra: type.Type.clone(message.extra)
1034
+ }
1035
+ });
1036
+ } else if (moduleId === "pull") {
1037
+ this.handleInternalPullEvent(command, message);
1038
+ } else if (moduleId == "online") {
1039
+ if ((message?.extra?.server_time_ago || 0) < 240) {
1040
+ this.onCustomEvent(
1041
+ "onPullOnlineEvent",
1042
+ [command, message.params, message.extra],
1043
+ true
1044
+ );
1045
+ this.emit({
1046
+ type: pull.SubscriptionType.Online,
1047
+ data: {
1048
+ command,
1049
+ params: type.Type.clone(message.params),
1050
+ extra: type.Type.clone(message.extra)
1051
+ }
1052
+ });
1053
+ }
1054
+ if (command === "userStatusChange") {
1055
+ this.emitUserStatusChange(
1056
+ message.params.user_id,
1057
+ message.params.online
1058
+ );
1059
+ }
1060
+ } else {
1061
+ this.onCustomEvent(
1062
+ "onPullEvent-" + moduleId,
1063
+ [command, message.params, message.extra],
1064
+ true
1065
+ );
1066
+ this.onCustomEvent(
1067
+ "onPullEvent",
1068
+ [moduleId, command, message.params, message.extra],
1069
+ true
1070
+ );
1071
+ this.emit({
1072
+ type: pull.SubscriptionType.Server,
1073
+ moduleId,
1074
+ data: {
1075
+ command,
1076
+ params: type.Type.clone(message.params),
1077
+ extra: type.Type.clone(message.extra)
1078
+ }
1079
+ });
1080
+ }
1081
+ } catch (error) {
1082
+ this.getLogger().warning("PULL ERROR", {
1083
+ errorType: "broadcastMessages execute error",
1084
+ errorEvent: error,
1085
+ // app-defined message.params / extra may carry a credential key (#43)
1086
+ message: redact.redactSensitiveParams(message)
1087
+ });
1088
+ }
1089
+ if (message.extra && message.extra.revision_web) {
1090
+ this.checkRevision(text.Text.toInteger(message.extra.revision_web));
1091
+ }
1092
+ }
1093
+ /**
1094
+ * @process
1095
+ *
1096
+ * @param messages
1097
+ */
1098
+ broadcastMessages(messages) {
1099
+ for (const message of messages) {
1100
+ this.broadcastMessage(message);
1101
+ }
1102
+ }
1103
+ // endregion ////
1104
+ // region sendMessage ////
1105
+ /**
1106
+ * Sends batch of messages to the multiple public channels.
1107
+ *
1108
+ * @param messageBatchList Array of messages to send.
1109
+ * @return void
1110
+ */
1111
+ async sendMessageBatch(messageBatchList) {
1112
+ if (!this.isPublishingEnabled()) {
1113
+ this.getLogger().error(`Client publishing is not supported or is disabled`);
1114
+ return Promise.reject(
1115
+ new Error(`Client publishing is not supported or is disabled`)
1116
+ );
1117
+ }
1118
+ if (this.isJsonRpc()) {
1119
+ const rpcRequest = this._jsonRpcAdapter?.createPublishRequest(messageBatchList);
1120
+ this.connector?.send(JSON.stringify(rpcRequest));
1121
+ return Promise.resolve(true);
1122
+ } else {
1123
+ const userIds = {};
1124
+ for (const messageBatch of messageBatchList) {
1125
+ if (typeof messageBatch.userList !== "undefined") {
1126
+ for (const user of messageBatch.userList) {
1127
+ const userId = Number(user);
1128
+ userIds[userId] = userId;
1129
+ }
1130
+ }
1131
+ }
1132
+ this._channelManager?.getPublicIds(Object.values(userIds)).then((publicIds) => {
1133
+ const response = this.connector?.send(
1134
+ this.encodeMessageBatch(messageBatchList, publicIds)
1135
+ );
1136
+ return Promise.resolve(response);
1137
+ });
1138
+ }
1139
+ }
1140
+ /**
1141
+ * @param messageBatchList
1142
+ * @param publicIds
1143
+ */
1144
+ encodeMessageBatch(messageBatchList, publicIds) {
1145
+ const messages = [];
1146
+ messageBatchList.forEach((messageFields) => {
1147
+ const messageBody = messageFields.body;
1148
+ let receivers = [];
1149
+ if (messageFields.userList) {
1150
+ receivers = this.createMessageReceivers(
1151
+ messageFields.userList,
1152
+ publicIds
1153
+ );
1154
+ }
1155
+ if (messageFields.channelList) {
1156
+ if (!type.Type.isArray(messageFields.channelList)) {
1157
+ throw new TypeError("messageFields.publicChannels must be an array");
1158
+ }
1159
+ messageFields.channelList.forEach((publicChannel) => {
1160
+ let publicId;
1161
+ let signature;
1162
+ if (typeof publicChannel === "string" && publicChannel.includes(".")) {
1163
+ const fields = publicChannel.toString().split(".");
1164
+ publicId = fields[0];
1165
+ signature = fields[1];
1166
+ } else if (typeof publicChannel === "object" && "publicId" in publicChannel && "signature" in publicChannel) {
1167
+ publicId = publicChannel?.publicId;
1168
+ signature = publicChannel?.signature;
1169
+ } else {
1170
+ throw new Error(
1171
+ `Public channel MUST be either a string, formatted like "{publicId}.{signature}" or an object with fields 'publicId' and 'signature'`
1172
+ );
1173
+ }
1174
+ receivers.push(
1175
+ index.Receiver.create({
1176
+ id: this.encodeId(publicId),
1177
+ signature: this.encodeId(signature)
1178
+ })
1179
+ );
1180
+ });
1181
+ }
1182
+ const message = index.IncomingMessage.create({
1183
+ receivers,
1184
+ body: JSON.stringify(messageBody),
1185
+ expiry: messageFields.expiry || 0
1186
+ });
1187
+ messages.push(message);
1188
+ });
1189
+ const requestBatch = index.RequestBatch.create({
1190
+ requests: [
1191
+ {
1192
+ incomingMessages: {
1193
+ messages
1194
+ }
1195
+ }
1196
+ ]
1197
+ });
1198
+ return index.RequestBatch.encode(requestBatch).finish();
1199
+ }
1200
+ /**
1201
+ * @memo fix return type
1202
+ * @param users
1203
+ * @param publicIds
1204
+ */
1205
+ createMessageReceivers(users, publicIds) {
1206
+ const result = [];
1207
+ for (const userId of users) {
1208
+ if (!publicIds[userId] || !publicIds[userId].publicId) {
1209
+ throw new Error(`Could not determine public id for user ${userId}`);
1210
+ }
1211
+ result.push(
1212
+ index.Receiver.create({
1213
+ id: this.encodeId(publicIds[userId].publicId),
1214
+ signature: this.encodeId(publicIds[userId].signature)
1215
+ })
1216
+ );
1217
+ }
1218
+ return result;
1219
+ }
1220
+ // endregion ////
1221
+ // region _userStatusCallbacks ////
1222
+ /**
1223
+ * @param userId
1224
+ * @param isOnline
1225
+ */
1226
+ emitUserStatusChange(userId, isOnline) {
1227
+ if (this._userStatusCallbacks[userId]) {
1228
+ for (const callback of this._userStatusCallbacks[userId]) {
1229
+ callback({
1230
+ userId,
1231
+ isOnline
1232
+ });
1233
+ }
1234
+ }
1235
+ }
1236
+ restoreUserStatusSubscription() {
1237
+ for (const userId in this._userStatusCallbacks) {
1238
+ if (Object.prototype.hasOwnProperty.call(this._userStatusCallbacks, userId) && this._userStatusCallbacks[userId].length > 0) {
1239
+ this._jsonRpcAdapter?.executeOutgoingRpcCommand(
1240
+ pull.RpcMethod.SubscribeStatusChange,
1241
+ {
1242
+ userId
1243
+ }
1244
+ );
1245
+ }
1246
+ }
1247
+ }
1248
+ // endregion ////
1249
+ // region Config ////
1250
+ async loadConfig(_logTag) {
1251
+ if (!this._config) {
1252
+ this._config = Object.assign({}, EmptyConfig);
1253
+ let config;
1254
+ if (this._storage) {
1255
+ config = this._storage.get(pull.LsKeys.PullConfig, null);
1256
+ }
1257
+ if (this.isConfigActual(config) && this.checkRevision(config.api.revision_web)) {
1258
+ return Promise.resolve(config);
1259
+ } else if (this._storage) {
1260
+ this._storage.remove(pull.LsKeys.PullConfig);
1261
+ }
1262
+ } else if (this.isConfigActual(this._config) && this.checkRevision(this._config.api.revision_web)) {
1263
+ return Promise.resolve(this._config);
1264
+ } else {
1265
+ this._config = Object.assign({}, EmptyConfig);
1266
+ }
1267
+ return new Promise((resolve, reject) => {
1268
+ this._restClient.actions.v2.call.make({
1269
+ method: this._configGetMethod,
1270
+ params: { CACHE: "N" }
1271
+ }).then((response) => {
1272
+ const data = response.getData().result;
1273
+ const timeShift = Math.floor(
1274
+ (Date.now() - new Date(data.serverTime).getTime()) / 1e3
1275
+ );
1276
+ delete data.serverTime;
1277
+ const config = Object.assign({}, data);
1278
+ config.server.timeShift = timeShift;
1279
+ resolve(config);
1280
+ }).catch((error) => {
1281
+ reject(error);
1282
+ });
1283
+ });
1284
+ }
1285
+ /**
1286
+ * @param config
1287
+ */
1288
+ isConfigActual(config) {
1289
+ if (!type.Type.isPlainObject(config)) {
1290
+ return false;
1291
+ }
1292
+ if (Number(config["server"].config_timestamp) !== this._configTimestamp) {
1293
+ return false;
1294
+ }
1295
+ const now = /* @__PURE__ */ new Date();
1296
+ if (type.Type.isNumber(config["exp"]) && config["exp"] > 0 && config["exp"] < now.getTime() / 1e3) {
1297
+ return false;
1298
+ }
1299
+ const channelCount = Object.keys(config["channels"]).length;
1300
+ if (channelCount === 0) {
1301
+ return false;
1302
+ }
1303
+ for (const channelType in config["channels"]) {
1304
+ if (!Object.prototype.hasOwnProperty.call(config["channels"], channelType)) {
1305
+ continue;
1306
+ }
1307
+ const channel = config["channels"][channelType];
1308
+ const channelEnd = new Date(channel.end);
1309
+ if (channelEnd < now) {
1310
+ return false;
1311
+ }
1312
+ }
1313
+ return true;
1314
+ }
1315
+ startCheckConfig() {
1316
+ if (this._disposed) {
1317
+ return;
1318
+ }
1319
+ if (this._checkInterval) {
1320
+ clearInterval(this._checkInterval);
1321
+ this._checkInterval = null;
1322
+ }
1323
+ this._checkInterval = setInterval(
1324
+ this.checkConfig.bind(this),
1325
+ CONFIG_CHECK_INTERVAL
1326
+ );
1327
+ }
1328
+ stopCheckConfig() {
1329
+ if (this._checkInterval) {
1330
+ clearInterval(this._checkInterval);
1331
+ }
1332
+ this._checkInterval = null;
1333
+ }
1334
+ checkConfig() {
1335
+ if (this.isConfigActual(this._config)) {
1336
+ if (!this.checkRevision(text.Text.toInteger(this._config?.api.revision_web))) {
1337
+ return false;
1338
+ }
1339
+ } else {
1340
+ this.logToConsole("Stale config detected. Restarting");
1341
+ this.restart(pull.CloseReasons.CONFIG_EXPIRED, "config expired");
1342
+ }
1343
+ return true;
1344
+ }
1345
+ /**
1346
+ * @param config
1347
+ * @param allowCaching
1348
+ */
1349
+ setConfig(config, allowCaching) {
1350
+ for (const key in config) {
1351
+ if (Object.prototype.hasOwnProperty.call(config, key) && Object.prototype.hasOwnProperty.call(this._config, key)) {
1352
+ this._config[key] = config[key];
1353
+ }
1354
+ }
1355
+ if (config.publicChannels) {
1356
+ this.setPublicIds(Object.values(config.publicChannels));
1357
+ }
1358
+ this._configTimestamp = Number(config.server.config_timestamp);
1359
+ if (this._storage && allowCaching && !this._disposed) {
1360
+ try {
1361
+ this._storage.set(pull.LsKeys.PullConfig, config);
1362
+ } catch (error) {
1363
+ if (localStorage && localStorage.removeItem) {
1364
+ localStorage.removeItem("history");
1365
+ }
1366
+ this.getLogger().error(
1367
+ `${text.Text.getDateForLog()}: Pull: Could not cache config in local storage.`,
1368
+ { error }
1369
+ );
1370
+ }
1371
+ }
1372
+ }
1373
+ setPublicIds(publicIds) {
1374
+ this._channelManager.setPublicIds(publicIds);
1375
+ }
1376
+ /**
1377
+ * @param serverRevision
1378
+ */
1379
+ checkRevision(serverRevision) {
1380
+ if (this._skipCheckRevision) {
1381
+ return true;
1382
+ }
1383
+ if (serverRevision > 0 && serverRevision !== REVISION) {
1384
+ this._enabled = false;
1385
+ this.showNotification("PULL_OLD_REVISION");
1386
+ this.disconnect(pull.CloseReasons.NORMAL_CLOSURE, "check_revision");
1387
+ this.onCustomEvent("onPullRevisionUp", [serverRevision, REVISION]);
1388
+ this.emit({
1389
+ type: pull.SubscriptionType.Revision,
1390
+ data: {
1391
+ server: serverRevision,
1392
+ client: REVISION
1393
+ }
1394
+ });
1395
+ this.logToConsole(
1396
+ `Pull revision changed from ${REVISION} to ${serverRevision}. Reload required`
1397
+ );
1398
+ return false;
1399
+ }
1400
+ return true;
1401
+ }
1402
+ // endregion ////
1403
+ // region Connect|ReConnect|DisConnect ////
1404
+ disconnect(disconnectCode, disconnectReason) {
1405
+ if (this.connector) {
1406
+ this._isManualDisconnect = true;
1407
+ this.connector.disconnect(disconnectCode, disconnectReason);
1408
+ }
1409
+ }
1410
+ restoreWebSocketConnection() {
1411
+ if (this._connectionType === pull.ConnectionType.WebSocket) {
1412
+ return;
1413
+ }
1414
+ this._connectors.webSocket?.connect();
1415
+ }
1416
+ /**
1417
+ * @param connectionDelay
1418
+ */
1419
+ scheduleReconnect(connectionDelay = 0) {
1420
+ if (this._disposed || !this._enabled) {
1421
+ return;
1422
+ }
1423
+ if (!connectionDelay) {
1424
+ {
1425
+ connectionDelay = this.getConnectionAttemptDelay(
1426
+ this._connectionAttempt
1427
+ );
1428
+ }
1429
+ }
1430
+ if (this._reconnectTimeout) {
1431
+ clearTimeout(this._reconnectTimeout);
1432
+ this._reconnectTimeout = null;
1433
+ }
1434
+ this.logToConsole(
1435
+ `Pull: scheduling reconnection in ${connectionDelay} seconds; attempt # ${this._connectionAttempt}`
1436
+ );
1437
+ this._reconnectTimeout = setTimeout(() => {
1438
+ this.connect().catch((error) => {
1439
+ this.getLogger().error("scheduleReconnect", { error });
1440
+ });
1441
+ }, connectionDelay * 1e3);
1442
+ }
1443
+ scheduleRestoreWebSocketConnection() {
1444
+ if (this._disposed) {
1445
+ return;
1446
+ }
1447
+ this.logToConsole(
1448
+ `Pull: scheduling restoration of websocket connection in ${RESTORE_WEBSOCKET_TIMEOUT} seconds`
1449
+ );
1450
+ if (this._restoreWebSocketTimeout) {
1451
+ return;
1452
+ }
1453
+ this._restoreWebSocketTimeout = setTimeout(() => {
1454
+ this._restoreWebSocketTimeout = null;
1455
+ this.restoreWebSocketConnection();
1456
+ }, RESTORE_WEBSOCKET_TIMEOUT * 1e3);
1457
+ }
1458
+ /**
1459
+ * @returns {Promise}
1460
+ */
1461
+ async connect() {
1462
+ if (this._disposed || !this._enabled) {
1463
+ return Promise.reject();
1464
+ }
1465
+ if (this.connector?.connected) {
1466
+ return Promise.resolve();
1467
+ }
1468
+ if (this._reconnectTimeout) {
1469
+ clearTimeout(this._reconnectTimeout);
1470
+ this._reconnectTimeout = null;
1471
+ }
1472
+ this.status = pull.PullStatus.Connecting;
1473
+ this._connectionAttempt++;
1474
+ return new Promise((resolve, reject) => {
1475
+ this._connectPromise = {
1476
+ resolve,
1477
+ reject
1478
+ };
1479
+ this.connector?.connect();
1480
+ });
1481
+ }
1482
+ /**
1483
+ * @param disconnectCode
1484
+ * @param disconnectReason
1485
+ * @param restartDelay
1486
+ */
1487
+ scheduleRestart(disconnectCode, disconnectReason, restartDelay = 0) {
1488
+ if (this._disposed) {
1489
+ return;
1490
+ }
1491
+ if (this._restartTimeout) {
1492
+ clearTimeout(this._restartTimeout);
1493
+ this._restartTimeout = null;
1494
+ }
1495
+ if (restartDelay < 1) {
1496
+ restartDelay = Math.ceil(Math.random() * 30) + 5;
1497
+ }
1498
+ this._restartTimeout = setTimeout(
1499
+ () => this.restart(disconnectCode, disconnectReason),
1500
+ restartDelay * 1e3
1501
+ );
1502
+ }
1503
+ // endregion ////
1504
+ // region Handlers ////
1505
+ /**
1506
+ * @param messageFields
1507
+ */
1508
+ handleRpcIncomingMessage(messageFields) {
1509
+ this._session.mid = messageFields.mid;
1510
+ const body = messageFields.body;
1511
+ if (!messageFields.body.extra) {
1512
+ body.extra = {};
1513
+ }
1514
+ body.extra.sender = messageFields.sender;
1515
+ if ("user_params" in messageFields && type.Type.isPlainObject(messageFields.user_params)) {
1516
+ Object.assign(body.params, messageFields.user_params);
1517
+ }
1518
+ if ("dictionary" in messageFields && type.Type.isPlainObject(messageFields.dictionary)) {
1519
+ Object.assign(body.params, messageFields.dictionary);
1520
+ }
1521
+ if (this.checkDuplicate(messageFields.mid)) {
1522
+ this.addMessageToStat(body);
1523
+ this.trimDuplicates();
1524
+ this.broadcastMessage(body);
1525
+ }
1526
+ this.connector?.send(`mack:${messageFields.mid}`);
1527
+ return {};
1528
+ }
1529
+ /**
1530
+ * @param events
1531
+ */
1532
+ handleIncomingEvents(events) {
1533
+ const messages = [];
1534
+ if (events.length === 0) {
1535
+ this._session.mid = null;
1536
+ return;
1537
+ }
1538
+ for (const event of events) {
1539
+ this.updateSessionFromEvent(event);
1540
+ if (event.mid && !this.checkDuplicate(event.mid)) {
1541
+ continue;
1542
+ }
1543
+ this.addMessageToStat(
1544
+ event.text
1545
+ );
1546
+ messages.push(event.text);
1547
+ }
1548
+ this.trimDuplicates();
1549
+ this.broadcastMessages(messages);
1550
+ }
1551
+ /**
1552
+ * @param event
1553
+ */
1554
+ updateSessionFromEvent(event) {
1555
+ this._session.mid = event.mid || null;
1556
+ this._session.tag = event.tag || null;
1557
+ this._session.time = event.time || null;
1558
+ }
1559
+ /**
1560
+ * @process
1561
+ *
1562
+ * @param command
1563
+ * @param message
1564
+ */
1565
+ handleInternalPullEvent(command, message) {
1566
+ switch (command.toUpperCase()) {
1567
+ case pull.SystemCommands.CHANNEL_EXPIRE: {
1568
+ if (message.params.action === "reconnect") {
1569
+ const typeChanel = message.params?.channel.type;
1570
+ if (typeChanel === "private" && this._config?.channels?.private) {
1571
+ this._config.channels.private = message.params.new_channel;
1572
+ this.logToConsole(
1573
+ `Pull: new config for ${message.params.channel.type} channel set: [updated]`
1574
+ );
1575
+ }
1576
+ if (typeChanel === "shared" && this._config?.channels?.shared) {
1577
+ this._config.channels.shared = message.params.new_channel;
1578
+ this.logToConsole(
1579
+ `Pull: new config for ${message.params.channel.type} channel set: [updated]`
1580
+ );
1581
+ }
1582
+ this.reconnect(pull.CloseReasons.CONFIG_REPLACED, "config was replaced");
1583
+ } else {
1584
+ this.restart(pull.CloseReasons.CHANNEL_EXPIRED, "channel expired received");
1585
+ }
1586
+ break;
1587
+ }
1588
+ case pull.SystemCommands.CONFIG_EXPIRE: {
1589
+ this.restart(pull.CloseReasons.CONFIG_EXPIRED, "config expired received");
1590
+ break;
1591
+ }
1592
+ case pull.SystemCommands.SERVER_RESTART: {
1593
+ this.reconnect(
1594
+ pull.CloseReasons.SERVER_RESTARTED,
1595
+ "server was restarted",
1596
+ 15
1597
+ );
1598
+ break;
1599
+ }
1600
+ }
1601
+ }
1602
+ // region Handlers For Message ////
1603
+ /**
1604
+ * @param response
1605
+ */
1606
+ onIncomingMessage(response) {
1607
+ if (this.isJsonRpc()) {
1608
+ if (response === JSON_RPC_PING) {
1609
+ this.onJsonRpcPing();
1610
+ } else {
1611
+ this._jsonRpcAdapter?.parseJsonRpcMessage(response);
1612
+ }
1613
+ } else {
1614
+ const events = this.extractMessages(response);
1615
+ this.handleIncomingEvents(events);
1616
+ }
1617
+ }
1618
+ // region onLongPolling ////
1619
+ onLongPollingOpen() {
1620
+ this._unloading = false;
1621
+ this._starting = false;
1622
+ this._connectionAttempt = 0;
1623
+ this._isManualDisconnect = false;
1624
+ this.status = pull.PullStatus.Online;
1625
+ this.logToConsole("Pull: Long polling connection with push-server opened");
1626
+ if (this.isWebSocketEnabled()) {
1627
+ this.scheduleRestoreWebSocketConnection();
1628
+ }
1629
+ if (this._connectPromise) {
1630
+ this._connectPromise.resolve({});
1631
+ }
1632
+ }
1633
+ /**
1634
+ * @param response
1635
+ */
1636
+ onLongPollingDisconnect(response) {
1637
+ if (this._connectionType === pull.ConnectionType.LongPolling) {
1638
+ this.status = pull.PullStatus.Offline;
1639
+ }
1640
+ this.logToConsole(
1641
+ `Pull: Long polling connection with push-server closed. Code: ${response.code}, reason: ${response.reason}`
1642
+ );
1643
+ if (!this._isManualDisconnect) {
1644
+ this.scheduleReconnect();
1645
+ }
1646
+ this._isManualDisconnect = false;
1647
+ this.clearPingWaitTimeout();
1648
+ }
1649
+ /**
1650
+ * @param error
1651
+ */
1652
+ onLongPollingError(error) {
1653
+ this._starting = false;
1654
+ if (this._connectionType === pull.ConnectionType.LongPolling) {
1655
+ this.status = pull.PullStatus.Offline;
1656
+ }
1657
+ this.getLogger().error(
1658
+ `${text.Text.getDateForLog()}: Pull: Long polling connection error`,
1659
+ { error }
1660
+ );
1661
+ this.scheduleReconnect();
1662
+ if (this._connectPromise) {
1663
+ this._connectPromise.reject(error);
1664
+ }
1665
+ this.clearPingWaitTimeout();
1666
+ }
1667
+ // endregion ////
1668
+ // region onWebSocket ////
1669
+ /**
1670
+ * @param response
1671
+ */
1672
+ onWebSocketBlockChanged(response) {
1673
+ const isWebSocketBlocked = response.isWebSocketBlocked;
1674
+ if (isWebSocketBlocked && this._connectionType === pull.ConnectionType.WebSocket && !this.isConnected()) {
1675
+ if (this._reconnectTimeout) {
1676
+ clearTimeout(this._reconnectTimeout);
1677
+ this._reconnectTimeout = null;
1678
+ }
1679
+ this._connectionAttempt = 0;
1680
+ this._connectionType = pull.ConnectionType.LongPolling;
1681
+ this.scheduleReconnect(1);
1682
+ } else if (!isWebSocketBlocked && this._connectionType === pull.ConnectionType.LongPolling) {
1683
+ if (this._reconnectTimeout) {
1684
+ clearTimeout(this._reconnectTimeout);
1685
+ this._reconnectTimeout = null;
1686
+ }
1687
+ if (this._restoreWebSocketTimeout) {
1688
+ clearTimeout(this._restoreWebSocketTimeout);
1689
+ this._restoreWebSocketTimeout = null;
1690
+ }
1691
+ this._connectionAttempt = 0;
1692
+ this._connectionType = pull.ConnectionType.WebSocket;
1693
+ this.scheduleReconnect(1);
1694
+ }
1695
+ }
1696
+ onWebSocketOpen() {
1697
+ this._unloading = false;
1698
+ this._starting = false;
1699
+ this._connectionAttempt = 0;
1700
+ this._isManualDisconnect = false;
1701
+ this.status = pull.PullStatus.Online;
1702
+ this._sharedConfig.setWebSocketBlocked(false);
1703
+ this._sharedConfig.setLongPollingBlocked(true);
1704
+ if (this._connectionType == pull.ConnectionType.LongPolling) {
1705
+ this._connectionType = pull.ConnectionType.WebSocket;
1706
+ this._connectors.longPolling?.disconnect(
1707
+ pull.CloseReasons.CONFIG_REPLACED,
1708
+ "Fire at onWebSocketOpen"
1709
+ );
1710
+ }
1711
+ if (this._restoreWebSocketTimeout) {
1712
+ clearTimeout(this._restoreWebSocketTimeout);
1713
+ this._restoreWebSocketTimeout = null;
1714
+ }
1715
+ this.logToConsole("Pull: Websocket connection with push-server opened");
1716
+ if (this._connectPromise) {
1717
+ this._connectPromise.resolve({});
1718
+ }
1719
+ this.restoreUserStatusSubscription();
1720
+ }
1721
+ /**
1722
+ * @param response
1723
+ */
1724
+ onWebSocketDisconnect(response) {
1725
+ if (this._connectionType === pull.ConnectionType.WebSocket) {
1726
+ this.status = pull.PullStatus.Offline;
1727
+ }
1728
+ this.logToConsole(
1729
+ `Pull: Websocket connection with push-server closed. Code: ${response.code}, reason: ${response.reason}`,
1730
+ true
1731
+ );
1732
+ if (!this._isManualDisconnect) {
1733
+ if (response.code == pull.CloseReasons.WRONG_CHANNEL_ID) {
1734
+ this.scheduleRestart(
1735
+ pull.CloseReasons.WRONG_CHANNEL_ID,
1736
+ "wrong channel signature"
1737
+ );
1738
+ } else {
1739
+ this.scheduleReconnect();
1740
+ }
1741
+ }
1742
+ this._sharedConfig.setLongPollingBlocked(true);
1743
+ this._isManualDisconnect = false;
1744
+ this.clearPingWaitTimeout();
1745
+ }
1746
+ /**
1747
+ * @param error
1748
+ */
1749
+ onWebSocketError(error) {
1750
+ this._starting = false;
1751
+ if (this._connectionType === pull.ConnectionType.WebSocket) {
1752
+ this.status = pull.PullStatus.Offline;
1753
+ }
1754
+ this.getLogger().error(
1755
+ `${text.Text.getDateForLog()}: Pull: WebSocket connection error`,
1756
+ { error }
1757
+ );
1758
+ this.scheduleReconnect();
1759
+ if (this._connectPromise) {
1760
+ this._connectPromise.reject(error);
1761
+ }
1762
+ this.clearPingWaitTimeout();
1763
+ }
1764
+ // endregion ////
1765
+ // endregion ////
1766
+ // endregion ////
1767
+ // region extractMessages ////
1768
+ /**
1769
+ * @param pullEvent
1770
+ */
1771
+ extractMessages(pullEvent) {
1772
+ if (pullEvent instanceof ArrayBuffer) {
1773
+ return this.extractProtobufMessages(pullEvent);
1774
+ } else if (type.Type.isStringFilled(pullEvent)) {
1775
+ return this.extractPlainTextMessages(pullEvent);
1776
+ }
1777
+ throw new Error("Error pullEvent type");
1778
+ }
1779
+ /**
1780
+ * @param pullEvent
1781
+ */
1782
+ extractProtobufMessages(pullEvent) {
1783
+ const result = [];
1784
+ try {
1785
+ const responseBatch = index.ResponseBatch.decode(new Uint8Array(pullEvent));
1786
+ for (let i = 0; i < responseBatch.responses.length; i++) {
1787
+ const response = responseBatch.responses[i];
1788
+ if (response.command !== "outgoingMessages") {
1789
+ continue;
1790
+ }
1791
+ const messages = response.outgoingMessages.messages;
1792
+ for (const message of messages) {
1793
+ let messageFields;
1794
+ try {
1795
+ messageFields = JSON.parse(message.body);
1796
+ } catch (error) {
1797
+ this.getLogger().error(
1798
+ `${text.Text.getDateForLog()}: Pull: Could not parse message body`,
1799
+ { error }
1800
+ );
1801
+ continue;
1802
+ }
1803
+ if (!messageFields.extra) {
1804
+ messageFields.extra = {};
1805
+ }
1806
+ messageFields.extra.sender = {
1807
+ type: message.sender.type
1808
+ };
1809
+ if (message.sender.id instanceof Uint8Array) {
1810
+ messageFields.extra.sender.id = this.decodeId(message.sender.id);
1811
+ }
1812
+ const compatibleMessage = {
1813
+ mid: this.decodeId(message.id),
1814
+ text: messageFields
1815
+ };
1816
+ result.push(compatibleMessage);
1817
+ }
1818
+ }
1819
+ } catch (error) {
1820
+ this.getLogger().error(
1821
+ `${text.Text.getDateForLog()}: Pull: Could not parse message`,
1822
+ { error }
1823
+ );
1824
+ }
1825
+ return result;
1826
+ }
1827
+ /**
1828
+ * @param pullEvent
1829
+ */
1830
+ extractPlainTextMessages(pullEvent) {
1831
+ const result = [];
1832
+ const dataArray = pullEvent.match(/#!NGINXNMS!#(.*?)#!NGINXNME!#/g);
1833
+ if (dataArray === null) {
1834
+ this.getLogger().warning("PULL ERROR", {
1835
+ errorType: "parseResponse error parsing message",
1836
+ // The frame failed the NGINX-delimiter match, so its content is
1837
+ // unparseable anyway and could carry a credential (e.g. a channel
1838
+ // `signature`); log only its size, never the bytes (#43).
1839
+ byteLength: pullEvent.length
1840
+ });
1841
+ return [];
1842
+ }
1843
+ for (let i = 0; i < dataArray.length; i++) {
1844
+ dataArray[i] = dataArray[i].substring(12, dataArray[i].length - 12);
1845
+ if (dataArray[i].length <= 0) {
1846
+ continue;
1847
+ }
1848
+ let data;
1849
+ try {
1850
+ data = JSON.parse(dataArray[i]);
1851
+ } catch {
1852
+ continue;
1853
+ }
1854
+ result.push(data);
1855
+ }
1856
+ return result;
1857
+ }
1858
+ /**
1859
+ * Converts message id from byte[] to string
1860
+ * @param {Uint8Array} encodedId
1861
+ * @return {string}
1862
+ */
1863
+ decodeId(encodedId) {
1864
+ let result = "";
1865
+ for (const element_ of encodedId) {
1866
+ const hexByte = element_.toString(16);
1867
+ if (hexByte.length === 1) {
1868
+ result += "0";
1869
+ }
1870
+ result += hexByte;
1871
+ }
1872
+ return result;
1873
+ }
1874
+ /**
1875
+ * Converts message id from hex-encoded string to byte[]
1876
+ * @param {string} id Hex-encoded string.
1877
+ * @return {Uint8Array}
1878
+ */
1879
+ encodeId(id) {
1880
+ if (!id) {
1881
+ return new Uint8Array();
1882
+ }
1883
+ const result = [];
1884
+ for (let i = 0; i < id.length; i += 2) {
1885
+ result.push(Number.parseInt(id.slice(i, i + 2), 16));
1886
+ }
1887
+ return new Uint8Array(result);
1888
+ }
1889
+ // endregion ////
1890
+ // region Events.Status /////
1891
+ onOffline() {
1892
+ if (this._disposed) {
1893
+ return;
1894
+ }
1895
+ this.disconnect(pull.CloseReasons.NORMAL_CLOSURE, "offline");
1896
+ }
1897
+ onOnline() {
1898
+ if (this._disposed) {
1899
+ return;
1900
+ }
1901
+ this.connect().catch((error) => {
1902
+ this.getLogger().error("onOnline", { error });
1903
+ });
1904
+ }
1905
+ onBeforeUnload() {
1906
+ this._unloading = true;
1907
+ this.persistSession();
1908
+ this.scheduleReconnect(15);
1909
+ }
1910
+ // Persist the current session (with a short TTL) so a quick reload / re-init can
1911
+ // resume it. Shared by onBeforeUnload and destroy() — destroy() saves WITHOUT
1912
+ // scheduling a reconnect (#141).
1913
+ persistSession() {
1914
+ const session = type.Type.clone(this.session);
1915
+ session.ttl = Date.now() + LS_SESSION_CACHE_TIME * 1e3;
1916
+ if (this._storage) {
1917
+ try {
1918
+ this._storage.set(
1919
+ LS_SESSION,
1920
+ JSON.stringify(session)
1921
+ // LS_SESSION_CACHE_TIME
1922
+ );
1923
+ } catch (error) {
1924
+ this.getLogger().error(
1925
+ `${text.Text.getDateForLog()}: Pull: Could not save session info in local storage. Error: `,
1926
+ { error }
1927
+ );
1928
+ }
1929
+ }
1930
+ }
1931
+ // endregion ////
1932
+ // region PullStatus ////
1933
+ /**
1934
+ * @param status
1935
+ * @param delay
1936
+ */
1937
+ sendPullStatusDelayed(status, delay) {
1938
+ if (this._disposed) {
1939
+ return;
1940
+ }
1941
+ if (this._offlineTimeout) {
1942
+ clearTimeout(this._offlineTimeout);
1943
+ this._offlineTimeout = null;
1944
+ }
1945
+ this._offlineTimeout = setTimeout(() => {
1946
+ this._offlineTimeout = null;
1947
+ this.sendPullStatus(status);
1948
+ }, delay);
1949
+ }
1950
+ /**
1951
+ * @param status
1952
+ */
1953
+ sendPullStatus(status) {
1954
+ if (this._unloading) {
1955
+ return;
1956
+ }
1957
+ this.onCustomEvent("onPullStatus", [status]);
1958
+ this.emit({
1959
+ type: pull.SubscriptionType.Status,
1960
+ data: {
1961
+ status
1962
+ }
1963
+ });
1964
+ }
1965
+ // endregion ////
1966
+ // region _watchTagsQueue ////
1967
+ /**
1968
+ * @memo if private?
1969
+ * @param tagId
1970
+ * @param force
1971
+ */
1972
+ // @ts-expect-error When we rewrite it to something more modern, then we'll remove this
1973
+ extendWatch(tagId, force = false) {
1974
+ if (this._watchTagsQueue.get(tagId)) {
1975
+ return;
1976
+ }
1977
+ this._watchTagsQueue.set(tagId, true);
1978
+ if (force) {
1979
+ this.updateWatch(force);
1980
+ }
1981
+ }
1982
+ /**
1983
+ * @param force
1984
+ */
1985
+ updateWatch(force = false) {
1986
+ if (this._disposed) {
1987
+ return;
1988
+ }
1989
+ if (this._watchUpdateTimeout) {
1990
+ clearTimeout(this._watchUpdateTimeout);
1991
+ this._watchUpdateTimeout = null;
1992
+ }
1993
+ this._watchUpdateTimeout = setTimeout(
1994
+ () => {
1995
+ const watchTags = [...this._watchTagsQueue.keys()];
1996
+ if (watchTags.length > 0) {
1997
+ this._restClient.actions.v2.call.make({
1998
+ method: "pull.watch.extend",
1999
+ params: { tags: watchTags }
2000
+ }).then((response) => {
2001
+ const updatedTags = response.getData().result;
2002
+ for (const tagId of updatedTags) {
2003
+ this.clearWatch(tagId);
2004
+ }
2005
+ this.updateWatch();
2006
+ }).catch(() => {
2007
+ this.updateWatch();
2008
+ });
2009
+ } else {
2010
+ this.updateWatch();
2011
+ }
2012
+ },
2013
+ force ? this._watchForceUpdateInterval : this._watchUpdateInterval
2014
+ );
2015
+ }
2016
+ /**
2017
+ * @param tagId
2018
+ */
2019
+ clearWatch(tagId) {
2020
+ this._watchTagsQueue.delete(tagId);
2021
+ }
2022
+ // endregion ////
2023
+ // region Ping ////
2024
+ onJsonRpcPing() {
2025
+ this.updatePingWaitTimeout();
2026
+ this.connector?.send(JSON_RPC_PONG);
2027
+ }
2028
+ updatePingWaitTimeout() {
2029
+ if (this._disposed) {
2030
+ return;
2031
+ }
2032
+ if (this._pingWaitTimeout) {
2033
+ clearTimeout(this._pingWaitTimeout);
2034
+ this._pingWaitTimeout = null;
2035
+ }
2036
+ this._pingWaitTimeout = setTimeout(
2037
+ this._onPingTimeoutHandler,
2038
+ PING_TIMEOUT * 2 * 1e3
2039
+ );
2040
+ }
2041
+ clearPingWaitTimeout() {
2042
+ if (this._pingWaitTimeout) {
2043
+ clearTimeout(this._pingWaitTimeout);
2044
+ }
2045
+ this._pingWaitTimeout = null;
2046
+ }
2047
+ onPingTimeout() {
2048
+ this._pingWaitTimeout = null;
2049
+ if (this._disposed || !this._enabled || !this.isConnected()) {
2050
+ return;
2051
+ }
2052
+ this.getLogger().warning(`No pings are received in ${PING_TIMEOUT * 2} seconds. Reconnecting`);
2053
+ this.disconnect(pull.CloseReasons.STUCK, "connection stuck");
2054
+ this.scheduleReconnect();
2055
+ }
2056
+ // endregion ////
2057
+ // region Time ////
2058
+ /**
2059
+ * Returns reconnect delay in seconds
2060
+ *
2061
+ * @param attemptNumber
2062
+ * @return {number}
2063
+ */
2064
+ getConnectionAttemptDelay(attemptNumber) {
2065
+ let result;
2066
+ if (attemptNumber < 1) {
2067
+ result = 0.5;
2068
+ } else if (attemptNumber < 3) {
2069
+ result = 15;
2070
+ } else if (attemptNumber < 5) {
2071
+ result = 45;
2072
+ } else if (attemptNumber < 10) {
2073
+ result = 600;
2074
+ } else {
2075
+ result = 3600;
2076
+ }
2077
+ return result + result * Math.random() * 0.2;
2078
+ }
2079
+ // endregion ////
2080
+ // region Tools ////
2081
+ /**
2082
+ * @param mid
2083
+ */
2084
+ checkDuplicate(mid) {
2085
+ if (this._session.lastMessageIds.includes(mid)) {
2086
+ this.getLogger().warning(`Duplicate message ${mid} skipped`);
2087
+ return false;
2088
+ } else {
2089
+ this._session.lastMessageIds.push(mid);
2090
+ return true;
2091
+ }
2092
+ }
2093
+ trimDuplicates() {
2094
+ if (this._session.lastMessageIds.length > MAX_IDS_TO_STORE) {
2095
+ this._session.lastMessageIds = this._session.lastMessageIds.slice(-MAX_IDS_TO_STORE);
2096
+ }
2097
+ }
2098
+ // endregion ////
2099
+ // region Logging ////
2100
+ /**
2101
+ * @param message
2102
+ */
2103
+ logMessage(message) {
2104
+ if (!this._debug) {
2105
+ return;
2106
+ }
2107
+ if (message.extra?.sender && message.extra.sender.type === pull.SenderType.Client) {
2108
+ this.getLogger().info(
2109
+ `onPullClientEvent-${message.module_id}`,
2110
+ redact.redactSensitiveParams({
2111
+ command: message.command,
2112
+ params: message.params,
2113
+ extra: message.extra
2114
+ })
2115
+ );
2116
+ } else if (message.module_id == "online") {
2117
+ this.getLogger().info(
2118
+ `onPullOnlineEvent`,
2119
+ redact.redactSensitiveParams({
2120
+ command: message.command,
2121
+ params: message.params,
2122
+ extra: message.extra
2123
+ })
2124
+ );
2125
+ } else {
2126
+ this.getLogger().info(
2127
+ `onPullEvent`,
2128
+ redact.redactSensitiveParams({
2129
+ moduleId: message.module_id,
2130
+ command: message.command,
2131
+ params: message.params,
2132
+ extra: message.extra
2133
+ })
2134
+ );
2135
+ }
2136
+ }
2137
+ /**
2138
+ * @param message
2139
+ * @param force
2140
+ */
2141
+ logToConsole(message, force = false) {
2142
+ if (this._loggingEnabled || force) {
2143
+ this.getLogger().debug(`${text.Text.getDateForLog()}: ${message}`);
2144
+ }
2145
+ }
2146
+ /**
2147
+ * @param message
2148
+ */
2149
+ addMessageToStat(message) {
2150
+ if (!this._session.history[message.module_id]) {
2151
+ this._session.history[message.module_id] = {};
2152
+ }
2153
+ if (!this._session.history[message.module_id][message.command]) {
2154
+ this.session.history[message.module_id][message.command] = 0;
2155
+ }
2156
+ this._session.history[message.module_id][message.command]++;
2157
+ this._session.messageCount++;
2158
+ }
2159
+ /**
2160
+ * @param text
2161
+ */
2162
+ showNotification(text) {
2163
+ this.getLogger().notice(text);
2164
+ }
2165
+ // endregion ////
2166
+ // region onCustomEvent ////
2167
+ /**
2168
+ * @memo may be need to use onCustomEvent
2169
+ * @memo ? force
2170
+ */
2171
+ onCustomEvent(eventName, data, force = false) {
2172
+ }
2173
+ // endregion ////
2174
+ }
2175
+
2176
+ exports.PullClient = PullClient;
2177
+ //# sourceMappingURL=client.cjs.map