@cratis/arc 22.0.2 → 22.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/queries/ObservableQueryFor.js +6 -1
- package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
- package/dist/cjs/queries/QueryInstanceCache.js +6 -6
- package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
- package/dist/cjs/queries/QueryResult.js +23 -4
- package/dist/cjs/queries/QueryResult.js.map +1 -1
- package/dist/cjs/queries/QueryResultWithState.js +20 -7
- package/dist/cjs/queries/QueryResultWithState.js.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.js +120 -58
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.js +121 -51
- package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/IQueryResult.d.ts +1 -0
- package/dist/esm/queries/IQueryResult.d.ts.map +1 -1
- package/dist/esm/queries/ObservableQueryFor.d.ts.map +1 -1
- package/dist/esm/queries/ObservableQueryFor.js +6 -1
- package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
- package/dist/esm/queries/QueryInstanceCache.d.ts +1 -1
- package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
- package/dist/esm/queries/QueryInstanceCache.js +6 -6
- package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
- package/dist/esm/queries/QueryResult.d.ts +2 -0
- package/dist/esm/queries/QueryResult.d.ts.map +1 -1
- package/dist/esm/queries/QueryResult.js +23 -4
- package/dist/esm/queries/QueryResult.js.map +1 -1
- package/dist/esm/queries/QueryResultWithState.d.ts +3 -3
- package/dist/esm/queries/QueryResultWithState.d.ts.map +1 -1
- package/dist/esm/queries/QueryResultWithState.js +20 -7
- package/dist/esm/queries/QueryResultWithState.js.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts +11 -4
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.js +120 -58
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.d.ts +13 -2
- package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.js +121 -51
- package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts +2 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js +34 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js +26 -2
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js.map +1 -1
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js +60 -3
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js.map +1 -1
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts +2 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js +83 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js +22 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js.map +1 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts +2 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js +17 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js.map +1 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts +2 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js +16 -0
- package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js.map +1 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts +2 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js +19 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js.map +1 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts +2 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js +19 -0
- package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts +7 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js +12 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts +2 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js +15 -4
- package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js +44 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js +74 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js +74 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js +59 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js +58 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js +6 -3
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +23 -6
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js +20 -5
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js +20 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js +68 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js +38 -13
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js +54 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js +18 -4
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +22 -5
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js +108 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js +33 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js +26 -4
- package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js.map +1 -1
- package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js +62 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js +18 -5
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js.map +1 -1
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js +56 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js +16 -3
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js +33 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/queries/IQueryResult.ts +10 -0
- package/queries/ObservableQueryFor.ts +44 -16
- package/queries/QueryInstanceCache.ts +42 -19
- package/queries/QueryResult.ts +145 -79
- package/queries/QueryResultWithState.ts +32 -9
- package/queries/ServerSentEventHubConnection.ts +270 -83
- package/queries/WebSocketHubConnection.ts +188 -56
- package/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.ts +46 -0
- package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.ts +91 -57
- package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.ts +125 -53
- package/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.ts +107 -0
- package/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.ts +63 -0
- package/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.ts +25 -0
- package/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.ts +24 -0
- package/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.ts +28 -0
- package/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.ts +25 -0
- package/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.ts +15 -0
- package/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.ts +18 -7
- package/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.ts +59 -0
- package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.ts +113 -0
- package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.ts +109 -0
- package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.ts +81 -0
- package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.ts +83 -0
- package/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.ts +30 -21
- package/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +56 -32
- package/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.ts +23 -6
- package/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.ts +41 -0
- package/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.ts +92 -0
- package/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.ts +69 -30
- package/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.ts +69 -0
- package/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.ts +43 -24
- package/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +53 -29
- package/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.ts +131 -0
- package/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.ts +39 -0
- package/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.ts +72 -36
- package/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.ts +88 -0
- package/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.ts +54 -27
- package/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.ts +72 -0
- package/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.ts +43 -18
- package/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.ts +44 -0
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
4
|
import { Globals } from '../Globals';
|
|
5
|
-
import { DataReceived } from './ObservableQueryConnection';
|
|
5
|
+
import type { DataReceived } from './ObservableQueryConnection';
|
|
6
6
|
import { HubConnectionKeepAlive } from './HubConnectionKeepAlive';
|
|
7
|
-
import { IReconnectPolicy } from './IReconnectPolicy';
|
|
7
|
+
import type { IReconnectPolicy } from './IReconnectPolicy';
|
|
8
8
|
import { ReconnectPolicy } from './ReconnectPolicy';
|
|
9
9
|
import { QueryResult } from './QueryResult';
|
|
10
10
|
|
|
@@ -26,11 +26,20 @@ export enum HubMessageType {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* Wire format for messages exchanged over the
|
|
29
|
+
* Wire format for messages exchanged over the observable query WebSocket and SSE hub transports.
|
|
30
30
|
*/
|
|
31
31
|
export interface HubMessage {
|
|
32
32
|
type: HubMessageType;
|
|
33
33
|
queryId?: string;
|
|
34
|
+
|
|
35
|
+
/** Optional positive safe-integer revision used to reject stale replacement messages. */
|
|
36
|
+
revision?: number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Whether the server supports revision-aware subscription operations and result frames.
|
|
40
|
+
* Only present on {@link HubMessageType.Connected} messages from capable servers.
|
|
41
|
+
*/
|
|
42
|
+
supportsSubscriptionRevisions?: boolean;
|
|
34
43
|
payload?: any;
|
|
35
44
|
timestamp?: number;
|
|
36
45
|
|
|
@@ -57,6 +66,7 @@ export interface SubscriptionRequest {
|
|
|
57
66
|
interface ActiveSubscription {
|
|
58
67
|
request: SubscriptionRequest;
|
|
59
68
|
callback: DataReceived<any>;
|
|
69
|
+
revision: number;
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/**
|
|
@@ -65,7 +75,9 @@ interface ActiveSubscription {
|
|
|
65
75
|
*
|
|
66
76
|
* Multiple query subscriptions are carried over the same physical WebSocket. Each subscription
|
|
67
77
|
* is identified by a client-generated {@code queryId}; the server tags every result message with
|
|
68
|
-
* the same id so responses can be routed to the correct callback.
|
|
78
|
+
* the same id so responses can be routed to the correct callback. The client initially subscribes
|
|
79
|
+
* without revisions for compatibility with older servers, then replaces active subscriptions with
|
|
80
|
+
* revision-aware operations when the server advertises support in a Connected message.
|
|
69
81
|
*/
|
|
70
82
|
export class WebSocketHubConnection {
|
|
71
83
|
private _socket?: WebSocket;
|
|
@@ -75,24 +87,30 @@ export class WebSocketHubConnection {
|
|
|
75
87
|
private _lastPingSentTime?: number;
|
|
76
88
|
private _lastPongLatency: number = 0;
|
|
77
89
|
private _latencySamples: number[] = [];
|
|
90
|
+
private _nextRevision = 0;
|
|
91
|
+
private _supportsSubscriptionRevisions = false;
|
|
92
|
+
private _reconnectPending = false;
|
|
78
93
|
|
|
79
94
|
/**
|
|
80
95
|
* Initializes a new instance of {@link WebSocketHubConnection}.
|
|
81
|
-
* @param {string}
|
|
82
|
-
* @param {string}
|
|
96
|
+
* @param {string} _url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).
|
|
97
|
+
* @param {string} _microservice The microservice name to pass as a query argument.
|
|
83
98
|
* @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).
|
|
84
|
-
* @param {IReconnectPolicy}
|
|
99
|
+
* @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).
|
|
85
100
|
*/
|
|
86
101
|
constructor(
|
|
87
102
|
private readonly _url: string,
|
|
88
103
|
private readonly _microservice: string,
|
|
89
104
|
pingIntervalMs: number = 10000,
|
|
90
|
-
private readonly _policy: IReconnectPolicy = new ReconnectPolicy()
|
|
105
|
+
private readonly _policy: IReconnectPolicy = new ReconnectPolicy(),
|
|
91
106
|
) {
|
|
92
107
|
this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {
|
|
93
108
|
if (this._socket?.readyState === WebSocket.OPEN) {
|
|
94
109
|
this._lastPingSentTime = Date.now();
|
|
95
|
-
this.sendMessage({
|
|
110
|
+
this.sendMessage({
|
|
111
|
+
type: HubMessageType.Ping,
|
|
112
|
+
timestamp: this._lastPingSentTime,
|
|
113
|
+
});
|
|
96
114
|
}
|
|
97
115
|
});
|
|
98
116
|
}
|
|
@@ -123,7 +141,9 @@ export class WebSocketHubConnection {
|
|
|
123
141
|
*/
|
|
124
142
|
get averageLatency(): number {
|
|
125
143
|
if (this._latencySamples.length === 0) return 0;
|
|
126
|
-
return
|
|
144
|
+
return (
|
|
145
|
+
this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length
|
|
146
|
+
);
|
|
127
147
|
}
|
|
128
148
|
|
|
129
149
|
/**
|
|
@@ -133,12 +153,17 @@ export class WebSocketHubConnection {
|
|
|
133
153
|
* @param {SubscriptionRequest} request The subscription request payload.
|
|
134
154
|
* @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.
|
|
135
155
|
*/
|
|
136
|
-
subscribe(
|
|
137
|
-
|
|
156
|
+
subscribe(
|
|
157
|
+
queryId: string,
|
|
158
|
+
request: SubscriptionRequest,
|
|
159
|
+
callback: DataReceived<any>,
|
|
160
|
+
): void {
|
|
161
|
+
const subscription = { request, callback, revision: this.getNextRevision() };
|
|
162
|
+
this._subscriptions.set(queryId, subscription);
|
|
138
163
|
this.ensureConnected();
|
|
139
164
|
|
|
140
165
|
if (this._socket?.readyState === WebSocket.OPEN) {
|
|
141
|
-
this.sendSubscribeMessage(queryId,
|
|
166
|
+
this.sendSubscribeMessage(queryId, subscription);
|
|
142
167
|
}
|
|
143
168
|
// If not yet open, sendAllSubscriptions will fire in onopen.
|
|
144
169
|
}
|
|
@@ -148,10 +173,18 @@ export class WebSocketHubConnection {
|
|
|
148
173
|
* @param {string} queryId The identifier of the subscription to cancel.
|
|
149
174
|
*/
|
|
150
175
|
unsubscribe(queryId: string): void {
|
|
176
|
+
const subscription = this._subscriptions.get(queryId);
|
|
151
177
|
this._subscriptions.delete(queryId);
|
|
152
178
|
|
|
153
|
-
if (this._socket?.readyState === WebSocket.OPEN) {
|
|
154
|
-
|
|
179
|
+
if (this._socket?.readyState === WebSocket.OPEN && subscription) {
|
|
180
|
+
const message: HubMessage = {
|
|
181
|
+
type: HubMessageType.Unsubscribe,
|
|
182
|
+
queryId,
|
|
183
|
+
};
|
|
184
|
+
if (this._supportsSubscriptionRevisions) {
|
|
185
|
+
message.revision = subscription.revision;
|
|
186
|
+
}
|
|
187
|
+
this.sendMessage(message);
|
|
155
188
|
}
|
|
156
189
|
|
|
157
190
|
// If no subscriptions remain, close the connection to free resources.
|
|
@@ -164,12 +197,8 @@ export class WebSocketHubConnection {
|
|
|
164
197
|
* Permanently close this hub connection and clean up all subscriptions.
|
|
165
198
|
*/
|
|
166
199
|
dispose(): void {
|
|
167
|
-
this._disconnected = true;
|
|
168
200
|
this._subscriptions.clear();
|
|
169
|
-
this.
|
|
170
|
-
this._policy.cancel();
|
|
171
|
-
this._socket?.close();
|
|
172
|
-
this._socket = undefined;
|
|
201
|
+
this.close();
|
|
173
202
|
}
|
|
174
203
|
|
|
175
204
|
private ensureConnected(): void {
|
|
@@ -178,10 +207,18 @@ export class WebSocketHubConnection {
|
|
|
178
207
|
this._disconnected = false;
|
|
179
208
|
}
|
|
180
209
|
|
|
181
|
-
if (
|
|
210
|
+
if (
|
|
211
|
+
this._socket &&
|
|
212
|
+
(this._socket.readyState === WebSocket.OPEN ||
|
|
213
|
+
this._socket.readyState === WebSocket.CONNECTING)
|
|
214
|
+
) {
|
|
215
|
+
this.cancelPendingReconnect();
|
|
182
216
|
return;
|
|
183
217
|
}
|
|
184
218
|
|
|
219
|
+
// A subscription can arrive while an earlier close is waiting in reconnect backoff. The immediate open owns
|
|
220
|
+
// the connection now, so the delayed callback must not be allowed to create a competing socket later.
|
|
221
|
+
this.cancelPendingReconnect();
|
|
185
222
|
this.openSocket();
|
|
186
223
|
}
|
|
187
224
|
|
|
@@ -189,75 +226,116 @@ export class WebSocketHubConnection {
|
|
|
189
226
|
this._disconnected = true;
|
|
190
227
|
this._keepAlive.stop();
|
|
191
228
|
this._policy.cancel();
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// fire after a new subscription has reset _disconnected to false and opened a
|
|
195
|
-
// fresh socket. Without this, the stale onclose triggers an unintended
|
|
196
|
-
// reconnect via the back-off policy, causing a 1-10 second delay before the
|
|
197
|
-
// new page's queries receive their first data.
|
|
198
|
-
this._socket.onopen = null;
|
|
199
|
-
this._socket.onclose = null;
|
|
200
|
-
this._socket.onerror = null;
|
|
201
|
-
this._socket.onmessage = null;
|
|
202
|
-
this._socket.close();
|
|
203
|
-
}
|
|
229
|
+
this._reconnectPending = false;
|
|
230
|
+
const socket = this._socket;
|
|
204
231
|
this._socket = undefined;
|
|
232
|
+
this._supportsSubscriptionRevisions = false;
|
|
233
|
+
if (socket) {
|
|
234
|
+
this.detachAndCloseSocket(socket);
|
|
235
|
+
}
|
|
205
236
|
}
|
|
206
237
|
|
|
207
238
|
private openSocket(): void {
|
|
239
|
+
const currentSocket = this._socket;
|
|
240
|
+
if (
|
|
241
|
+
currentSocket &&
|
|
242
|
+
(currentSocket.readyState === WebSocket.OPEN ||
|
|
243
|
+
currentSocket.readyState === WebSocket.CONNECTING)
|
|
244
|
+
) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (currentSocket) {
|
|
249
|
+
this._socket = undefined;
|
|
250
|
+
this.detachAndCloseSocket(currentSocket);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
this._supportsSubscriptionRevisions = false;
|
|
254
|
+
|
|
208
255
|
let url = this._url;
|
|
209
256
|
if (this._microservice?.length > 0) {
|
|
210
257
|
const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;
|
|
211
258
|
url += (url.includes('?') ? '&' : '?') + param;
|
|
212
259
|
}
|
|
213
260
|
|
|
214
|
-
|
|
261
|
+
const socket = new WebSocket(url);
|
|
262
|
+
this._socket = socket;
|
|
215
263
|
|
|
216
|
-
|
|
217
|
-
if (this._disconnected) return;
|
|
218
|
-
console.log(
|
|
264
|
+
socket.onopen = () => {
|
|
265
|
+
if (this._socket !== socket || this._disconnected) return;
|
|
266
|
+
console.log('Hub connection established', url);
|
|
267
|
+
this.cancelPendingReconnect();
|
|
219
268
|
this._policy.reset();
|
|
220
269
|
this._keepAlive.start();
|
|
221
270
|
this.sendAllSubscriptions();
|
|
222
271
|
};
|
|
223
272
|
|
|
224
|
-
|
|
225
|
-
if (this._disconnected) return;
|
|
226
|
-
console.log(
|
|
273
|
+
socket.onclose = () => {
|
|
274
|
+
if (this._socket !== socket || this._disconnected) return;
|
|
275
|
+
console.log('Hub connection closed', url);
|
|
276
|
+
this._socket = undefined;
|
|
277
|
+
this._supportsSubscriptionRevisions = false;
|
|
227
278
|
this._keepAlive.stop();
|
|
228
279
|
if (this._subscriptions.size === 0) return;
|
|
229
|
-
this.
|
|
280
|
+
this._reconnectPending = true;
|
|
281
|
+
const scheduled = this._policy.schedule(() => {
|
|
282
|
+
this._reconnectPending = false;
|
|
230
283
|
if (!this._disconnected && this._subscriptions.size > 0) {
|
|
231
|
-
this.
|
|
284
|
+
this.ensureConnected();
|
|
232
285
|
}
|
|
233
286
|
}, this._url);
|
|
287
|
+
if (!scheduled) {
|
|
288
|
+
this._reconnectPending = false;
|
|
289
|
+
}
|
|
234
290
|
};
|
|
235
291
|
|
|
236
|
-
|
|
237
|
-
if (this._disconnected) return;
|
|
238
|
-
console.error(
|
|
292
|
+
socket.onerror = (error) => {
|
|
293
|
+
if (this._socket !== socket || this._disconnected) return;
|
|
294
|
+
console.error('Hub connection error', url, error);
|
|
239
295
|
this._keepAlive.stop();
|
|
240
296
|
// onclose will fire after onerror, triggering reconnect
|
|
241
297
|
};
|
|
242
298
|
|
|
243
|
-
|
|
244
|
-
if (this._disconnected) return;
|
|
299
|
+
socket.onmessage = (ev) => {
|
|
300
|
+
if (this._socket !== socket || this._disconnected) return;
|
|
245
301
|
this.handleMessage(ev.data as string);
|
|
246
302
|
};
|
|
247
303
|
}
|
|
248
304
|
|
|
305
|
+
private cancelPendingReconnect(): void {
|
|
306
|
+
if (!this._reconnectPending) return;
|
|
307
|
+
|
|
308
|
+
this._policy.cancel();
|
|
309
|
+
this._reconnectPending = false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private detachAndCloseSocket(socket: WebSocket): void {
|
|
313
|
+
socket.onopen = null;
|
|
314
|
+
socket.onclose = null;
|
|
315
|
+
socket.onerror = null;
|
|
316
|
+
socket.onmessage = null;
|
|
317
|
+
socket.close();
|
|
318
|
+
}
|
|
319
|
+
|
|
249
320
|
private sendAllSubscriptions(): void {
|
|
250
321
|
for (const [queryId, sub] of this._subscriptions) {
|
|
251
|
-
this.sendSubscribeMessage(queryId, sub
|
|
322
|
+
this.sendSubscribeMessage(queryId, sub);
|
|
252
323
|
}
|
|
253
324
|
}
|
|
254
325
|
|
|
255
|
-
private sendSubscribeMessage(
|
|
256
|
-
|
|
326
|
+
private sendSubscribeMessage(
|
|
327
|
+
queryId: string,
|
|
328
|
+
subscription: ActiveSubscription,
|
|
329
|
+
): void {
|
|
330
|
+
const message: HubMessage = {
|
|
257
331
|
type: HubMessageType.Subscribe,
|
|
258
332
|
queryId,
|
|
259
|
-
payload: request,
|
|
260
|
-
}
|
|
333
|
+
payload: subscription.request,
|
|
334
|
+
};
|
|
335
|
+
if (this._supportsSubscriptionRevisions) {
|
|
336
|
+
message.revision = subscription.revision;
|
|
337
|
+
}
|
|
338
|
+
this.sendMessage(message);
|
|
261
339
|
}
|
|
262
340
|
|
|
263
341
|
private sendMessage(message: HubMessage): void {
|
|
@@ -274,6 +352,9 @@ export class WebSocketHubConnection {
|
|
|
274
352
|
this._keepAlive.recordActivity();
|
|
275
353
|
|
|
276
354
|
switch (message.type) {
|
|
355
|
+
case HubMessageType.Connected:
|
|
356
|
+
this.handleConnected(message);
|
|
357
|
+
break;
|
|
277
358
|
case HubMessageType.QueryResult:
|
|
278
359
|
this.handleQueryResult(message);
|
|
279
360
|
break;
|
|
@@ -281,11 +362,17 @@ export class WebSocketHubConnection {
|
|
|
281
362
|
this.handlePong(message);
|
|
282
363
|
break;
|
|
283
364
|
case HubMessageType.Unauthorized:
|
|
284
|
-
console.warn(
|
|
365
|
+
console.warn('Hub: query unauthorized', message.queryId);
|
|
285
366
|
this.handleUnauthorized(message);
|
|
286
367
|
break;
|
|
287
368
|
case HubMessageType.Error:
|
|
288
|
-
|
|
369
|
+
if (this.isMessageForCurrentSubscription(message)) {
|
|
370
|
+
console.error(
|
|
371
|
+
'Hub: query error',
|
|
372
|
+
message.queryId,
|
|
373
|
+
message.payload,
|
|
374
|
+
);
|
|
375
|
+
}
|
|
289
376
|
break;
|
|
290
377
|
}
|
|
291
378
|
} catch (error) {
|
|
@@ -293,11 +380,26 @@ export class WebSocketHubConnection {
|
|
|
293
380
|
}
|
|
294
381
|
}
|
|
295
382
|
|
|
383
|
+
private handleConnected(message: HubMessage): void {
|
|
384
|
+
if (
|
|
385
|
+
message.supportsSubscriptionRevisions !== true ||
|
|
386
|
+
this._supportsSubscriptionRevisions
|
|
387
|
+
) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
this._supportsSubscriptionRevisions = true;
|
|
392
|
+
|
|
393
|
+
// The legacy subscriptions sent on socket open keep this client compatible with older servers.
|
|
394
|
+
// Ordered WebSocket delivery means these revision-aware replacements are processed afterwards.
|
|
395
|
+
this.sendAllSubscriptions();
|
|
396
|
+
}
|
|
397
|
+
|
|
296
398
|
private handleQueryResult(message: HubMessage): void {
|
|
297
399
|
if (!message.queryId) return;
|
|
298
400
|
|
|
299
401
|
const sub = this._subscriptions.get(message.queryId);
|
|
300
|
-
if (!sub) return;
|
|
402
|
+
if (!sub || !this.isMessageForCurrentSubscription(message)) return;
|
|
301
403
|
|
|
302
404
|
const result = message.payload as QueryResult<any>;
|
|
303
405
|
sub.callback(result);
|
|
@@ -307,12 +409,42 @@ export class WebSocketHubConnection {
|
|
|
307
409
|
if (!message.queryId) return;
|
|
308
410
|
|
|
309
411
|
const sub = this._subscriptions.get(message.queryId);
|
|
310
|
-
if (!sub) return;
|
|
412
|
+
if (!sub || !this.isMessageForCurrentSubscription(message)) return;
|
|
311
413
|
|
|
312
414
|
this._subscriptions.delete(message.queryId);
|
|
313
415
|
sub.callback(QueryResult.unauthorized());
|
|
314
416
|
}
|
|
315
417
|
|
|
418
|
+
private isMessageForCurrentSubscription(message: HubMessage): boolean {
|
|
419
|
+
if (!message.queryId) return false;
|
|
420
|
+
|
|
421
|
+
if (!this._supportsSubscriptionRevisions) {
|
|
422
|
+
return (
|
|
423
|
+
message.revision === undefined &&
|
|
424
|
+
this._subscriptions.has(message.queryId)
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
this.isValidRevision(message.revision) &&
|
|
430
|
+
this._subscriptions.get(message.queryId)?.revision === message.revision
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private isValidRevision(revision: number | undefined): revision is number {
|
|
435
|
+
return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
private getNextRevision(): number {
|
|
439
|
+
if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {
|
|
440
|
+
throw new RangeError(
|
|
441
|
+
'WebSocket hub subscription revision exhausted the safe integer range',
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return ++this._nextRevision;
|
|
446
|
+
}
|
|
447
|
+
|
|
316
448
|
private handlePong(message: HubMessage): void {
|
|
317
449
|
if (message.timestamp && this._lastPingSentTime) {
|
|
318
450
|
const latency = Date.now() - message.timestamp;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import * as sinon from 'sinon';
|
|
5
|
+
import { given } from '../../../given';
|
|
6
|
+
import { createFetchHelper } from '../../../helpers/fetchHelper';
|
|
7
|
+
import type { QueryResult } from '../../QueryResult';
|
|
8
|
+
import { an_observable_query_for } from '../given/an_observable_query_for';
|
|
9
|
+
|
|
10
|
+
describe(
|
|
11
|
+
'when performing with a not ready result',
|
|
12
|
+
given(an_observable_query_for, (context) => {
|
|
13
|
+
let result: QueryResult<string>;
|
|
14
|
+
let fetchHelper: { stubFetch: () => sinon.SinonStub; restore: () => void };
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
fetchHelper = createFetchHelper();
|
|
18
|
+
const fetchStub = fetchHelper.stubFetch();
|
|
19
|
+
// SAFETY: The query only consumes this response's JSON payload, status, and success flag.
|
|
20
|
+
fetchStub.resolves({
|
|
21
|
+
json: sinon.stub().resolves({
|
|
22
|
+
data: null,
|
|
23
|
+
isSuccess: false,
|
|
24
|
+
isReady: false,
|
|
25
|
+
isAuthorized: true,
|
|
26
|
+
isValid: true,
|
|
27
|
+
hasExceptions: false,
|
|
28
|
+
validationResults: [],
|
|
29
|
+
exceptionMessages: [],
|
|
30
|
+
exceptionStackTrace: '',
|
|
31
|
+
paging: { page: 0, size: 0, totalItems: 0, totalPages: 0 },
|
|
32
|
+
}),
|
|
33
|
+
ok: true,
|
|
34
|
+
status: 202,
|
|
35
|
+
} as unknown as Response);
|
|
36
|
+
|
|
37
|
+
context.query.setOrigin('https://api.example.com');
|
|
38
|
+
result = await context.query.perform({ id: 'test-id' });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => fetchHelper.restore());
|
|
42
|
+
|
|
43
|
+
it('should return the not ready result', () => result.isReady.should.be.false);
|
|
44
|
+
it('should not report an exception', () => result.hasExceptions.should.be.false);
|
|
45
|
+
}),
|
|
46
|
+
);
|
package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.ts
CHANGED
|
@@ -9,61 +9,95 @@ import { ObservableQuerySubscription } from '../../ObservableQuerySubscription';
|
|
|
9
9
|
|
|
10
10
|
import * as sinon from 'sinon';
|
|
11
11
|
|
|
12
|
-
describe(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
originalQueryDirectMode = Globals.queryDirectMode;
|
|
21
|
-
originalTransportMethod = Globals.queryTransportMethod;
|
|
22
|
-
|
|
23
|
-
Globals.queryDirectMode = true;
|
|
24
|
-
Globals.queryTransportMethod = QueryTransportMethod.ServerSentEvents;
|
|
25
|
-
|
|
26
|
-
context.query.setOrigin('https://example.com');
|
|
27
|
-
callback = sinon.stub();
|
|
28
|
-
|
|
29
|
-
const FakeEventSourceConstructor = function (this: EventSource, url: string) {
|
|
30
|
-
capturedUrl = url;
|
|
31
|
-
Object.assign(this, {
|
|
32
|
-
onopen: null,
|
|
33
|
-
onerror: null,
|
|
34
|
-
onmessage: null,
|
|
35
|
-
close: sinon.stub(),
|
|
36
|
-
addEventListener: sinon.stub(),
|
|
37
|
-
removeEventListener: sinon.stub(),
|
|
38
|
-
});
|
|
12
|
+
describe(
|
|
13
|
+
'when subscribing with direct mode and SSE transport',
|
|
14
|
+
given(an_observable_query_for, (context) => {
|
|
15
|
+
let callback: sinon.SinonStub;
|
|
16
|
+
let subscription: ObservableQuerySubscription<string>;
|
|
17
|
+
let capturedUrl: string;
|
|
18
|
+
let eventSourceInstance: EventSource & {
|
|
19
|
+
onmessage: ((event: { data: string }) => void) | null;
|
|
39
20
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
21
|
+
let originalQueryDirectMode: boolean;
|
|
22
|
+
let originalTransportMethod: QueryTransportMethod;
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
originalQueryDirectMode = Globals.queryDirectMode;
|
|
26
|
+
originalTransportMethod = Globals.queryTransportMethod;
|
|
27
|
+
|
|
28
|
+
Globals.queryDirectMode = true;
|
|
29
|
+
Globals.queryTransportMethod = QueryTransportMethod.ServerSentEvents;
|
|
30
|
+
|
|
31
|
+
context.query.setOrigin('https://example.com');
|
|
32
|
+
callback = sinon.stub();
|
|
33
|
+
|
|
34
|
+
const FakeEventSourceConstructor = function (this: EventSource, url: string) {
|
|
35
|
+
capturedUrl = url;
|
|
36
|
+
eventSourceInstance = this as EventSource & {
|
|
37
|
+
onmessage: ((event: { data: string }) => void) | null;
|
|
38
|
+
};
|
|
39
|
+
Object.assign(this, {
|
|
40
|
+
onopen: null,
|
|
41
|
+
onerror: null,
|
|
42
|
+
onmessage: null,
|
|
43
|
+
close: sinon.stub(),
|
|
44
|
+
addEventListener: sinon.stub(),
|
|
45
|
+
removeEventListener: sinon.stub(),
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
(globalThis as Record<string, unknown>)['EventSource'] =
|
|
49
|
+
FakeEventSourceConstructor;
|
|
50
|
+
|
|
51
|
+
subscription = context.query.subscribe(callback, { id: 'test-id' });
|
|
52
|
+
|
|
53
|
+
const result = {
|
|
54
|
+
data: 'ready result',
|
|
55
|
+
isSuccess: true,
|
|
56
|
+
isAuthorized: true,
|
|
57
|
+
isValid: true,
|
|
58
|
+
hasExceptions: false,
|
|
59
|
+
validationResults: [],
|
|
60
|
+
exceptionMessages: [],
|
|
61
|
+
exceptionStackTrace: '',
|
|
62
|
+
paging: { page: 0, size: 0, totalItems: 0, totalPages: 0 },
|
|
63
|
+
};
|
|
64
|
+
eventSourceInstance.onmessage?.({ data: JSON.stringify(result) });
|
|
65
|
+
eventSourceInstance.onmessage?.({
|
|
66
|
+
data: JSON.stringify({ ...result, isSuccess: false, isReady: false }),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
Globals.queryDirectMode = originalQueryDirectMode;
|
|
72
|
+
Globals.queryTransportMethod = originalTransportMethod;
|
|
73
|
+
if (subscription) {
|
|
74
|
+
subscription.unsubscribe();
|
|
75
|
+
}
|
|
76
|
+
delete (globalThis as Record<string, unknown>)['EventSource'];
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should connect to the per-query SSE URL', () => {
|
|
80
|
+
capturedUrl.should.include('/api/test/test-id');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should not connect to the hub SSE endpoint', () => {
|
|
84
|
+
capturedUrl.should.not.include('/.cratis/queries/sse');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should not include a query name parameter', () => {
|
|
88
|
+
capturedUrl.should.not.include('query=');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return a subscription', () => {
|
|
92
|
+
subscription.should.not.be.undefined;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should normalize omitted readiness to true', () => {
|
|
96
|
+
callback.firstCall.args[0].isReady.should.be.true;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should preserve false readiness', () => {
|
|
100
|
+
callback.secondCall.args[0].isReady.should.be.false;
|
|
101
|
+
});
|
|
102
|
+
}),
|
|
103
|
+
);
|