@cratis/arc 20.1.3 → 20.1.4
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/identity/IdentityProvider.d.ts +2 -1
- package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
- package/dist/cjs/identity/IdentityProvider.js +16 -2
- package/dist/cjs/identity/IdentityProvider.js.map +1 -1
- package/dist/cjs/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts +2 -0
- package/dist/cjs/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts.map +1 -0
- package/dist/cjs/queries/QueryInstanceCache.d.ts +8 -0
- package/dist/cjs/queries/QueryInstanceCache.d.ts.map +1 -1
- package/dist/cjs/queries/QueryInstanceCache.js +70 -9
- package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
- package/dist/cjs/queries/QueryResult.d.ts +1 -0
- package/dist/cjs/queries/QueryResult.d.ts.map +1 -1
- package/dist/cjs/queries/QueryResult.js +18 -0
- package/dist/cjs/queries/QueryResult.js.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts +1 -0
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.js +12 -0
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.d.ts +1 -0
- package/dist/cjs/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.js +11 -0
- package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts.map +1 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts +2 -0
- package/dist/cjs/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts.map +1 -0
- package/dist/cjs/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
- package/dist/cjs/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
- package/dist/cjs/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
- package/dist/cjs/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
- package/dist/esm/identity/IdentityProvider.d.ts +2 -1
- package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
- package/dist/esm/identity/IdentityProvider.js +16 -2
- package/dist/esm/identity/IdentityProvider.js.map +1 -1
- package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts +2 -0
- package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts.map +1 -0
- package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.js +19 -0
- package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.js.map +1 -0
- package/dist/esm/queries/QueryInstanceCache.d.ts +8 -0
- package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
- package/dist/esm/queries/QueryInstanceCache.js +70 -9
- package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
- package/dist/esm/queries/QueryResult.d.ts +1 -0
- package/dist/esm/queries/QueryResult.d.ts.map +1 -1
- package/dist/esm/queries/QueryResult.js +18 -0
- package/dist/esm/queries/QueryResult.js.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts +1 -0
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.js +12 -0
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.d.ts +1 -0
- package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.js +11 -0
- package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.js +23 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js +23 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js +21 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.js +17 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.js +23 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js +22 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js +28 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js +25 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.js +25 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.js +12 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.js.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts +2 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js +23 -0
- package/dist/esm/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.js.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +35 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +33 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/identity/IdentityProvider.ts +23 -2
- package/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts +26 -0
- package/package.json +1 -1
- package/queries/QueryInstanceCache.ts +133 -12
- package/queries/QueryResult.ts +19 -0
- package/queries/ServerSentEventHubConnection.ts +12 -0
- package/queries/WebSocketHubConnection.ts +11 -0
- package/queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts +31 -0
- package/queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts +31 -0
- package/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.ts +28 -0
- package/queries/for_QueryInstanceCache/when_disposing/an_empty_cache.ts +21 -0
- package/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.ts +30 -0
- package/queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.ts +31 -0
- package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts +36 -0
- package/queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts +33 -0
- package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.ts +32 -0
- package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.ts +18 -0
- package/queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.ts +33 -0
- package/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +51 -0
- package/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +47 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var Globals = require('../Globals.js');
|
|
4
4
|
var HubConnectionKeepAlive = require('./HubConnectionKeepAlive.js');
|
|
5
5
|
var ReconnectPolicy = require('./ReconnectPolicy.js');
|
|
6
|
+
var QueryResult = require('./QueryResult.js');
|
|
6
7
|
|
|
7
8
|
exports.HubMessageType = void 0;
|
|
8
9
|
(function (HubMessageType) {
|
|
@@ -158,6 +159,7 @@ class WebSocketHubConnection {
|
|
|
158
159
|
break;
|
|
159
160
|
case exports.HubMessageType.Unauthorized:
|
|
160
161
|
console.warn(`Hub: query '${message.queryId}' unauthorized`);
|
|
162
|
+
this.handleUnauthorized(message);
|
|
161
163
|
break;
|
|
162
164
|
case exports.HubMessageType.Error:
|
|
163
165
|
console.error(`Hub: query '${message.queryId}' error:`, message.payload);
|
|
@@ -177,6 +179,15 @@ class WebSocketHubConnection {
|
|
|
177
179
|
const result = message.payload;
|
|
178
180
|
sub.callback(result);
|
|
179
181
|
}
|
|
182
|
+
handleUnauthorized(message) {
|
|
183
|
+
if (!message.queryId)
|
|
184
|
+
return;
|
|
185
|
+
const sub = this._subscriptions.get(message.queryId);
|
|
186
|
+
if (!sub)
|
|
187
|
+
return;
|
|
188
|
+
this._subscriptions.delete(message.queryId);
|
|
189
|
+
sub.callback(QueryResult.QueryResult.unauthorized());
|
|
190
|
+
}
|
|
180
191
|
handlePong(message) {
|
|
181
192
|
if (message.timestamp && this._lastPingSentTime) {
|
|
182
193
|
const latency = Date.now() - message.timestamp;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as integers by the Cratis JSON configuration.\n */\nexport enum HubMessageType {\n Subscribe = 0,\n Unsubscribe = 1,\n QueryResult = 2,\n Unauthorized = 3,\n Error = 4,\n Ping = 5,\n Pong = 6,\n Connected = 7,\n}\n\n/**\n * Wire format for messages exchanged over the {@link WebSocketHubConnection}.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n payload?: any;\n timestamp?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({ type: HubMessageType.Ping, timestamp: this._lastPingSentTime });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n this._subscriptions.set(queryId, { request, callback });\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, request);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendMessage({ type: HubMessageType.Unsubscribe, queryId });\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {\n return;\n }\n\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private openSocket(): void {\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._socket = new WebSocket(url);\n\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n this._socket.onclose = () => {\n if (this._disconnected) return;\n console.log(`Hub connection closed: '${url}'`);\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openSocket();\n }\n }, this._url);\n };\n\n this._socket.onerror = (error) => {\n if (this._disconnected) return;\n console.error(`Hub connection error: '${url}'`, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n this._socket.onmessage = (ev) => {\n if (this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub.request);\n }\n }\n\n private sendSubscribeMessage(queryId: string, request: SubscriptionRequest): void {\n this.sendMessage({\n type: HubMessageType.Subscribe,\n queryId,\n payload: request,\n });\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn(`Hub: query '${message.queryId}' unauthorized`);\n break;\n case HubMessageType.Error:\n console.error(`Hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","ReconnectPolicy","HubConnectionKeepAlive","Globals"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as integers by the Cratis JSON configuration.\n */\nexport enum HubMessageType {\n Subscribe = 0,\n Unsubscribe = 1,\n QueryResult = 2,\n Unauthorized = 3,\n Error = 4,\n Ping = 5,\n Pong = 6,\n Connected = 7,\n}\n\n/**\n * Wire format for messages exchanged over the {@link WebSocketHubConnection}.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n payload?: any;\n timestamp?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({ type: HubMessageType.Ping, timestamp: this._lastPingSentTime });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n this._subscriptions.set(queryId, { request, callback });\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, request);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendMessage({ type: HubMessageType.Unsubscribe, queryId });\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {\n return;\n }\n\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private openSocket(): void {\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._socket = new WebSocket(url);\n\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n this._socket.onclose = () => {\n if (this._disconnected) return;\n console.log(`Hub connection closed: '${url}'`);\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openSocket();\n }\n }, this._url);\n };\n\n this._socket.onerror = (error) => {\n if (this._disconnected) return;\n console.error(`Hub connection error: '${url}'`, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n this._socket.onmessage = (ev) => {\n if (this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub.request);\n }\n }\n\n private sendSubscribeMessage(queryId: string, request: SubscriptionRequest): void {\n this.sendMessage({\n type: HubMessageType.Subscribe,\n queryId,\n payload: request,\n });\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn(`Hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`Hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","ReconnectPolicy","HubConnectionKeepAlive","Globals","QueryResult"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after_release_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_acquiring/after_release_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_cancellation_before_timeout.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_deferring_dispose/with_cancellation_before_timeout.ts"],"names":[],"mappings":""}
|
package/dist/cjs/queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"without_cancellation.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_deferring_dispose/without_cancellation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"an_empty_cache.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/an_empty_cache.ts"],"names":[],"mappings":""}
|
package/dist/cjs/queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_active_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/with_active_subscriptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_pending_deferred_cleanup.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_disposing/with_pending_deferred_cleanup.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"the_only_subscriber_in_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_in_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"the_only_subscriber_outside_development_mode.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_releasing/the_only_subscriber_outside_development_mode.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_active_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_active_subscriptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_no_subscriptions.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_no_subscriptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_pending_deferred_cleanup.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryInstanceCache/when_tearing_down_all_subscriptions/with_pending_deferred_cleanup.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifies_subscriber_and_removes_subscription.d.ts","sourceRoot":"","sources":["../../../../../queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifies_subscriber_and_removes_subscription.d.ts","sourceRoot":"","sources":["../../../../../queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts"],"names":[],"mappings":""}
|
|
@@ -13,7 +13,8 @@ export declare class IdentityProvider extends IIdentityProvider {
|
|
|
13
13
|
static getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
|
|
14
14
|
getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
|
|
15
15
|
static refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>>;
|
|
16
|
+
private static notSet;
|
|
16
17
|
private static getCookie;
|
|
17
|
-
|
|
18
|
+
static clearIdentityCookie(): void;
|
|
18
19
|
}
|
|
19
20
|
//# sourceMappingURL=IdentityProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,qBAAa,gBAAiB,SAAQ,iBAAiB;IAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAsB;IAChD,MAAM,CAAC,mBAAmB,EAAE,cAAc,GAAG,SAAS,CAAC;IACvD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAM;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAM3B,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ7D,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQhD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;WAUzB,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAsB/G,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;WAIjG,OAAO,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,qBAAa,gBAAiB,SAAQ,iBAAiB;IAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAsB;IAChD,MAAM,CAAC,mBAAmB,EAAE,cAAc,GAAG,SAAS,CAAC;IACvD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAM;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAM3B,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ7D,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQhD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;WAUzB,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAsB/G,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;WAIjG,OAAO,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IA8BlH,OAAO,CAAC,MAAM,CAAC,MAAM;IAYrB,OAAO,CAAC,MAAM,CAAC,SAAS;IAiBxB,MAAM,CAAC,mBAAmB,IAAI,IAAI;CAIrC"}
|
|
@@ -43,7 +43,7 @@ class IdentityProvider extends IIdentityProvider {
|
|
|
43
43
|
return IdentityProvider.getCurrent(type);
|
|
44
44
|
}
|
|
45
45
|
static async refresh(type) {
|
|
46
|
-
IdentityProvider.
|
|
46
|
+
IdentityProvider.clearIdentityCookie();
|
|
47
47
|
const origin = IdentityProvider.origin || Globals.origin || '';
|
|
48
48
|
const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';
|
|
49
49
|
const route = joinPaths(apiBasePath, '/.cratis/me');
|
|
@@ -52,6 +52,9 @@ class IdentityProvider extends IIdentityProvider {
|
|
|
52
52
|
method: 'GET',
|
|
53
53
|
headers: IdentityProvider.httpHeadersCallback?.() ?? {}
|
|
54
54
|
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
return IdentityProvider.notSet(type);
|
|
57
|
+
}
|
|
55
58
|
const result = await response.json();
|
|
56
59
|
const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;
|
|
57
60
|
return {
|
|
@@ -64,6 +67,17 @@ class IdentityProvider extends IIdentityProvider {
|
|
|
64
67
|
refresh: () => IdentityProvider.refresh(type)
|
|
65
68
|
};
|
|
66
69
|
}
|
|
70
|
+
static notSet(type) {
|
|
71
|
+
return {
|
|
72
|
+
id: '',
|
|
73
|
+
name: '',
|
|
74
|
+
roles: [],
|
|
75
|
+
details: {},
|
|
76
|
+
isSet: false,
|
|
77
|
+
isInRole: () => false,
|
|
78
|
+
refresh: () => IdentityProvider.refresh(type)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
67
81
|
static getCookie() {
|
|
68
82
|
if (typeof document === 'undefined')
|
|
69
83
|
return [];
|
|
@@ -76,7 +90,7 @@ class IdentityProvider extends IIdentityProvider {
|
|
|
76
90
|
}
|
|
77
91
|
return [];
|
|
78
92
|
}
|
|
79
|
-
static
|
|
93
|
+
static clearIdentityCookie() {
|
|
80
94
|
if (typeof document === 'undefined')
|
|
81
95
|
return;
|
|
82
96
|
document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.
|
|
1
|
+
{"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearIdentityCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n if (!response.ok) {\n return IdentityProvider.notSet(type);\n }\n\n const result = await response.json() as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static notSet<TDetails extends object = object>(type?: Constructor<TDetails>): IIdentity<TDetails> {\n return {\n id: '',\n name: '',\n roles: [],\n details: {} as TDetails,\n isSet: false,\n isInRole: () => false,\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n /**\n * Clears the identity cookie used by Arc to cache the current identity.\n * Call this when the user logs out to ensure subsequent requests and WebSocket\n * connections do not carry stale credentials.\n */\n static clearIdentityCookie(): void {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_unauthorized_response.d.ts","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IdentityProvider } from '../../IdentityProvider';
|
|
2
|
+
import { an_identity_provider } from '../given/an_identity_provider';
|
|
3
|
+
import { given } from '../../../given';
|
|
4
|
+
describe('when refreshing with unauthorized response', given(an_identity_provider, context => {
|
|
5
|
+
let result;
|
|
6
|
+
beforeEach(async () => {
|
|
7
|
+
context.fetchStub.resolves({
|
|
8
|
+
ok: false,
|
|
9
|
+
status: 401,
|
|
10
|
+
});
|
|
11
|
+
result = await IdentityProvider.refresh();
|
|
12
|
+
});
|
|
13
|
+
it('should return identity with isSet false', () => result.isSet.should.be.false);
|
|
14
|
+
it('should return empty identity id', () => result.id.should.equal(''));
|
|
15
|
+
it('should return empty identity name', () => result.name.should.equal(''));
|
|
16
|
+
it('should return empty roles', () => result.roles.should.be.empty);
|
|
17
|
+
it('should provide a refresh method', () => result.refresh.should.be.a('function'));
|
|
18
|
+
}));
|
|
19
|
+
//# sourceMappingURL=with_unauthorized_response.js.map
|
package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_unauthorized_response.js","sourceRoot":"","sources":["../../../../../identity/for_IdentityProvider/when_refreshing/with_unauthorized_response.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,QAAQ,CAAC,4CAA4C,EAAE,KAAK,CAAC,oBAAoB,EAAE,OAAO,CAAC,EAAE;IACzF,IAAI,MAAiB,CAAC;IAEtB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC;YACvB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;SACF,CAAC,CAAC;QAEf,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAClF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACpE,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AACxF,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -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;
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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"}
|