@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
@@ -8,9 +8,13 @@ export interface QueryCacheEntry<TDataType> {
8
8
  readonly listeners: Set<QueryCacheListener<TDataType>>;
9
9
  teardown?: () => void;
10
10
  subscribed: boolean;
11
+ pendingCleanup?: ReturnType<typeof setTimeout>;
11
12
  }
12
13
  export declare class QueryInstanceCache {
13
14
  private readonly _entries;
15
+ private readonly _development;
16
+ private _pendingDispose?;
17
+ constructor(development?: boolean);
14
18
  buildKey(queryTypeName: string, args?: object): QueryCacheKey;
15
19
  getOrCreate<TInstance>(key: QueryCacheKey, factory: () => TInstance): {
16
20
  instance: TInstance;
@@ -25,5 +29,9 @@ export declare class QueryInstanceCache {
25
29
  isSubscribed(key: QueryCacheKey): boolean;
26
30
  release(key: QueryCacheKey): void;
27
31
  has(key: QueryCacheKey): boolean;
32
+ teardownAllSubscriptions(): void;
33
+ dispose(): void;
34
+ deferDispose(): void;
35
+ cancelPendingDispose(): void;
28
36
  }
29
37
  //# sourceMappingURL=QueryInstanceCache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueryInstanceCache.d.ts","sourceRoot":"","sources":["../../../queries/QueryInstanceCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAK9D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAKnC,MAAM,MAAM,kBAAkB,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AAM9F,MAAM,WAAW,eAAe,CAAC,SAAS;IAItC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAK3B,UAAU,CAAC,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAK7C,eAAe,EAAE,MAAM,CAAC;IAKxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAMvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAKtB,UAAU,EAAE,OAAO,CAAC;CACvB;AAUD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsD;IAQ/E,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa;IAuB7D,WAAW,CAAC,SAAS,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,SAAS,GACzB;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;IAuB1C,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAcjC,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,SAAS;IAUzF,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI;IAkB3F,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI;IAczF,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI;IAc5F,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAc3D,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;IASzC,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IA4BjC,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;CAGnC"}
1
+ {"version":3,"file":"QueryInstanceCache.d.ts","sourceRoot":"","sources":["../../../queries/QueryInstanceCache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAK9D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAKnC,MAAM,MAAM,kBAAkB,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AAM9F,MAAM,WAAW,eAAe,CAAC,SAAS;IAItC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAK3B,UAAU,CAAC,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAK7C,eAAe,EAAE,MAAM,CAAC;IAKxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAMvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAKtB,UAAU,EAAE,OAAO,CAAC;IAOpB,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CAClD;AAUD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsD;IAC/E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,eAAe,CAAC,CAAgC;gBAO5C,WAAW,GAAE,OAAe;IAUxC,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa;IAuB7D,WAAW,CAAC,SAAS,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,SAAS,GACzB;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;IAyB1C,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAmBjC,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,oBAAoB,CAAC,SAAS,CAAC,GAAG,SAAS;IAUzF,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI;IAkB3F,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI;IAczF,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,SAAS,CAAC,GAAG,IAAI;IAc5F,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAc3D,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;IAczC,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IA2CjC,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO;IAchC,wBAAwB,IAAI,IAAI;IAkBhC,OAAO,IAAI,IAAI;IAwBf,YAAY,IAAI,IAAI;IAiBpB,oBAAoB,IAAI,IAAI;CAM/B"}
@@ -1,5 +1,10 @@
1
1
  class QueryInstanceCache {
2
2
  _entries = new Map();
3
+ _development;
4
+ _pendingDispose;
5
+ constructor(development = false) {
6
+ this._development = development;
7
+ }
3
8
  buildKey(queryTypeName, args) {
4
9
  if (!args || Object.keys(args).length === 0) {
5
10
  return `${queryTypeName}::`;
@@ -30,6 +35,10 @@ class QueryInstanceCache {
30
35
  acquire(key) {
31
36
  const entry = this._entries.get(key);
32
37
  if (entry) {
38
+ if (entry.pendingCleanup !== undefined) {
39
+ clearTimeout(entry.pendingCleanup);
40
+ entry.pendingCleanup = undefined;
41
+ }
33
42
  entry.subscriberCount++;
34
43
  }
35
44
  }
@@ -72,21 +81,73 @@ class QueryInstanceCache {
72
81
  if (entry) {
73
82
  entry.subscriberCount--;
74
83
  if (entry.subscriberCount <= 0) {
75
- entry.subscribed = false;
76
- entry.teardown?.();
77
- entry.teardown = undefined;
78
- setTimeout(() => {
79
- const current = this._entries.get(key);
80
- if (current && current.subscriberCount <= 0) {
81
- this._entries.delete(key);
82
- }
83
- }, 0);
84
+ if (this._development) {
85
+ entry.pendingCleanup = setTimeout(() => {
86
+ const current = this._entries.get(key);
87
+ if (current && current.subscriberCount <= 0) {
88
+ current.subscribed = false;
89
+ current.teardown?.();
90
+ current.teardown = undefined;
91
+ current.pendingCleanup = undefined;
92
+ this._entries.delete(key);
93
+ }
94
+ }, 0);
95
+ }
96
+ else {
97
+ entry.subscribed = false;
98
+ entry.teardown?.();
99
+ entry.teardown = undefined;
100
+ setTimeout(() => {
101
+ const current = this._entries.get(key);
102
+ if (current && current.subscriberCount <= 0) {
103
+ this._entries.delete(key);
104
+ }
105
+ }, 0);
106
+ }
84
107
  }
85
108
  }
86
109
  }
87
110
  has(key) {
88
111
  return this._entries.has(key);
89
112
  }
113
+ teardownAllSubscriptions() {
114
+ for (const [, entry] of this._entries) {
115
+ if (entry.pendingCleanup !== undefined) {
116
+ clearTimeout(entry.pendingCleanup);
117
+ entry.pendingCleanup = undefined;
118
+ }
119
+ entry.subscribed = false;
120
+ entry.teardown?.();
121
+ entry.teardown = undefined;
122
+ }
123
+ }
124
+ dispose() {
125
+ for (const [, entry] of this._entries) {
126
+ if (entry.pendingCleanup !== undefined) {
127
+ clearTimeout(entry.pendingCleanup);
128
+ entry.pendingCleanup = undefined;
129
+ }
130
+ entry.subscribed = false;
131
+ entry.teardown?.();
132
+ entry.teardown = undefined;
133
+ }
134
+ this._entries.clear();
135
+ }
136
+ deferDispose() {
137
+ if (this._pendingDispose !== undefined) {
138
+ clearTimeout(this._pendingDispose);
139
+ }
140
+ this._pendingDispose = setTimeout(() => {
141
+ this._pendingDispose = undefined;
142
+ this.dispose();
143
+ }, 0);
144
+ }
145
+ cancelPendingDispose() {
146
+ if (this._pendingDispose !== undefined) {
147
+ clearTimeout(this._pendingDispose);
148
+ this._pendingDispose = undefined;
149
+ }
150
+ }
90
151
  }
91
152
 
92
153
  export { QueryInstanceCache };
@@ -1 +1 @@
1
- {"version":3,"file":"QueryInstanceCache.js","sources":["../../../queries/QueryInstanceCache.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 { QueryResultWithState } from './QueryResultWithState';\n\n/**\n * Represents a key that uniquely identifies a query instance in the cache, based on the query type name and its serialized arguments.\n */\nexport type QueryCacheKey = string;\n\n/**\n * Callback invoked when the cached result for an entry changes.\n */\nexport type QueryCacheListener<TDataType> = (result: QueryResultWithState<TDataType>) => void;\n\n/**\n * Represents a single entry in the {@link QueryInstanceCache}.\n * @template TDataType The type of data returned by the query.\n */\nexport interface QueryCacheEntry<TDataType> {\n /**\n * The cached query instance.\n */\n readonly instance: unknown;\n\n /**\n * The last result received from the query, if any.\n */\n lastResult?: QueryResultWithState<TDataType>;\n\n /**\n * The number of active subscribers holding a reference to this entry.\n */\n subscriberCount: number;\n\n /**\n * Set of listener callbacks that are notified when {@link lastResult} changes.\n */\n readonly listeners: Set<QueryCacheListener<TDataType>>;\n\n /**\n * Cleanup function returned by the first subscriber that starts the query connection.\n * Called when the last subscriber releases the entry.\n */\n teardown?: () => void;\n\n /**\n * Whether an active subscription has been established for this entry.\n */\n subscribed: boolean;\n}\n\n/**\n * Provides a cache for query instances, keyed by query type and serialized arguments.\n *\n * Two callers requesting the same query type with identical arguments receive the same\n * cached instance and immediately see the last known result — without an additional\n * round trip to the server. When the last subscriber releases its reference the entry\n * is evicted.\n */\nexport class QueryInstanceCache {\n private readonly _entries = new Map<QueryCacheKey, QueryCacheEntry<unknown>>();\n\n /**\n * Builds the cache key for a query.\n * @param queryTypeName The name of the query constructor (i.e. `constructor.name`).\n * @param args Optional arguments supplied to the query.\n * @returns A stable string key.\n */\n buildKey(queryTypeName: string, args?: object): QueryCacheKey {\n if (!args || Object.keys(args).length === 0) {\n return `${queryTypeName}::`;\n }\n\n const sorted = Object.keys(args)\n .sort()\n .reduce<Record<string, unknown>>((accumulator, key) => {\n accumulator[key] = (args as Record<string, unknown>)[key];\n return accumulator;\n }, {});\n\n return `${queryTypeName}::${JSON.stringify(sorted)}`;\n }\n\n /**\n * Returns a cached instance for the given key, or creates a new one using the provided factory.\n * The subscriber count of the entry is incremented.\n * @template TInstance The type of the query instance.\n * @param key The cache key produced by {@link buildKey}.\n * @param factory A zero-argument factory that creates a fresh query instance when one is not yet cached.\n * @returns The cached (or newly created) instance and whether it was newly created.\n */\n getOrCreate<TInstance>(\n key: QueryCacheKey,\n factory: () => TInstance\n ): { instance: TInstance; isNew: boolean } {\n if (!this._entries.has(key)) {\n const entry: QueryCacheEntry<unknown> = {\n instance: factory(),\n lastResult: undefined,\n subscriberCount: 0,\n listeners: new Set(),\n subscribed: false,\n };\n\n this._entries.set(key, entry);\n return { instance: entry.instance as TInstance, isNew: true };\n }\n\n const entry = this._entries.get(key)!;\n return { instance: entry.instance as TInstance, isNew: false };\n }\n\n /**\n * Increments the active subscriber count for the given key.\n * Call from `useEffect` setup to pair with {@link release} in the cleanup.\n * @param key The cache key produced by {@link buildKey}.\n */\n acquire(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.subscriberCount++;\n }\n }\n\n /**\n * Returns the last cached result for the given key, or `undefined` if no result has been stored yet.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @returns The last {@link QueryResultWithState}, or `undefined`.\n */\n getLastResult<TDataType>(key: QueryCacheKey): QueryResultWithState<TDataType> | undefined {\n return this._entries.get(key)?.lastResult as QueryResultWithState<TDataType> | undefined;\n }\n\n /**\n * Stores the most recent result for the given key and notifies all registered listeners.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param result The result to store.\n */\n setLastResult<TDataType>(key: QueryCacheKey, result: QueryResultWithState<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.lastResult = result as QueryResultWithState<unknown>;\n\n for (const listener of entry.listeners) {\n (listener as QueryCacheListener<TDataType>)(result);\n }\n }\n }\n\n /**\n * Registers a listener that is invoked whenever the cached result for the given key changes.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to register.\n */\n addListener<TDataType>(key: QueryCacheKey, listener: QueryCacheListener<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.add(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Removes a previously registered listener.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to remove.\n */\n removeListener<TDataType>(key: QueryCacheKey, listener: QueryCacheListener<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.delete(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Stores a teardown function for the given key and marks the entry as subscribed.\n * Called automatically when the last subscriber releases the entry.\n * @param key The cache key produced by {@link buildKey}.\n * @param teardown Cleanup function that disconnects the underlying query subscription.\n */\n setTeardown(key: QueryCacheKey, teardown: () => void): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.teardown = teardown;\n entry.subscribed = true;\n }\n }\n\n /**\n * Returns whether an active subscription exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if a subscription has been established; `false` otherwise.\n */\n isSubscribed(key: QueryCacheKey): boolean {\n return this._entries.get(key)?.subscribed ?? false;\n }\n\n /**\n * Decrements the subscriber count for the given key. When the count reaches zero the teardown\n * function is called (if set) and the entry is evicted.\n * @param key The cache key produced by {@link buildKey}.\n */\n release(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.subscriberCount--;\n\n if (entry.subscriberCount <= 0) {\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n\n // Defer deletion so React Strict Mode re-mounts can re-acquire the entry.\n setTimeout(() => {\n const current = this._entries.get(key);\n\n if (current && current.subscriberCount <= 0) {\n this._entries.delete(key);\n }\n }, 0);\n }\n }\n }\n\n /**\n * Returns whether an entry exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if an entry exists; `false` otherwise.\n */\n has(key: QueryCacheKey): boolean {\n return this._entries.has(key);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryInstanceCache.js","sources":["../../../queries/QueryInstanceCache.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 { QueryResultWithState } from './QueryResultWithState';\n\n/**\n * Represents a key that uniquely identifies a query instance in the cache, based on the query type name and its serialized arguments.\n */\nexport type QueryCacheKey = string;\n\n/**\n * Callback invoked when the cached result for an entry changes.\n */\nexport type QueryCacheListener<TDataType> = (result: QueryResultWithState<TDataType>) => void;\n\n/**\n * Represents a single entry in the {@link QueryInstanceCache}.\n * @template TDataType The type of data returned by the query.\n */\nexport interface QueryCacheEntry<TDataType> {\n /**\n * The cached query instance.\n */\n readonly instance: unknown;\n\n /**\n * The last result received from the query, if any.\n */\n lastResult?: QueryResultWithState<TDataType>;\n\n /**\n * The number of active subscribers holding a reference to this entry.\n */\n subscriberCount: number;\n\n /**\n * Set of listener callbacks that are notified when {@link lastResult} changes.\n */\n readonly listeners: Set<QueryCacheListener<TDataType>>;\n\n /**\n * Cleanup function returned by the first subscriber that starts the query connection.\n * Called when the last subscriber releases the entry.\n */\n teardown?: () => void;\n\n /**\n * Whether an active subscription has been established for this entry.\n */\n subscribed: boolean;\n\n /**\n * Timer handle for deferred cleanup when running in development mode.\n * Allows React StrictMode re-mounts to cancel the pending teardown\n * so the connection is reused instead of torn down and recreated.\n */\n pendingCleanup?: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Provides a cache for query instances, keyed by query type and serialized arguments.\n *\n * Two callers requesting the same query type with identical arguments receive the same\n * cached instance and immediately see the last known result — without an additional\n * round trip to the server. When the last subscriber releases its reference the entry\n * is evicted.\n */\nexport class QueryInstanceCache {\n private readonly _entries = new Map<QueryCacheKey, QueryCacheEntry<unknown>>();\n private readonly _development: boolean;\n private _pendingDispose?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link QueryInstanceCache}.\n * @param development When true, teardown is deferred on release so React StrictMode\n * re-mounts can re-acquire the entry without an unnecessary disconnect/reconnect cycle.\n */\n constructor(development: boolean = false) {\n this._development = development;\n }\n\n /**\n * Builds the cache key for a query.\n * @param queryTypeName The name of the query constructor (i.e. `constructor.name`).\n * @param args Optional arguments supplied to the query.\n * @returns A stable string key.\n */\n buildKey(queryTypeName: string, args?: object): QueryCacheKey {\n if (!args || Object.keys(args).length === 0) {\n return `${queryTypeName}::`;\n }\n\n const sorted = Object.keys(args)\n .sort()\n .reduce<Record<string, unknown>>((accumulator, key) => {\n accumulator[key] = (args as Record<string, unknown>)[key];\n return accumulator;\n }, {});\n\n return `${queryTypeName}::${JSON.stringify(sorted)}`;\n }\n\n /**\n * Returns a cached instance for the given key, or creates a new one using the provided factory.\n * The subscriber count of the entry is incremented.\n * @template TInstance The type of the query instance.\n * @param key The cache key produced by {@link buildKey}.\n * @param factory A zero-argument factory that creates a fresh query instance when one is not yet cached.\n * @returns The cached (or newly created) instance and whether it was newly created.\n */\n getOrCreate<TInstance>(\n key: QueryCacheKey,\n factory: () => TInstance\n ): { instance: TInstance; isNew: boolean } {\n if (!this._entries.has(key)) {\n const entry: QueryCacheEntry<unknown> = {\n instance: factory(),\n lastResult: undefined,\n subscriberCount: 0,\n listeners: new Set(),\n subscribed: false,\n };\n\n this._entries.set(key, entry);\n return { instance: entry.instance as TInstance, isNew: true };\n }\n\n const entry = this._entries.get(key)!;\n return { instance: entry.instance as TInstance, isNew: false };\n }\n\n /**\n * Increments the active subscriber count for the given key.\n * If a deferred cleanup was pending (from a recent {@link release} in development mode),\n * it is cancelled so the existing subscription is reused.\n * Call from `useEffect` setup to pair with {@link release} in the cleanup.\n * @param key The cache key produced by {@link buildKey}.\n */\n acquire(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscriberCount++;\n }\n }\n\n /**\n * Returns the last cached result for the given key, or `undefined` if no result has been stored yet.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @returns The last {@link QueryResultWithState}, or `undefined`.\n */\n getLastResult<TDataType>(key: QueryCacheKey): QueryResultWithState<TDataType> | undefined {\n return this._entries.get(key)?.lastResult as QueryResultWithState<TDataType> | undefined;\n }\n\n /**\n * Stores the most recent result for the given key and notifies all registered listeners.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param result The result to store.\n */\n setLastResult<TDataType>(key: QueryCacheKey, result: QueryResultWithState<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.lastResult = result as QueryResultWithState<unknown>;\n\n for (const listener of entry.listeners) {\n (listener as QueryCacheListener<TDataType>)(result);\n }\n }\n }\n\n /**\n * Registers a listener that is invoked whenever the cached result for the given key changes.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to register.\n */\n addListener<TDataType>(key: QueryCacheKey, listener: QueryCacheListener<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.add(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Removes a previously registered listener.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to remove.\n */\n removeListener<TDataType>(key: QueryCacheKey, listener: QueryCacheListener<TDataType>): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.delete(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Stores a teardown function for the given key and marks the entry as subscribed.\n * Called automatically when the last subscriber releases the entry.\n * @param key The cache key produced by {@link buildKey}.\n * @param teardown Cleanup function that disconnects the underlying query subscription.\n */\n setTeardown(key: QueryCacheKey, teardown: () => void): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.teardown = teardown;\n entry.subscribed = true;\n }\n }\n\n /**\n * Returns whether an active subscription exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if a subscription has been established; `false` otherwise.\n */\n isSubscribed(key: QueryCacheKey): boolean {\n return this._entries.get(key)?.subscribed ?? false;\n }\n\n /**\n * Decrements the subscriber count for the given key. When the count reaches zero the teardown\n * function is called (if set) and the entry is evicted.\n *\n * In development mode, both teardown and eviction are deferred by one microtask so that\n * React StrictMode re-mounts can re-acquire the entry and cancel the cleanup. This prevents\n * an unnecessary disconnect/reconnect cycle during the synthetic unmount/remount that\n * StrictMode performs in development builds.\n * @param key The cache key produced by {@link buildKey}.\n */\n release(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.subscriberCount--;\n\n if (entry.subscriberCount <= 0) {\n if (this._development) {\n // Defer both teardown and deletion so StrictMode re-mounts can cancel.\n entry.pendingCleanup = setTimeout(() => {\n const current = this._entries.get(key);\n\n if (current && current.subscriberCount <= 0) {\n current.subscribed = false;\n current.teardown?.();\n current.teardown = undefined;\n current.pendingCleanup = undefined;\n this._entries.delete(key);\n }\n }, 0);\n } else {\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n\n // Defer deletion so React Strict Mode re-mounts can re-acquire the entry.\n setTimeout(() => {\n const current = this._entries.get(key);\n\n if (current && current.subscriberCount <= 0) {\n this._entries.delete(key);\n }\n }, 0);\n }\n }\n }\n }\n\n /**\n * Returns whether an entry exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if an entry exists; `false` otherwise.\n */\n has(key: QueryCacheKey): boolean {\n return this._entries.has(key);\n }\n\n /**\n * Tears down all active subscriptions and marks every entry as not subscribed,\n * but preserves entries, subscriber counts, and listeners. This allows\n * hooks whose effects re-run afterward to detect that the entry is no longer\n * subscribed and re-establish a fresh connection.\n *\n * Use this when the underlying transport must be replaced (e.g. after an\n * authentication change that requires new WebSocket connections with updated\n * credentials).\n */\n teardownAllSubscriptions(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n }\n\n /**\n * Immediately tears down all subscriptions, cancels any pending deferred cleanups,\n * and evicts all entries. Call when the owning component (e.g. the {@link Arc} provider)\n * unmounts permanently so that all query connections are closed synchronously.\n */\n dispose(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n\n this._entries.clear();\n }\n\n /**\n * Schedules a deferred {@link dispose} using {@code setTimeout(0)}.\n *\n * This allows React StrictMode re-mounts to call {@link cancelPendingDispose}\n * before the dispose fires, avoiding the destruction of cache entries that child\n * effects are about to re-acquire.\n *\n * If a deferred dispose is already pending, it is replaced.\n */\n deferDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n }\n\n this._pendingDispose = setTimeout(() => {\n this._pendingDispose = undefined;\n this.dispose();\n }, 0);\n }\n\n /**\n * Cancels a pending deferred dispose scheduled by {@link deferDispose}.\n *\n * Call from the {@code useEffect} setup phase so that a StrictMode re-mount\n * prevents the synthetic unmount's deferred dispose from firing.\n */\n cancelPendingDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n this._pendingDispose = undefined;\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ type ServerPagingInfo = {
27
27
  };
28
28
  export declare class QueryResult<TDataType = object> implements IQueryResult<TDataType> {
29
29
  static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType>;
30
+ static unauthorized<TDataType>(): QueryResult<TDataType>;
30
31
  static noSuccess: QueryResult;
31
32
  constructor(result: ServerQueryResult, instanceType: Constructor, enumerable: boolean);
32
33
  readonly data: TDataType;
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../../../queries/QueryResult.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,KAAK,iBAAiB,GAAG;IAErB,IAAI,EAAE,GAAG,CAAC;IAEV,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;IAC5C,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC;CAC5B,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB,CAAA;AAMD,qBAAa,WAAW,CAAC,SAAS,GAAG,MAAM,CAAE,YAAW,YAAY,CAAC,SAAS,CAAC;IAE3E,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;IAoBxE,MAAM,CAAC,SAAS,EAAE,WAAW,CAeX;gBAQN,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO;IAiCrF,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAGzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAG5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAG5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAG/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAG1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAGhC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IAG/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAGrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAKrC,IAAI,OAAO,IAAI,OAAO,CAQrB;CACJ"}
1
+ {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../../../queries/QueryResult.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,KAAK,iBAAiB,GAAG;IAErB,IAAI,EAAE,GAAG,CAAC;IAEV,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;IAC5C,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,gBAAgB,CAAC;CAC5B,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB,CAAA;AAMD,qBAAa,WAAW,CAAC,SAAS,GAAG,MAAM,CAAE,YAAW,YAAY,CAAC,SAAS,CAAC;IAE3E,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;IAoBxE,MAAM,CAAC,YAAY,CAAC,SAAS,KAAK,WAAW,CAAC,SAAS,CAAC;IAmBxD,MAAM,CAAC,SAAS,EAAE,WAAW,CAeX;gBAQN,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO;IAiCrF,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAGzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAG5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAG5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAG/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAG1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAGhC,QAAQ,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IAG/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAGrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAKrC,IAAI,OAAO,IAAI,OAAO,CAQrB;CACJ"}
@@ -21,6 +21,24 @@ class QueryResult {
21
21
  }
22
22
  }, Object, false);
23
23
  }
24
+ static unauthorized() {
25
+ return new QueryResult({
26
+ data: null,
27
+ isSuccess: false,
28
+ isAuthorized: false,
29
+ isValid: true,
30
+ hasExceptions: false,
31
+ validationResults: [],
32
+ exceptionMessages: [],
33
+ exceptionStackTrace: '',
34
+ paging: {
35
+ totalItems: 0,
36
+ totalPages: 0,
37
+ page: 0,
38
+ size: 0
39
+ }
40
+ }, Object, false);
41
+ }
24
42
  static noSuccess = new QueryResult({
25
43
  data: {},
26
44
  isSuccess: false,
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.js","sources":["../../../queries/QueryResult.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 { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\n\ntype ServerQueryResult = {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n data: any;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n isSuccess: boolean;\n isAuthorized: boolean;\n isValid: boolean;\n hasExceptions: boolean;\n validationResults: ServerValidationResult[];\n exceptionMessages: string[];\n exceptionStackTrace: string;\n paging: ServerPagingInfo;\n}\n\ntype ServerValidationResult = {\n severity: number;\n message: string;\n members: string[];\n state: object;\n}\n\ntype ServerPagingInfo = {\n page: number;\n size: number; \n totalItems: number;\n totalPages: number;\n}\n\n/**\n * Represents the result from executing a {@link IQueryFor}.\n * @template TDataType The data type.\n */\nexport class QueryResult<TDataType = object> implements IQueryResult<TDataType> {\n\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult({\n data: defaultValue as object,\n isSuccess: true,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n\n }, Object, false);\n }\n\n static noSuccess: QueryResult = new QueryResult({\n data: {},\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n\n /**\n * Creates an instance of query result.\n * @param {*} result The raw result from the backend.\n * @param {Constructor} instanceType The type of instance to deserialize.\n * @param {boolean} enumerable Whether or not the result is supposed be an enumerable or not.\n */\n constructor(result: ServerQueryResult, instanceType: Constructor, enumerable: boolean) {\n this.isSuccess = result.isSuccess;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(_ => new ValidationResult(_.severity, _.message, _.members, _.state));\n this.exceptionMessages = result.exceptionMessages;\n this.exceptionStackTrace = result.exceptionStackTrace;\n this.paging = new PagingInfo();\n this.paging.page = result.paging.page;\n this.paging.size = result.paging.size;\n this.paging.totalItems = result.paging.totalItems;\n this.paging.totalPages = result.paging.totalPages;\n\n if (result.data) {\n let data: object = result.data;\n if (enumerable) {\n if (Array.isArray(result.data)) {\n data = JsonSerializer.deserializeArrayFromInstance(instanceType, data);\n } else {\n data = [];\n }\n } else {\n data = JsonSerializer.deserializeFromInstance(instanceType, data);\n }\n\n this.data = data as TDataType;\n } else {\n this.data = null as TDataType;\n }\n }\n\n /** @inheritdoc */\n readonly data: TDataType;\n\n /** @inheritdoc */\n readonly paging: PagingInfo;\n\n /** @inheritdoc */\n readonly isSuccess: boolean;\n\n /** @inheritdoc */\n readonly isAuthorized: boolean;\n\n /** @inheritdoc */\n readonly isValid: boolean;\n\n /** @inheritdoc */\n readonly hasExceptions: boolean;\n\n /** @inheritdoc */\n readonly validationResults: ValidationResult[];\n\n /** @inheritdoc */\n readonly exceptionMessages: string[];\n\n /** @inheritdoc */\n readonly exceptionStackTrace: string;\n\n /**\n * Gets whether or not the query has data.\n */\n get hasData(): boolean {\n if (this.data) {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return true;\n }\n return false;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryResult.js","sources":["../../../queries/QueryResult.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 { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\n\ntype ServerQueryResult = {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n data: any;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n isSuccess: boolean;\n isAuthorized: boolean;\n isValid: boolean;\n hasExceptions: boolean;\n validationResults: ServerValidationResult[];\n exceptionMessages: string[];\n exceptionStackTrace: string;\n paging: ServerPagingInfo;\n}\n\ntype ServerValidationResult = {\n severity: number;\n message: string;\n members: string[];\n state: object;\n}\n\ntype ServerPagingInfo = {\n page: number;\n size: number; \n totalItems: number;\n totalPages: number;\n}\n\n/**\n * Represents the result from executing a {@link IQueryFor}.\n * @template TDataType The data type.\n */\nexport class QueryResult<TDataType = object> implements IQueryResult<TDataType> {\n\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult({\n data: defaultValue as object,\n isSuccess: true,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n\n }, Object, false);\n }\n\n static unauthorized<TDataType>(): QueryResult<TDataType> {\n return new QueryResult({\n data: null as unknown as object,\n isSuccess: false,\n isAuthorized: false,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n }\n\n static noSuccess: QueryResult = new QueryResult({\n data: {},\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n\n /**\n * Creates an instance of query result.\n * @param {*} result The raw result from the backend.\n * @param {Constructor} instanceType The type of instance to deserialize.\n * @param {boolean} enumerable Whether or not the result is supposed be an enumerable or not.\n */\n constructor(result: ServerQueryResult, instanceType: Constructor, enumerable: boolean) {\n this.isSuccess = result.isSuccess;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(_ => new ValidationResult(_.severity, _.message, _.members, _.state));\n this.exceptionMessages = result.exceptionMessages;\n this.exceptionStackTrace = result.exceptionStackTrace;\n this.paging = new PagingInfo();\n this.paging.page = result.paging.page;\n this.paging.size = result.paging.size;\n this.paging.totalItems = result.paging.totalItems;\n this.paging.totalPages = result.paging.totalPages;\n\n if (result.data) {\n let data: object = result.data;\n if (enumerable) {\n if (Array.isArray(result.data)) {\n data = JsonSerializer.deserializeArrayFromInstance(instanceType, data);\n } else {\n data = [];\n }\n } else {\n data = JsonSerializer.deserializeFromInstance(instanceType, data);\n }\n\n this.data = data as TDataType;\n } else {\n this.data = null as TDataType;\n }\n }\n\n /** @inheritdoc */\n readonly data: TDataType;\n\n /** @inheritdoc */\n readonly paging: PagingInfo;\n\n /** @inheritdoc */\n readonly isSuccess: boolean;\n\n /** @inheritdoc */\n readonly isAuthorized: boolean;\n\n /** @inheritdoc */\n readonly isValid: boolean;\n\n /** @inheritdoc */\n readonly hasExceptions: boolean;\n\n /** @inheritdoc */\n readonly validationResults: ValidationResult[];\n\n /** @inheritdoc */\n readonly exceptionMessages: string[];\n\n /** @inheritdoc */\n readonly exceptionStackTrace: string;\n\n /**\n * Gets whether or not the query has data.\n */\n get hasData(): boolean {\n if (this.data) {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return true;\n }\n return false;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectPolicy.d.ts","sourceRoot":"","sources":["../../../queries/ReconnectPolicy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAczE,qBAAa,eAAgB,YAAW,gBAAgB;IAYhD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAdhC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,MAAM,CAAC,CAAgC;gBAU1B,YAAY,GAAE,MAAY,EAC1B,eAAe,GAAE,MAAY,EAC7B,YAAY,GAAE,MAAY,EAC1B,WAAW,GAAE,MAAe;IAIjD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAGD,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAchE,KAAK,IAAI,IAAI;IAMb,MAAM,IAAI,IAAI;CAMjB"}
1
+ {"version":3,"file":"ReconnectPolicy.d.ts","sourceRoot":"","sources":["../../../queries/ReconnectPolicy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAczE,qBAAa,eAAgB,YAAW,gBAAgB;IAYhD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAdhC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,MAAM,CAAC,CAAgC;gBAU1B,YAAY,GAAE,MAAY,EAC1B,eAAe,GAAE,MAAY,EAC7B,YAAY,GAAE,MAAY,EAC1B,WAAW,GAAE,MAAe;IAIjD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAGD,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAkBhE,KAAK,IAAI,IAAI;IAMb,MAAM,IAAI,IAAI;CAMjB"}
@@ -19,6 +19,7 @@ class ReconnectPolicy {
19
19
  console.log(`Reconnect: abandoned after ${this._maxAttempts} attempts for '${label}'`);
20
20
  return false;
21
21
  }
22
+ this.cancel();
22
23
  this._attempt++;
23
24
  const delay = Math.min(this._initialDelayMs + this._delayStepMs * this._attempt, this._maxDelayMs);
24
25
  console.log(`Reconnect: attempt ${this._attempt} in ${delay}ms for '${label}'`);
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectPolicy.js","sources":["../../../queries/ReconnectPolicy.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 { IReconnectPolicy, ReconnectCallback } from './IReconnectPolicy';\n\n/**\n * Default exponential back-off reconnect policy shared by all observable query connections.\n *\n * Delay formula: `Math.min(initialDelayMs + delayStepMs * attempt, maxDelayMs)`\n *\n * With the default parameters:\n * - Attempt 1 → 1 000 ms\n * - Attempt 2 → 1 500 ms\n * - …\n * - Attempt 19+ → 10 000 ms (capped)\n * - After 100 attempts → abandoned (returns `false`)\n */\nexport class ReconnectPolicy implements IReconnectPolicy {\n private _attempt = 0;\n private _timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link ReconnectPolicy}.\n * @param {number} maxAttempts Maximum number of reconnect attempts before giving up (default: 100).\n * @param {number} initialDelayMs Base delay in milliseconds added to every attempt (default: 500).\n * @param {number} delayStepMs Additional delay per attempt in milliseconds (default: 500).\n * @param {number} maxDelayMs Upper bound on the computed delay in milliseconds (default: 10 000).\n */\n constructor(\n private readonly _maxAttempts: number = 100,\n private readonly _initialDelayMs: number = 500,\n private readonly _delayStepMs: number = 500,\n private readonly _maxDelayMs: number = 10_000,\n ) {}\n\n /** @inheritdoc */\n get attempt(): number {\n return this._attempt;\n }\n\n /** @inheritdoc */\n schedule(onReconnect: ReconnectCallback, label: string): boolean {\n if (this._attempt >= this._maxAttempts) {\n console.log(`Reconnect: abandoned after ${this._maxAttempts} attempts for '${label}'`);\n return false;\n }\n\n this._attempt++;\n const delay = Math.min(this._initialDelayMs + this._delayStepMs * this._attempt, this._maxDelayMs);\n console.log(`Reconnect: attempt ${this._attempt} in ${delay}ms for '${label}'`);\n this._timer = setTimeout(onReconnect, delay);\n return true;\n }\n\n /** @inheritdoc */\n reset(): void {\n this._attempt = 0;\n this.cancel();\n }\n\n /** @inheritdoc */\n cancel(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n"],"names":[],"mappings":"MAiBa,eAAe,CAAA;AAYH,IAAA,YAAA;AACA,IAAA,eAAA;AACA,IAAA,YAAA;AACA,IAAA,WAAA;IAdb,QAAQ,GAAG,CAAC;AACZ,IAAA,MAAM;IASd,WAAA,CACqB,YAAA,GAAuB,GAAG,EAC1B,eAAA,GAA0B,GAAG,EAC7B,YAAA,GAAuB,GAAG,EAC1B,WAAA,GAAsB,MAAM,EAAA;QAH5B,IAAA,CAAA,YAAY,GAAZ,YAAY;QACZ,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,YAAY,GAAZ,YAAY;QACZ,IAAA,CAAA,WAAW,GAAX,WAAW;IAC7B;AAGH,IAAA,IAAI,OAAO,GAAA;QACP,OAAO,IAAI,CAAC,QAAQ;IACxB;IAGA,QAAQ,CAAC,WAA8B,EAAE,KAAa,EAAA;QAClD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,CAAA,2BAAA,EAA8B,IAAI,CAAC,YAAY,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,CAAG,CAAC;AACtF,YAAA,OAAO,KAAK;QAChB;QAEA,IAAI,CAAC,QAAQ,EAAE;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;AAClG,QAAA,OAAO,CAAC,GAAG,CAAC,CAAA,mBAAA,EAAsB,IAAI,CAAC,QAAQ,CAAA,IAAA,EAAO,KAAK,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,CAAG,CAAC;QAC/E,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC;AAC5C,QAAA,OAAO,IAAI;IACf;IAGA,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,QAAQ,GAAG,CAAC;QACjB,IAAI,CAAC,MAAM,EAAE;IACjB;IAGA,MAAM,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACb,YAAA,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;AACzB,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS;QAC3B;IACJ;AACH;;;;"}
1
+ {"version":3,"file":"ReconnectPolicy.js","sources":["../../../queries/ReconnectPolicy.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 { IReconnectPolicy, ReconnectCallback } from './IReconnectPolicy';\n\n/**\n * Default exponential back-off reconnect policy shared by all observable query connections.\n *\n * Delay formula: `Math.min(initialDelayMs + delayStepMs * attempt, maxDelayMs)`\n *\n * With the default parameters:\n * - Attempt 1 → 1 000 ms\n * - Attempt 2 → 1 500 ms\n * - …\n * - Attempt 19+ → 10 000 ms (capped)\n * - After 100 attempts → abandoned (returns `false`)\n */\nexport class ReconnectPolicy implements IReconnectPolicy {\n private _attempt = 0;\n private _timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link ReconnectPolicy}.\n * @param {number} maxAttempts Maximum number of reconnect attempts before giving up (default: 100).\n * @param {number} initialDelayMs Base delay in milliseconds added to every attempt (default: 500).\n * @param {number} delayStepMs Additional delay per attempt in milliseconds (default: 500).\n * @param {number} maxDelayMs Upper bound on the computed delay in milliseconds (default: 10 000).\n */\n constructor(\n private readonly _maxAttempts: number = 100,\n private readonly _initialDelayMs: number = 500,\n private readonly _delayStepMs: number = 500,\n private readonly _maxDelayMs: number = 10_000,\n ) {}\n\n /** @inheritdoc */\n get attempt(): number {\n return this._attempt;\n }\n\n /** @inheritdoc */\n schedule(onReconnect: ReconnectCallback, label: string): boolean {\n if (this._attempt >= this._maxAttempts) {\n console.log(`Reconnect: abandoned after ${this._maxAttempts} attempts for '${label}'`);\n return false;\n }\n\n // Cancel any pending reconnect timer so we don't fire multiple\n // concurrent reconnect attempts when schedule() is called rapidly.\n this.cancel();\n\n this._attempt++;\n const delay = Math.min(this._initialDelayMs + this._delayStepMs * this._attempt, this._maxDelayMs);\n console.log(`Reconnect: attempt ${this._attempt} in ${delay}ms for '${label}'`);\n this._timer = setTimeout(onReconnect, delay);\n return true;\n }\n\n /** @inheritdoc */\n reset(): void {\n this._attempt = 0;\n this.cancel();\n }\n\n /** @inheritdoc */\n cancel(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n"],"names":[],"mappings":"MAiBa,eAAe,CAAA;AAYH,IAAA,YAAA;AACA,IAAA,eAAA;AACA,IAAA,YAAA;AACA,IAAA,WAAA;IAdb,QAAQ,GAAG,CAAC;AACZ,IAAA,MAAM;IASd,WAAA,CACqB,YAAA,GAAuB,GAAG,EAC1B,eAAA,GAA0B,GAAG,EAC7B,YAAA,GAAuB,GAAG,EAC1B,WAAA,GAAsB,MAAM,EAAA;QAH5B,IAAA,CAAA,YAAY,GAAZ,YAAY;QACZ,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,YAAY,GAAZ,YAAY;QACZ,IAAA,CAAA,WAAW,GAAX,WAAW;IAC7B;AAGH,IAAA,IAAI,OAAO,GAAA;QACP,OAAO,IAAI,CAAC,QAAQ;IACxB;IAGA,QAAQ,CAAC,WAA8B,EAAE,KAAa,EAAA;QAClD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,CAAA,2BAAA,EAA8B,IAAI,CAAC,YAAY,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,CAAG,CAAC;AACtF,YAAA,OAAO,KAAK;QAChB;QAIA,IAAI,CAAC,MAAM,EAAE;QAEb,IAAI,CAAC,QAAQ,EAAE;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;AAClG,QAAA,OAAO,CAAC,GAAG,CAAC,CAAA,mBAAA,EAAsB,IAAI,CAAC,QAAQ,CAAA,IAAA,EAAO,KAAK,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,CAAG,CAAC;QAC/E,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC;AAC5C,QAAA,OAAO,IAAI;IACf;IAGA,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,QAAQ,GAAG,CAAC;QACjB,IAAI,CAAC,MAAM,EAAE;IACjB;IAGA,MAAM,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACb,YAAA,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;AACzB,YAAA,IAAI,CAAC,MAAM,GAAG,SAAS;QAC3B;IACJ;AACH;;;;"}
@@ -33,6 +33,7 @@ export declare class ServerSentEventHubConnection implements IObservableQueryHub
33
33
  private handleMessage;
34
34
  private handleConnected;
35
35
  private handleQueryResult;
36
+ private handleUnauthorized;
36
37
  private sendSubscribe;
37
38
  private sendUnsubscribe;
38
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAwB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAe/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC;IActE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAe3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAclC,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,eAAe;CAkB1B"}
1
+ {"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAwB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAe/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC;IAqBtE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAe3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAclC,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,eAAe;CAkB1B"}
@@ -1,6 +1,7 @@
1
1
  import { Globals } from '../Globals.js';
2
2
  import { HubConnectionKeepAlive } from './HubConnectionKeepAlive.js';
3
3
  import { ReconnectPolicy } from './ReconnectPolicy.js';
4
+ import { QueryResult } from './QueryResult.js';
4
5
  import { HubMessageType } from './WebSocketHubConnection.js';
5
6
 
6
7
  class ServerSentEventHubConnection {
@@ -26,12 +27,13 @@ class ServerSentEventHubConnection {
26
27
  this._microservice = _microservice;
27
28
  this._connectTimeoutMs = _connectTimeoutMs;
28
29
  this._policy = _policy;
30
+ const idleThresholdMs = Math.round(keepAliveIntervalMs * 1.5);
29
31
  this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {
30
32
  if (!this._disconnected && this._subscriptions.size > 0) {
31
- console.warn(`SSE hub: no messages received for ${keepAliveIntervalMs}ms, reconnecting '${this._sseUrl}'`);
33
+ console.warn(`SSE hub: no messages received for ${idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);
32
34
  this.reconnect();
33
35
  }
34
- });
36
+ }, idleThresholdMs);
35
37
  }
36
38
  get queryCount() {
37
39
  return this._subscriptions.size;
@@ -166,6 +168,7 @@ class ServerSentEventHubConnection {
166
168
  break;
167
169
  case HubMessageType.Unauthorized:
168
170
  console.warn(`SSE hub: query '${message.queryId}' unauthorized`);
171
+ this.handleUnauthorized(message);
169
172
  break;
170
173
  case HubMessageType.Error:
171
174
  console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);
@@ -194,6 +197,16 @@ class ServerSentEventHubConnection {
194
197
  const result = message.payload;
195
198
  sub.callback(result);
196
199
  }
200
+ handleUnauthorized(message) {
201
+ if (!message.queryId)
202
+ return;
203
+ const sub = this._subscriptions.get(message.queryId);
204
+ if (!sub)
205
+ return;
206
+ this._subscriptions.delete(message.queryId);
207
+ this._pendingSubscriptions.delete(message.queryId);
208
+ sub.callback(QueryResult.unauthorized());
209
+ }
197
210
  sendSubscribe(queryId, request) {
198
211
  if (!this._connectionId)
199
212
  return;
@@ -207,8 +220,14 @@ class ServerSentEventHubConnection {
207
220
  method: 'POST',
208
221
  headers: { 'Content-Type': 'application/json', ...customHeaders },
209
222
  body: JSON.stringify(body),
223
+ }).then(response => {
224
+ if (!response.ok) {
225
+ console.warn(`SSE hub: subscribe POST for '${queryId}' returned ${response.status}, reconnecting`);
226
+ this.reconnect();
227
+ }
210
228
  }).catch(error => {
211
- console.error(`SSE hub: subscribe POST failed for '${queryId}'`, error);
229
+ console.error(`SSE hub: subscribe POST failed for '${queryId}', reconnecting`, error);
230
+ this.reconnect();
212
231
  });
213
232
  }
214
233
  sendUnsubscribe(queryId) {
@@ -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":[],"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":[],"mappings":"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"}
@@ -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"}
@@ -1,6 +1,7 @@
1
1
  import { Globals } from '../Globals.js';
2
2
  import { HubConnectionKeepAlive } from './HubConnectionKeepAlive.js';
3
3
  import { ReconnectPolicy } from './ReconnectPolicy.js';
4
+ import { QueryResult } from './QueryResult.js';
4
5
 
5
6
  var HubMessageType;
6
7
  (function (HubMessageType) {
@@ -156,6 +157,7 @@ class WebSocketHubConnection {
156
157
  break;
157
158
  case HubMessageType.Unauthorized:
158
159
  console.warn(`Hub: query '${message.queryId}' unauthorized`);
160
+ this.handleUnauthorized(message);
159
161
  break;
160
162
  case HubMessageType.Error:
161
163
  console.error(`Hub: query '${message.queryId}' error:`, message.payload);
@@ -175,6 +177,15 @@ class WebSocketHubConnection {
175
177
  const result = message.payload;
176
178
  sub.callback(result);
177
179
  }
180
+ handleUnauthorized(message) {
181
+ if (!message.queryId)
182
+ return;
183
+ const sub = this._subscriptions.get(message.queryId);
184
+ if (!sub)
185
+ return;
186
+ this._subscriptions.delete(message.queryId);
187
+ sub.callback(QueryResult.unauthorized());
188
+ }
178
189
  handlePong(message) {
179
190
  if (message.timestamp && this._lastPingSentTime) {
180
191
  const latency = Date.now() - message.timestamp;