@cratis/arc 20.1.3 → 20.1.5

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 (185) hide show
  1. package/dist/cjs/identity/IdentityProvider.d.ts +2 -1
  2. package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
  3. package/dist/cjs/identity/IdentityProvider.js +16 -2
  4. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  5. package/dist/cjs/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts +2 -0
  6. package/dist/cjs/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts.map +1 -0
  7. package/dist/cjs/queries/HubConnectionKeepAlive.d.ts +2 -1
  8. package/dist/cjs/queries/HubConnectionKeepAlive.d.ts.map +1 -1
  9. package/dist/cjs/queries/HubConnectionKeepAlive.js +4 -2
  10. package/dist/cjs/queries/HubConnectionKeepAlive.js.map +1 -1
  11. package/dist/cjs/queries/QueryInstanceCache.d.ts +8 -0
  12. package/dist/cjs/queries/QueryInstanceCache.d.ts.map +1 -1
  13. package/dist/cjs/queries/QueryInstanceCache.js +70 -9
  14. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  15. package/dist/cjs/queries/QueryResult.d.ts +1 -0
  16. package/dist/cjs/queries/QueryResult.d.ts.map +1 -1
  17. package/dist/cjs/queries/QueryResult.js +18 -0
  18. package/dist/cjs/queries/QueryResult.js.map +1 -1
  19. package/dist/cjs/queries/ReconnectPolicy.d.ts.map +1 -1
  20. package/dist/cjs/queries/ReconnectPolicy.js +1 -0
  21. package/dist/cjs/queries/ReconnectPolicy.js.map +1 -1
  22. package/dist/cjs/queries/ServerSentEventHubConnection.d.ts +1 -0
  23. package/dist/cjs/queries/ServerSentEventHubConnection.d.ts.map +1 -1
  24. package/dist/cjs/queries/ServerSentEventHubConnection.js +22 -3
  25. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  26. package/dist/cjs/queries/WebSocketHubConnection.d.ts +1 -0
  27. package/dist/cjs/queries/WebSocketHubConnection.d.ts.map +1 -1
  28. package/dist/cjs/queries/WebSocketHubConnection.js +11 -0
  29. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  30. package/dist/cjs/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.d.ts +2 -0
  31. package/dist/cjs/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.d.ts.map +1 -0
  32. package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +2 -0
  33. package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +1 -0
  34. package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts +2 -0
  35. package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts.map +1 -0
  36. package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts +2 -0
  37. package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts.map +1 -0
  38. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts +2 -0
  39. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts.map +1 -0
  40. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts +2 -0
  41. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts.map +1 -0
  42. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts +2 -0
  43. package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts.map +1 -0
  44. package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +2 -0
  45. package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +1 -0
  46. package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +2 -0
  47. package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +1 -0
  48. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts +2 -0
  49. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts.map +1 -0
  50. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts +2 -0
  51. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts.map +1 -0
  52. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts +2 -0
  53. package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts.map +1 -0
  54. package/dist/cjs/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.d.ts +2 -0
  55. package/dist/cjs/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.d.ts.map +1 -0
  56. package/dist/cjs/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
  57. package/dist/cjs/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
  58. package/dist/cjs/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.d.ts +2 -0
  59. package/dist/cjs/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.d.ts.map +1 -0
  60. package/dist/cjs/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
  61. package/dist/cjs/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
  62. package/dist/esm/identity/IdentityProvider.d.ts +2 -1
  63. package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
  64. package/dist/esm/identity/IdentityProvider.js +16 -2
  65. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  66. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts +2 -0
  67. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts.map +1 -0
  68. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.js +19 -0
  69. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.js.map +1 -0
  70. package/dist/esm/queries/HubConnectionKeepAlive.d.ts +2 -1
  71. package/dist/esm/queries/HubConnectionKeepAlive.d.ts.map +1 -1
  72. package/dist/esm/queries/HubConnectionKeepAlive.js +4 -2
  73. package/dist/esm/queries/HubConnectionKeepAlive.js.map +1 -1
  74. package/dist/esm/queries/QueryInstanceCache.d.ts +8 -0
  75. package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
  76. package/dist/esm/queries/QueryInstanceCache.js +70 -9
  77. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  78. package/dist/esm/queries/QueryResult.d.ts +1 -0
  79. package/dist/esm/queries/QueryResult.d.ts.map +1 -1
  80. package/dist/esm/queries/QueryResult.js +18 -0
  81. package/dist/esm/queries/QueryResult.js.map +1 -1
  82. package/dist/esm/queries/ReconnectPolicy.d.ts.map +1 -1
  83. package/dist/esm/queries/ReconnectPolicy.js +1 -0
  84. package/dist/esm/queries/ReconnectPolicy.js.map +1 -1
  85. package/dist/esm/queries/ServerSentEventHubConnection.d.ts +1 -0
  86. package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
  87. package/dist/esm/queries/ServerSentEventHubConnection.js +22 -3
  88. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  89. package/dist/esm/queries/WebSocketHubConnection.d.ts +1 -0
  90. package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
  91. package/dist/esm/queries/WebSocketHubConnection.js +11 -0
  92. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  93. package/dist/esm/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.d.ts +2 -0
  94. package/dist/esm/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.d.ts.map +1 -0
  95. package/dist/esm/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.js +33 -0
  96. package/dist/esm/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.js.map +1 -0
  97. package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +2 -0
  98. package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +1 -0
  99. package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.js +23 -0
  100. package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.js.map +1 -0
  101. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts +2 -0
  102. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts.map +1 -0
  103. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js +23 -0
  104. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js.map +1 -0
  105. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts +2 -0
  106. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts.map +1 -0
  107. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js +21 -0
  108. package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js.map +1 -0
  109. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts +2 -0
  110. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts.map +1 -0
  111. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.js +17 -0
  112. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.js.map +1 -0
  113. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts +2 -0
  114. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts.map +1 -0
  115. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.js +23 -0
  116. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.js.map +1 -0
  117. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts +2 -0
  118. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts.map +1 -0
  119. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js +22 -0
  120. package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js.map +1 -0
  121. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +2 -0
  122. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +1 -0
  123. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js +28 -0
  124. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js.map +1 -0
  125. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +2 -0
  126. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +1 -0
  127. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js +25 -0
  128. package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js.map +1 -0
  129. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts +2 -0
  130. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts.map +1 -0
  131. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.js +25 -0
  132. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.js.map +1 -0
  133. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts +2 -0
  134. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts.map +1 -0
  135. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.js +12 -0
  136. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.js.map +1 -0
  137. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts +2 -0
  138. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts.map +1 -0
  139. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js +23 -0
  140. package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js.map +1 -0
  141. package/dist/esm/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.d.ts +2 -0
  142. package/dist/esm/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.d.ts.map +1 -0
  143. package/dist/esm/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.js +24 -0
  144. package/dist/esm/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.js.map +1 -0
  145. package/dist/esm/queries/for_ServerSentEventHubConnection/when_keep_alive_is_idle/triggers_reconnect.js +1 -1
  146. package/dist/esm/queries/for_ServerSentEventHubConnection/when_keep_alive_is_idle/triggers_reconnect.js.map +1 -1
  147. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
  148. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
  149. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +35 -0
  150. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -0
  151. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.d.ts +2 -0
  152. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.d.ts.map +1 -0
  153. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.js +33 -0
  154. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.js.map +1 -0
  155. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
  156. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
  157. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +33 -0
  158. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -0
  159. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  160. package/identity/IdentityProvider.ts +23 -2
  161. package/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts +26 -0
  162. package/package.json +1 -1
  163. package/queries/HubConnectionKeepAlive.ts +20 -6
  164. package/queries/QueryInstanceCache.ts +133 -12
  165. package/queries/QueryResult.ts +19 -0
  166. package/queries/ReconnectPolicy.ts +4 -0
  167. package/queries/ServerSentEventHubConnection.ts +29 -4
  168. package/queries/WebSocketHubConnection.ts +11 -0
  169. package/queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.ts +46 -0
  170. package/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts +31 -0
  171. package/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts +31 -0
  172. package/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.ts +28 -0
  173. package/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.ts +21 -0
  174. package/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.ts +30 -0
  175. package/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.ts +31 -0
  176. package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts +36 -0
  177. package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts +33 -0
  178. package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.ts +32 -0
  179. package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.ts +18 -0
  180. package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.ts +33 -0
  181. package/queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.ts +36 -0
  182. package/queries/for_ServerSentEventHubConnection/when_keep_alive_is_idle/triggers_reconnect.ts +5 -2
  183. package/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +51 -0
  184. package/queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.ts +51 -0
  185. package/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +47 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.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 { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs How long without any server message before the connection\n * is considered stale and a reconnect is forced (default: 30 000 ms).\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire interval, the connection is stale and we reconnect.\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${keepAliveIntervalMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n });\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\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 /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\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.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\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 sendSubscribe(queryId: string, request: SubscriptionRequest): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n request,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: subscribe POST failed for '${queryId}'`, error);\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["ReconnectPolicy","HubConnectionKeepAlive","Globals","HubMessageType"],"mappings":"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"}
1
+ {"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.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 { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs How long without any server message before the connection\n * is considered stale and a reconnect is forced (default: 30 000 ms).\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire idle threshold, the connection is stale and we reconnect.\n //\n // The idle threshold is set to 1.5× the check interval so the server's keep-alive\n // ping (which fires on the same cadence) has time to arrive over the network before\n // the client declares the connection dead. Without this tolerance the client's timer\n // and the server's timer race — the client often fires first and reconnects\n // unnecessarily.\n const idleThresholdMs = Math.round(keepAliveIntervalMs * 1.5);\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n }, idleThresholdMs);\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\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 /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\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.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\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 this._pendingSubscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private sendSubscribe(queryId: string, request: SubscriptionRequest): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n request,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).then(response => {\n if (!response.ok) {\n console.warn(`SSE hub: subscribe POST for '${queryId}' returned ${response.status}, reconnecting`);\n this.reconnect();\n }\n }).catch(error => {\n console.error(`SSE hub: subscribe POST failed for '${queryId}', reconnecting`, error);\n this.reconnect();\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["ReconnectPolicy","HubConnectionKeepAlive","Globals","HubMessageType","QueryResult"],"mappings":";;;;;;;;MA8Ba,4BAA4B,CAAA;AAwBhB,IAAA,OAAA;AACA,IAAA,aAAA;AACA,IAAA,eAAA;AACA,IAAA,aAAA;AAEA,IAAA,iBAAA;AACA,IAAA,OAAA;AA7Bb,IAAA,YAAY;AACZ,IAAA,aAAa;IACb,aAAa,GAAG,KAAK;AACrB,IAAA,cAAc,GAAoC,IAAI,GAAG,EAAE;AAC3D,IAAA,qBAAqB,GAAoC,IAAI,GAAG,EAAE;IAClE,gBAAgB,GAAW,CAAC;IAC5B,eAAe,GAAa,EAAE;AAC9B,IAAA,oBAAoB;AACX,IAAA,UAAU;AAc3B,IAAA,WAAA,CACqB,OAAe,EACf,aAAqB,EACrB,eAAuB,EACvB,aAAqB,EACtC,mBAAA,GAA8B,KAAK,EAClB,iBAAA,GAA4B,KAAK,EACjC,OAAA,GAA4B,IAAIA,+BAAe,EAAE,EAAA;QANjD,IAAA,CAAA,OAAO,GAAP,OAAO;QACP,IAAA,CAAA,aAAa,GAAb,aAAa;QACb,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,aAAa,GAAb,aAAa;QAEb,IAAA,CAAA,iBAAiB,GAAjB,iBAAiB;QACjB,IAAA,CAAA,OAAO,GAAP,OAAO;QAWxB,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAIC,6CAAsB,CAAC,mBAAmB,EAAE,MAAK;AACnE,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE;gBACrD,OAAO,CAAC,IAAI,CAAC,CAAA,kCAAA,EAAqC,eAAe,CAAA,kBAAA,EAAqB,IAAI,CAAC,OAAO,CAAA,CAAA,CAAG,CAAC;gBACtG,IAAI,CAAC,SAAS,EAAE;YACpB;QACJ,CAAC,EAAE,eAAe,CAAC;IACvB;AAGA,IAAA,IAAI,UAAU,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI;IACnC;AAGA,IAAA,IAAI,eAAe,GAAA;QACf,OAAO,IAAI,CAAC,gBAAgB;IAChC;AAGA,IAAA,IAAI,cAAc,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,CAAC;QAC/C,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM;IACxF;AAGA,IAAA,SAAS,CAAC,OAAe,EAAE,OAA4B,EAAE,QAA2B,EAAA;AAChF,QAAA,MAAM,GAAG,GAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;QACrD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAErC,IAAI,CAAC,eAAe,EAAE;AAEtB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;QACxC;aAAO;YAEH,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAChD;IACJ;AAGA,IAAA,WAAW,CAAC,OAAe,EAAA;AACvB,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;AACnC,QAAA,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC;AAE1C,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QACjC;QAEA,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE;YAChC,IAAI,CAAC,KAAK,EAAE;QAChB;IACJ;IAGA,OAAO,GAAA;AACH,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE;AAC3B,QAAA,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE;AAClC,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACrB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;IAClC;IAEQ,eAAe,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,aAAa,GAAG,KAAK;QAC9B;AAEA,QAAA,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU,KAAK,WAAW,CAAC,MAAM,EAAE;YAC1E;QACJ;QAEA,IAAI,CAAC,eAAe,EAAE;IAC1B;IAEQ,KAAK,GAAA;AACT,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;AACzB,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACrB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;IAClC;IAEQ,eAAe,GAAA;AACnB,QAAA,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO;QACtB,IAAI,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,CAAC,EAAE;AAChC,YAAA,MAAM,KAAK,GAAG,CAAA,EAAGC,eAAO,CAAC,2BAA2B,CAAA,CAAA,EAAI,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;AAChG,YAAA,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,KAAK;QAClD;AAEA,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC;AAExC,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,MAAK;YAC5B,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,GAAG,CAAA,CAAA,CAAG,CAAC;AACvD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACpB,YAAA,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE;YAIvB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,YAAA,IAAI,CAAC,oBAAoB,GAAG,UAAU,CAAC,MAAK;gBACxC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;oBAC5C,OAAO,CAAC,IAAI,CAAC,CAAA,qCAAA,EAAwC,IAAI,CAAC,iBAAiB,CAAA,cAAA,EAAiB,GAAG,CAAA,CAAA,CAAG,CAAC;oBACnG,IAAI,CAAC,SAAS,EAAE;gBACpB;AACJ,YAAA,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC;AAC9B,QAAA,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,CAAC,KAAmB,KAAI;YAClD,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE;AAChC,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAc,CAAC;AAC5C,QAAA,CAAC;AAED,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,MAAK;YAC7B,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,OAAO,CAAC,IAAI,CAAC,8BAA8B,GAAG,CAAA,CAAA,CAAG,CAAC;YAClD,IAAI,CAAC,SAAS,EAAE;AACpB,QAAA,CAAC;IACL;IAEQ,SAAS,GAAA;AACb,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAG1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;QAI9B,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE;YAC9C,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAChD;AAEA,QAAA,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC;YAAE;AAEpC,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAK;AACvB,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE;gBACrD,IAAI,CAAC,eAAe,EAAE;YAC1B;AACJ,QAAA,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACpB;IAEQ,mBAAmB,GAAA;AACvB,QAAA,IAAI,IAAI,CAAC,oBAAoB,KAAK,SAAS,EAAE;AACzC,YAAA,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC;AACvC,YAAA,IAAI,CAAC,oBAAoB,GAAG,SAAS;QACzC;IACJ;AAEQ,IAAA,aAAa,CAAC,OAAe,EAAA;AACjC,QAAA,IAAI;YACA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe;AAEjD,YAAA,QAAQ,OAAO,CAAC,IAAI;gBAChB,KAAKC,qCAAc,CAAC,SAAS;AACzB,oBAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;oBAC7B;gBACJ,KAAKA,qCAAc,CAAC,WAAW;AAC3B,oBAAA,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;oBAC/B;gBACJ,KAAKA,qCAAc,CAAC,IAAI;oBAEpB;gBACJ,KAAKA,qCAAc,CAAC,YAAY;oBAC5B,OAAO,CAAC,IAAI,CAAC,CAAA,gBAAA,EAAmB,OAAO,CAAC,OAAO,CAAA,cAAA,CAAgB,CAAC;AAChE,oBAAA,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;oBAChC;gBACJ,KAAKA,qCAAc,CAAC,KAAK;AACrB,oBAAA,OAAO,CAAC,KAAK,CAAC,CAAA,gBAAA,EAAmB,OAAO,CAAC,OAAO,CAAA,QAAA,CAAU,EAAE,OAAO,CAAC,OAAO,CAAC;oBAC5E;;QAEZ;QAAE,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC;QAC1D;IACJ;AAEQ,IAAA,eAAe,CAAC,OAAmB,EAAA;AACvC,QAAA,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,OAAiB;QAC9C,OAAO,CAAC,GAAG,CAAC,CAAA,4BAAA,EAA+B,IAAI,CAAC,aAAa,CAAA,CAAA,CAAG,CAAC;QAGjE,IAAI,CAAC,mBAAmB,EAAE;QAG1B,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,qBAAqB,EAAE;YACrD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC;QAC5C;AACA,QAAA,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE;IACtC;AAEQ,IAAA,iBAAiB,CAAC,OAAmB,EAAA;QACzC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE;AAEtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;AACpD,QAAA,IAAI,CAAC,GAAG;YAAE;AAEV,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,OAA2B;AAClD,QAAA,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;IACxB;AAEQ,IAAA,kBAAkB,CAAC,OAAmB,EAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE;AAEtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;AACpD,QAAA,IAAI,CAAC,GAAG;YAAE;QAEV,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;QAC3C,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;QAClD,GAAG,CAAC,QAAQ,CAACC,uBAAW,CAAC,YAAY,EAAE,CAAC;IAC5C;IAEQ,aAAa,CAAC,OAAe,EAAE,OAA4B,EAAA;QAC/D,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAEzB,QAAA,MAAM,IAAI,GAAG;YACT,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,OAAO;YACP,OAAO;SACV;QAED,MAAM,aAAa,GAAGF,eAAO,CAAC,mBAAmB,IAAI,IAAI,EAAE;AAE3D,QAAA,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE;AACtB,YAAA,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,aAAa,EAAE;AACjE,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC7B,SAAA,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAG;AACf,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,CAAA,6BAAA,EAAgC,OAAO,CAAA,WAAA,EAAc,QAAQ,CAAC,MAAM,CAAA,cAAA,CAAgB,CAAC;gBAClG,IAAI,CAAC,SAAS,EAAE;YACpB;AACJ,QAAA,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAG;YACb,OAAO,CAAC,KAAK,CAAC,CAAA,oCAAA,EAAuC,OAAO,CAAA,eAAA,CAAiB,EAAE,KAAK,CAAC;YACrF,IAAI,CAAC,SAAS,EAAE;AACpB,QAAA,CAAC,CAAC;IACN;AAEQ,IAAA,eAAe,CAAC,OAAe,EAAA;QACnC,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAEzB,QAAA,MAAM,IAAI,GAAG;YACT,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,OAAO;SACV;QAED,MAAM,aAAa,GAAGA,eAAO,CAAC,mBAAmB,IAAI,IAAI,EAAE;AAE3D,QAAA,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE;AACxB,YAAA,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,GAAG,aAAa,EAAE;AACjE,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC7B,SAAA,CAAC,CAAC,KAAK,CAAC,KAAK,IAAG;YACb,OAAO,CAAC,KAAK,CAAC,CAAA,sCAAA,EAAyC,OAAO,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAC7E,QAAA,CAAC,CAAC;IACN;AACH;;;;"}
@@ -50,6 +50,7 @@ export declare class WebSocketHubConnection {
50
50
  private sendMessage;
51
51
  private handleMessage;
52
52
  private handleQueryResult;
53
+ private handleUnauthorized;
53
54
  private handlePong;
54
55
  }
55
56
  //# sourceMappingURL=WebSocketHubConnection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/WebSocketHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUtD,oBAAY,cAAc;IACtB,SAAS,IAAI;IACb,WAAW,IAAI;IACf,WAAW,IAAI;IACf,YAAY,IAAI;IAChB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,SAAS,IAAI;CAChB;AAKD,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAeD,qBAAa,sBAAsB;IAiB3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAnB5B,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;gBAUlB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACtC,cAAc,GAAE,MAAc,EACb,OAAO,GAAE,gBAAwC;IAatE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAG3B;IASD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAc3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBlC,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,UAAU;IA0ClB,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,UAAU;CAWrB"}
1
+ {"version":3,"file":"WebSocketHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/WebSocketHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUtD,oBAAY,cAAc;IACtB,SAAS,IAAI;IACb,WAAW,IAAI;IACf,WAAW,IAAI;IACf,YAAY,IAAI;IAChB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,SAAS,IAAI;CAChB;AAKD,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAeD,qBAAa,sBAAsB;IAiB3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAnB5B,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;gBAUlB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACtC,cAAc,GAAE,MAAc,EACb,OAAO,GAAE,gBAAwC;IAatE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAG3B;IASD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAc3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBlC,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,UAAU;IA0ClB,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,UAAU;CAWrB"}
@@ -3,6 +3,7 @@
3
3
  var Globals = require('../Globals.js');
4
4
  var HubConnectionKeepAlive = require('./HubConnectionKeepAlive.js');
5
5
  var ReconnectPolicy = require('./ReconnectPolicy.js');
6
+ var QueryResult = require('./QueryResult.js');
6
7
 
7
8
  exports.HubMessageType = void 0;
8
9
  (function (HubMessageType) {
@@ -158,6 +159,7 @@ class WebSocketHubConnection {
158
159
  break;
159
160
  case exports.HubMessageType.Unauthorized:
160
161
  console.warn(`Hub: query '${message.queryId}' unauthorized`);
162
+ this.handleUnauthorized(message);
161
163
  break;
162
164
  case exports.HubMessageType.Error:
163
165
  console.error(`Hub: query '${message.queryId}' error:`, message.payload);
@@ -177,6 +179,15 @@ class WebSocketHubConnection {
177
179
  const result = message.payload;
178
180
  sub.callback(result);
179
181
  }
182
+ handleUnauthorized(message) {
183
+ if (!message.queryId)
184
+ return;
185
+ const sub = this._subscriptions.get(message.queryId);
186
+ if (!sub)
187
+ return;
188
+ this._subscriptions.delete(message.queryId);
189
+ sub.callback(QueryResult.QueryResult.unauthorized());
190
+ }
180
191
  handlePong(message) {
181
192
  if (message.timestamp && this._lastPingSentTime) {
182
193
  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 integers by the Cratis JSON configuration.\n */\nexport enum HubMessageType {\n Subscribe = 0,\n Unsubscribe = 1,\n QueryResult = 2,\n Unauthorized = 3,\n Error = 4,\n Ping = 5,\n Pong = 6,\n Connected = 7,\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/**\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}\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 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 this._socket?.close();\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 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 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","ReconnectPolicy","HubConnectionKeepAlive","Globals"],"mappings":"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"}
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 integers by the Cratis JSON configuration.\n */\nexport enum HubMessageType {\n Subscribe = 0,\n Unsubscribe = 1,\n QueryResult = 2,\n Unauthorized = 3,\n Error = 4,\n Ping = 5,\n Pong = 6,\n Connected = 7,\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/**\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}\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 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 this._socket?.close();\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","ReconnectPolicy","HubConnectionKeepAlive","Globals","QueryResult"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=respects_threshold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"respects_threshold.d.ts","sourceRoot":"","sources":["../../../../../queries/for_HubConnectionKeepAlive/when_started_with_custom_idle_threshold/respects_threshold.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=after_release_in_development_mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"after_release_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_cancellation_before_timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_cancellation_before_timeout.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=without_cancellation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"without_cancellation.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=an_empty_cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"an_empty_cache.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/an_empty_cache.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_active_subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_active_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_pending_deferred_cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_pending_deferred_cleanup.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=the_only_subscriber_in_development_mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"the_only_subscriber_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=the_only_subscriber_outside_development_mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"the_only_subscriber_outside_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_active_subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_active_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_no_subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_no_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_pending_deferred_cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_pending_deferred_cleanup.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cancels_previous_timer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancels_previous_timer.d.ts","sourceRoot":"","sources":["../../../../../../queries/for_ReconnectPolicy/when_scheduling/and_rescheduled_before_first_fires/cancels_previous_timer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=notifies_subscriber_and_removes_subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifies_subscriber_and_removes_subscription.d.ts","sourceRoot":"","sources":["../../../../../queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=and_subscribe_post_fails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"and_subscribe_post_fails.d.ts","sourceRoot":"","sources":["../../../../../queries/for_ServerSentEventHubConnection/when_subscribing/and_subscribe_post_fails.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=notifies_subscriber_and_removes_subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifies_subscriber_and_removes_subscription.d.ts","sourceRoot":"","sources":["../../../../../queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts"],"names":[],"mappings":""}
@@ -13,7 +13,8 @@ export declare class IdentityProvider extends IIdentityProvider {
13
13
  static getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
14
14
  getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
15
15
  static refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
16
+ private static notSet;
16
17
  private static getCookie;
17
- private static clearCookie;
18
+ static clearIdentityCookie(): void;
18
19
  }
19
20
  //# sourceMappingURL=IdentityProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,qBAAa,gBAAiB,SAAQ,iBAAiB;IAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAsB;IAChD,MAAM,CAAC,mBAAmB,EAAE,cAAc,GAAG,SAAS,CAAC;IACvD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAM;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAM3B,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ7D,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQhD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;WAUzB,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAsB/G,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;WAIjG,OAAO,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IA0BlH,OAAO,CAAC,MAAM,CAAC,SAAS;IAYxB,OAAO,CAAC,MAAM,CAAC,WAAW;CAI7B"}
1
+ {"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,qBAAa,gBAAiB,SAAQ,iBAAiB;IAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAsB;IAChD,MAAM,CAAC,mBAAmB,EAAE,cAAc,GAAG,SAAS,CAAC;IACvD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAM;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAM3B,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ7D,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQhD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;WAUzB,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAsB/G,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;WAIjG,OAAO,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IA8BlH,OAAO,CAAC,MAAM,CAAC,MAAM;IAYrB,OAAO,CAAC,MAAM,CAAC,SAAS;IAiBxB,MAAM,CAAC,mBAAmB,IAAI,IAAI;CAIrC"}
@@ -43,7 +43,7 @@ class IdentityProvider extends IIdentityProvider {
43
43
  return IdentityProvider.getCurrent(type);
44
44
  }
45
45
  static async refresh(type) {
46
- IdentityProvider.clearCookie();
46
+ IdentityProvider.clearIdentityCookie();
47
47
  const origin = IdentityProvider.origin || Globals.origin || '';
48
48
  const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';
49
49
  const route = joinPaths(apiBasePath, '/.cratis/me');
@@ -52,6 +52,9 @@ class IdentityProvider extends IIdentityProvider {
52
52
  method: 'GET',
53
53
  headers: IdentityProvider.httpHeadersCallback?.() ?? {}
54
54
  });
55
+ if (!response.ok) {
56
+ return IdentityProvider.notSet(type);
57
+ }
55
58
  const result = await response.json();
56
59
  const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;
57
60
  return {
@@ -64,6 +67,17 @@ class IdentityProvider extends IIdentityProvider {
64
67
  refresh: () => IdentityProvider.refresh(type)
65
68
  };
66
69
  }
70
+ static notSet(type) {
71
+ return {
72
+ id: '',
73
+ name: '',
74
+ roles: [],
75
+ details: {},
76
+ isSet: false,
77
+ isInRole: () => false,
78
+ refresh: () => IdentityProvider.refresh(type)
79
+ };
80
+ }
67
81
  static getCookie() {
68
82
  if (typeof document === 'undefined')
69
83
  return [];
@@ -76,7 +90,7 @@ class IdentityProvider extends IIdentityProvider {
76
90
  }
77
91
  return [];
78
92
  }
79
- static clearCookie() {
93
+ static clearIdentityCookie() {
80
94
  if (typeof document === 'undefined')
81
95
  return;
82
96
  document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
@@ -1 +1 @@
1
- {"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.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 { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n const result = await response.json() as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n private static clearCookie() {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.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 { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearIdentityCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n if (!response.ok) {\n return IdentityProvider.notSet(type);\n }\n\n const result = await response.json() as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static notSet<TDetails extends object = object>(type?: Constructor<TDetails>): IIdentity<TDetails> {\n return {\n id: '',\n name: '',\n roles: [],\n details: {} as TDetails,\n isSet: false,\n isInRole: () => false,\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n /**\n * Clears the identity cookie used by Arc to cache the current identity.\n * Call this when the user logs out to ensure subsequent requests and WebSocket\n * connections do not carry stale credentials.\n */\n static clearIdentityCookie(): void {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_unauthorized_response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_unauthorized_response.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { IdentityProvider } from '../../IdentityProvider';
2
+ import { an_identity_provider } from '../given/an_identity_provider';
3
+ import { given } from '../../../given';
4
+ describe('when refreshing with unauthorized response', given(an_identity_provider, context => {
5
+ let result;
6
+ beforeEach(async () => {
7
+ context.fetchStub.resolves({
8
+ ok: false,
9
+ status: 401,
10
+ });
11
+ result = await IdentityProvider.refresh();
12
+ });
13
+ it('should return identity with isSet false', () => result.isSet.should.be.false);
14
+ it('should return empty identity id', () => result.id.should.equal(''));
15
+ it('should return empty identity name', () => result.name.should.equal(''));
16
+ it('should return empty roles', () => result.roles.should.be.empty);
17
+ it('should provide a refresh method', () => result.refresh.should.be.a('function'));
18
+ }));
19
+ //# sourceMappingURL=with_unauthorized_response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_unauthorized_response.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,QAAQ,CAAC,4CAA4C,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IACzF,IAAI,MAAiB,CAAC;IAEtB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC;YACvB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;SACF,CAAC,CAAC;QAEf,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAClF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACpE,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AACxF,CAAC,CAAC,CAAC,CAAC"}
@@ -3,7 +3,8 @@ export declare class HubConnectionKeepAlive {
3
3
  private readonly _onIdle;
4
4
  private _lastActivityTime;
5
5
  private _timer?;
6
- constructor(_intervalMs: number, _onIdle: () => void);
6
+ private readonly _idleThresholdMs;
7
+ constructor(_intervalMs: number, _onIdle: () => void, idleThresholdMs?: number);
7
8
  start(): void;
8
9
  stop(): void;
9
10
  recordActivity(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"HubConnectionKeepAlive.d.ts","sourceRoot":"","sources":["../../../queries/HubConnectionKeepAlive.ts"],"names":[],"mappings":"AAeA,qBAAa,sBAAsB;IAW3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX5B,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,MAAM,CAAC,CAAiC;gBAS3B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,IAAI;IAMxC,KAAK,IAAI,IAAI;IAab,IAAI,IAAI,IAAI;IAWZ,cAAc,IAAI,IAAI;CAGzB"}
1
+ {"version":3,"file":"HubConnectionKeepAlive.d.ts","sourceRoot":"","sources":["../../../queries/HubConnectionKeepAlive.ts"],"names":[],"mappings":"AAqBA,qBAAa,sBAAsB;IAgB3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhB5B,OAAO,CAAC,iBAAiB,CAAc;IACvC,OAAO,CAAC,MAAM,CAAC,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAarB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,IAAI,EACpC,eAAe,CAAC,EAAE,MAAM;IAQ5B,KAAK,IAAI,IAAI;IAab,IAAI,IAAI,IAAI;IAWZ,cAAc,IAAI,IAAI;CAGzB"}
@@ -3,15 +3,17 @@ class HubConnectionKeepAlive {
3
3
  _onIdle;
4
4
  _lastActivityTime = Date.now();
5
5
  _timer;
6
- constructor(_intervalMs, _onIdle) {
6
+ _idleThresholdMs;
7
+ constructor(_intervalMs, _onIdle, idleThresholdMs) {
7
8
  this._intervalMs = _intervalMs;
8
9
  this._onIdle = _onIdle;
10
+ this._idleThresholdMs = idleThresholdMs ?? _intervalMs;
9
11
  }
10
12
  start() {
11
13
  this.stop();
12
14
  this._lastActivityTime = Date.now();
13
15
  this._timer = setInterval(() => {
14
- if (Date.now() - this._lastActivityTime >= this._intervalMs) {
16
+ if (Date.now() - this._lastActivityTime >= this._idleThresholdMs) {
15
17
  this._onIdle();
16
18
  }
17
19
  }, this._intervalMs);
@@ -1 +1 @@
1
- {"version":3,"file":"HubConnectionKeepAlive.js","sources":["../../../queries/HubConnectionKeepAlive.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\n/**\n * Manages keep-alive behavior for hub connections (both WebSocket and Server-Sent Events).\n *\n * Records connection activity (any message received or sent). An interval fires every\n * {@link intervalMs} milliseconds; if no activity has been recorded since the last tick the\n * provided {@link onIdle} callback is invoked the caller decides whether to send a ping,\n * trigger a reconnect, or take some other action.\n *\n * Both {@link WebSocketHubConnection} and {@link ServerSentEventHubConnection} own one instance\n * of this class so the keep-alive logic is written once and behaves identically for both\n * transports.\n */\nexport class HubConnectionKeepAlive {\n private _lastActivityTime = Date.now();\n private _timer?: ReturnType<typeof setInterval>;\n\n /**\n * Initializes a new instance of {@link HubConnectionKeepAlive}.\n * @param {number} intervalMs How often (in milliseconds) to check for idle connections.\n * @param {() => void} onIdle Callback invoked when the interval fires and no activity has\n * been recorded in the last {@link intervalMs} milliseconds.\n */\n constructor(\n private readonly _intervalMs: number,\n private readonly _onIdle: () => void,\n ) {}\n\n /**\n * Start the keep-alive timer. Safe to call multiple times — a running timer is stopped first.\n */\n start(): void {\n this.stop();\n this._lastActivityTime = Date.now();\n this._timer = setInterval(() => {\n if (Date.now() - this._lastActivityTime >= this._intervalMs) {\n this._onIdle();\n }\n }, this._intervalMs);\n }\n\n /**\n * Stop the keep-alive timer.\n */\n stop(): void {\n if (this._timer !== undefined) {\n clearInterval(this._timer);\n this._timer = undefined;\n }\n }\n\n /**\n * Record that the connection has been active (message sent or received).\n * Resets the idle timer so that a keep-alive is not sent while data is already flowing.\n */\n recordActivity(): void {\n this._lastActivityTime = Date.now();\n }\n}\n"],"names":[],"mappings":"MAea,sBAAsB,CAAA;AAWV,IAAA,WAAA;AACA,IAAA,OAAA;AAXb,IAAA,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;AAC9B,IAAA,MAAM;IAQd,WAAA,CACqB,WAAmB,EACnB,OAAmB,EAAA;QADnB,IAAA,CAAA,WAAW,GAAX,WAAW;QACX,IAAA,CAAA,OAAO,GAAP,OAAO;IACzB;IAKH,KAAK,GAAA;QACD,IAAI,CAAC,IAAI,EAAE;AACX,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;AACnC,QAAA,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,MAAK;AAC3B,YAAA,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,WAAW,EAAE;gBACzD,IAAI,CAAC,OAAO,EAAE;YAClB;AACJ,QAAA,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC;IACxB;IAKA,IAAI,GAAA;AACA,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE;AAC3B,YAAA,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS;QAC3B;IACJ;IAMA,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;IACvC;AACH;;;;"}
1
+ {"version":3,"file":"HubConnectionKeepAlive.js","sources":["../../../queries/HubConnectionKeepAlive.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\n/**\n * Manages keep-alive behavior for hub connections (both WebSocket and Server-Sent Events).\n *\n * Records connection activity (any message received or sent). An interval fires every\n * {@link intervalMs} milliseconds; if no activity has been recorded since the last\n * {@link idleThresholdMs} milliseconds the provided {@link onIdle} callback is invoked —\n * the caller decides whether to send a ping, trigger a reconnect, or take some other action.\n *\n * The idle threshold defaults to the check interval but can be set higher to tolerate\n * network latency between the server's keep-alive ping and the client's idle check.\n * For SSE connections, where the idle callback triggers a reconnect, a tolerance of\n * 1.5× the server's keep-alive interval prevents spurious reconnects caused by the\n * client's timer firing just before the server's ping arrives.\n *\n * Both {@link WebSocketHubConnection} and {@link ServerSentEventHubConnection} own one instance\n * of this class so the keep-alive logic is written once and behaves identically for both\n * transports.\n */\nexport class HubConnectionKeepAlive {\n private _lastActivityTime = Date.now();\n private _timer?: ReturnType<typeof setInterval>;\n private readonly _idleThresholdMs: number;\n\n /**\n * Initializes a new instance of {@link HubConnectionKeepAlive}.\n * @param {number} intervalMs How often (in milliseconds) to check for idle connections.\n * @param {() => void} onIdle Callback invoked when the interval fires and no activity has\n * been recorded within the idle threshold.\n * @param {number} idleThresholdMs Optional. How long (in milliseconds) without activity\n * before the connection is considered idle. Defaults to {@link intervalMs}. Set this\n * higher than {@link intervalMs} when the peer sends keep-alive messages on a similar\n * cadence to account for network latency and timer jitter.\n */\n constructor(\n private readonly _intervalMs: number,\n private readonly _onIdle: () => void,\n idleThresholdMs?: number,\n ) {\n this._idleThresholdMs = idleThresholdMs ?? _intervalMs;\n }\n\n /**\n * Start the keep-alive timer. Safe to call multiple times — a running timer is stopped first.\n */\n start(): void {\n this.stop();\n this._lastActivityTime = Date.now();\n this._timer = setInterval(() => {\n if (Date.now() - this._lastActivityTime >= this._idleThresholdMs) {\n this._onIdle();\n }\n }, this._intervalMs);\n }\n\n /**\n * Stop the keep-alive timer.\n */\n stop(): void {\n if (this._timer !== undefined) {\n clearInterval(this._timer);\n this._timer = undefined;\n }\n }\n\n /**\n * Record that the connection has been active (message sent or received).\n * Resets the idle timer so that a keep-alive is not sent while data is already flowing.\n */\n recordActivity(): void {\n this._lastActivityTime = Date.now();\n }\n}\n"],"names":[],"mappings":"MAqBa,sBAAsB,CAAA;AAgBV,IAAA,WAAA;AACA,IAAA,OAAA;AAhBb,IAAA,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;AAC9B,IAAA,MAAM;AACG,IAAA,gBAAgB;AAYjC,IAAA,WAAA,CACqB,WAAmB,EACnB,OAAmB,EACpC,eAAwB,EAAA;QAFP,IAAA,CAAA,WAAW,GAAX,WAAW;QACX,IAAA,CAAA,OAAO,GAAP,OAAO;AAGxB,QAAA,IAAI,CAAC,gBAAgB,GAAG,eAAe,IAAI,WAAW;IAC1D;IAKA,KAAK,GAAA;QACD,IAAI,CAAC,IAAI,EAAE;AACX,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;AACnC,QAAA,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,MAAK;AAC3B,YAAA,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,gBAAgB,EAAE;gBAC9D,IAAI,CAAC,OAAO,EAAE;YAClB;AACJ,QAAA,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC;IACxB;IAKA,IAAI,GAAA;AACA,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE;AAC3B,YAAA,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS;QAC3B;IACJ;IAMA,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;IACvC;AACH;;;;"}