@cratis/arc 22.0.2 → 22.2.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 (189) hide show
  1. package/dist/cjs/queries/ObservableQueryFor.js +6 -1
  2. package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
  3. package/dist/cjs/queries/QueryInstanceCache.js +6 -6
  4. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  5. package/dist/cjs/queries/QueryResult.js +23 -4
  6. package/dist/cjs/queries/QueryResult.js.map +1 -1
  7. package/dist/cjs/queries/QueryResultWithState.js +20 -7
  8. package/dist/cjs/queries/QueryResultWithState.js.map +1 -1
  9. package/dist/cjs/queries/ServerSentEventHubConnection.js +120 -58
  10. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  11. package/dist/cjs/queries/WebSocketHubConnection.js +121 -51
  12. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  13. package/dist/esm/queries/IQueryResult.d.ts +1 -0
  14. package/dist/esm/queries/IQueryResult.d.ts.map +1 -1
  15. package/dist/esm/queries/ObservableQueryFor.d.ts.map +1 -1
  16. package/dist/esm/queries/ObservableQueryFor.js +6 -1
  17. package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
  18. package/dist/esm/queries/QueryInstanceCache.d.ts +1 -1
  19. package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
  20. package/dist/esm/queries/QueryInstanceCache.js +6 -6
  21. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  22. package/dist/esm/queries/QueryResult.d.ts +2 -0
  23. package/dist/esm/queries/QueryResult.d.ts.map +1 -1
  24. package/dist/esm/queries/QueryResult.js +23 -4
  25. package/dist/esm/queries/QueryResult.js.map +1 -1
  26. package/dist/esm/queries/QueryResultWithState.d.ts +3 -3
  27. package/dist/esm/queries/QueryResultWithState.d.ts.map +1 -1
  28. package/dist/esm/queries/QueryResultWithState.js +20 -7
  29. package/dist/esm/queries/QueryResultWithState.js.map +1 -1
  30. package/dist/esm/queries/ServerSentEventHubConnection.d.ts +11 -4
  31. package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
  32. package/dist/esm/queries/ServerSentEventHubConnection.js +120 -58
  33. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  34. package/dist/esm/queries/WebSocketHubConnection.d.ts +13 -2
  35. package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
  36. package/dist/esm/queries/WebSocketHubConnection.js +121 -51
  37. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  38. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts +2 -0
  39. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts.map +1 -0
  40. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js +34 -0
  41. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js.map +1 -0
  42. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js +26 -2
  43. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js.map +1 -1
  44. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js +60 -3
  45. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js.map +1 -1
  46. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts +2 -0
  47. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts.map +1 -0
  48. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js +83 -0
  49. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js.map +1 -0
  50. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts +2 -0
  51. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts.map +1 -0
  52. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js +22 -0
  53. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js.map +1 -0
  54. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts +2 -0
  55. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts.map +1 -0
  56. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js +17 -0
  57. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js.map +1 -0
  58. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts +2 -0
  59. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts.map +1 -0
  60. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js +16 -0
  61. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js.map +1 -0
  62. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts +2 -0
  63. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts.map +1 -0
  64. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js +19 -0
  65. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js.map +1 -0
  66. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts +2 -0
  67. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts.map +1 -0
  68. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js +19 -0
  69. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js.map +1 -0
  70. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts +7 -0
  71. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts.map +1 -0
  72. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js +12 -0
  73. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js.map +1 -0
  74. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts +2 -1
  75. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts.map +1 -1
  76. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js +15 -4
  77. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js.map +1 -1
  78. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts +2 -0
  79. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts.map +1 -0
  80. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js +44 -0
  81. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js.map +1 -0
  82. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts +2 -0
  83. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts.map +1 -0
  84. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js +74 -0
  85. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js.map +1 -0
  86. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts +2 -0
  87. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts.map +1 -0
  88. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js +74 -0
  89. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js.map +1 -0
  90. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts +2 -0
  91. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts.map +1 -0
  92. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js +59 -0
  93. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js.map +1 -0
  94. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts +2 -0
  95. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts.map +1 -0
  96. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js +58 -0
  97. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js.map +1 -0
  98. package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js +6 -3
  99. package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js.map +1 -1
  100. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +23 -6
  101. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
  102. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js +20 -5
  103. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js.map +1 -1
  104. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts +2 -0
  105. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts.map +1 -0
  106. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js +20 -0
  107. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js.map +1 -0
  108. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts +2 -0
  109. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts.map +1 -0
  110. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js +68 -0
  111. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js.map +1 -0
  112. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js +38 -13
  113. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js.map +1 -1
  114. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts +2 -0
  115. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts.map +1 -0
  116. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js +54 -0
  117. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js.map +1 -0
  118. package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js +18 -4
  119. package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
  120. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +22 -5
  121. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
  122. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts +2 -0
  123. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts.map +1 -0
  124. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js +108 -0
  125. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js.map +1 -0
  126. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts +2 -0
  127. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts.map +1 -0
  128. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js +33 -0
  129. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js.map +1 -0
  130. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js +26 -4
  131. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js.map +1 -1
  132. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts +2 -0
  133. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts.map +1 -0
  134. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js +62 -0
  135. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js.map +1 -0
  136. package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js +18 -5
  137. package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js.map +1 -1
  138. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts +2 -0
  139. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts.map +1 -0
  140. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js +56 -0
  141. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js.map +1 -0
  142. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js +16 -3
  143. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
  144. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts +2 -0
  145. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts.map +1 -0
  146. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js +33 -0
  147. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js.map +1 -0
  148. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  149. package/package.json +1 -1
  150. package/queries/IQueryResult.ts +10 -0
  151. package/queries/ObservableQueryFor.ts +44 -16
  152. package/queries/QueryInstanceCache.ts +42 -19
  153. package/queries/QueryResult.ts +145 -79
  154. package/queries/QueryResultWithState.ts +32 -9
  155. package/queries/ServerSentEventHubConnection.ts +270 -83
  156. package/queries/WebSocketHubConnection.ts +188 -56
  157. package/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.ts +46 -0
  158. package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.ts +91 -57
  159. package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.ts +125 -53
  160. package/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.ts +107 -0
  161. package/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.ts +63 -0
  162. package/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.ts +25 -0
  163. package/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.ts +24 -0
  164. package/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.ts +28 -0
  165. package/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.ts +25 -0
  166. package/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.ts +15 -0
  167. package/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.ts +18 -7
  168. package/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.ts +59 -0
  169. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.ts +113 -0
  170. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.ts +109 -0
  171. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.ts +81 -0
  172. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.ts +83 -0
  173. package/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.ts +30 -21
  174. package/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +56 -32
  175. package/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.ts +23 -6
  176. package/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.ts +41 -0
  177. package/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.ts +92 -0
  178. package/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.ts +69 -30
  179. package/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.ts +69 -0
  180. package/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.ts +43 -24
  181. package/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +53 -29
  182. package/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.ts +131 -0
  183. package/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.ts +39 -0
  184. package/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.ts +72 -36
  185. package/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.ts +88 -0
  186. package/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.ts +54 -27
  187. package/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.ts +72 -0
  188. package/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.ts +43 -18
  189. package/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.ts +44 -0
@@ -27,7 +27,9 @@ var QueryResult = require('./QueryResult.js');
27
27
  *
28
28
  * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription
29
29
  * is identified by a client-generated {@code queryId}; the server tags every result message with
30
- * the same id so responses can be routed to the correct callback.
30
+ * the same id so responses can be routed to the correct callback. The client initially subscribes
31
+ * without revisions for compatibility with older servers, then replaces active subscriptions with
32
+ * revision-aware operations when the server advertises support in a Connected message.
31
33
  */ class WebSocketHubConnection {
32
34
  _url;
33
35
  _microservice;
@@ -39,12 +41,15 @@ var QueryResult = require('./QueryResult.js');
39
41
  _lastPingSentTime;
40
42
  _lastPongLatency = 0;
41
43
  _latencySamples = [];
44
+ _nextRevision = 0;
45
+ _supportsSubscriptionRevisions = false;
46
+ _reconnectPending = false;
42
47
  /**
43
48
  * Initializes a new instance of {@link WebSocketHubConnection}.
44
- * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).
45
- * @param {string} microservice The microservice name to pass as a query argument.
49
+ * @param {string} _url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).
50
+ * @param {string} _microservice The microservice name to pass as a query argument.
46
51
  * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).
47
- * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).
52
+ * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).
48
53
  */ constructor(_url, _microservice, pingIntervalMs = 10000, _policy = new ReconnectPolicy.ReconnectPolicy()){
49
54
  this._url = _url;
50
55
  this._microservice = _microservice;
@@ -87,13 +92,15 @@ var QueryResult = require('./QueryResult.js');
87
92
  * @param {SubscriptionRequest} request The subscription request payload.
88
93
  * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.
89
94
  */ subscribe(queryId, request, callback) {
90
- this._subscriptions.set(queryId, {
95
+ const subscription = {
91
96
  request,
92
- callback
93
- });
97
+ callback,
98
+ revision: this.getNextRevision()
99
+ };
100
+ this._subscriptions.set(queryId, subscription);
94
101
  this.ensureConnected();
95
102
  if (this._socket?.readyState === WebSocket.OPEN) {
96
- this.sendSubscribeMessage(queryId, request);
103
+ this.sendSubscribeMessage(queryId, subscription);
97
104
  }
98
105
  // If not yet open, sendAllSubscriptions will fire in onopen.
99
106
  }
@@ -101,12 +108,17 @@ var QueryResult = require('./QueryResult.js');
101
108
  * Unsubscribe from a query on this hub connection.
102
109
  * @param {string} queryId The identifier of the subscription to cancel.
103
110
  */ unsubscribe(queryId) {
111
+ const subscription = this._subscriptions.get(queryId);
104
112
  this._subscriptions.delete(queryId);
105
- if (this._socket?.readyState === WebSocket.OPEN) {
106
- this.sendMessage({
113
+ if (this._socket?.readyState === WebSocket.OPEN && subscription) {
114
+ const message = {
107
115
  type: "Unsubscribe",
108
116
  queryId
109
- });
117
+ };
118
+ if (this._supportsSubscriptionRevisions) {
119
+ message.revision = subscription.revision;
120
+ }
121
+ this.sendMessage(message);
110
122
  }
111
123
  // If no subscriptions remain, close the connection to free resources.
112
124
  if (this._subscriptions.size === 0) {
@@ -116,12 +128,8 @@ var QueryResult = require('./QueryResult.js');
116
128
  /**
117
129
  * Permanently close this hub connection and clean up all subscriptions.
118
130
  */ dispose() {
119
- this._disconnected = true;
120
131
  this._subscriptions.clear();
121
- this._keepAlive.stop();
122
- this._policy.cancel();
123
- this._socket?.close();
124
- this._socket = undefined;
132
+ this.close();
125
133
  }
126
134
  ensureConnected() {
127
135
  if (this._disconnected) {
@@ -129,75 +137,107 @@ var QueryResult = require('./QueryResult.js');
129
137
  this._disconnected = false;
130
138
  }
131
139
  if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {
140
+ this.cancelPendingReconnect();
132
141
  return;
133
142
  }
143
+ // A subscription can arrive while an earlier close is waiting in reconnect backoff. The immediate open owns
144
+ // the connection now, so the delayed callback must not be allowed to create a competing socket later.
145
+ this.cancelPendingReconnect();
134
146
  this.openSocket();
135
147
  }
136
148
  close() {
137
149
  this._disconnected = true;
138
150
  this._keepAlive.stop();
139
151
  this._policy.cancel();
140
- if (this._socket) {
141
- // Detach all handlers BEFORE closing so that the async onclose event cannot
142
- // fire after a new subscription has reset _disconnected to false and opened a
143
- // fresh socket. Without this, the stale onclose triggers an unintended
144
- // reconnect via the back-off policy, causing a 1-10 second delay before the
145
- // new page's queries receive their first data.
146
- this._socket.onopen = null;
147
- this._socket.onclose = null;
148
- this._socket.onerror = null;
149
- this._socket.onmessage = null;
150
- this._socket.close();
151
- }
152
+ this._reconnectPending = false;
153
+ const socket = this._socket;
152
154
  this._socket = undefined;
155
+ this._supportsSubscriptionRevisions = false;
156
+ if (socket) {
157
+ this.detachAndCloseSocket(socket);
158
+ }
153
159
  }
154
160
  openSocket() {
161
+ const currentSocket = this._socket;
162
+ if (currentSocket && (currentSocket.readyState === WebSocket.OPEN || currentSocket.readyState === WebSocket.CONNECTING)) {
163
+ return;
164
+ }
165
+ if (currentSocket) {
166
+ this._socket = undefined;
167
+ this.detachAndCloseSocket(currentSocket);
168
+ }
169
+ this._supportsSubscriptionRevisions = false;
155
170
  let url = this._url;
156
171
  if (this._microservice?.length > 0) {
157
172
  const param = `${Globals.Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;
158
173
  url += (url.includes('?') ? '&' : '?') + param;
159
174
  }
160
- this._socket = new WebSocket(url);
161
- this._socket.onopen = ()=>{
162
- if (this._disconnected) return;
163
- console.log(`Hub connection established: '${url}'`);
175
+ const socket = new WebSocket(url);
176
+ this._socket = socket;
177
+ socket.onopen = ()=>{
178
+ if (this._socket !== socket || this._disconnected) return;
179
+ console.log('Hub connection established', url);
180
+ this.cancelPendingReconnect();
164
181
  this._policy.reset();
165
182
  this._keepAlive.start();
166
183
  this.sendAllSubscriptions();
167
184
  };
168
- this._socket.onclose = ()=>{
169
- if (this._disconnected) return;
170
- console.log(`Hub connection closed: '${url}'`);
185
+ socket.onclose = ()=>{
186
+ if (this._socket !== socket || this._disconnected) return;
187
+ console.log('Hub connection closed', url);
188
+ this._socket = undefined;
189
+ this._supportsSubscriptionRevisions = false;
171
190
  this._keepAlive.stop();
172
191
  if (this._subscriptions.size === 0) return;
173
- this._policy.schedule(()=>{
192
+ this._reconnectPending = true;
193
+ const scheduled = this._policy.schedule(()=>{
194
+ this._reconnectPending = false;
174
195
  if (!this._disconnected && this._subscriptions.size > 0) {
175
- this.openSocket();
196
+ this.ensureConnected();
176
197
  }
177
198
  }, this._url);
199
+ if (!scheduled) {
200
+ this._reconnectPending = false;
201
+ }
178
202
  };
179
- this._socket.onerror = (error)=>{
180
- if (this._disconnected) return;
181
- console.error(`Hub connection error: '${url}'`, error);
203
+ socket.onerror = (error)=>{
204
+ if (this._socket !== socket || this._disconnected) return;
205
+ console.error('Hub connection error', url, error);
182
206
  this._keepAlive.stop();
183
207
  // onclose will fire after onerror, triggering reconnect
184
208
  };
185
- this._socket.onmessage = (ev)=>{
186
- if (this._disconnected) return;
209
+ socket.onmessage = (ev)=>{
210
+ if (this._socket !== socket || this._disconnected) return;
187
211
  this.handleMessage(ev.data);
188
212
  };
189
213
  }
214
+ cancelPendingReconnect() {
215
+ if (!this._reconnectPending) return;
216
+ this._policy.cancel();
217
+ this._reconnectPending = false;
218
+ }
219
+ detachAndCloseSocket(socket) {
220
+ socket.onopen = null;
221
+ socket.onclose = null;
222
+ socket.onerror = null;
223
+ socket.onmessage = null;
224
+ socket.close();
225
+ }
190
226
  sendAllSubscriptions() {
191
227
  for (const [queryId, sub] of this._subscriptions){
192
- this.sendSubscribeMessage(queryId, sub.request);
228
+ this.sendSubscribeMessage(queryId, sub);
193
229
  }
194
230
  }
195
- sendSubscribeMessage(queryId, request) {
196
- this.sendMessage({
231
+ sendSubscribeMessage(queryId, subscription) {
232
+ const message = {
197
233
  type: "Subscribe",
198
234
  queryId,
199
- payload: request
200
- });
235
+ payload: subscription.request
236
+ };
237
+ if (this._supportsSubscriptionRevisions) {
238
+ message.revision = subscription.revision;
239
+ }
240
+ this.sendMessage(message);
201
241
  }
202
242
  sendMessage(message) {
203
243
  if (this._socket?.readyState === WebSocket.OPEN) {
@@ -210,6 +250,9 @@ var QueryResult = require('./QueryResult.js');
210
250
  // Every received message is activity — skip keep-alive ping if data is flowing.
211
251
  this._keepAlive.recordActivity();
212
252
  switch(message.type){
253
+ case "Connected":
254
+ this.handleConnected(message);
255
+ break;
213
256
  case "QueryResult":
214
257
  this.handleQueryResult(message);
215
258
  break;
@@ -217,31 +260,58 @@ var QueryResult = require('./QueryResult.js');
217
260
  this.handlePong(message);
218
261
  break;
219
262
  case "Unauthorized":
220
- console.warn(`Hub: query '${message.queryId}' unauthorized`);
263
+ console.warn('Hub: query unauthorized', message.queryId);
221
264
  this.handleUnauthorized(message);
222
265
  break;
223
266
  case "Error":
224
- console.error(`Hub: query '${message.queryId}' error:`, message.payload);
267
+ if (this.isMessageForCurrentSubscription(message)) {
268
+ console.error('Hub: query error', message.queryId, message.payload);
269
+ }
225
270
  break;
226
271
  }
227
272
  } catch (error) {
228
273
  console.error('Hub: error parsing message', error);
229
274
  }
230
275
  }
276
+ handleConnected(message) {
277
+ if (message.supportsSubscriptionRevisions !== true || this._supportsSubscriptionRevisions) {
278
+ return;
279
+ }
280
+ this._supportsSubscriptionRevisions = true;
281
+ // The legacy subscriptions sent on socket open keep this client compatible with older servers.
282
+ // Ordered WebSocket delivery means these revision-aware replacements are processed afterwards.
283
+ this.sendAllSubscriptions();
284
+ }
231
285
  handleQueryResult(message) {
232
286
  if (!message.queryId) return;
233
287
  const sub = this._subscriptions.get(message.queryId);
234
- if (!sub) return;
288
+ if (!sub || !this.isMessageForCurrentSubscription(message)) return;
235
289
  const result = message.payload;
236
290
  sub.callback(result);
237
291
  }
238
292
  handleUnauthorized(message) {
239
293
  if (!message.queryId) return;
240
294
  const sub = this._subscriptions.get(message.queryId);
241
- if (!sub) return;
295
+ if (!sub || !this.isMessageForCurrentSubscription(message)) return;
242
296
  this._subscriptions.delete(message.queryId);
243
297
  sub.callback(QueryResult.QueryResult.unauthorized());
244
298
  }
299
+ isMessageForCurrentSubscription(message) {
300
+ if (!message.queryId) return false;
301
+ if (!this._supportsSubscriptionRevisions) {
302
+ return message.revision === undefined && this._subscriptions.has(message.queryId);
303
+ }
304
+ return this.isValidRevision(message.revision) && this._subscriptions.get(message.queryId)?.revision === message.revision;
305
+ }
306
+ isValidRevision(revision) {
307
+ return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;
308
+ }
309
+ getNextRevision() {
310
+ if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {
311
+ throw new RangeError('WebSocket hub subscription revision exhausted the safe integer range');
312
+ }
313
+ return ++this._nextRevision;
314
+ }
245
315
  handlePong(message) {
246
316
  if (message.timestamp && this._lastPingSentTime) {
247
317
  const latency = Date.now() - message.timestamp;
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the {@link WebSocketHubConnection}.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n payload?: any;\n timestamp?: number;\n\n /**\n * The server's keep-alive interval in milliseconds, or 0 when keep-alive is disabled.\n * Only present on {@link HubMessageType.Connected} messages.\n */\n keepAliveIntervalMs?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({ type: HubMessageType.Ping, timestamp: this._lastPingSentTime });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n this._subscriptions.set(queryId, { request, callback });\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, request);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendMessage({ type: HubMessageType.Unsubscribe, queryId });\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {\n return;\n }\n\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n if (this._socket) {\n // Detach all handlers BEFORE closing so that the async onclose event cannot\n // fire after a new subscription has reset _disconnected to false and opened a\n // fresh socket. Without this, the stale onclose triggers an unintended\n // reconnect via the back-off policy, causing a 1-10 second delay before the\n // new page's queries receive their first data.\n this._socket.onopen = null;\n this._socket.onclose = null;\n this._socket.onerror = null;\n this._socket.onmessage = null;\n this._socket.close();\n }\n this._socket = undefined;\n }\n\n private openSocket(): void {\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._socket = new WebSocket(url);\n\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n this._socket.onclose = () => {\n if (this._disconnected) return;\n console.log(`Hub connection closed: '${url}'`);\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openSocket();\n }\n }, this._url);\n };\n\n this._socket.onerror = (error) => {\n if (this._disconnected) return;\n console.error(`Hub connection error: '${url}'`, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n this._socket.onmessage = (ev) => {\n if (this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub.request);\n }\n }\n\n private sendSubscribeMessage(queryId: string, request: SubscriptionRequest): void {\n this.sendMessage({\n type: HubMessageType.Subscribe,\n queryId,\n payload: request,\n });\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn(`Hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`Hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","set","ensureConnected","sendSubscribeMessage","unsubscribe","delete","close","dispose","clear","stop","cancel","undefined","CONNECTING","openSocket","onopen","onclose","onerror","onmessage","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","console","log","reset","start","sendAllSubscriptions","schedule","error","ev","handleMessage","data","sub","payload","message","send","JSON","stringify","rawData","parse","recordActivity","handleQueryResult","handlePong","warn","handleUnauthorized","get","result","QueryResult","unauthorized","latency","push","shift"],"mappings":";;;;;;;AAAA;AACA;AASA;;;IAMO,IAAKA,cAAAA,iBAAAA,SAAAA,cAAAA,EAAAA;;;;;;;;;AAAAA,IAAAA,OAAAA,cAAAA;AASX,CAAA,CAAA,EAAA;AAoCD;;;;;;;AAOC,IACM,MAAMC,sBAAAA,CAAAA;;;;IACDC,OAAAA;AACAC,IAAAA,aAAAA,GAAgB,KAAA;AAChBC,IAAAA,cAAAA,GAAkD,IAAIC,GAAAA,EAAAA;IAC7CC,UAAAA;IACTC,iBAAAA;AACAC,IAAAA,gBAAAA,GAA2B,CAAA;AAC3BC,IAAAA,eAAAA,GAA4B,EAAE;AAEtC;;;;;;AAMC,QACD,WAAA,CACqBC,IAAY,EAC7B,aAAsC,EACtCC,cAAAA,GAAyB,KAAK,EACbC,OAAAA,GAA4B,IAAIC,iCAAiB,CACpE;aAJmBH,IAAAA,GAAAA,IAAAA;aACAI,aAAAA,GAAAA,aAAAA;aAEAF,OAAAA,GAAAA,OAAAA;AAEjB,QAAA,IAAI,CAACN,UAAU,GAAG,IAAIS,8CAAuBJ,cAAAA,EAAgB,IAAA;AACzD,YAAA,IAAI,IAAI,CAACT,OAAO,EAAEc,UAAAA,KAAeC,SAAAA,CAAUC,IAAI,EAAE;AAC7C,gBAAA,IAAI,CAACX,iBAAiB,GAAGY,IAAAA,CAAKC,GAAG,EAAA;gBACjC,IAAI,CAACC,WAAW,CAAC;oBAAEC,IAAI,EAAA,MAAA;oBAAuBC,SAAAA,EAAW,IAAI,CAAChB;AAAkB,iBAAA,CAAA;AACpF,YAAA;AACJ,QAAA,CAAA,CAAA;AACJ,IAAA;AAEA;;AAEC,QACD,IAAIiB,UAAAA,GAAqB;AACrB,QAAA,OAAO,IAAI,CAACpB,cAAc,CAACqB,IAAI;AACnC,IAAA;AAEA;;AAEC,QACD,IAAIC,WAAAA,GAAuB;AACvB,QAAA,OAAO,IAAI,CAACxB,OAAO,EAAEc,UAAAA,KAAeC,UAAUC,IAAI;AACtD,IAAA;AAEA;;AAEC,QACD,IAAIS,eAAAA,GAA0B;QAC1B,OAAO,IAAI,CAACnB,gBAAgB;AAChC,IAAA;AAEA;;AAEC,QACD,IAAIoB,cAAAA,GAAyB;AACzB,QAAA,IAAI,IAAI,CAACnB,eAAe,CAACoB,MAAM,KAAK,GAAG,OAAO,CAAA;AAC9C,QAAA,OAAO,IAAI,CAACpB,eAAe,CAACqB,MAAM,CAAC,CAACC,CAAAA,EAAGC,CAAAA,GAAMD,CAAAA,GAAIC,GAAG,CAAA,CAAA,GAAK,IAAI,CAACvB,eAAe,CAACoB,MAAM;AACxF,IAAA;AAEA;;;;;;AAMC,QACDI,UAAUC,OAAe,EAAEC,OAA4B,EAAEC,QAA2B,EAAQ;AACxF,QAAA,IAAI,CAAChC,cAAc,CAACiC,GAAG,CAACH,OAAAA,EAAS;AAAEC,YAAAA,OAAAA;AAASC,YAAAA;AAAS,SAAA,CAAA;AACrD,QAAA,IAAI,CAACE,eAAe,EAAA;AAEpB,QAAA,IAAI,IAAI,CAACpC,OAAO,EAAEc,UAAAA,KAAeC,SAAAA,CAAUC,IAAI,EAAE;YAC7C,IAAI,CAACqB,oBAAoB,CAACL,OAAAA,EAASC,OAAAA,CAAAA;AACvC,QAAA;;AAEJ,IAAA;AAEA;;;QAIAK,WAAAA,CAAYN,OAAe,EAAQ;AAC/B,QAAA,IAAI,CAAC9B,cAAc,CAACqC,MAAM,CAACP,OAAAA,CAAAA;AAE3B,QAAA,IAAI,IAAI,CAAChC,OAAO,EAAEc,UAAAA,KAAeC,SAAAA,CAAUC,IAAI,EAAE;YAC7C,IAAI,CAACG,WAAW,CAAC;gBAAEC,IAAI,EAAA,aAAA;AAA8BY,gBAAAA;AAAQ,aAAA,CAAA;AACjE,QAAA;;AAGA,QAAA,IAAI,IAAI,CAAC9B,cAAc,CAACqB,IAAI,KAAK,CAAA,EAAG;AAChC,YAAA,IAAI,CAACiB,KAAK,EAAA;AACd,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDC,OAAAA,GAAgB;QACZ,IAAI,CAACxC,aAAa,GAAG,IAAA;QACrB,IAAI,CAACC,cAAc,CAACwC,KAAK,EAAA;QACzB,IAAI,CAACtC,UAAU,CAACuC,IAAI,EAAA;QACpB,IAAI,CAACjC,OAAO,CAACkC,MAAM,EAAA;QACnB,IAAI,CAAC5C,OAAO,EAAEwC,KAAAA,EAAAA;QACd,IAAI,CAACxC,OAAO,GAAG6C,SAAAA;AACnB,IAAA;IAEQT,eAAAA,GAAwB;QAC5B,IAAI,IAAI,CAACnC,aAAa,EAAE;;YAEpB,IAAI,CAACA,aAAa,GAAG,KAAA;AACzB,QAAA;QAEA,IAAI,IAAI,CAACD,OAAO,KAAK,IAAI,CAACA,OAAO,CAACc,UAAU,KAAKC,UAAUC,IAAI,IAAI,IAAI,CAAChB,OAAO,CAACc,UAAU,KAAKC,SAAAA,CAAU+B,UAAS,CAAA,EAAI;AAClH,YAAA;AACJ,QAAA;AAEA,QAAA,IAAI,CAACC,UAAU,EAAA;AACnB,IAAA;IAEQP,KAAAA,GAAc;QAClB,IAAI,CAACvC,aAAa,GAAG,IAAA;QACrB,IAAI,CAACG,UAAU,CAACuC,IAAI,EAAA;QACpB,IAAI,CAACjC,OAAO,CAACkC,MAAM,EAAA;QACnB,IAAI,IAAI,CAAC5C,OAAO,EAAE;;;;;;AAMd,YAAA,IAAI,CAACA,OAAO,CAACgD,MAAM,GAAG,IAAA;AACtB,YAAA,IAAI,CAAChD,OAAO,CAACiD,OAAO,GAAG,IAAA;AACvB,YAAA,IAAI,CAACjD,OAAO,CAACkD,OAAO,GAAG,IAAA;AACvB,YAAA,IAAI,CAAClD,OAAO,CAACmD,SAAS,GAAG,IAAA;YACzB,IAAI,CAACnD,OAAO,CAACwC,KAAK,EAAA;AACtB,QAAA;QACA,IAAI,CAACxC,OAAO,GAAG6C,SAAAA;AACnB,IAAA;IAEQE,UAAAA,GAAmB;QACvB,IAAIK,GAAAA,GAAM,IAAI,CAAC5C,IAAI;AACnB,QAAA,IAAI,IAAI,CAACI,aAAa,EAAEe,SAAS,CAAA,EAAG;YAChC,MAAM0B,KAAAA,GAAQ,CAAA,EAAGC,eAAAA,CAAQC,2BAA2B,CAAC,CAAC,EAAEC,kBAAAA,CAAmB,IAAI,CAAC5C,aAAa,CAAA,CAAA,CAAG;YAChGwC,GAAAA,IAAQA,CAAAA,GAAAA,CAAIK,QAAQ,CAAC,GAAA,CAAA,GAAO,GAAA,GAAM,GAAE,IAAKJ,KAAAA;AAC7C,QAAA;AAEA,QAAA,IAAI,CAACrD,OAAO,GAAG,IAAIe,SAAAA,CAAUqC,GAAAA,CAAAA;AAE7B,QAAA,IAAI,CAACpD,OAAO,CAACgD,MAAM,GAAG,IAAA;YAClB,IAAI,IAAI,CAAC/C,aAAa,EAAE;AACxByD,YAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,6BAA6B,EAAEP,GAAAA,CAAI,CAAC,CAAC,CAAA;YAClD,IAAI,CAAC1C,OAAO,CAACkD,KAAK,EAAA;YAClB,IAAI,CAACxD,UAAU,CAACyD,KAAK,EAAA;AACrB,YAAA,IAAI,CAACC,oBAAoB,EAAA;AAC7B,QAAA,CAAA;AAEA,QAAA,IAAI,CAAC9D,OAAO,CAACiD,OAAO,GAAG,IAAA;YACnB,IAAI,IAAI,CAAChD,aAAa,EAAE;AACxByD,YAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,wBAAwB,EAAEP,GAAAA,CAAI,CAAC,CAAC,CAAA;YAC7C,IAAI,CAAChD,UAAU,CAACuC,IAAI,EAAA;AACpB,YAAA,IAAI,IAAI,CAACzC,cAAc,CAACqB,IAAI,KAAK,CAAA,EAAG;AACpC,YAAA,IAAI,CAACb,OAAO,CAACqD,QAAQ,CAAC,IAAA;gBAClB,IAAI,CAAC,IAAI,CAAC9D,aAAa,IAAI,IAAI,CAACC,cAAc,CAACqB,IAAI,GAAG,CAAA,EAAG;AACrD,oBAAA,IAAI,CAACwB,UAAU,EAAA;AACnB,gBAAA;YACJ,CAAA,EAAG,IAAI,CAACvC,IAAI,CAAA;AAChB,QAAA,CAAA;AAEA,QAAA,IAAI,CAACR,OAAO,CAACkD,OAAO,GAAG,CAACc,KAAAA,GAAAA;YACpB,IAAI,IAAI,CAAC/D,aAAa,EAAE;YACxByD,OAAAA,CAAQM,KAAK,CAAC,CAAC,uBAAuB,EAAEZ,GAAAA,CAAI,CAAC,CAAC,EAAEY,KAAAA,CAAAA;YAChD,IAAI,CAAC5D,UAAU,CAACuC,IAAI,EAAA;;AAExB,QAAA,CAAA;AAEA,QAAA,IAAI,CAAC3C,OAAO,CAACmD,SAAS,GAAG,CAACc,EAAAA,GAAAA;YACtB,IAAI,IAAI,CAAChE,aAAa,EAAE;AACxB,YAAA,IAAI,CAACiE,aAAa,CAACD,EAAAA,CAAGE,IAAI,CAAA;AAC9B,QAAA,CAAA;AACJ,IAAA;IAEQL,oBAAAA,GAA6B;QACjC,KAAK,MAAM,CAAC9B,OAAAA,EAASoC,GAAAA,CAAI,IAAI,IAAI,CAAClE,cAAc,CAAE;AAC9C,YAAA,IAAI,CAACmC,oBAAoB,CAACL,OAAAA,EAASoC,IAAInC,OAAO,CAAA;AAClD,QAAA;AACJ,IAAA;IAEQI,oBAAAA,CAAqBL,OAAe,EAAEC,OAA4B,EAAQ;QAC9E,IAAI,CAACd,WAAW,CAAC;YACbC,IAAI,EAAA,WAAA;AACJY,YAAAA,OAAAA;YACAqC,OAAAA,EAASpC;AACb,SAAA,CAAA;AACJ,IAAA;AAEQd,IAAAA,WAAAA,CAAYmD,OAAmB,EAAQ;AAC3C,QAAA,IAAI,IAAI,CAACtE,OAAO,EAAEc,UAAAA,KAAeC,SAAAA,CAAUC,IAAI,EAAE;AAC7C,YAAA,IAAI,CAAChB,OAAO,CAACuE,IAAI,CAACC,IAAAA,CAAKC,SAAS,CAACH,OAAAA,CAAAA,CAAAA;AACrC,QAAA;AACJ,IAAA;AAEQJ,IAAAA,aAAAA,CAAcQ,OAAe,EAAQ;QACzC,IAAI;YACA,MAAMJ,OAAAA,GAAUE,IAAAA,CAAKG,KAAK,CAACD,OAAAA,CAAAA;;YAG3B,IAAI,CAACtE,UAAU,CAACwE,cAAc,EAAA;AAE9B,YAAA,OAAQN,QAAQlD,IAAI;AAChB,gBAAA,KAAA,aAAA;oBACI,IAAI,CAACyD,iBAAiB,CAACP,OAAAA,CAAAA;AACvB,oBAAA;AACJ,gBAAA,KAAA,MAAA;oBACI,IAAI,CAACQ,UAAU,CAACR,OAAAA,CAAAA;AAChB,oBAAA;AACJ,gBAAA,KAAA,cAAA;oBACIZ,OAAAA,CAAQqB,IAAI,CAAC,CAAC,YAAY,EAAET,OAAAA,CAAQtC,OAAO,CAAC,cAAc,CAAC,CAAA;oBAC3D,IAAI,CAACgD,kBAAkB,CAACV,OAAAA,CAAAA;AACxB,oBAAA;AACJ,gBAAA,KAAA,OAAA;AACIZ,oBAAAA,OAAAA,CAAQM,KAAK,CAAC,CAAC,YAAY,EAAEM,OAAAA,CAAQtC,OAAO,CAAC,QAAQ,CAAC,EAAEsC,OAAAA,CAAQD,OAAO,CAAA;AACvE,oBAAA;AACR;AACJ,QAAA,CAAA,CAAE,OAAOL,KAAAA,EAAO;YACZN,OAAAA,CAAQM,KAAK,CAAC,4BAAA,EAA8BA,KAAAA,CAAAA;AAChD,QAAA;AACJ,IAAA;AAEQa,IAAAA,iBAAAA,CAAkBP,OAAmB,EAAQ;QACjD,IAAI,CAACA,OAAAA,CAAQtC,OAAO,EAAE;QAEtB,MAAMoC,GAAAA,GAAM,IAAI,CAAClE,cAAc,CAAC+E,GAAG,CAACX,QAAQtC,OAAO,CAAA;AACnD,QAAA,IAAI,CAACoC,GAAAA,EAAK;QAEV,MAAMc,MAAAA,GAASZ,QAAQD,OAAO;AAC9BD,QAAAA,GAAAA,CAAIlC,QAAQ,CAACgD,MAAAA,CAAAA;AACjB,IAAA;AAEQF,IAAAA,kBAAAA,CAAmBV,OAAmB,EAAQ;QAClD,IAAI,CAACA,OAAAA,CAAQtC,OAAO,EAAE;QAEtB,MAAMoC,GAAAA,GAAM,IAAI,CAAClE,cAAc,CAAC+E,GAAG,CAACX,QAAQtC,OAAO,CAAA;AACnD,QAAA,IAAI,CAACoC,GAAAA,EAAK;AAEV,QAAA,IAAI,CAAClE,cAAc,CAACqC,MAAM,CAAC+B,QAAQtC,OAAO,CAAA;QAC1CoC,GAAAA,CAAIlC,QAAQ,CAACiD,uBAAAA,CAAYC,YAAY,EAAA,CAAA;AACzC,IAAA;AAEQN,IAAAA,UAAAA,CAAWR,OAAmB,EAAQ;AAC1C,QAAA,IAAIA,QAAQjD,SAAS,IAAI,IAAI,CAAChB,iBAAiB,EAAE;AAC7C,YAAA,MAAMgF,OAAAA,GAAUpE,IAAAA,CAAKC,GAAG,EAAA,GAAKoD,QAAQjD,SAAS;YAC9C,IAAI,CAACf,gBAAgB,GAAG+E,OAAAA;AACxB,YAAA,IAAI,CAAC9E,eAAe,CAAC+E,IAAI,CAACD,OAAAA,CAAAA;AAE1B,YAAA,IAAI,IAAI,CAAC9E,eAAe,CAACoB,MAAM,GAAG,GAAA,EAAK;gBACnC,IAAI,CAACpB,eAAe,CAACgF,KAAK,EAAA;AAC9B,YAAA;AACJ,QAAA;AACJ,IAAA;AACJ;;;;;"}
1
+ {"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport type { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport type { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the observable query WebSocket and SSE hub transports.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n\n /** Optional positive safe-integer revision used to reject stale replacement messages. */\n revision?: number;\n\n /**\n * Whether the server supports revision-aware subscription operations and result frames.\n * Only present on {@link HubMessageType.Connected} messages from capable servers.\n */\n supportsSubscriptionRevisions?: boolean;\n payload?: any;\n timestamp?: number;\n\n /**\n * The server's keep-alive interval in milliseconds, or 0 when keep-alive is disabled.\n * Only present on {@link HubMessageType.Connected} messages.\n */\n keepAliveIntervalMs?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n revision: number;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback. The client initially subscribes\n * without revisions for compatibility with older servers, then replaces active subscriptions with\n * revision-aware operations when the server advertises support in a Connected message.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _nextRevision = 0;\n private _supportsSubscriptionRevisions = false;\n private _reconnectPending = false;\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} _url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy(),\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({\n type: HubMessageType.Ping,\n timestamp: this._lastPingSentTime,\n });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return (\n this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length\n );\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(\n queryId: string,\n request: SubscriptionRequest,\n callback: DataReceived<any>,\n ): void {\n const subscription = { request, callback, revision: this.getNextRevision() };\n this._subscriptions.set(queryId, subscription);\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, subscription);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n const subscription = this._subscriptions.get(queryId);\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN && subscription) {\n const message: HubMessage = {\n type: HubMessageType.Unsubscribe,\n queryId,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._subscriptions.clear();\n this.close();\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (\n this._socket &&\n (this._socket.readyState === WebSocket.OPEN ||\n this._socket.readyState === WebSocket.CONNECTING)\n ) {\n this.cancelPendingReconnect();\n return;\n }\n\n // A subscription can arrive while an earlier close is waiting in reconnect backoff. The immediate open owns\n // the connection now, so the delayed callback must not be allowed to create a competing socket later.\n this.cancelPendingReconnect();\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n this._reconnectPending = false;\n const socket = this._socket;\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n if (socket) {\n this.detachAndCloseSocket(socket);\n }\n }\n\n private openSocket(): void {\n const currentSocket = this._socket;\n if (\n currentSocket &&\n (currentSocket.readyState === WebSocket.OPEN ||\n currentSocket.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (currentSocket) {\n this._socket = undefined;\n this.detachAndCloseSocket(currentSocket);\n }\n\n this._supportsSubscriptionRevisions = false;\n\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n const socket = new WebSocket(url);\n this._socket = socket;\n\n socket.onopen = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection established', url);\n this.cancelPendingReconnect();\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n socket.onclose = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection closed', url);\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._reconnectPending = true;\n const scheduled = this._policy.schedule(() => {\n this._reconnectPending = false;\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.ensureConnected();\n }\n }, this._url);\n if (!scheduled) {\n this._reconnectPending = false;\n }\n };\n\n socket.onerror = (error) => {\n if (this._socket !== socket || this._disconnected) return;\n console.error('Hub connection error', url, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n socket.onmessage = (ev) => {\n if (this._socket !== socket || this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private cancelPendingReconnect(): void {\n if (!this._reconnectPending) return;\n\n this._policy.cancel();\n this._reconnectPending = false;\n }\n\n private detachAndCloseSocket(socket: WebSocket): void {\n socket.onopen = null;\n socket.onclose = null;\n socket.onerror = null;\n socket.onmessage = null;\n socket.close();\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub);\n }\n }\n\n private sendSubscribeMessage(\n queryId: string,\n subscription: ActiveSubscription,\n ): void {\n const message: HubMessage = {\n type: HubMessageType.Subscribe,\n queryId,\n payload: subscription.request,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn('Hub: query unauthorized', message.queryId);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n if (this.isMessageForCurrentSubscription(message)) {\n console.error(\n 'Hub: query error',\n message.queryId,\n message.payload,\n );\n }\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n if (\n message.supportsSubscriptionRevisions !== true ||\n this._supportsSubscriptionRevisions\n ) {\n return;\n }\n\n this._supportsSubscriptionRevisions = true;\n\n // The legacy subscriptions sent on socket open keep this client compatible with older servers.\n // Ordered WebSocket delivery means these revision-aware replacements are processed afterwards.\n this.sendAllSubscriptions();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private isMessageForCurrentSubscription(message: HubMessage): boolean {\n if (!message.queryId) return false;\n\n if (!this._supportsSubscriptionRevisions) {\n return (\n message.revision === undefined &&\n this._subscriptions.has(message.queryId)\n );\n }\n\n return (\n this.isValidRevision(message.revision) &&\n this._subscriptions.get(message.queryId)?.revision === message.revision\n );\n }\n\n private isValidRevision(revision: number | undefined): revision is number {\n return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;\n }\n\n private getNextRevision(): number {\n if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n 'WebSocket hub subscription revision exhausted the safe integer range',\n );\n }\n\n return ++this._nextRevision;\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_nextRevision","_supportsSubscriptionRevisions","_reconnectPending","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","subscription","revision","getNextRevision","set","ensureConnected","sendSubscribeMessage","unsubscribe","get","delete","message","close","dispose","clear","CONNECTING","cancelPendingReconnect","openSocket","stop","cancel","socket","undefined","detachAndCloseSocket","currentSocket","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","onopen","console","log","reset","start","sendAllSubscriptions","onclose","scheduled","schedule","onerror","error","onmessage","ev","handleMessage","data","sub","payload","send","JSON","stringify","rawData","parse","recordActivity","handleConnected","handleQueryResult","handlePong","warn","handleUnauthorized","isMessageForCurrentSubscription","supportsSubscriptionRevisions","result","QueryResult","unauthorized","has","isValidRevision","Number","isSafeInteger","MAX_SAFE_INTEGER","RangeError","latency","push","shift"],"mappings":"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"}
@@ -5,6 +5,7 @@ export interface IQueryResult<TDataType> {
5
5
  readonly data: TDataType;
6
6
  readonly paging: PagingInfo;
7
7
  readonly isSuccess: boolean;
8
+ readonly isReady?: boolean;
8
9
  readonly isAuthorized: boolean;
9
10
  readonly isValid: boolean;
10
11
  readonly hasExceptions: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"IQueryResult.d.ts","sourceRoot":"","sources":["../../../queries/IQueryResult.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,MAAM,WAAW,YAAY,CAAC,SAAS;IAInC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAKzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAK5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAK5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAK/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAK1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAKhC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IAK/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAKrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAOrC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAKxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC7B"}
1
+ {"version":3,"file":"IQueryResult.d.ts","sourceRoot":"","sources":["../../../queries/IQueryResult.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,MAAM,WAAW,YAAY,CAAC,SAAS;IAInC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAKzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAK5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAU5B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAK3B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAK/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAK1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAKhC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IAK/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAKrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAOrC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAKxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryFor.d.ts","sourceRoot":"","sources":["../../../queries/ObservableQueryFor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AASzD,8BAAsB,kBAAkB,CAAC,SAAS,EAAE,WAAW,GAAG,MAAM,CAAE,YAAW,mBAAmB,CAAC,SAAS,EAAE,WAAW,CAAC;IAwBhH,QAAQ,CAAC,SAAS,EAAE,WAAW;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO;IAvBzE,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAwC;IAC5D,OAAO,CAAC,oBAAoB,CAAiB;IAC7C,OAAO,CAAC,WAAW,CAAC,CAAkB;IAEtC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAM;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;IAE1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC9D,QAAQ,KAAK,yBAAyB,IAAI,MAAM,EAAE,CAAC;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IAOf,YAAqB,SAAS,EAAE,WAAW,EAAW,UAAU,EAAE,OAAO,EAOxE;IAKD,OAAO,SAEN;IAGD,eAAe,CAAC,YAAY,EAAE,MAAM,QAEnC;IAGD,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAExC;IAGD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE9B;IAGD,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAErD;IAGD,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAE3C;IAGD,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,2BAA2B,CAAC,SAAS,CAAC,CAoDpH;IAGK,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CA4CjE;IAED,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,iBAAiB;CAO5B"}
1
+ {"version":3,"file":"ObservableQueryFor.d.ts","sourceRoot":"","sources":["../../../queries/ObservableQueryFor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AASzD,8BAAsB,kBAAkB,CACpC,SAAS,EACT,WAAW,GAAG,MAAM,CACtB,YAAW,mBAAmB,CAAC,SAAS,EAAE,WAAW,CAAC;IAyBhD,QAAQ,CAAC,SAAS,EAAE,WAAW;IAC/B,QAAQ,CAAC,UAAU,EAAE,OAAO;IAzBhC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAwC;IAC5D,OAAO,CAAC,oBAAoB,CAAiB;IAC7C,OAAO,CAAC,WAAW,CAAC,CAAkB;IAEtC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAM;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;IAE1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC9D,QAAQ,KAAK,yBAAyB,IAAI,MAAM,EAAE,CAAC;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IAOf,YACa,SAAS,EAAE,WAAW,EACtB,UAAU,EAAE,OAAO,EAQ/B;IAKD,OAAO,SAEN;IAGD,eAAe,CAAC,YAAY,EAAE,MAAM,QAEnC;IAGD,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAExC;IAGD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE9B;IAGD,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAErD;IAGD,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAE3C;IAGD,SAAS,CACL,QAAQ,EAAE,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAC9C,IAAI,CAAC,EAAE,WAAW,GACnB,2BAA2B,CAAC,SAAS,CAAC,CA8DxC;IAGK,OAAO,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAgDjE;IAED,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,iBAAiB;CAO5B"}
@@ -105,6 +105,11 @@ import { executeQueryHttpRequest } from './QueryHttpRequest.js';
105
105
  this._connection.connect((data)=>{
106
106
  const result = data;
107
107
  try {
108
+ // Observable transports deliver structural query-result envelopes directly instead of
109
+ // constructing QueryResult. Servers predating readiness therefore omit the member;
110
+ // those results are complete by definition and must be normalized before subscribers
111
+ // observe them. Preserve an explicit false transient state from newer servers.
112
+ result.isReady ??= true;
108
113
  this.deserializeResult(result);
109
114
  callback(result);
110
115
  } catch (ex) {
@@ -133,7 +138,7 @@ import { executeQueryHttpRequest } from './QueryHttpRequest.js';
133
138
  const parameterValues = ParametersHelper.collectParameterValues(this);
134
139
  const headers = {
135
140
  ...this._httpHeadersCallback?.() || {},
136
- 'Accept': 'application/json',
141
+ Accept: 'application/json',
137
142
  'Content-Type': 'application/json'
138
143
  };
139
144
  if (this._microservice?.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryFor.js","sources":["../../../queries/ObservableQueryFor.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type { IObservableQueryFor, OnNextResult } from './IObservableQueryFor';\nimport { ObservableQuerySubscription } from './ObservableQuerySubscription';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport type { QueryValidator } from './QueryValidator';\nimport type { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { NullObservableQueryConnection } from './NullObservableQueryConnection';\nimport { createObservableQueryConnection } from './ObservableQueryConnectionFactory';\nimport type { Constructor } from '@cratis/fundamentals';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\nimport { QueryResult } from './QueryResult';\nimport { Sorting } from './Sorting';\nimport { Paging } from './Paging';\nimport { SortDirection } from './SortDirection';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport type { GetHttpHeaders } from '../GetHttpHeaders';\nimport type { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport type { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class ObservableQueryFor<TDataType, TParameters = object> implements IObservableQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _connection?: IObservableQueryConnection<TDataType>;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n\n abstract readonly route: string;\n abstract readonly defaultValue: TDataType;\n readonly roles: string[] = [];\n readonly validation?: QueryValidator<any>;\n /** Backend fully-qualified query name used when subscribing via the SSE hub. Overridden in generated proxies. */\n readonly queryName?: string;\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n sorting: Sorting;\n paging: Paging;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(readonly modelType: Constructor, readonly enumerable: boolean) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /**\n * Disposes the query.\n */\n dispose() {\n this._connection?.disconnect();\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n subscribe(callback: OnNextResult<QueryResult<TDataType>>, args?: TParameters): ObservableQuerySubscription<TDataType> {\n if (this._connection) {\n this._connection.disconnect();\n }\n\n const clientValidationErrors = this.validation?.validate(args as object || {}) || [];\n if (clientValidationErrors.length > 0) {\n // Serve the failure through the connection rather than throwing, so a subscriber sees an invalid result\n // on its normal callback path instead of the empty result an unestablished connection would emit.\n this._connection = new NullObservableQueryConnection(\n this.defaultValue,\n QueryResult.validationFailed(clientValidationErrors, this));\n } else if (this.validateArguments(args)) {\n this._connection = createObservableQueryConnection({\n route: this.route,\n queryName: this.queryName ?? this.constructor.name,\n origin: this._origin,\n apiBasePath: this._apiBasePath,\n microservice: this._microservice,\n args: args as object,\n });\n } else {\n this._connection = new NullObservableQueryConnection(this.defaultValue);\n }\n\n // Descriptor-backed instance properties provide defaults; fresh args passed to subscribe()\n // must take precedence over any stale instance property values. Spread parameterValues\n // first so that the caller-supplied args can override them.\n //\n // In direct mode the route arguments are already embedded in the URL path, so only\n // the unused (non-route) parameters are appended as additional query arguments.\n // In multiplexed mode ALL arguments — including route-derived ones — must be included\n // in the subscribe payload so the server can execute the query correctly.\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const { unusedParameters } = UrlHelpers.replaceRouteParameters(this.route, args as object);\n const connectionQueryArguments: any = {\n ...parameterValues,\n ...(Globals.queryDirectMode ? unusedParameters : (args as object) || {}),\n ...this.buildQueryArguments()\n };\n\n const subscriber = new ObservableQuerySubscription(this._connection);\n this._connection.connect(data => {\n const result: any = data;\n try {\n this.deserializeResult(result);\n callback(result);\n } catch (ex) {\n console.log(ex);\n }\n }, connectionQueryArguments);\n return subscriber;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = { ...QueryResult.noSuccess, ...{ data: this.defaultValue } } as QueryResult<TDataType>;\n\n const clientValidationErrors = this.validation?.validate(args as object || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!this.validateArguments(args)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ...(this._httpHeadersCallback?.() || {}),\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n const response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers\n });\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n\n private validateArguments(args?: TParameters): boolean {\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const combinedArgs = { ...(args as object || {}), ...parameterValues };\n return ValidateRequestArguments(this.constructor.name, this.requiredRequestParameters, combinedArgs as object);\n }\n\n private buildQueryArguments(): any {\n const queryArguments: any = {};\n\n if (this.paging && this.paging.pageSize > 0) {\n queryArguments.pageSize = this.paging.pageSize;\n queryArguments.page = this.paging.page;\n }\n\n if (this.sorting.hasSorting) {\n queryArguments.sortBy = this.sorting.field;\n queryArguments.sortDirection = (this.sorting.direction === SortDirection.descending) ? 'desc' : 'asc';\n }\n\n return queryArguments;\n }\n\n private deserializeResult(result: any): void {\n if (this.enumerable) {\n result.data = deserializeQueryModels(this.modelType, result.data);\n } else if (result.data) {\n result.data = deserializeQueryModel(this.modelType, result.data);\n }\n }\n}\n"],"names":["ObservableQueryFor","_microservice","_apiBasePath","_origin","_connection","_httpHeadersCallback","_httpMethod","roles","validation","queryName","sorting","paging","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","dispose","disconnect","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","subscribe","args","clientValidationErrors","validate","length","NullObservableQueryConnection","defaultValue","QueryResult","validationFailed","validateArguments","createObservableQueryConnection","route","name","parameterValues","ParametersHelper","collectParameterValues","unusedParameters","UrlHelpers","replaceRouteParameters","connectionQueryArguments","queryDirectMode","buildQueryArguments","subscriber","ObservableQuerySubscription","connect","data","result","deserializeResult","ex","console","log","perform","noSuccess","Promise","resolve","headers","microserviceHttpHeader","response","executeQueryHttpRequest","json","combinedArgs","ValidateRequestArguments","requiredRequestParameters","queryArguments","pageSize","page","hasSorting","sortBy","field","sortDirection","direction","SortDirection","descending","deserializeQueryModels","deserializeQueryModel"],"mappings":"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"}
1
+ {"version":3,"file":"ObservableQueryFor.js","sources":["../../../queries/ObservableQueryFor.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type { IObservableQueryFor, OnNextResult } from './IObservableQueryFor';\nimport { ObservableQuerySubscription } from './ObservableQuerySubscription';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport type { QueryValidator } from './QueryValidator';\nimport type { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { NullObservableQueryConnection } from './NullObservableQueryConnection';\nimport { createObservableQueryConnection } from './ObservableQueryConnectionFactory';\nimport type { Constructor } from '@cratis/fundamentals';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\nimport { QueryResult } from './QueryResult';\nimport { Sorting } from './Sorting';\nimport { Paging } from './Paging';\nimport { SortDirection } from './SortDirection';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport type { GetHttpHeaders } from '../GetHttpHeaders';\nimport type { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport type { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class ObservableQueryFor<\n TDataType,\n TParameters = object,\n> implements IObservableQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _connection?: IObservableQueryConnection<TDataType>;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n\n abstract readonly route: string;\n abstract readonly defaultValue: TDataType;\n readonly roles: string[] = [];\n readonly validation?: QueryValidator<any>;\n /** Backend fully-qualified query name used when subscribing via the SSE hub. Overridden in generated proxies. */\n readonly queryName?: string;\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n sorting: Sorting;\n paging: Paging;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(\n readonly modelType: Constructor,\n readonly enumerable: boolean,\n ) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /**\n * Disposes the query.\n */\n dispose() {\n this._connection?.disconnect();\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n subscribe(\n callback: OnNextResult<QueryResult<TDataType>>,\n args?: TParameters,\n ): ObservableQuerySubscription<TDataType> {\n if (this._connection) {\n this._connection.disconnect();\n }\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n // Serve the failure through the connection rather than throwing, so a subscriber sees an invalid result\n // on its normal callback path instead of the empty result an unestablished connection would emit.\n this._connection = new NullObservableQueryConnection(\n this.defaultValue,\n QueryResult.validationFailed(clientValidationErrors, this),\n );\n } else if (this.validateArguments(args)) {\n this._connection = createObservableQueryConnection({\n route: this.route,\n queryName: this.queryName ?? this.constructor.name,\n origin: this._origin,\n apiBasePath: this._apiBasePath,\n microservice: this._microservice,\n args: args as object,\n });\n } else {\n this._connection = new NullObservableQueryConnection(this.defaultValue);\n }\n\n // Descriptor-backed instance properties provide defaults; fresh args passed to subscribe()\n // must take precedence over any stale instance property values. Spread parameterValues\n // first so that the caller-supplied args can override them.\n //\n // In direct mode the route arguments are already embedded in the URL path, so only\n // the unused (non-route) parameters are appended as additional query arguments.\n // In multiplexed mode ALL arguments — including route-derived ones — must be included\n // in the subscribe payload so the server can execute the query correctly.\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const { unusedParameters } = UrlHelpers.replaceRouteParameters(\n this.route,\n args as object,\n );\n const connectionQueryArguments: any = {\n ...parameterValues,\n ...(Globals.queryDirectMode ? unusedParameters : (args as object) || {}),\n ...this.buildQueryArguments(),\n };\n\n const subscriber = new ObservableQuerySubscription(this._connection);\n this._connection.connect((data) => {\n const result: any = data;\n try {\n // Observable transports deliver structural query-result envelopes directly instead of\n // constructing QueryResult. Servers predating readiness therefore omit the member;\n // those results are complete by definition and must be normalized before subscribers\n // observe them. Preserve an explicit false transient state from newer servers.\n result.isReady ??= true;\n this.deserializeResult(result);\n callback(result);\n } catch (ex) {\n console.log(ex);\n }\n }, connectionQueryArguments);\n return subscriber;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = {\n ...QueryResult.noSuccess,\n ...{ data: this.defaultValue },\n } as QueryResult<TDataType>;\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!this.validateArguments(args)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ...(this._httpHeadersCallback?.() || {}),\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n const response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers,\n });\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n\n private validateArguments(args?: TParameters): boolean {\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const combinedArgs = { ...((args as object) || {}), ...parameterValues };\n return ValidateRequestArguments(\n this.constructor.name,\n this.requiredRequestParameters,\n combinedArgs as object,\n );\n }\n\n private buildQueryArguments(): any {\n const queryArguments: any = {};\n\n if (this.paging && this.paging.pageSize > 0) {\n queryArguments.pageSize = this.paging.pageSize;\n queryArguments.page = this.paging.page;\n }\n\n if (this.sorting.hasSorting) {\n queryArguments.sortBy = this.sorting.field;\n queryArguments.sortDirection =\n this.sorting.direction === SortDirection.descending ? 'desc' : 'asc';\n }\n\n return queryArguments;\n }\n\n private deserializeResult(result: any): void {\n if (this.enumerable) {\n result.data = deserializeQueryModels(this.modelType, result.data);\n } else if (result.data) {\n result.data = deserializeQueryModel(this.modelType, result.data);\n }\n }\n}\n"],"names":["ObservableQueryFor","_microservice","_apiBasePath","_origin","_connection","_httpHeadersCallback","_httpMethod","roles","validation","queryName","sorting","paging","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","dispose","disconnect","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","subscribe","args","clientValidationErrors","validate","length","NullObservableQueryConnection","defaultValue","QueryResult","validationFailed","validateArguments","createObservableQueryConnection","route","name","parameterValues","ParametersHelper","collectParameterValues","unusedParameters","UrlHelpers","replaceRouteParameters","connectionQueryArguments","queryDirectMode","buildQueryArguments","subscriber","ObservableQuerySubscription","connect","data","result","isReady","deserializeResult","ex","console","log","perform","noSuccess","Promise","resolve","headers","Accept","microserviceHttpHeader","response","executeQueryHttpRequest","json","combinedArgs","ValidateRequestArguments","requiredRequestParameters","queryArguments","pageSize","page","hasSorting","sortBy","field","sortDirection","direction","SortDirection","descending","deserializeQueryModels","deserializeQueryModel"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { QueryResultWithState } from './QueryResultWithState';
2
- import { CacheDiagnostics } from './ObservableQueryDiagnosticsSnapshot';
2
+ import type { CacheDiagnostics } from './ObservableQueryDiagnosticsSnapshot';
3
3
  export type QueryCacheKey = string;
4
4
  export type QueryCacheListener<TDataType> = (result: QueryResultWithState<TDataType>) => void;
5
5
  export interface QueryCacheEntry<TDataType> {
@@ -1 +1 @@
1
- {"version":3,"file":"QueryInstanceCache.d.ts","sourceRoot":"","sources":["../../../queries/QueryInstanceCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAyB,MAAM,sCAAsC,CAAC;AAM/F,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAKnC,MAAM,MAAM,kBAAkB,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AAM9F,MAAM,WAAW,eAAe,CAAC,SAAS;IAItC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAK3B,UAAU,CAAC,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAK7C,eAAe,EAAE,MAAM,CAAC;IAKxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAMvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAKtB,UAAU,EAAE,OAAO,CAAC;IAOpB,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CAClD;AAUD,qBAAa,kBAAkB;IAWf,OAAO,CAAC,QAAQ,CAAC,YAAY;IAVzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsD;IAC/E,OAAO,CAAC,eAAe,CAAC,CAAgC;IASxD,YAA6B,YAAY,GAAE,MAAe,EACzD;IAUD,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAa5D;IAUD,WAAW,CAAC,SAAS,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,SAAS,GACzB;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAgBzC;IASD,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAWhC;IAQD,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,SAAS,CAExF;IAQD,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAiC1F;IAUD,OAAO,CAAC,kBAAkB;IA8B1B,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI,CAMxF;IAQD,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI,CAM3F;IAQD,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAO1D;IAOD,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAExC;IAUD,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAuBhC;IAOD,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAE/B;IAYD,wBAAwB,IAAI,IAAI,CAW/B;IAOD,OAAO,IAAI,IAAI,CAad;IAWD,YAAY,IAAI,IAAI,CASnB;IAQD,oBAAoB,IAAI,IAAI,CAK3B;IAMD,sBAAsB,IAAI,gBAAgB,CAwCzC;CACJ"}
1
+ {"version":3,"file":"QueryInstanceCache.d.ts","sourceRoot":"","sources":["../../../queries/QueryInstanceCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EACR,gBAAgB,EAEnB,MAAM,sCAAsC,CAAC;AAM9C,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAKnC,MAAM,MAAM,kBAAkB,CAAC,SAAS,IAAI,CACxC,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,KACtC,IAAI,CAAC;AAMV,MAAM,WAAW,eAAe,CAAC,SAAS;IAItC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAK3B,UAAU,CAAC,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAK7C,eAAe,EAAE,MAAM,CAAC;IAKxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAMvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAKtB,UAAU,EAAE,OAAO,CAAC;IAOpB,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CAClD;AAUD,qBAAa,kBAAkB;IAWf,OAAO,CAAC,QAAQ,CAAC,YAAY;IAVzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsD;IAC/E,OAAO,CAAC,eAAe,CAAC,CAAgC;IASxD,YAA6B,YAAY,GAAE,MAAe,EAAI;IAU9D,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,CAa5D;IAUD,WAAW,CAAC,SAAS,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,SAAS,GACzB;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAgBzC;IASD,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAWhC;IAQD,aAAa,CAAC,SAAS,EACnB,GAAG,EAAE,aAAa,GACnB,oBAAoB,CAAC,SAAS,CAAC,GAAG,SAAS,CAI7C;IAQD,aAAa,CAAC,SAAS,EACnB,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,GACxC,IAAI,CAqCN;IAUD,OAAO,CAAC,kBAAkB;IAgC1B,WAAW,CAAC,SAAS,EACjB,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GACxC,IAAI,CAMN;IAQD,cAAc,CAAC,SAAS,EACpB,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GACxC,IAAI,CAMN;IAQD,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAO1D;IAOD,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAExC;IAUD,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAuBhC;IAOD,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAE/B;IAYD,wBAAwB,IAAI,IAAI,CAW/B;IAOD,OAAO,IAAI,IAAI,CAad;IAWD,YAAY,IAAI,IAAI,CASnB;IAQD,oBAAoB,IAAI,IAAI,CAK3B;IAMD,sBAAsB,IAAI,gBAAgB,CAwCzC;CACJ"}
@@ -25,7 +25,7 @@ import { reconcileQueryData } from './reconcileQueryData.js';
25
25
  }
26
26
  /**
27
27
  * Builds the cache key for a query.
28
- * @param queryTypeName The stable type name for the query. Use the instance's {@link queryName}
28
+ * @param queryTypeName The stable type name for the query. Use the instance's `queryName`
29
29
  * (a hardcoded fully-qualified string in generated proxies) rather than {@link Function.name},
30
30
  * which is unstable under minification.
31
31
  * @param args Optional arguments supplied to the query.
@@ -107,12 +107,12 @@ import { reconcileQueryData } from './reconcileQueryData.js';
107
107
  // change keep their previous references. A full snapshot — which is what the server re-sends
108
108
  // whenever a subscription is re-established — otherwise arrives as all-new references and
109
109
  // makes every consumer treat every item as changed.
110
- const reconciled = previousResult !== undefined ? this.withReconciledData(previousResult, result) : result;
110
+ const reconciled = previousResult === undefined ? result : this.withReconciledData(previousResult, result);
111
111
  entry.lastResult = reconciled;
112
112
  // Reconciliation returns the previous data reference when nothing changed, so identity is
113
- // enough to detect it. Only `data` and `isSuccess` matter here — the other fields (e.g.
114
- // changeSet) are ephemeral and do not affect what the user sees.
115
- if (previousResult !== undefined && previousResult.isSuccess === reconciled.isSuccess && previousResult.data === reconciled.data) {
113
+ // enough to detect it. Data, success, and readiness affect what the user sees; changeSet is
114
+ // ephemeral and does not independently require a notification.
115
+ if (previousResult !== undefined && previousResult.isSuccess === reconciled.isSuccess && previousResult.isReady === reconciled.isReady && previousResult.data === reconciled.data) {
116
116
  return;
117
117
  }
118
118
  for (const listener of entry.listeners){
@@ -131,7 +131,7 @@ import { reconcileQueryData } from './reconcileQueryData.js';
131
131
  if (reconciledData === next.data) {
132
132
  return next;
133
133
  }
134
- return new QueryResultWithState(reconciledData, next.paging, next.isSuccess, next.isAuthorized, next.isValid, next.validationResults, next.hasExceptions, next.exceptionMessages, next.exceptionStackTrace, next.isPerforming, next.changeSet);
134
+ return new QueryResultWithState(reconciledData, next.paging, next.isSuccess, next.isAuthorized, next.isValid, next.validationResults, next.hasExceptions, next.exceptionMessages, next.exceptionStackTrace, next.isPerforming, next.changeSet, next.isReady);
135
135
  }
136
136
  /**
137
137
  * Registers a listener that is invoked whenever the cached result for the given key changes.