@cendarsoss/pusher-js 8.4.11

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 (425) hide show
  1. package/.editorconfig +14 -0
  2. package/.github/ISSUE_TEMPLATE.md +11 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  4. package/.github/dependabot.yml +14 -0
  5. package/.github/stale.yml +26 -0
  6. package/.github/workflows/release.yml +112 -0
  7. package/.github/workflows/release_pr.yml +43 -0
  8. package/.github/workflows/run-tests.yml +62 -0
  9. package/.gitmodules +3 -0
  10. package/.prettierrc +2 -0
  11. package/CHANGELOG.md +928 -0
  12. package/DELTA_COMPRESSION.md +365 -0
  13. package/DELTA_USAGE.md +179 -0
  14. package/IMPLEMENTATION_SUMMARY.md +261 -0
  15. package/IMPORT_GUIDE.md +638 -0
  16. package/LIBRARY_STRUCTURE_ANALYSIS.md +940 -0
  17. package/LICENCE +19 -0
  18. package/Makefile +14 -0
  19. package/README.md +709 -0
  20. package/TAG_FILTERING_CLIENT.md +471 -0
  21. package/bower.json +19 -0
  22. package/bun.lock +2695 -0
  23. package/dist/node/filter.js +252 -0
  24. package/dist/node/filter.js.map +1 -0
  25. package/dist/node/pusher.js +4434 -0
  26. package/dist/node/pusher.js.map +1 -0
  27. package/dist/web/filter.mjs +252 -0
  28. package/dist/web/filter.mjs.map +1 -0
  29. package/dist/web/pusher.mjs +5889 -0
  30. package/dist/web/pusher.mjs.map +1 -0
  31. package/examples/delta-compression-example.html +372 -0
  32. package/examples/delta-seamless-example.html +185 -0
  33. package/index.d.ts +36 -0
  34. package/integration_tests_server/index.js +176 -0
  35. package/integration_tests_server/package-lock.json +1177 -0
  36. package/integration_tests_server/package.json +15 -0
  37. package/interactive/.env +16 -0
  38. package/interactive/CONFLATION_TEST.md +73 -0
  39. package/interactive/DELTA_COMPRESSION_TESTING.md +262 -0
  40. package/interactive/bun.lock +208 -0
  41. package/interactive/package-lock.json +1075 -0
  42. package/interactive/package.json +32 -0
  43. package/interactive/public/app.js +1363 -0
  44. package/interactive/public/bundle-entry.js +14 -0
  45. package/interactive/public/conflation-test.html +508 -0
  46. package/interactive/public/conflation-test.js +785 -0
  47. package/interactive/public/delta-compression.js +1090 -0
  48. package/interactive/public/dist/bundle.js +5857 -0
  49. package/interactive/public/index.html +392 -0
  50. package/interactive/public/main.js +20 -0
  51. package/interactive/public/style.css +823 -0
  52. package/interactive/server.js +246 -0
  53. package/interactive/test-bundle.html +89 -0
  54. package/interactive/test-delta.js +146 -0
  55. package/node.js +1 -0
  56. package/package.json +94 -0
  57. package/pusher-with-encryption/index.js +1 -0
  58. package/react-native/index.d.ts +29 -0
  59. package/react-native/index.js +1 -0
  60. package/spec/config/jasmine/helpers/reporter.js +14 -0
  61. package/spec/config/jasmine/integration.json +13 -0
  62. package/spec/config/jasmine/unit.json +13 -0
  63. package/spec/config/jasmine/webpack.integration.js +33 -0
  64. package/spec/config/jasmine/webpack.unit.js +30 -0
  65. package/spec/config/karma/available_browsers.json +4957 -0
  66. package/spec/config/karma/config.ci.js +25 -0
  67. package/spec/config/karma/config.common.js +50 -0
  68. package/spec/config/karma/config.integration.js +26 -0
  69. package/spec/config/karma/config.unit.js +10 -0
  70. package/spec/config/karma/config.worker.js +34 -0
  71. package/spec/config/karma/integration.js +24 -0
  72. package/spec/config/karma/unit.js +20 -0
  73. package/spec/javascripts/helpers/mocks.js +274 -0
  74. package/spec/javascripts/helpers/node/integration.js +33 -0
  75. package/spec/javascripts/helpers/node/mock-dom-dependencies.ts +1 -0
  76. package/spec/javascripts/helpers/pusher_integration.js +1 -0
  77. package/spec/javascripts/helpers/pusher_integration_class.ts +12 -0
  78. package/spec/javascripts/helpers/timers/promises.js +9 -0
  79. package/spec/javascripts/helpers/waitsFor.js +37 -0
  80. package/spec/javascripts/helpers/web/integration.js +44 -0
  81. package/spec/javascripts/helpers/worker/mock-dom-dependencies.js +1 -0
  82. package/spec/javascripts/integration/core/cluster_config_spec.js +153 -0
  83. package/spec/javascripts/integration/core/falling_back_spec.js +195 -0
  84. package/spec/javascripts/integration/core/pusher_spec/index.js +68 -0
  85. package/spec/javascripts/integration/core/pusher_spec/test_builder.js +715 -0
  86. package/spec/javascripts/integration/core/timeout_configuration_spec.js +200 -0
  87. package/spec/javascripts/integration/core/transport_lists_spec.js +103 -0
  88. package/spec/javascripts/integration/index.node.js +12 -0
  89. package/spec/javascripts/integration/index.web.js +63 -0
  90. package/spec/javascripts/integration/index.worker.js +13 -0
  91. package/spec/javascripts/integration/web/dom/jsonp_spec.js +97 -0
  92. package/spec/javascripts/integration/web/dom/script_request_spec.js +90 -0
  93. package/spec/javascripts/polyfills/index.js +105 -0
  94. package/spec/javascripts/unit/core/channels/channel_spec.js +355 -0
  95. package/spec/javascripts/unit/core/channels/channels_spec.js +94 -0
  96. package/spec/javascripts/unit/core/channels/encrypted_channel_spec.js +343 -0
  97. package/spec/javascripts/unit/core/channels/presence_channel_spec.js +553 -0
  98. package/spec/javascripts/unit/core/channels/private_channel_spec.js +182 -0
  99. package/spec/javascripts/unit/core/config_spec.js +507 -0
  100. package/spec/javascripts/unit/core/connection/connection_manager_spec.js +656 -0
  101. package/spec/javascripts/unit/core/connection/connection_spec.js +286 -0
  102. package/spec/javascripts/unit/core/connection/handshake_spec.js +160 -0
  103. package/spec/javascripts/unit/core/connection/protocol_spec.js +420 -0
  104. package/spec/javascripts/unit/core/defaults_spec.js +26 -0
  105. package/spec/javascripts/unit/core/events_dispatcher_spec.js +385 -0
  106. package/spec/javascripts/unit/core/http/http_polling_socket_spec.js +60 -0
  107. package/spec/javascripts/unit/core/http/http_request_spec.js +185 -0
  108. package/spec/javascripts/unit/core/http/http_socket_spec.js +370 -0
  109. package/spec/javascripts/unit/core/http/http_streaming_socket_spec.js +56 -0
  110. package/spec/javascripts/unit/core/http/http_xhr_request_spec.js +164 -0
  111. package/spec/javascripts/unit/core/logger_spec.js +133 -0
  112. package/spec/javascripts/unit/core/pusher_spec.js +613 -0
  113. package/spec/javascripts/unit/core/pusher_with_encryption_spec.js +18 -0
  114. package/spec/javascripts/unit/core/strategies/best_connected_ever_strategy_spec.js +104 -0
  115. package/spec/javascripts/unit/core/strategies/delayed_strategy_spec.js +95 -0
  116. package/spec/javascripts/unit/core/strategies/first_connected_strategy_spec.js +68 -0
  117. package/spec/javascripts/unit/core/strategies/if_strategy_spec.js +165 -0
  118. package/spec/javascripts/unit/core/strategies/sequential_strategy_spec.js +213 -0
  119. package/spec/javascripts/unit/core/strategies/transport_strategy_spec.js +250 -0
  120. package/spec/javascripts/unit/core/strategies/websocket_prioritized_cached_strategy_spec.js +400 -0
  121. package/spec/javascripts/unit/core/timeline/timeline_spec.js +153 -0
  122. package/spec/javascripts/unit/core/transports/assistant_to_the_transport_manager_spec.js +223 -0
  123. package/spec/javascripts/unit/core/transports/hosts_and_ports_spec.js +85 -0
  124. package/spec/javascripts/unit/core/transports/transport_connection_spec.js +585 -0
  125. package/spec/javascripts/unit/core/transports/transport_manager_spec.js +64 -0
  126. package/spec/javascripts/unit/core/user_spec.js +303 -0
  127. package/spec/javascripts/unit/core/utils/periodic_timer_spec.js +74 -0
  128. package/spec/javascripts/unit/core/utils/timers_spec.js +157 -0
  129. package/spec/javascripts/unit/core/utils/url_store_spec.js +14 -0
  130. package/spec/javascripts/unit/core/watchlist_spec.js +48 -0
  131. package/spec/javascripts/unit/core_with_runtime/auth/channel_authorizer_spec.js +137 -0
  132. package/spec/javascripts/unit/core_with_runtime/auth/deprecated_channel_authorizer_spec.js +48 -0
  133. package/spec/javascripts/unit/core_with_runtime/auth/user_authorizer_spec.js +128 -0
  134. package/spec/javascripts/unit/core_with_runtime/readme.md +5 -0
  135. package/spec/javascripts/unit/index.node.js +11 -0
  136. package/spec/javascripts/unit/index.web.js +12 -0
  137. package/spec/javascripts/unit/index.worker.js +11 -0
  138. package/spec/javascripts/unit/isomorphic/transports/hosts_and_ports_spec.js +82 -0
  139. package/spec/javascripts/unit/isomorphic/transports/transports_spec.js +202 -0
  140. package/spec/javascripts/unit/node/timeline_sender_spec.js +83 -0
  141. package/spec/javascripts/unit/web/dom/dependency_loader_spec.js +249 -0
  142. package/spec/javascripts/unit/web/dom/jsonp_request_spec.js +130 -0
  143. package/spec/javascripts/unit/web/dom/script_receiver_factory_spec.js +68 -0
  144. package/spec/javascripts/unit/web/http/http_xdomain_request_spec.js +222 -0
  145. package/spec/javascripts/unit/web/pusher_authorizer_spec.js +64 -0
  146. package/spec/javascripts/unit/web/timeline/timeline_sender_spec.js +131 -0
  147. package/spec/javascripts/unit/web/transports/hosts_and_ports_spec.js +127 -0
  148. package/spec/javascripts/unit/web/transports/transports_spec.js +444 -0
  149. package/spec/javascripts/unit/worker/channel_authorizer_spec.js +156 -0
  150. package/spec/javascripts/unit/worker/timeline_sender_spec.js +76 -0
  151. package/src/core/auth/auth_transports.ts +18 -0
  152. package/src/core/auth/channel_authorizer.ts +64 -0
  153. package/src/core/auth/deprecated_channel_authorizer.ts +56 -0
  154. package/src/core/auth/options.ts +76 -0
  155. package/src/core/auth/user_authenticator.ts +62 -0
  156. package/src/core/base64.ts +49 -0
  157. package/src/core/channels/channel.ts +173 -0
  158. package/src/core/channels/channel_table.ts +7 -0
  159. package/src/core/channels/channels.ts +86 -0
  160. package/src/core/channels/encrypted_channel.ts +150 -0
  161. package/src/core/channels/filter.ts +342 -0
  162. package/src/core/channels/members.ts +80 -0
  163. package/src/core/channels/metadata.ts +5 -0
  164. package/src/core/channels/presence_channel.ts +113 -0
  165. package/src/core/channels/private_channel.ts +25 -0
  166. package/src/core/config.ts +189 -0
  167. package/src/core/connection/callbacks.ts +21 -0
  168. package/src/core/connection/connection.ts +160 -0
  169. package/src/core/connection/connection_manager.ts +371 -0
  170. package/src/core/connection/connection_manager_options.ts +14 -0
  171. package/src/core/connection/handshake/handshake_payload.ts +10 -0
  172. package/src/core/connection/handshake/index.ts +90 -0
  173. package/src/core/connection/protocol/action.ts +8 -0
  174. package/src/core/connection/protocol/message-types.ts +11 -0
  175. package/src/core/connection/protocol/protocol.ts +166 -0
  176. package/src/core/defaults.ts +66 -0
  177. package/src/core/delta/channel_state.ts +194 -0
  178. package/src/core/delta/decoders.ts +129 -0
  179. package/src/core/delta/index.ts +10 -0
  180. package/src/core/delta/manager.ts +504 -0
  181. package/src/core/delta/types.ts +60 -0
  182. package/src/core/errors.ts +69 -0
  183. package/src/core/events/callback.ts +6 -0
  184. package/src/core/events/callback_registry.ts +75 -0
  185. package/src/core/events/callback_table.ts +7 -0
  186. package/src/core/events/dispatcher.ts +84 -0
  187. package/src/core/http/ajax.ts +24 -0
  188. package/src/core/http/http_factory.ts +16 -0
  189. package/src/core/http/http_polling_socket.ts +24 -0
  190. package/src/core/http/http_request.ts +81 -0
  191. package/src/core/http/http_socket.ts +220 -0
  192. package/src/core/http/http_streaming_socket.ts +19 -0
  193. package/src/core/http/request_hooks.ts +9 -0
  194. package/src/core/http/socket_hooks.ts +11 -0
  195. package/src/core/http/state.ts +7 -0
  196. package/src/core/http/url_location.ts +6 -0
  197. package/src/core/logger.ts +66 -0
  198. package/src/core/options.ts +61 -0
  199. package/src/core/pusher-licence.js +7 -0
  200. package/src/core/pusher-with-encryption.js +1 -0
  201. package/src/core/pusher-with-encryption.ts +14 -0
  202. package/src/core/pusher.js +10 -0
  203. package/src/core/pusher.ts +412 -0
  204. package/src/core/reachability.ts +7 -0
  205. package/src/core/socket.ts +14 -0
  206. package/src/core/strategies/best_connected_ever_strategy.ts +81 -0
  207. package/src/core/strategies/delayed_strategy.ts +48 -0
  208. package/src/core/strategies/first_connected_strategy.ts +31 -0
  209. package/src/core/strategies/if_strategy.ts +34 -0
  210. package/src/core/strategies/sequential_strategy.ts +129 -0
  211. package/src/core/strategies/strategy.ts +8 -0
  212. package/src/core/strategies/strategy_builder.ts +67 -0
  213. package/src/core/strategies/strategy_options.ts +18 -0
  214. package/src/core/strategies/strategy_runner.ts +6 -0
  215. package/src/core/strategies/transport_strategy.ts +144 -0
  216. package/src/core/strategies/websocket_prioritized_cached_strategy.ts +157 -0
  217. package/src/core/timeline/level.ts +7 -0
  218. package/src/core/timeline/timeline.ts +90 -0
  219. package/src/core/timeline/timeline_sender.ts +33 -0
  220. package/src/core/timeline/timeline_transport.ts +11 -0
  221. package/src/core/transports/assistant_to_the_transport_manager.ts +104 -0
  222. package/src/core/transports/ping_delay_options.ts +7 -0
  223. package/src/core/transports/transport.ts +54 -0
  224. package/src/core/transports/transport_connection.ts +241 -0
  225. package/src/core/transports/transport_connection_options.ts +8 -0
  226. package/src/core/transports/transport_hooks.ts +16 -0
  227. package/src/core/transports/transport_manager.ts +52 -0
  228. package/src/core/transports/transports_table.ts +12 -0
  229. package/src/core/transports/url_scheme.ts +13 -0
  230. package/src/core/transports/url_schemes.ts +47 -0
  231. package/src/core/user.ts +186 -0
  232. package/src/core/util.ts +34 -0
  233. package/src/core/utils/collections.ts +353 -0
  234. package/src/core/utils/factory.ts +79 -0
  235. package/src/core/utils/flat_promise.ts +10 -0
  236. package/src/core/utils/timers/abstract_timer.ts +39 -0
  237. package/src/core/utils/timers/index.ts +39 -0
  238. package/src/core/utils/timers/scheduling.ts +11 -0
  239. package/src/core/utils/timers/timed_callback.ts +5 -0
  240. package/src/core/utils/url_store.ts +48 -0
  241. package/src/core/watchlist.ts +31 -0
  242. package/src/d.ts/constants/index.d.ts +5 -0
  243. package/src/d.ts/faye-websocket/faye-websocket.d.ts +21 -0
  244. package/src/d.ts/global/global.d.ts +1 -0
  245. package/src/d.ts/module/module.d.ts +12 -0
  246. package/src/d.ts/tweetnacl-util/index.d.ts +6 -0
  247. package/src/d.ts/window/events.d.ts +4 -0
  248. package/src/d.ts/window/sockjs.d.ts +3 -0
  249. package/src/d.ts/window/websocket.d.ts +4 -0
  250. package/src/d.ts/window/xmlhttprequest.d.ts +3 -0
  251. package/src/filter.ts +5 -0
  252. package/src/index.ts +8 -0
  253. package/src/runtimes/interface.ts +60 -0
  254. package/src/runtimes/isomorphic/auth/xhr_auth.ts +90 -0
  255. package/src/runtimes/isomorphic/default_strategy.ts +155 -0
  256. package/src/runtimes/isomorphic/http/http.ts +32 -0
  257. package/src/runtimes/isomorphic/http/http_xhr_request.ts +35 -0
  258. package/src/runtimes/isomorphic/runtime.ts +62 -0
  259. package/src/runtimes/isomorphic/timeline/xhr_timeline.ts +50 -0
  260. package/src/runtimes/isomorphic/transports/transport_connection_initializer.ts +19 -0
  261. package/src/runtimes/isomorphic/transports/transports.ts +83 -0
  262. package/src/runtimes/node/net_info.ts +10 -0
  263. package/src/runtimes/node/runtime.ts +68 -0
  264. package/src/runtimes/react-native/net_info.ts +42 -0
  265. package/src/runtimes/react-native/runtime.ts +65 -0
  266. package/src/runtimes/web/auth/jsonp_auth.ts +51 -0
  267. package/src/runtimes/web/browser.ts +24 -0
  268. package/src/runtimes/web/default_strategy.ts +201 -0
  269. package/src/runtimes/web/dom/dependencies.ts +16 -0
  270. package/src/runtimes/web/dom/dependency_loader.ts +93 -0
  271. package/src/runtimes/web/dom/json2.js +486 -0
  272. package/src/runtimes/web/dom/jsonp_request.ts +52 -0
  273. package/src/runtimes/web/dom/script_receiver.ts +8 -0
  274. package/src/runtimes/web/dom/script_receiver_factory.ts +57 -0
  275. package/src/runtimes/web/dom/script_request.ts +85 -0
  276. package/src/runtimes/web/http/http.ts +8 -0
  277. package/src/runtimes/web/http/http_xdomain_request.ts +37 -0
  278. package/src/runtimes/web/net_info.ts +50 -0
  279. package/src/runtimes/web/runtime.ts +174 -0
  280. package/src/runtimes/web/timeline/jsonp_timeline.ts +34 -0
  281. package/src/runtimes/web/transports/transport_connection_initializer.ts +39 -0
  282. package/src/runtimes/web/transports/transports.ts +67 -0
  283. package/src/runtimes/worker/auth/fetch_auth.ts +69 -0
  284. package/src/runtimes/worker/net_info.ts +10 -0
  285. package/src/runtimes/worker/runtime.ts +75 -0
  286. package/src/runtimes/worker/timeline/fetch_timeline.ts +39 -0
  287. package/tsconfig.json +18 -0
  288. package/types/spec/javascripts/helpers/node/mock-dom-dependencies.d.ts +1 -0
  289. package/types/spec/javascripts/helpers/pusher_integration_class.d.ts +4 -0
  290. package/types/src/core/auth/auth_transports.d.ts +9 -0
  291. package/types/src/core/auth/channel_authorizer.d.ts +3 -0
  292. package/types/src/core/auth/deprecated_channel_authorizer.d.ts +18 -0
  293. package/types/src/core/auth/options.d.ts +48 -0
  294. package/types/src/core/auth/user_authenticator.d.ts +3 -0
  295. package/types/src/core/base64.d.ts +1 -0
  296. package/types/src/core/channels/channel.d.ts +25 -0
  297. package/types/src/core/channels/channel_table.d.ts +5 -0
  298. package/types/src/core/channels/channels.d.ts +12 -0
  299. package/types/src/core/channels/encrypted_channel.d.ts +15 -0
  300. package/types/src/core/channels/filter.d.ts +33 -0
  301. package/types/src/core/channels/members.d.ts +14 -0
  302. package/types/src/core/channels/metadata.d.ts +4 -0
  303. package/types/src/core/channels/presence_channel.d.ts +13 -0
  304. package/types/src/core/channels/private_channel.d.ts +5 -0
  305. package/types/src/core/config.d.ts +31 -0
  306. package/types/src/core/connection/callbacks.d.ts +18 -0
  307. package/types/src/core/connection/connection.d.ts +16 -0
  308. package/types/src/core/connection/connection_manager.d.ts +50 -0
  309. package/types/src/core/connection/connection_manager_options.d.ts +11 -0
  310. package/types/src/core/connection/handshake/handshake_payload.d.ts +8 -0
  311. package/types/src/core/connection/handshake/index.d.ts +12 -0
  312. package/types/src/core/connection/protocol/action.d.ts +7 -0
  313. package/types/src/core/connection/protocol/message-types.d.ts +10 -0
  314. package/types/src/core/connection/protocol/protocol.d.ts +10 -0
  315. package/types/src/core/defaults.d.ts +26 -0
  316. package/types/src/core/delta/channel_state.d.ts +23 -0
  317. package/types/src/core/delta/decoders.d.ts +12 -0
  318. package/types/src/core/delta/index.d.ts +4 -0
  319. package/types/src/core/delta/manager.d.ts +27 -0
  320. package/types/src/core/delta/types.d.ts +50 -0
  321. package/types/src/core/errors.d.ts +28 -0
  322. package/types/src/core/events/callback.d.ts +5 -0
  323. package/types/src/core/events/callback_registry.d.ts +11 -0
  324. package/types/src/core/events/callback_table.d.ts +5 -0
  325. package/types/src/core/events/dispatcher.d.ts +14 -0
  326. package/types/src/core/http/ajax.d.ts +16 -0
  327. package/types/src/core/http/http_factory.d.ts +13 -0
  328. package/types/src/core/http/http_polling_socket.d.ts +3 -0
  329. package/types/src/core/http/http_request.d.ts +17 -0
  330. package/types/src/core/http/http_socket.d.ts +32 -0
  331. package/types/src/core/http/http_streaming_socket.d.ts +3 -0
  332. package/types/src/core/http/request_hooks.d.ts +6 -0
  333. package/types/src/core/http/socket_hooks.d.ts +8 -0
  334. package/types/src/core/http/state.d.ts +6 -0
  335. package/types/src/core/http/url_location.d.ts +5 -0
  336. package/types/src/core/logger.d.ts +11 -0
  337. package/types/src/core/options.d.ts +36 -0
  338. package/types/src/core/pusher-with-encryption.d.ts +5 -0
  339. package/types/src/core/pusher.d.ts +56 -0
  340. package/types/src/core/reachability.d.ts +5 -0
  341. package/types/src/core/socket.d.ts +12 -0
  342. package/types/src/core/strategies/best_connected_ever_strategy.d.ts +10 -0
  343. package/types/src/core/strategies/delayed_strategy.d.ts +15 -0
  344. package/types/src/core/strategies/first_connected_strategy.d.ts +8 -0
  345. package/types/src/core/strategies/if_strategy.d.ts +10 -0
  346. package/types/src/core/strategies/sequential_strategy.d.ts +16 -0
  347. package/types/src/core/strategies/strategy.d.ts +6 -0
  348. package/types/src/core/strategies/strategy_builder.d.ts +5 -0
  349. package/types/src/core/strategies/strategy_options.d.ts +16 -0
  350. package/types/src/core/strategies/strategy_runner.d.ts +5 -0
  351. package/types/src/core/strategies/transport_strategy.d.ts +15 -0
  352. package/types/src/core/strategies/websocket_prioritized_cached_strategy.d.ts +20 -0
  353. package/types/src/core/timeline/level.d.ts +6 -0
  354. package/types/src/core/timeline/timeline.d.ts +25 -0
  355. package/types/src/core/timeline/timeline_sender.d.ts +13 -0
  356. package/types/src/core/timeline/timeline_transport.d.ts +6 -0
  357. package/types/src/core/transports/assistant_to_the_transport_manager.d.ts +14 -0
  358. package/types/src/core/transports/ping_delay_options.d.ts +6 -0
  359. package/types/src/core/transports/transport.d.ts +8 -0
  360. package/types/src/core/transports/transport_connection.d.ts +35 -0
  361. package/types/src/core/transports/transport_connection_options.d.ts +6 -0
  362. package/types/src/core/transports/transport_hooks.d.ts +13 -0
  363. package/types/src/core/transports/transport_manager.d.ts +14 -0
  364. package/types/src/core/transports/transports_table.d.ts +10 -0
  365. package/types/src/core/transports/url_scheme.d.ts +11 -0
  366. package/types/src/core/transports/url_schemes.d.ts +4 -0
  367. package/types/src/core/user.d.ts +21 -0
  368. package/types/src/core/util.d.ts +8 -0
  369. package/types/src/core/utils/collections.d.ts +18 -0
  370. package/types/src/core/utils/factory.d.ts +29 -0
  371. package/types/src/core/utils/flat_promise.d.ts +6 -0
  372. package/types/src/core/utils/timers/abstract_timer.d.ts +10 -0
  373. package/types/src/core/utils/timers/index.d.ts +9 -0
  374. package/types/src/core/utils/timers/scheduling.d.ts +8 -0
  375. package/types/src/core/utils/timers/timed_callback.d.ts +4 -0
  376. package/types/src/core/utils/url_store.d.ts +4 -0
  377. package/types/src/core/watchlist.d.ts +8 -0
  378. package/types/src/runtimes/interface.d.ts +43 -0
  379. package/types/src/runtimes/isomorphic/auth/xhr_auth.d.ts +3 -0
  380. package/types/src/runtimes/isomorphic/default_strategy.d.ts +5 -0
  381. package/types/src/runtimes/isomorphic/http/http.d.ts +3 -0
  382. package/types/src/runtimes/isomorphic/http/http_xhr_request.d.ts +3 -0
  383. package/types/src/runtimes/isomorphic/runtime.d.ts +2 -0
  384. package/types/src/runtimes/isomorphic/timeline/xhr_timeline.d.ts +6 -0
  385. package/types/src/runtimes/isomorphic/transports/transport_connection_initializer.d.ts +1 -0
  386. package/types/src/runtimes/isomorphic/transports/transports.d.ts +5 -0
  387. package/types/src/runtimes/node/net_info.d.ts +6 -0
  388. package/types/src/runtimes/node/runtime.d.ts +3 -0
  389. package/types/src/runtimes/react-native/net_info.d.ts +8 -0
  390. package/types/src/runtimes/react-native/runtime.d.ts +3 -0
  391. package/types/src/runtimes/web/auth/jsonp_auth.d.ts +3 -0
  392. package/types/src/runtimes/web/browser.d.ts +19 -0
  393. package/types/src/runtimes/web/default_strategy.d.ts +5 -0
  394. package/types/src/runtimes/web/dom/dependencies.d.ts +4 -0
  395. package/types/src/runtimes/web/dom/dependency_loader.d.ts +10 -0
  396. package/types/src/runtimes/web/dom/jsonp_request.d.ts +10 -0
  397. package/types/src/runtimes/web/dom/script_receiver.d.ts +7 -0
  398. package/types/src/runtimes/web/dom/script_receiver_factory.d.ts +10 -0
  399. package/types/src/runtimes/web/dom/script_request.d.ts +9 -0
  400. package/types/src/runtimes/web/http/http.d.ts +2 -0
  401. package/types/src/runtimes/web/http/http_xdomain_request.d.ts +3 -0
  402. package/types/src/runtimes/web/net_info.d.ts +7 -0
  403. package/types/src/runtimes/web/runtime.d.ts +3 -0
  404. package/types/src/runtimes/web/timeline/jsonp_timeline.d.ts +6 -0
  405. package/types/src/runtimes/web/transports/transport_connection_initializer.d.ts +1 -0
  406. package/types/src/runtimes/web/transports/transports.d.ts +2 -0
  407. package/types/src/runtimes/worker/auth/fetch_auth.d.ts +3 -0
  408. package/types/src/runtimes/worker/net_info.d.ts +6 -0
  409. package/types/src/runtimes/worker/runtime.d.ts +3 -0
  410. package/types/src/runtimes/worker/timeline/fetch_timeline.d.ts +6 -0
  411. package/vite.config.js +52 -0
  412. package/vite.config.node.js +72 -0
  413. package/webpack/config.node.js +26 -0
  414. package/webpack/config.react-native.js +35 -0
  415. package/webpack/config.shared.js +50 -0
  416. package/webpack/config.web.js +36 -0
  417. package/webpack/config.worker.js +42 -0
  418. package/webpack/dev.server.js +17 -0
  419. package/webpack/hosting_config.js +6 -0
  420. package/with-encryption/index.d.ts +29 -0
  421. package/with-encryption/index.js +4 -0
  422. package/worker/index.d.ts +29 -0
  423. package/worker/index.js +1 -0
  424. package/worker/with-encryption/index.d.ts +29 -0
  425. package/worker/with-encryption/index.js +1 -0
@@ -0,0 +1,785 @@
1
+ // Conflation Keys Test Suite
2
+ // Tests delta compression with 100+ conflation keys
3
+
4
+ class ConflationTestSuite {
5
+ constructor() {
6
+ this.pusher = null;
7
+ this.deltaManager = null;
8
+ this.channel = null;
9
+ this.stats = {
10
+ messagesSent: 0,
11
+ messagesReceived: 0,
12
+ deltaMessages: 0,
13
+ fullMessages: 0,
14
+ uniqueKeys: new Set(),
15
+ totalBytesWithout: 0,
16
+ totalBytesWith: 0,
17
+ };
18
+ this.testResults = {};
19
+ this.consoleLines = [];
20
+
21
+ this.init();
22
+ }
23
+
24
+ init() {
25
+ // Bind UI controls
26
+ document
27
+ .getElementById("connect-btn")
28
+ .addEventListener("click", () => this.connect());
29
+ document
30
+ .getElementById("disconnect-btn")
31
+ .addEventListener("click", () => this.disconnect());
32
+ document
33
+ .getElementById("run-all-tests")
34
+ .addEventListener("click", () => this.runAllTests());
35
+ document
36
+ .getElementById("run-test1")
37
+ .addEventListener("click", () => this.runTest1());
38
+ document
39
+ .getElementById("run-test2")
40
+ .addEventListener("click", () => this.runTest2());
41
+ document
42
+ .getElementById("run-test3")
43
+ .addEventListener("click", () => this.runTest3());
44
+ document
45
+ .getElementById("run-test4")
46
+ .addEventListener("click", () => this.runTest4());
47
+ document
48
+ .getElementById("clear-console")
49
+ .addEventListener("click", () => this.clearConsole());
50
+ document
51
+ .getElementById("delta-toggle")
52
+ .addEventListener("change", (e) =>
53
+ this.toggleDeltaCompression(e.target.checked),
54
+ );
55
+ }
56
+
57
+ log(message, level = "info") {
58
+ const timestamp = new Date().toLocaleTimeString();
59
+ const line = document.createElement("div");
60
+ line.className = `console-line console-${level}`;
61
+ line.innerHTML = `<span class="console-timestamp">[${timestamp}]</span>${message}`;
62
+
63
+ const console = document.getElementById("console");
64
+ console.appendChild(line);
65
+ console.scrollTop = console.scrollHeight;
66
+
67
+ this.consoleLines.push({ timestamp, message, level });
68
+ }
69
+
70
+ clearConsole() {
71
+ document.getElementById("console").innerHTML = "";
72
+ this.consoleLines = [];
73
+ }
74
+
75
+ updateStats() {
76
+ document.getElementById("messages-sent").textContent =
77
+ this.stats.messagesSent;
78
+ document.getElementById("messages-received").textContent =
79
+ this.stats.messagesReceived;
80
+ document.getElementById("delta-count").textContent =
81
+ this.stats.deltaMessages;
82
+ document.getElementById("full-count").textContent = this.stats.fullMessages;
83
+ document.getElementById("unique-keys").textContent =
84
+ this.stats.uniqueKeys.size;
85
+
86
+ const bandwidthSaved =
87
+ this.stats.totalBytesWithout > 0
88
+ ? (
89
+ (1 - this.stats.totalBytesWith / this.stats.totalBytesWithout) *
90
+ 100
91
+ ).toFixed(1)
92
+ : 0;
93
+ document.getElementById("bandwidth-saved").textContent =
94
+ bandwidthSaved + "%";
95
+
96
+ const avgCompression =
97
+ this.stats.totalBytesWithout > 0
98
+ ? (
99
+ (this.stats.totalBytesWith / this.stats.totalBytesWithout) *
100
+ 100
101
+ ).toFixed(1)
102
+ : 0;
103
+ document.getElementById("avg-compression").textContent =
104
+ avgCompression + "%";
105
+ }
106
+
107
+ async connect() {
108
+ this.log("Connecting to Sockudo server...", "info");
109
+
110
+ // Load configuration from backend server
111
+ try {
112
+ const configResponse = await fetch("/config");
113
+ if (!configResponse.ok) {
114
+ throw new Error(`Failed to load config: ${configResponse.status}`);
115
+ }
116
+ const config = await configResponse.json();
117
+ this.log(`✅ Loaded config from backend server`, "success");
118
+
119
+ this.pusher = new Pusher(config.pusherKey, {
120
+ wsHost: config.pusherHost,
121
+ wsPort: config.pusherPort,
122
+ forceTLS: config.pusherUseTLS,
123
+ enabledTransports: ["ws"],
124
+ disabledTransports: ["sockjs"],
125
+ authEndpoint: config.authEndpoint,
126
+ cluster: config.pusherCluster || "mt1",
127
+ });
128
+
129
+ // Initialize delta compression manager
130
+ this.deltaManager = new DeltaCompressionManager(this.pusher, {
131
+ algorithms: ["fossil", "xdelta3"],
132
+ debug: true,
133
+ onStats: (stats) => {
134
+ this.stats.deltaMessages = stats.deltaMessages;
135
+ this.stats.fullMessages = stats.fullMessages;
136
+ this.stats.totalBytesWith = stats.totalBytesWithCompression;
137
+ this.stats.totalBytesWithout = stats.totalBytesWithoutCompression;
138
+ // Total messages received = full messages + delta messages
139
+ // We only count the messages that come through price-update event separately
140
+ // So we need to add delta messages to get the true total
141
+ this.updateStats();
142
+ },
143
+ });
144
+
145
+ // Track delta messages separately - they don't trigger price-update event
146
+ this.pusher.bind_global((eventName, data) => {
147
+ // Debug: Log all events to see what we're receiving
148
+ if (
149
+ eventName !== "pusher:ping" &&
150
+ eventName !== "pusher:pong" &&
151
+ !eventName.startsWith("pusher_internal")
152
+ ) {
153
+ console.log(
154
+ "🔔 Global event:",
155
+ eventName,
156
+ "| Data keys:",
157
+ typeof data === "object" && data !== null
158
+ ? Object.keys(data).slice(0, 5)
159
+ : typeof data,
160
+ );
161
+ }
162
+
163
+ if (eventName === "pusher:delta") {
164
+ // Delta messages don't trigger the price-update event, so count them here
165
+ this.stats.messagesReceived++;
166
+ console.log(
167
+ "🔵 pusher:delta event received, total count:",
168
+ this.stats.messagesReceived,
169
+ );
170
+
171
+ // Extract conflation key from delta message to track unique keys
172
+ try {
173
+ const parsedData =
174
+ typeof data === "string" ? JSON.parse(data) : data;
175
+ if (parsedData.conflation_key) {
176
+ this.stats.uniqueKeys.add(parsedData.conflation_key);
177
+ }
178
+ } catch (e) {
179
+ console.error("Failed to parse delta message:", e);
180
+ }
181
+
182
+ this.updateStats();
183
+ }
184
+ return true; // Allow event to propagate to DeltaCompressionManager
185
+ });
186
+ } catch (error) {
187
+ this.log(`❌ Configuration error: ${error.message}`, "error");
188
+ this.log(
189
+ `Make sure to run 'npm start' in test/interactive directory`,
190
+ "error",
191
+ );
192
+ return;
193
+ }
194
+
195
+ this.pusher.connection.bind("connected", () => {
196
+ this.log("✅ Connected to Sockudo server", "success");
197
+ document.getElementById("connection-status").textContent = "Connected";
198
+ document.getElementById("connection-status").className =
199
+ "status-value connected";
200
+ document.getElementById("connect-btn").disabled = true;
201
+ document.getElementById("disconnect-btn").disabled = false;
202
+ document.getElementById("run-all-tests").disabled = false;
203
+ document.getElementById("run-test1").disabled = false;
204
+ document.getElementById("run-test2").disabled = false;
205
+ document.getElementById("run-test3").disabled = false;
206
+ document.getElementById("run-test4").disabled = false;
207
+ document.getElementById("delta-toggle").disabled = false;
208
+ });
209
+
210
+ this.pusher.connection.bind("disconnected", () => {
211
+ this.log("⚠️ Disconnected from server", "warning");
212
+ document.getElementById("connection-status").textContent = "Disconnected";
213
+ document.getElementById("connection-status").className =
214
+ "status-value disconnected";
215
+ });
216
+
217
+ this.pusher.connection.bind("error", (err) => {
218
+ this.log(`❌ Connection error: ${err.message}`, "error");
219
+ });
220
+
221
+ // Subscribe to test channel with conflation keys
222
+ this.channel = this.pusher.subscribe("market-data");
223
+
224
+ this.channel.bind("pusher:subscription_succeeded", () => {
225
+ this.log("✅ Subscribed to market-data channel", "success");
226
+ });
227
+
228
+ this.channel.bind("pusher:delta_cache_sync", (data) => {
229
+ this.log("🔄 Received delta cache sync", "info");
230
+
231
+ // Parse data if it's a string
232
+ let parsedData = data;
233
+ if (typeof data === "string") {
234
+ try {
235
+ parsedData = JSON.parse(data);
236
+ } catch (e) {
237
+ console.error("Failed to parse cache sync data:", e);
238
+ }
239
+ }
240
+
241
+ console.log("Cache sync data:", parsedData);
242
+ });
243
+
244
+ this.channel.bind("price-update", (data) => {
245
+ this.stats.messagesReceived++;
246
+ console.log(
247
+ "📨 price-update event received, total count:",
248
+ this.stats.messagesReceived,
249
+ );
250
+
251
+ if (data.asset) {
252
+ this.stats.uniqueKeys.add(data.asset);
253
+ }
254
+
255
+ // Debug: Check if this is a full message
256
+ if (data && typeof data === "object" && "__delta_seq" in data) {
257
+ console.log("🟢 FULL MESSAGE DETECTED:", {
258
+ seq: data.__delta_seq,
259
+ full: data.__delta_full,
260
+ conflation_key: data.__conflation_key,
261
+ asset: data.asset,
262
+ allKeys: Object.keys(data),
263
+ });
264
+ }
265
+
266
+ this.updateStats();
267
+ });
268
+ }
269
+
270
+ disconnect() {
271
+ if (this.pusher) {
272
+ this.pusher.disconnect();
273
+ this.pusher = null;
274
+ this.log("Disconnected from server", "info");
275
+ document.getElementById("connect-btn").disabled = false;
276
+ document.getElementById("disconnect-btn").disabled = true;
277
+ document.getElementById("run-all-tests").disabled = true;
278
+ document.getElementById("run-test1").disabled = true;
279
+ document.getElementById("run-test2").disabled = true;
280
+ document.getElementById("run-test3").disabled = true;
281
+ document.getElementById("run-test4").disabled = true;
282
+ document.getElementById("delta-toggle").disabled = true;
283
+ document.getElementById("delta-toggle").checked = false;
284
+ this.updateToggleUI(false);
285
+ }
286
+ }
287
+
288
+ toggleDeltaCompression(enabled) {
289
+ if (!this.pusher || this.pusher.connection.state !== "connected") {
290
+ this.log("❌ Cannot toggle delta compression: Not connected", "error");
291
+ document.getElementById("delta-toggle").checked = false;
292
+ this.updateToggleUI(false);
293
+ return;
294
+ }
295
+
296
+ if (enabled) {
297
+ this.log("🗜️ Enabling delta compression...", "info");
298
+ this.pusher.connection.send_event("pusher:enable_delta_compression", {});
299
+ this.updateToggleUI(true);
300
+ } else {
301
+ this.log("⚠️ Disabling delta compression...", "warning");
302
+ // Note: There's no standard disable event, this just stops tracking
303
+ this.deltaManager = null;
304
+ this.updateToggleUI(false);
305
+ }
306
+ }
307
+
308
+ updateToggleUI(enabled) {
309
+ const slider = document.getElementById("delta-toggle-slider");
310
+ const knob = document.getElementById("delta-toggle-knob");
311
+
312
+ if (enabled) {
313
+ slider.style.backgroundColor = "#667eea";
314
+ knob.style.transform = "translateX(26px)";
315
+ } else {
316
+ slider.style.backgroundColor = "#ccc";
317
+ knob.style.transform = "translateX(0px)";
318
+ }
319
+ }
320
+
321
+ async runAllTests() {
322
+ this.log("🚀 Running all tests...", "info");
323
+ await this.runTest1();
324
+ await this.sleep(2000);
325
+ await this.runTest2();
326
+ await this.sleep(2000);
327
+ await this.runTest3();
328
+ await this.sleep(2000);
329
+ await this.runTest4();
330
+ this.log("✅ All tests completed!", "success");
331
+ }
332
+
333
+ async runTest1() {
334
+ this.log(
335
+ "🧪 Test 1: Sending messages for 100 different conflation keys...",
336
+ "info",
337
+ );
338
+ this.setTestStatus("test1", "running");
339
+ this.clearTestResults("test1");
340
+
341
+ const assets = this.generateAssetList(100);
342
+ const startTime = Date.now();
343
+
344
+ try {
345
+ for (let i = 0; i < assets.length; i++) {
346
+ const asset = assets[i];
347
+ await this.sendPriceUpdate(asset, 100 + i, 1000 + i * 10);
348
+ this.addTestResult(
349
+ "test1",
350
+ `Sent: ${asset} - Price: ${100 + i}`,
351
+ "info",
352
+ );
353
+ await this.sleep(50); // Small delay between messages
354
+ }
355
+
356
+ const duration = Date.now() - startTime;
357
+ this.log(`✅ Test 1 completed in ${duration}ms`, "success");
358
+ this.addTestResult(
359
+ "test1",
360
+ `✅ Sent ${assets.length} messages`,
361
+ "success",
362
+ );
363
+ this.addTestResult("test1", `Duration: ${duration}ms`, "info");
364
+ this.setTestStatus("test1", "passed");
365
+ } catch (error) {
366
+ this.log(`❌ Test 1 failed: ${error.message}`, "error");
367
+ this.addTestResult("test1", `❌ Error: ${error.message}`, "error");
368
+ this.setTestStatus("test1", "failed");
369
+ }
370
+ }
371
+
372
+ async runTest2() {
373
+ this.log(
374
+ "🧪 Test 2: Sending interleaved messages for multiple assets...",
375
+ "info",
376
+ );
377
+ this.setTestStatus("test2", "running");
378
+ this.clearTestResults("test2");
379
+
380
+ const assets = ["BTC", "ETH", "ADA", "DOT", "SOL"];
381
+ const startTime = Date.now();
382
+
383
+ try {
384
+ // Send 10 rounds of updates for each asset (interleaved)
385
+ for (let round = 0; round < 10; round++) {
386
+ for (const asset of assets) {
387
+ const price = 100 + round + Math.random() * 10;
388
+ const volume = 1000 + round * 100;
389
+ await this.sendPriceUpdate(asset, price, volume);
390
+ this.addTestResult(
391
+ "test2",
392
+ `Round ${round + 1}: ${asset} = $${price.toFixed(2)}`,
393
+ "info",
394
+ );
395
+ await this.sleep(30);
396
+ }
397
+ }
398
+
399
+ const duration = Date.now() - startTime;
400
+ this.log(`✅ Test 2 completed in ${duration}ms`, "success");
401
+ this.addTestResult(
402
+ "test2",
403
+ `✅ Sent ${assets.length * 10} interleaved messages`,
404
+ "success",
405
+ );
406
+ this.addTestResult("test2", `Duration: ${duration}ms`, "info");
407
+ this.setTestStatus("test2", "passed");
408
+ } catch (error) {
409
+ this.log(`❌ Test 2 failed: ${error.message}`, "error");
410
+ this.addTestResult("test2", `❌ Error: ${error.message}`, "error");
411
+ this.setTestStatus("test2", "failed");
412
+ }
413
+ }
414
+
415
+ async runTest3() {
416
+ this.log("🧪 Test 3: Testing cache sync on subscription...", "info");
417
+ this.setTestStatus("test3", "running");
418
+ this.clearTestResults("test3");
419
+
420
+ try {
421
+ // Make sure delta compression is enabled
422
+ if (!document.getElementById("delta-toggle").checked) {
423
+ this.addTestResult(
424
+ "test3",
425
+ "⚠️ Delta compression not enabled, enabling now...",
426
+ "info",
427
+ );
428
+ document.getElementById("delta-toggle").checked = true;
429
+ this.toggleDeltaCompression(true);
430
+ await this.sleep(500);
431
+ }
432
+
433
+ // First, send some messages with conflation keys
434
+ this.addTestResult(
435
+ "test3",
436
+ "Sending initial messages with conflation keys...",
437
+ "info",
438
+ );
439
+ await this.sendPriceUpdate("BTC", 50000, 1000);
440
+ await this.sleep(200);
441
+ await this.sendPriceUpdate("BTC", 50100, 1100);
442
+ await this.sleep(200);
443
+ await this.sendPriceUpdate("ETH", 3000, 500);
444
+ await this.sleep(200);
445
+ await this.sendPriceUpdate("ETH", 3050, 550);
446
+ await this.sleep(500);
447
+
448
+ this.addTestResult(
449
+ "test3",
450
+ "Initial messages sent, waiting for processing...",
451
+ "info",
452
+ );
453
+ await this.sleep(1000);
454
+
455
+ // Unsubscribe and resubscribe to test cache sync
456
+ this.addTestResult("test3", "Unsubscribing from channel...", "info");
457
+ this.pusher.unsubscribe("market-data");
458
+ await this.sleep(1000);
459
+
460
+ this.addTestResult("test3", "Resubscribing to channel...", "info");
461
+
462
+ // Listen for cache sync event
463
+ const cacheSyncReceived = new Promise((resolve) => {
464
+ const newChannel = this.pusher.subscribe("market-data");
465
+
466
+ // IMPORTANT: Rebind the price-update handler to the new channel
467
+ newChannel.bind("price-update", (data) => {
468
+ this.stats.messagesReceived++;
469
+ console.log(
470
+ "📨 price-update event received, total count:",
471
+ this.stats.messagesReceived,
472
+ );
473
+
474
+ if (data.asset) {
475
+ this.stats.uniqueKeys.add(data.asset);
476
+ }
477
+
478
+ // Debug: Check if this is a full message
479
+ if (data && typeof data === "object" && "__delta_seq" in data) {
480
+ console.log("🟢 FULL MESSAGE DETECTED:", {
481
+ seq: data.__delta_seq,
482
+ full: data.__delta_full,
483
+ conflation_key: data.__conflation_key,
484
+ asset: data.asset,
485
+ allKeys: Object.keys(data),
486
+ });
487
+ }
488
+
489
+ this.updateStats();
490
+ });
491
+
492
+ newChannel.bind("pusher:delta_cache_sync", (data) => {
493
+ this.log("✅ Received cache sync!", "success");
494
+
495
+ // Parse data if it's a string
496
+ let parsedData = data;
497
+ if (typeof data === "string") {
498
+ try {
499
+ parsedData = JSON.parse(data);
500
+ } catch (e) {
501
+ console.error("Failed to parse cache sync data:", e);
502
+ }
503
+ }
504
+
505
+ this.addTestResult("test3", `✅ Cache sync received!`, "success");
506
+ this.addTestResult(
507
+ "test3",
508
+ `Conflation key: ${parsedData.conflation_key || "none"}`,
509
+ "info",
510
+ );
511
+ this.addTestResult(
512
+ "test3",
513
+ `Max messages per key: ${parsedData.max_messages_per_key || 0}`,
514
+ "info",
515
+ );
516
+
517
+ if (parsedData.states) {
518
+ const stateKeys = Object.keys(parsedData.states);
519
+ this.addTestResult(
520
+ "test3",
521
+ `States for ${stateKeys.length} keys: ${stateKeys.join(", ")}`,
522
+ "info",
523
+ );
524
+ }
525
+
526
+ this.channel = newChannel;
527
+ resolve(true);
528
+ });
529
+
530
+ newChannel.bind("pusher:subscription_succeeded", () => {
531
+ this.addTestResult(
532
+ "test3",
533
+ "✅ Subscription succeeded, waiting for cache sync...",
534
+ "info",
535
+ );
536
+ });
537
+
538
+ // Timeout after 5 seconds
539
+ setTimeout(() => {
540
+ this.channel = newChannel;
541
+ resolve(false);
542
+ }, 5000);
543
+ });
544
+
545
+ const received = await cacheSyncReceived;
546
+
547
+ if (received) {
548
+ this.log("✅ Test 3 completed", "success");
549
+ this.setTestStatus("test3", "passed");
550
+ } else {
551
+ this.log(
552
+ "⚠️ Test 3: Cache sync not received (cache might be empty or feature disabled)",
553
+ "warning",
554
+ );
555
+ this.addTestResult(
556
+ "test3",
557
+ "⚠️ Cache sync not received within 5 seconds",
558
+ "error",
559
+ );
560
+ this.addTestResult(
561
+ "test3",
562
+ "Note: Cache sync requires delta compression enabled and existing cached messages",
563
+ "info",
564
+ );
565
+ this.setTestStatus("test3", "failed");
566
+ }
567
+ } catch (error) {
568
+ this.log(`❌ Test 3 failed: ${error.message}`, "error");
569
+ this.addTestResult("test3", `❌ Error: ${error.message}`, "error");
570
+ this.setTestStatus("test3", "failed");
571
+ }
572
+ }
573
+
574
+ async runTest4() {
575
+ this.log(
576
+ "🧪 Test 4: Comparing bandwidth with/without conflation...",
577
+ "info",
578
+ );
579
+ this.setTestStatus("test4", "running");
580
+ this.clearTestResults("test4");
581
+
582
+ try {
583
+ const beforeStats = {
584
+ totalBytes: this.stats.totalBytesWith,
585
+ messages: this.stats.messagesReceived,
586
+ };
587
+
588
+ // Send test data
589
+ this.addTestResult("test4", "Sending test messages...", "info");
590
+ const assets = ["BTC", "ETH", "ADA"];
591
+
592
+ for (let i = 0; i < 20; i++) {
593
+ for (const asset of assets) {
594
+ await this.sendPriceUpdate(asset, 100 + i, 1000);
595
+ await this.sleep(20);
596
+ }
597
+ }
598
+
599
+ // Wait for all messages to be received via WebSocket
600
+ // Since we send messages with 20ms delay, and there's network latency,
601
+ // we need to wait longer to ensure all messages arrive
602
+ this.addTestResult(
603
+ "test4",
604
+ "Waiting for all messages to arrive...",
605
+ "info",
606
+ );
607
+ await this.sleep(2000);
608
+
609
+ const afterStats = {
610
+ totalBytes: this.stats.totalBytesWith,
611
+ messages: this.stats.messagesReceived,
612
+ };
613
+
614
+ const messagesSent = afterStats.messages - beforeStats.messages;
615
+ const bytesUsed = afterStats.totalBytes - beforeStats.totalBytes;
616
+ const avgBytesPerMessage =
617
+ messagesSent > 0 ? (bytesUsed / messagesSent).toFixed(0) : 0;
618
+
619
+ this.addTestResult("test4", `✅ Test completed`, "success");
620
+ this.addTestResult("test4", `Messages sent: ${messagesSent}`, "info");
621
+ this.addTestResult("test4", `Bytes used: ${bytesUsed}`, "info");
622
+ this.addTestResult(
623
+ "test4",
624
+ `Avg bytes/message: ${avgBytesPerMessage}`,
625
+ "info",
626
+ );
627
+
628
+ this.log(`✅ Test 4 completed`, "success");
629
+ this.setTestStatus("test4", "passed");
630
+ } catch (error) {
631
+ this.log(`❌ Test 4 failed: ${error.message}`, "error");
632
+ this.addTestResult("test4", `❌ Error: ${error.message}`, "error");
633
+ this.setTestStatus("test4", "failed");
634
+ }
635
+ }
636
+
637
+ async sendPriceUpdate(asset, price, volume) {
638
+ const message = {
639
+ asset: asset,
640
+ price: price.toFixed(2),
641
+ volume: volume,
642
+ timestamp: new Date().toISOString(),
643
+ market: "SPOT",
644
+ exchange: "TEST",
645
+ };
646
+
647
+ try {
648
+ // Send via backend server which uses Pusher SDK with proper authentication
649
+ const response = await fetch("/trigger-event", {
650
+ method: "POST",
651
+ headers: {
652
+ "Content-Type": "application/json",
653
+ },
654
+ body: JSON.stringify({
655
+ channel: "market-data",
656
+ event: "price-update",
657
+ data: message,
658
+ }),
659
+ });
660
+
661
+ if (!response.ok) {
662
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
663
+ }
664
+
665
+ const result = await response.json();
666
+ if (!result.success) {
667
+ throw new Error(result.error || "Failed to send event");
668
+ }
669
+
670
+ this.stats.messagesSent++;
671
+ console.log(
672
+ "📤 Message sent successfully, total sent:",
673
+ this.stats.messagesSent,
674
+ "| Asset:",
675
+ asset,
676
+ );
677
+ this.updateStats();
678
+
679
+ return message;
680
+ } catch (error) {
681
+ this.log(`❌ Failed to send message: ${error.message}`, "error");
682
+ throw error;
683
+ }
684
+ }
685
+
686
+ generateAssetList(count) {
687
+ const cryptos = [
688
+ "BTC",
689
+ "ETH",
690
+ "ADA",
691
+ "DOT",
692
+ "SOL",
693
+ "AVAX",
694
+ "MATIC",
695
+ "ATOM",
696
+ "LINK",
697
+ "UNI",
698
+ "XRP",
699
+ "LTC",
700
+ "BCH",
701
+ "XLM",
702
+ "DOGE",
703
+ "SHIB",
704
+ "TRX",
705
+ "ETC",
706
+ "FIL",
707
+ "AAVE",
708
+ "ALGO",
709
+ "VET",
710
+ "ICP",
711
+ "THETA",
712
+ "XTZ",
713
+ "EOS",
714
+ "CAKE",
715
+ "RUNE",
716
+ "EGLD",
717
+ "FTM",
718
+ "NEAR",
719
+ "FLOW",
720
+ "MANA",
721
+ "SAND",
722
+ "AXS",
723
+ "CHZ",
724
+ "ENJ",
725
+ "BAT",
726
+ "ZIL",
727
+ "COMP",
728
+ "MKR",
729
+ "SNX",
730
+ "YFI",
731
+ "UMA",
732
+ "CRV",
733
+ "BAL",
734
+ "LRC",
735
+ "SUSHI",
736
+ "1INCH",
737
+ "REN",
738
+ "KNC",
739
+ "ANT",
740
+ "NMR",
741
+ "MLN",
742
+ "STORJ",
743
+ "GRT",
744
+ "OMG",
745
+ "ZRX",
746
+ "REP",
747
+ "BNT",
748
+ ];
749
+
750
+ // Generate more if needed
751
+ const result = [...cryptos];
752
+ for (let i = cryptos.length; i < count; i++) {
753
+ result.push(`TOKEN${i + 1}`);
754
+ }
755
+
756
+ return result.slice(0, count);
757
+ }
758
+
759
+ setTestStatus(testId, status) {
760
+ const statusEl = document.getElementById(`${testId}-status`);
761
+ statusEl.className = `test-status ${status}`;
762
+ }
763
+
764
+ clearTestResults(testId) {
765
+ document.getElementById(`${testId}-results`).innerHTML = "";
766
+ }
767
+
768
+ addTestResult(testId, message, level = "info") {
769
+ const resultsEl = document.getElementById(`${testId}-results`);
770
+ const line = document.createElement("div");
771
+ line.className = `test-log ${level}`;
772
+ line.textContent = message;
773
+ resultsEl.appendChild(line);
774
+ resultsEl.scrollTop = resultsEl.scrollHeight;
775
+ }
776
+
777
+ sleep(ms) {
778
+ return new Promise((resolve) => setTimeout(resolve, ms));
779
+ }
780
+ }
781
+
782
+ // Initialize test suite when page loads
783
+ window.addEventListener("DOMContentLoaded", () => {
784
+ window.testSuite = new ConflationTestSuite();
785
+ });