@cratis/arc 22.87.1 → 22.88.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/commands/for_Command/when_executing/and_fetch_throws_exception.ts +2 -0
- package/commands/for_Command/when_validating/and_fetch_throws_exception.ts +2 -0
- package/dist/cjs/queries/ObservableQueryConnection.d.ts +1 -0
- package/dist/cjs/queries/ObservableQueryConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ObservableQueryConnection.js +11 -6
- package/dist/cjs/queries/ObservableQueryConnection.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 +9 -7
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/ServerSentEventQueryConnection.d.ts +1 -0
- package/dist/cjs/queries/ServerSentEventQueryConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ServerSentEventQueryConnection.js +17 -13
- package/dist/cjs/queries/ServerSentEventQueryConnection.js.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.js +3 -0
- package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/cjs/validation/ValidationResultReason.d.ts +1 -0
- package/dist/cjs/validation/ValidationResultReason.d.ts.map +1 -1
- package/dist/cjs/validation/ValidationResultReason.js +5 -1
- package/dist/cjs/validation/ValidationResultReason.js.map +1 -1
- package/dist/cjs/validation/rules/NotEmptyRule.js +1 -1
- package/dist/cjs/validation/rules/NotEmptyRule.js.map +1 -1
- package/dist/esm/commands/for_Command/when_executing/and_fetch_throws_exception.js +1 -0
- package/dist/esm/commands/for_Command/when_executing/and_fetch_throws_exception.js.map +1 -1
- package/dist/esm/commands/for_Command/when_validating/and_fetch_throws_exception.js +1 -0
- package/dist/esm/commands/for_Command/when_validating/and_fetch_throws_exception.js.map +1 -1
- package/dist/esm/queries/ObservableQueryConnection.d.ts +1 -0
- package/dist/esm/queries/ObservableQueryConnection.d.ts.map +1 -1
- package/dist/esm/queries/ObservableQueryConnection.js +11 -6
- package/dist/esm/queries/ObservableQueryConnection.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 +9 -7
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/ServerSentEventQueryConnection.d.ts +1 -0
- package/dist/esm/queries/ServerSentEventQueryConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventQueryConnection.js +17 -13
- package/dist/esm/queries/ServerSentEventQueryConnection.js.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.js +3 -0
- package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_server_validation_failing.d.ts +2 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_server_validation_failing.d.ts.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_server_validation_failing.js +36 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_server_validation_failing.js.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_server_validation_failing.d.ts +2 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_server_validation_failing.d.ts.map +1 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_server_validation_failing.js +110 -0
- package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_server_validation_failing.js.map +1 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_server_validation_failing.d.ts +2 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_server_validation_failing.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_server_validation_failing.js +36 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_server_validation_failing.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/validation/ValidationResultReason.d.ts +1 -0
- package/dist/esm/validation/ValidationResultReason.d.ts.map +1 -1
- package/dist/esm/validation/ValidationResultReason.js +5 -1
- package/dist/esm/validation/ValidationResultReason.js.map +1 -1
- package/dist/esm/validation/rules/NotEmptyRule.js +1 -1
- package/dist/esm/validation/rules/NotEmptyRule.js.map +1 -1
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_a_byte_order_mark.d.ts +2 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_a_byte_order_mark.d.ts.map +1 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_a_byte_order_mark.js +8 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_a_byte_order_mark.js.map +1 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_mixed_unicode_whitespace.d.ts +2 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_mixed_unicode_whitespace.d.ts.map +1 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_mixed_unicode_whitespace.js +8 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_mixed_unicode_whitespace.js.map +1 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_next_line_whitespace.d.ts +2 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_next_line_whitespace.d.ts.map +1 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_next_line_whitespace.js +8 -0
- package/dist/esm/validation/rules/for_NotEmptyRule/when_validating/with_next_line_whitespace.js.map +1 -0
- package/package.json +1 -1
- package/queries/ObservableQueryConnection.ts +13 -8
- package/queries/ServerSentEventHubConnection.ts +10 -9
- package/queries/ServerSentEventQueryConnection.ts +18 -13
- package/queries/WebSocketHubConnection.ts +3 -0
- package/queries/for_ObservableQueryFor/when_performing/with_server_validation_failing.ts +43 -0
- package/queries/for_ObservableQueryFor/when_subscribing/with_server_validation_failing.ts +130 -0
- package/queries/for_QueryFor/when_performing/with_server_validation_failing.ts +43 -0
- package/validation/ValidationResultReason.ts +7 -1
- package/validation/rules/NotEmptyRule.ts +1 -1
- package/validation/rules/for_NotEmptyRule/when_validating/with_a_byte_order_mark.ts +11 -0
- package/validation/rules/for_NotEmptyRule/when_validating/with_mixed_unicode_whitespace.ts +11 -0
- package/validation/rules/for_NotEmptyRule/when_validating/with_next_line_whitespace.ts +11 -0
|
@@ -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.js';\nimport type { DataReceived } from './ObservableQueryConnection.js';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive.js';\nimport type { IReconnectPolicy } from './IReconnectPolicy.js';\nimport { ReconnectPolicy } from './ReconnectPolicy.js';\nimport { QueryResult } from './QueryResult.js';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the observable query WebSocket and SSE hub transports.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n\n /** Optional positive safe-integer revision used to reject stale replacement messages. */\n revision?: number;\n\n /**\n * Whether the server supports revision-aware subscription operations and result frames.\n * Only present on {@link HubMessageType.Connected} messages from capable servers.\n */\n supportsSubscriptionRevisions?: boolean;\n payload?: any;\n timestamp?: number;\n\n /**\n * The server's keep-alive interval in milliseconds, or 0 when keep-alive is disabled.\n * Only present on {@link HubMessageType.Connected} messages.\n */\n keepAliveIntervalMs?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n revision: number;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback. The client initially subscribes\n * without revisions for compatibility with older servers, then replaces active subscriptions with\n * revision-aware operations when the server advertises support in a Connected message.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _nextRevision = 0;\n private _supportsSubscriptionRevisions = false;\n private _reconnectPending = false;\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} _url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy(),\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({\n type: HubMessageType.Ping,\n timestamp: this._lastPingSentTime,\n });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return (\n this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length\n );\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(\n queryId: string,\n request: SubscriptionRequest,\n callback: DataReceived<any>,\n ): void {\n const subscription = { request, callback, revision: this.getNextRevision() };\n this._subscriptions.set(queryId, subscription);\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, subscription);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n const subscription = this._subscriptions.get(queryId);\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN && subscription) {\n const message: HubMessage = {\n type: HubMessageType.Unsubscribe,\n queryId,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._subscriptions.clear();\n this.close();\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (\n this._socket &&\n (this._socket.readyState === WebSocket.OPEN ||\n this._socket.readyState === WebSocket.CONNECTING)\n ) {\n this.cancelPendingReconnect();\n return;\n }\n\n // A subscription can arrive while an earlier close is waiting in reconnect backoff. The immediate open owns\n // the connection now, so the delayed callback must not be allowed to create a competing socket later.\n this.cancelPendingReconnect();\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n this._reconnectPending = false;\n const socket = this._socket;\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n if (socket) {\n this.detachAndCloseSocket(socket);\n }\n }\n\n private openSocket(): void {\n const currentSocket = this._socket;\n if (\n currentSocket &&\n (currentSocket.readyState === WebSocket.OPEN ||\n currentSocket.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (currentSocket) {\n this._socket = undefined;\n this.detachAndCloseSocket(currentSocket);\n }\n\n this._supportsSubscriptionRevisions = false;\n\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n const socket = new WebSocket(url);\n this._socket = socket;\n\n socket.onopen = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection established', url);\n this.cancelPendingReconnect();\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n socket.onclose = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection closed', url);\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._reconnectPending = true;\n const scheduled = this._policy.schedule(() => {\n this._reconnectPending = false;\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.ensureConnected();\n }\n }, this._url);\n if (!scheduled) {\n this._reconnectPending = false;\n }\n };\n\n socket.onerror = (error) => {\n if (this._socket !== socket || this._disconnected) return;\n console.error('Hub connection error', url, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n socket.onmessage = (ev) => {\n if (this._socket !== socket || this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private cancelPendingReconnect(): void {\n if (!this._reconnectPending) return;\n\n this._policy.cancel();\n this._reconnectPending = false;\n }\n\n private detachAndCloseSocket(socket: WebSocket): void {\n socket.onopen = null;\n socket.onclose = null;\n socket.onerror = null;\n socket.onmessage = null;\n socket.close();\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub);\n }\n }\n\n private sendSubscribeMessage(\n queryId: string,\n subscription: ActiveSubscription,\n ): void {\n const message: HubMessage = {\n type: HubMessageType.Subscribe,\n queryId,\n payload: subscription.request,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn('Hub: query unauthorized', message.queryId);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n if (this.isMessageForCurrentSubscription(message)) {\n console.error(\n 'Hub: query error',\n message.queryId,\n message.payload,\n );\n }\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n if (\n message.supportsSubscriptionRevisions !== true ||\n this._supportsSubscriptionRevisions\n ) {\n return;\n }\n\n this._supportsSubscriptionRevisions = true;\n\n // The legacy subscriptions sent on socket open keep this client compatible with older servers.\n // Ordered WebSocket delivery means these revision-aware replacements are processed afterwards.\n this.sendAllSubscriptions();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private isMessageForCurrentSubscription(message: HubMessage): boolean {\n if (!message.queryId) return false;\n\n if (!this._supportsSubscriptionRevisions) {\n return (\n message.revision === undefined &&\n this._subscriptions.has(message.queryId)\n );\n }\n\n return (\n this.isValidRevision(message.revision) &&\n this._subscriptions.get(message.queryId)?.revision === message.revision\n );\n }\n\n private isValidRevision(revision: number | undefined): revision is number {\n return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;\n }\n\n private getNextRevision(): number {\n if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n 'WebSocket hub subscription revision exhausted the safe integer range',\n );\n }\n\n return ++this._nextRevision;\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_nextRevision","_supportsSubscriptionRevisions","_reconnectPending","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","subscription","revision","getNextRevision","set","ensureConnected","sendSubscribeMessage","unsubscribe","get","delete","message","close","dispose","clear","CONNECTING","cancelPendingReconnect","openSocket","stop","cancel","socket","undefined","detachAndCloseSocket","currentSocket","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","onopen","console","log","reset","start","sendAllSubscriptions","onclose","scheduled","schedule","onerror","error","onmessage","ev","handleMessage","data","sub","payload","send","JSON","stringify","rawData","parse","recordActivity","handleConnected","handleQueryResult","handlePong","warn","handleUnauthorized","isMessageForCurrentSubscription","supportsSubscriptionRevisions","result","QueryResult","unauthorized","has","isValidRevision","Number","isSafeInteger","MAX_SAFE_INTEGER","RangeError","latency","push","shift"],"mappings":"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"}
|
|
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.js';\nimport type { DataReceived } from './ObservableQueryConnection.js';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive.js';\nimport type { IReconnectPolicy } from './IReconnectPolicy.js';\nimport { ReconnectPolicy } from './ReconnectPolicy.js';\nimport { QueryResult } from './QueryResult.js';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the observable query WebSocket and SSE hub transports.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n\n /** Optional positive safe-integer revision used to reject stale replacement messages. */\n revision?: number;\n\n /**\n * Whether the server supports revision-aware subscription operations and result frames.\n * Only present on {@link HubMessageType.Connected} messages from capable servers.\n */\n supportsSubscriptionRevisions?: boolean;\n payload?: any;\n timestamp?: number;\n\n /**\n * The server's keep-alive interval in milliseconds, or 0 when keep-alive is disabled.\n * Only present on {@link HubMessageType.Connected} messages.\n */\n keepAliveIntervalMs?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n revision: number;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback. The client initially subscribes\n * without revisions for compatibility with older servers, then replaces active subscriptions with\n * revision-aware operations when the server advertises support in a Connected message.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _nextRevision = 0;\n private _supportsSubscriptionRevisions = false;\n private _reconnectPending = false;\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} _url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy(),\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({\n type: HubMessageType.Ping,\n timestamp: this._lastPingSentTime,\n });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return (\n this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length\n );\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(\n queryId: string,\n request: SubscriptionRequest,\n callback: DataReceived<any>,\n ): void {\n const subscription = { request, callback, revision: this.getNextRevision() };\n this._subscriptions.set(queryId, subscription);\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, subscription);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n const subscription = this._subscriptions.get(queryId);\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN && subscription) {\n const message: HubMessage = {\n type: HubMessageType.Unsubscribe,\n queryId,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._subscriptions.clear();\n this.close();\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (\n this._socket &&\n (this._socket.readyState === WebSocket.OPEN ||\n this._socket.readyState === WebSocket.CONNECTING)\n ) {\n this.cancelPendingReconnect();\n return;\n }\n\n // A subscription can arrive while an earlier close is waiting in reconnect backoff. The immediate open owns\n // the connection now, so the delayed callback must not be allowed to create a competing socket later.\n this.cancelPendingReconnect();\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n this._reconnectPending = false;\n const socket = this._socket;\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n if (socket) {\n this.detachAndCloseSocket(socket);\n }\n }\n\n private openSocket(): void {\n const currentSocket = this._socket;\n if (\n currentSocket &&\n (currentSocket.readyState === WebSocket.OPEN ||\n currentSocket.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (currentSocket) {\n this._socket = undefined;\n this.detachAndCloseSocket(currentSocket);\n }\n\n this._supportsSubscriptionRevisions = false;\n\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n const socket = new WebSocket(url);\n this._socket = socket;\n\n socket.onopen = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection established', url);\n this.cancelPendingReconnect();\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n socket.onclose = () => {\n if (this._socket !== socket || this._disconnected) return;\n console.log('Hub connection closed', url);\n this._socket = undefined;\n this._supportsSubscriptionRevisions = false;\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._reconnectPending = true;\n const scheduled = this._policy.schedule(() => {\n this._reconnectPending = false;\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.ensureConnected();\n }\n }, this._url);\n if (!scheduled) {\n this._reconnectPending = false;\n }\n };\n\n socket.onerror = (error) => {\n if (this._socket !== socket || this._disconnected) return;\n console.error('Hub connection error', url, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n socket.onmessage = (ev) => {\n if (this._socket !== socket || this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private cancelPendingReconnect(): void {\n if (!this._reconnectPending) return;\n\n this._policy.cancel();\n this._reconnectPending = false;\n }\n\n private detachAndCloseSocket(socket: WebSocket): void {\n socket.onopen = null;\n socket.onclose = null;\n socket.onerror = null;\n socket.onmessage = null;\n socket.close();\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub);\n }\n }\n\n private sendSubscribeMessage(\n queryId: string,\n subscription: ActiveSubscription,\n ): void {\n const message: HubMessage = {\n type: HubMessageType.Subscribe,\n queryId,\n payload: subscription.request,\n };\n if (this._supportsSubscriptionRevisions) {\n message.revision = subscription.revision;\n }\n this.sendMessage(message);\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn('Hub: query unauthorized', message.queryId);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n if (this.isMessageForCurrentSubscription(message)) {\n console.error(\n 'Hub: query error',\n message.queryId,\n message.payload,\n );\n }\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n if (\n message.supportsSubscriptionRevisions !== true ||\n this._supportsSubscriptionRevisions\n ) {\n return;\n }\n\n this._supportsSubscriptionRevisions = true;\n\n // The legacy subscriptions sent on socket open keep this client compatible with older servers.\n // Ordered WebSocket delivery means these revision-aware replacements are processed afterwards.\n this.sendAllSubscriptions();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n const result = message.payload as QueryResult<any>;\n if (result?.isValid === false) {\n this._subscriptions.delete(message.queryId);\n }\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private isMessageForCurrentSubscription(message: HubMessage): boolean {\n if (!message.queryId) return false;\n\n if (!this._supportsSubscriptionRevisions) {\n return (\n message.revision === undefined &&\n this._subscriptions.has(message.queryId)\n );\n }\n\n return (\n this.isValidRevision(message.revision) &&\n this._subscriptions.get(message.queryId)?.revision === message.revision\n );\n }\n\n private isValidRevision(revision: number | undefined): revision is number {\n return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;\n }\n\n private getNextRevision(): number {\n if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n 'WebSocket hub subscription revision exhausted the safe integer range',\n );\n }\n\n return ++this._nextRevision;\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_nextRevision","_supportsSubscriptionRevisions","_reconnectPending","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","subscription","revision","getNextRevision","set","ensureConnected","sendSubscribeMessage","unsubscribe","get","delete","message","close","dispose","clear","CONNECTING","cancelPendingReconnect","openSocket","stop","cancel","socket","undefined","detachAndCloseSocket","currentSocket","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","onopen","console","log","reset","start","sendAllSubscriptions","onclose","scheduled","schedule","onerror","error","onmessage","ev","handleMessage","data","sub","payload","send","JSON","stringify","rawData","parse","recordActivity","handleConnected","handleQueryResult","handlePong","warn","handleUnauthorized","isMessageForCurrentSubscription","supportsSubscriptionRevisions","result","isValid","QueryResult","unauthorized","has","isValidRevision","Number","isSafeInteger","MAX_SAFE_INTEGER","RangeError","latency","push","shift"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ export declare const ValidationResultReason: {
|
|
|
5
5
|
readonly ValidatorFailed: 'validatorFailed';
|
|
6
6
|
readonly DependencyUnavailable: 'dependencyUnavailable';
|
|
7
7
|
readonly MalformedRequest: 'malformedRequest';
|
|
8
|
+
readonly FrameworkFailure: 'frameworkFailure';
|
|
8
9
|
};
|
|
9
10
|
export type ValidationResultReason = string;
|
|
10
11
|
//# sourceMappingURL=ValidationResultReason.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationResultReason.d.ts","sourceRoot":"","sources":["../../../validation/ValidationResultReason.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB;aAK/B,IAAI,EAAE,MAAM;aAKZ,oBAAoB,EAAE,sBAAsB;aAK5C,mBAAmB,EAAE,qBAAqB;aAM1C,eAAe,EAAE,iBAAiB;aAMlC,qBAAqB,EAAE,uBAAuB;aAM9C,gBAAgB,EAAE,kBAAkB;CAC9B,CAAC;AAKX,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"ValidationResultReason.d.ts","sourceRoot":"","sources":["../../../validation/ValidationResultReason.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB;aAK/B,IAAI,EAAE,MAAM;aAKZ,oBAAoB,EAAE,sBAAsB;aAK5C,mBAAmB,EAAE,qBAAqB;aAM1C,eAAe,EAAE,iBAAiB;aAMlC,qBAAqB,EAAE,uBAAuB;aAM9C,gBAAgB,EAAE,kBAAkB;aAMpC,gBAAgB,EAAE,kBAAkB;CAC9B,CAAC;AAKX,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC"}
|
|
@@ -33,7 +33,11 @@
|
|
|
33
33
|
/**
|
|
34
34
|
* The request itself could not be read - a malformed body, or a value that could not be bound. No rule was
|
|
35
35
|
* reached.
|
|
36
|
-
*/ MalformedRequest: 'malformedRequest'
|
|
36
|
+
*/ MalformedRequest: 'malformedRequest',
|
|
37
|
+
/**
|
|
38
|
+
* The framework could not fulfill a command contract or complete its effects. This is framework-composed;
|
|
39
|
+
* the message is a developer diagnostic, not end-user copy.
|
|
40
|
+
*/ FrameworkFailure: 'frameworkFailure'
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
exports.ValidationResultReason = ValidationResultReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationResultReason.js","sources":["../../../validation/ValidationResultReason.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Holds the well-known values for what composed a validation result - the machine-readable counterpart to its\n * message.\n * @remarks\n * A rejection's message is a developer diagnostic, not copy to show a user. Branch on this instead of matching the\n * message, and render your own wording for anything the framework composed.\n *\n * This is deliberately not an enum. Rejections are composed in Arc, in Chronicle and in application code, so the set\n * is open: treat an unrecognized value the way you would treat {@link ValidationResultReason.Rule} rather than as an\n * error.\n */\nexport const ValidationResultReason = {\n\n /**\n * A rule authored by the application rejected the input. The message is the author's, and is meant to be shown.\n */\n Rule: 'rule',\n\n /**\n * The append was rejected because the event source moved on since it was read. Retryable - re-read and resubmit.\n */\n ConcurrencyViolation: 'concurrencyViolation',\n\n /**\n * A constraint on the event store rejected the append.\n */\n ConstraintViolation: 'constraintViolation',\n\n /**\n * A validator threw, and the framework substituted this result for the one the validator would have produced.\n * Nothing the author wrote survives, so the message is not theirs to show.\n */\n ValidatorFailed: 'validatorFailed',\n\n /**\n * Something the command needed in order to be evaluated was not available, most often the read model a\n * validator depends on. Raised before any rule ran, so nothing about the command's own rules was decided.\n */\n DependencyUnavailable: 'dependencyUnavailable',\n\n /**\n * The request itself could not be read - a malformed body, or a value that could not be bound. No rule was\n * reached.\n */\n MalformedRequest: 'malformedRequest'\n} as const;\n\n/**\n * The type of a validation result reason. Widened to string because the set is open.\n */\nexport type ValidationResultReason = string;\n"],"names":["ValidationResultReason","Rule","ConcurrencyViolation","ConstraintViolation","ValidatorFailed","DependencyUnavailable","MalformedRequest"],"mappings":";;AAAA;AACA;AAEA;;;;;;;;;;UAWaA,sBAAAA,GAAyB;AAElC;;AAEC,QACDC,IAAAA,EAAM,MAAA;AAEN;;AAEC,QACDC,oBAAAA,EAAsB,sBAAA;AAEtB;;AAEC,QACDC,mBAAAA,EAAqB,qBAAA;AAErB;;;AAGC,QACDC,eAAAA,EAAiB,iBAAA;AAEjB;;;AAGC,QACDC,qBAAAA,EAAuB,uBAAA;AAEvB;;;AAGC,QACDC,gBAAAA,EAAkB;AACtB;;"}
|
|
1
|
+
{"version":3,"file":"ValidationResultReason.js","sources":["../../../validation/ValidationResultReason.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Holds the well-known values for what composed a validation result - the machine-readable counterpart to its\n * message.\n * @remarks\n * A rejection's message is a developer diagnostic, not copy to show a user. Branch on this instead of matching the\n * message, and render your own wording for anything the framework composed.\n *\n * This is deliberately not an enum. Rejections are composed in Arc, in Chronicle and in application code, so the set\n * is open: treat an unrecognized value the way you would treat {@link ValidationResultReason.Rule} rather than as an\n * error.\n */\nexport const ValidationResultReason = {\n\n /**\n * A rule authored by the application rejected the input. The message is the author's, and is meant to be shown.\n */\n Rule: 'rule',\n\n /**\n * The append was rejected because the event source moved on since it was read. Retryable - re-read and resubmit.\n */\n ConcurrencyViolation: 'concurrencyViolation',\n\n /**\n * A constraint on the event store rejected the append.\n */\n ConstraintViolation: 'constraintViolation',\n\n /**\n * A validator threw, and the framework substituted this result for the one the validator would have produced.\n * Nothing the author wrote survives, so the message is not theirs to show.\n */\n ValidatorFailed: 'validatorFailed',\n\n /**\n * Something the command needed in order to be evaluated was not available, most often the read model a\n * validator depends on. Raised before any rule ran, so nothing about the command's own rules was decided.\n */\n DependencyUnavailable: 'dependencyUnavailable',\n\n /**\n * The request itself could not be read - a malformed body, or a value that could not be bound. No rule was\n * reached.\n */\n MalformedRequest: 'malformedRequest',\n\n /**\n * The framework could not fulfill a command contract or complete its effects. This is framework-composed;\n * the message is a developer diagnostic, not end-user copy.\n */\n FrameworkFailure: 'frameworkFailure'\n} as const;\n\n/**\n * The type of a validation result reason. Widened to string because the set is open.\n */\nexport type ValidationResultReason = string;\n"],"names":["ValidationResultReason","Rule","ConcurrencyViolation","ConstraintViolation","ValidatorFailed","DependencyUnavailable","MalformedRequest","FrameworkFailure"],"mappings":";;AAAA;AACA;AAEA;;;;;;;;;;UAWaA,sBAAAA,GAAyB;AAElC;;AAEC,QACDC,IAAAA,EAAM,MAAA;AAEN;;AAEC,QACDC,oBAAAA,EAAsB,sBAAA;AAEtB;;AAEC,QACDC,mBAAAA,EAAqB,qBAAA;AAErB;;;AAGC,QACDC,eAAAA,EAAiB,iBAAA;AAEjB;;;AAGC,QACDC,qBAAAA,EAAuB,uBAAA;AAEvB;;;AAGC,QACDC,gBAAAA,EAAkB,kBAAA;AAElB;;;AAGC,QACDC,gBAAAA,EAAkB;AACtB;;"}
|
|
@@ -18,7 +18,7 @@ var PropertyRule = require('../PropertyRule.js');
|
|
|
18
18
|
if (value === null || value === undefined) {
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
|
-
if (typeof value === 'string' &&
|
|
21
|
+
if (typeof value === 'string' && /^\p{White_Space}*$/u.test(value)) {
|
|
22
22
|
return false;
|
|
23
23
|
}
|
|
24
24
|
if (Array.isArray(value) && value.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotEmptyRule.js","sources":["../../../../validation/rules/NotEmptyRule.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 { PropertyRule } from '../PropertyRule.js';\n\n/**\n * Validation rule that checks if a value is not null, undefined, or empty.\n * @template T The type being validated.\n */\nexport class NotEmptyRule<T> extends PropertyRule<T, unknown> {\n /**\n * Initializes a new instance of the {@link NotEmptyRule} class.\n * @param propertyAccessor Function to access the property value from the instance.\n */\n constructor(propertyAccessor: (instance: T) => unknown) {\n super(propertyAccessor, \"'{PropertyName}' must not be empty.\");\n }\n\n /** @inheritdoc */\n protected isValid(value: unknown): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === 'string' &&
|
|
1
|
+
{"version":3,"file":"NotEmptyRule.js","sources":["../../../../validation/rules/NotEmptyRule.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 { PropertyRule } from '../PropertyRule.js';\n\n/**\n * Validation rule that checks if a value is not null, undefined, or empty.\n * @template T The type being validated.\n */\nexport class NotEmptyRule<T> extends PropertyRule<T, unknown> {\n /**\n * Initializes a new instance of the {@link NotEmptyRule} class.\n * @param propertyAccessor Function to access the property value from the instance.\n */\n constructor(propertyAccessor: (instance: T) => unknown) {\n super(propertyAccessor, \"'{PropertyName}' must not be empty.\");\n }\n\n /** @inheritdoc */\n protected isValid(value: unknown): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === 'string' && /^\\p{White_Space}*$/u.test(value)) {\n return false;\n }\n if (Array.isArray(value) && value.length === 0) {\n return false;\n }\n return true;\n }\n}\n\n/**\n * Validation rule that checks if a value is not null or undefined.\n * @template T The type being validated.\n */\nexport class NotNullRule<T> extends PropertyRule<T, unknown> {\n /**\n * Initializes a new instance of the {@link NotNullRule} class.\n * @param propertyAccessor Function to access the property value from the instance.\n */\n constructor(propertyAccessor: (instance: T) => unknown) {\n super(propertyAccessor, \"'{PropertyName}' must not be empty.\");\n }\n\n /** @inheritdoc */\n protected isValid(value: unknown): boolean {\n return value !== null && value !== undefined;\n }\n}\n"],"names":["NotEmptyRule","PropertyRule","propertyAccessor","isValid","value","undefined","test","Array","isArray","length","NotNullRule"],"mappings":";;;;AAAA;AACA;AAIA;;;IAIO,MAAMA,YAAAA,SAAwBC,yBAAAA,CAAAA;AACjC;;;QAIA,WAAA,CAAYC,gBAA0C,CAAE;AACpD,QAAA,KAAK,CAACA,gBAAAA,EAAkB,qCAAA,CAAA;AAC5B,IAAA;AAEA,uBACUC,OAAAA,CAAQC,KAAc,EAAW;QACvC,IAAIA,KAAAA,KAAU,IAAA,IAAQA,KAAAA,KAAUC,SAAAA,EAAW;YACvC,OAAO,KAAA;AACX,QAAA;AACA,QAAA,IAAI,OAAOD,KAAAA,KAAU,QAAA,IAAY,qBAAA,CAAsBE,IAAI,CAACF,KAAAA,CAAAA,EAAQ;YAChE,OAAO,KAAA;AACX,QAAA;AACA,QAAA,IAAIG,MAAMC,OAAO,CAACJ,UAAUA,KAAAA,CAAMK,MAAM,KAAK,CAAA,EAAG;YAC5C,OAAO,KAAA;AACX,QAAA;QACA,OAAO,IAAA;AACX,IAAA;AACJ;AAEA;;;IAIO,MAAMC,WAAAA,SAAuBT,yBAAAA,CAAAA;AAChC;;;QAIA,WAAA,CAAYC,gBAA0C,CAAE;AACpD,QAAA,KAAK,CAACA,gBAAAA,EAAkB,qCAAA,CAAA;AAC5B,IAAA;AAEA,uBACUC,OAAAA,CAAQC,KAAc,EAAW;QACvC,OAAOA,KAAAA,KAAU,QAAQA,KAAAA,KAAUC,SAAAA;AACvC,IAAA;AACJ;;;"}
|
|
@@ -3,6 +3,7 @@ import { given } from '../../../given.js';
|
|
|
3
3
|
describe("when executing and fetch throws exception", given(a_command, context => {
|
|
4
4
|
let result;
|
|
5
5
|
beforeEach(async () => {
|
|
6
|
+
context.fetchStub = context.fetchHelper.stubFetch();
|
|
6
7
|
context.fetchStub.rejects(new Error('Network error'));
|
|
7
8
|
result = await context.command.execute();
|
|
8
9
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"and_fetch_throws_exception.js","sourceRoot":"","sources":["../../../../../commands/for_Command/when_executing/and_fetch_throws_exception.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,QAAQ,CAAC,2CAA2C,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;IAC7E,IAAI,MAA6B,CAAC;IAElC,UAAU,CAAC,KAAK,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"and_fetch_throws_exception.js","sourceRoot":"","sources":["../../../../../commands/for_Command/when_executing/and_fetch_throws_exception.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,QAAQ,CAAC,2CAA2C,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;IAC7E,IAAI,MAA6B,CAAC;IAElC,UAAU,CAAC,KAAK,IAAI,EAAE;QAElB,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QACpD,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;QAEtD,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACjH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { given } from '../../../given.js';
|
|
|
3
3
|
describe("when validating and fetch throws exception", given(a_command, context => {
|
|
4
4
|
let result;
|
|
5
5
|
beforeEach(async () => {
|
|
6
|
+
context.fetchStub = context.fetchHelper.stubFetch();
|
|
6
7
|
context.fetchStub.rejects(new Error('Network error'));
|
|
7
8
|
result = await context.command.validate();
|
|
8
9
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"and_fetch_throws_exception.js","sourceRoot":"","sources":["../../../../../commands/for_Command/when_validating/and_fetch_throws_exception.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,QAAQ,CAAC,4CAA4C,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;IAC9E,IAAI,MAA6B,CAAC;IAElC,UAAU,CAAC,KAAK,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"and_fetch_throws_exception.js","sourceRoot":"","sources":["../../../../../commands/for_Command/when_validating/and_fetch_throws_exception.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,QAAQ,CAAC,4CAA4C,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;IAC9E,IAAI,MAA6B,CAAC;IAElC,UAAU,CAAC,KAAK,IAAI,EAAE;QAElB,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QACpD,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;QAEtD,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAC1E,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACrH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObservableQueryConnection.d.ts","sourceRoot":"","sources":["../../../queries/ObservableQueryConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,MAAM,YAAY,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AAK7E,qBAAa,yBAAyB,CAAC,SAAS,CAAE,YAAW,0BAA0B,CAAC,SAAS,CAAC;IAoBxE,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA0C,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAlB/H,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,aAAa,CAAC,CAAiC;IACvD,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAS;IAStC,YAAY,GAAG,EAAE,GAAG,EAAmB,aAAa,EAAE,MAAM,EAAE,cAAc,GAAE,MAAc,EAAmB,gBAAgB,GAAE,gBAAwC,EAaxK;IAKD,OAAO,SAEN;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAM3B;IAGD,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,QA4CrE;IAGD,UAAU,SAWT;IAED,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"ObservableQueryConnection.d.ts","sourceRoot":"","sources":["../../../queries/ObservableQueryConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,MAAM,YAAY,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AAK7E,qBAAa,yBAAyB,CAAC,SAAS,CAAE,YAAW,0BAA0B,CAAC,SAAS,CAAC;IAoBxE,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA0C,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAlB/H,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,aAAa,CAAC,CAAiC;IACvD,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAS;IAStC,YAAY,GAAG,EAAE,GAAG,EAAmB,aAAa,EAAE,MAAM,EAAE,cAAc,GAAE,MAAc,EAAmB,gBAAgB,GAAE,gBAAwC,EAaxK;IAKD,OAAO,SAEN;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAM3B;IAGD,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,QA4CrE;IAGD,UAAU,SAWT;IAED,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,UAAU;CAYrB"}
|
|
@@ -147,17 +147,22 @@ import { WebSocketMessageType } from './WebSocketMessage.js';
|
|
|
147
147
|
// For new-style messages (type === 'Data') the query result is wrapped in message.data.
|
|
148
148
|
// For legacy/backward-compatible messages (no type) the entire message IS the query result.
|
|
149
149
|
const data = message.type === WebSocketMessageType.Data ? message.data : message;
|
|
150
|
-
|
|
151
|
-
if (result?.isAuthorized === false) {
|
|
152
|
-
this.handleUnauthorized(result, dataReceived);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
dataReceived(result);
|
|
150
|
+
this.handleResult(data, dataReceived);
|
|
156
151
|
}
|
|
157
152
|
} catch (error) {
|
|
158
153
|
console.error('Error parsing WebSocket message:', error);
|
|
159
154
|
}
|
|
160
155
|
}
|
|
156
|
+
handleResult(result, dataReceived) {
|
|
157
|
+
if (result?.isAuthorized === false) {
|
|
158
|
+
this.handleUnauthorized(result, dataReceived);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (result?.isValid === false) {
|
|
162
|
+
this.disconnect();
|
|
163
|
+
}
|
|
164
|
+
dataReceived(result);
|
|
165
|
+
}
|
|
161
166
|
/**
|
|
162
167
|
* Handles the terminal result the server sends when the caller is no longer authorized for the query it is
|
|
163
168
|
* subscribed to. The subscription is over for good, so the result is delivered and the automatic reconnect is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObservableQueryConnection.js","sources":["../../../queries/ObservableQueryConnection.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.js';\nimport { IObservableQueryConnection } from './IObservableQueryConnection.js';\nimport { IReconnectPolicy } from './IReconnectPolicy.js';\nimport { ReconnectPolicy } from './ReconnectPolicy.js';\nimport { QueryResult } from './QueryResult.js';\nimport { WebSocketMessage, WebSocketMessageType } from './WebSocketMessage.js';\n\nexport type DataReceived<TDataType> = (data: QueryResult<TDataType>) => void;\n\n/**\n * Represents the connection for an observable query.\n */\nexport class ObservableQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n\n private _socket!: WebSocket;\n private _disconnected = false;\n private _unauthorized = false;\n private _url: string;\n private _pingInterval?: ReturnType<typeof setInterval>;\n private _pingIntervalMs: number = 10000;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectionStartTime?: number;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryConnection<TDataType>} class.\n * @param {Url} url The fully qualified Url.\n * @param {string} _microservice The microservice name.\n * @param {number} pingIntervalMs The ping interval in milliseconds (default: 10000).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(url: URL, private readonly _microservice: string, pingIntervalMs: number = 10000, private readonly _reconnectPolicy: IReconnectPolicy = new ReconnectPolicy()) {\n this._pingIntervalMs = pingIntervalMs;\n const secure = url.protocol?.indexOf('https') === 0 || false;\n\n this._url = `${secure ? 'wss' : 'ws'}://${url.host}${url.pathname}${url.search}`;\n if (this._microservice?.length > 0) {\n const microserviceParam = `${Globals.microserviceWSQueryArgument}=${this._microservice}`;\n if (this._url.indexOf('?') > 0) {\n this._url = `${this._url}&${microserviceParam}`;\n } else {\n this._url = `${this._url}?${microserviceParam}`;\n }\n }\n }\n\n /**\n * Disposes the connection.\n */\n dispose() {\n this.disconnect();\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 average latency since the connection started in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) {\n return 0;\n }\n const sum = this._latencySamples.reduce((acc, val) => acc + val, 0);\n return sum / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object) {\n let url = this._url;\n if (queryArguments) {\n if (url.indexOf('?') < 0) {\n url = `${url}?`;\n } else {\n url = `${url}&`;\n }\n const query = Object.keys(queryArguments).map(key => `${key}=${queryArguments[key]}`).join('&');\n url = `${url}${query}`;\n }\n\n const connectSocket = () => {\n this._socket = new WebSocket(url);\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Connection for '${url}' established`);\n this._reconnectPolicy.reset();\n this._connectionStartTime = Date.now();\n this.startPinging();\n };\n this._socket.onclose = () => {\n if (this._disconnected || this._unauthorized) return;\n console.log(`Unexpected connection closed for route '${url}'`);\n this.stopPinging();\n this._reconnectPolicy.schedule(connectSocket, url);\n };\n this._socket.onerror = (error) => {\n if (this._disconnected || this._unauthorized) return;\n console.log(`Error with connection for '${url}' - ${error}`);\n this.stopPinging();\n this._reconnectPolicy.schedule(connectSocket, url);\n };\n this._socket.onmessage = (ev) => {\n if (this._disconnected) {\n console.log('Received message after closing connection');\n return;\n }\n this.handleMessage(ev.data, dataReceived);\n };\n };\n\n if (this._disconnected || this._unauthorized) return;\n connectSocket();\n }\n\n /** @inheritdoc */\n disconnect() {\n if (this._disconnected) {\n return;\n }\n console.log(`Disconnecting '${this._url}'`);\n this._disconnected = true;\n this._reconnectPolicy.cancel();\n this.stopPinging();\n this._socket?.close();\n console.log(`Connection for '${this._url}' closed`);\n this._socket = undefined!;\n }\n\n private startPinging() {\n this.stopPinging();\n this._pingInterval = setInterval(() => {\n this.sendPing();\n }, this._pingIntervalMs);\n }\n\n private stopPinging() {\n if (this._pingInterval) {\n clearInterval(this._pingInterval);\n this._pingInterval = undefined;\n }\n }\n\n private sendPing() {\n if (this._disconnected || !this._socket || this._socket.readyState !== WebSocket.OPEN) {\n return;\n }\n\n this._lastPingSentTime = Date.now();\n const pingMessage: WebSocketMessage = {\n type: WebSocketMessageType.Ping,\n timestamp: this._lastPingSentTime\n };\n\n this._socket.send(JSON.stringify(pingMessage));\n }\n\n private handleMessage(rawData: string, dataReceived: DataReceived<TDataType>) {\n try {\n const message = JSON.parse(rawData) as WebSocketMessage;\n\n // Handle messages based on type\n if (message.type === WebSocketMessageType.Pong) {\n this.handlePong(message);\n } else if (message.type === WebSocketMessageType.Data || !message.type) {\n // For new-style messages (type === 'Data') the query result is wrapped in message.data.\n // For legacy/backward-compatible messages (no type) the entire message IS the query result.\n const data = message.type === WebSocketMessageType.Data ? message.data : message;\n const result = data as QueryResult<TDataType>;\n\n if (result?.isAuthorized === false) {\n this.handleUnauthorized(result, dataReceived);\n return;\n }\n\n dataReceived(result);\n }\n } catch (error) {\n console.error('Error parsing WebSocket message:', error);\n }\n }\n\n /**\n * Handles the terminal result the server sends when the caller is no longer authorized for the query it is\n * subscribed to. The subscription is over for good, so the result is delivered and the automatic reconnect is\n * suppressed — reconnecting would re-subscribe, be denied again, and loop.\n * @param {QueryResult<TDataType>} result The unauthorized result to deliver.\n * @param {DataReceived<TDataType>} dataReceived Callback that receives the result.\n */\n private handleUnauthorized(result: QueryResult<TDataType>, dataReceived: DataReceived<TDataType>) {\n console.warn(`Connection for '${this._url}' was ended by the server - no longer authorized`);\n this._unauthorized = true;\n this.stopPinging();\n this._reconnectPolicy.cancel();\n dataReceived(result);\n this._socket?.close();\n }\n\n private handlePong(message: WebSocketMessage) {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n // Keep only the last 100 samples for average calculation\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["ObservableQueryConnection","_socket","_disconnected","_unauthorized","_url","_pingInterval","_pingIntervalMs","_lastPingSentTime","_lastPongLatency","_latencySamples","_connectionStartTime","url","_microservice","pingIntervalMs","_reconnectPolicy","ReconnectPolicy","secure","protocol","indexOf","host","pathname","search","length","microserviceParam","Globals","microserviceWSQueryArgument","dispose","disconnect","lastPingLatency","averageLatency","sum","reduce","acc","val","connect","dataReceived","queryArguments","query","Object","keys","map","key","join","connectSocket","WebSocket","onopen","console","log","reset","Date","now","startPinging","onclose","stopPinging","schedule","onerror","error","onmessage","ev","handleMessage","data","cancel","close","undefined","setInterval","sendPing","clearInterval","readyState","OPEN","pingMessage","type","WebSocketMessageType","Ping","timestamp","send","JSON","stringify","rawData","message","parse","Pong","handlePong","Data","result","isAuthorized","handleUnauthorized","warn","latency","push","shift"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ObservableQueryConnection.js","sources":["../../../queries/ObservableQueryConnection.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.js';\nimport { IObservableQueryConnection } from './IObservableQueryConnection.js';\nimport { IReconnectPolicy } from './IReconnectPolicy.js';\nimport { ReconnectPolicy } from './ReconnectPolicy.js';\nimport { QueryResult } from './QueryResult.js';\nimport { WebSocketMessage, WebSocketMessageType } from './WebSocketMessage.js';\n\nexport type DataReceived<TDataType> = (data: QueryResult<TDataType>) => void;\n\n/**\n * Represents the connection for an observable query.\n */\nexport class ObservableQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n\n private _socket!: WebSocket;\n private _disconnected = false;\n private _unauthorized = false;\n private _url: string;\n private _pingInterval?: ReturnType<typeof setInterval>;\n private _pingIntervalMs: number = 10000;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectionStartTime?: number;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryConnection<TDataType>} class.\n * @param {Url} url The fully qualified Url.\n * @param {string} _microservice The microservice name.\n * @param {number} pingIntervalMs The ping interval in milliseconds (default: 10000).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(url: URL, private readonly _microservice: string, pingIntervalMs: number = 10000, private readonly _reconnectPolicy: IReconnectPolicy = new ReconnectPolicy()) {\n this._pingIntervalMs = pingIntervalMs;\n const secure = url.protocol?.indexOf('https') === 0 || false;\n\n this._url = `${secure ? 'wss' : 'ws'}://${url.host}${url.pathname}${url.search}`;\n if (this._microservice?.length > 0) {\n const microserviceParam = `${Globals.microserviceWSQueryArgument}=${this._microservice}`;\n if (this._url.indexOf('?') > 0) {\n this._url = `${this._url}&${microserviceParam}`;\n } else {\n this._url = `${this._url}?${microserviceParam}`;\n }\n }\n }\n\n /**\n * Disposes the connection.\n */\n dispose() {\n this.disconnect();\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 average latency since the connection started in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) {\n return 0;\n }\n const sum = this._latencySamples.reduce((acc, val) => acc + val, 0);\n return sum / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object) {\n let url = this._url;\n if (queryArguments) {\n if (url.indexOf('?') < 0) {\n url = `${url}?`;\n } else {\n url = `${url}&`;\n }\n const query = Object.keys(queryArguments).map(key => `${key}=${queryArguments[key]}`).join('&');\n url = `${url}${query}`;\n }\n\n const connectSocket = () => {\n this._socket = new WebSocket(url);\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Connection for '${url}' established`);\n this._reconnectPolicy.reset();\n this._connectionStartTime = Date.now();\n this.startPinging();\n };\n this._socket.onclose = () => {\n if (this._disconnected || this._unauthorized) return;\n console.log(`Unexpected connection closed for route '${url}'`);\n this.stopPinging();\n this._reconnectPolicy.schedule(connectSocket, url);\n };\n this._socket.onerror = (error) => {\n if (this._disconnected || this._unauthorized) return;\n console.log(`Error with connection for '${url}' - ${error}`);\n this.stopPinging();\n this._reconnectPolicy.schedule(connectSocket, url);\n };\n this._socket.onmessage = (ev) => {\n if (this._disconnected) {\n console.log('Received message after closing connection');\n return;\n }\n this.handleMessage(ev.data, dataReceived);\n };\n };\n\n if (this._disconnected || this._unauthorized) return;\n connectSocket();\n }\n\n /** @inheritdoc */\n disconnect() {\n if (this._disconnected) {\n return;\n }\n console.log(`Disconnecting '${this._url}'`);\n this._disconnected = true;\n this._reconnectPolicy.cancel();\n this.stopPinging();\n this._socket?.close();\n console.log(`Connection for '${this._url}' closed`);\n this._socket = undefined!;\n }\n\n private startPinging() {\n this.stopPinging();\n this._pingInterval = setInterval(() => {\n this.sendPing();\n }, this._pingIntervalMs);\n }\n\n private stopPinging() {\n if (this._pingInterval) {\n clearInterval(this._pingInterval);\n this._pingInterval = undefined;\n }\n }\n\n private sendPing() {\n if (this._disconnected || !this._socket || this._socket.readyState !== WebSocket.OPEN) {\n return;\n }\n\n this._lastPingSentTime = Date.now();\n const pingMessage: WebSocketMessage = {\n type: WebSocketMessageType.Ping,\n timestamp: this._lastPingSentTime\n };\n\n this._socket.send(JSON.stringify(pingMessage));\n }\n\n private handleMessage(rawData: string, dataReceived: DataReceived<TDataType>) {\n try {\n const message = JSON.parse(rawData) as WebSocketMessage;\n\n // Handle messages based on type\n if (message.type === WebSocketMessageType.Pong) {\n this.handlePong(message);\n } else if (message.type === WebSocketMessageType.Data || !message.type) {\n // For new-style messages (type === 'Data') the query result is wrapped in message.data.\n // For legacy/backward-compatible messages (no type) the entire message IS the query result.\n const data = message.type === WebSocketMessageType.Data ? message.data : message;\n this.handleResult(data as QueryResult<TDataType>, dataReceived);\n }\n } catch (error) {\n console.error('Error parsing WebSocket message:', error);\n }\n }\n\n private handleResult(result: QueryResult<TDataType>, dataReceived: DataReceived<TDataType>) {\n if (result?.isAuthorized === false) {\n this.handleUnauthorized(result, dataReceived);\n return;\n }\n\n if (result?.isValid === false) {\n this.disconnect();\n }\n dataReceived(result);\n }\n\n /**\n * Handles the terminal result the server sends when the caller is no longer authorized for the query it is\n * subscribed to. The subscription is over for good, so the result is delivered and the automatic reconnect is\n * suppressed — reconnecting would re-subscribe, be denied again, and loop.\n * @param {QueryResult<TDataType>} result The unauthorized result to deliver.\n * @param {DataReceived<TDataType>} dataReceived Callback that receives the result.\n */\n private handleUnauthorized(result: QueryResult<TDataType>, dataReceived: DataReceived<TDataType>) {\n console.warn(`Connection for '${this._url}' was ended by the server - no longer authorized`);\n this._unauthorized = true;\n this.stopPinging();\n this._reconnectPolicy.cancel();\n dataReceived(result);\n this._socket?.close();\n }\n\n private handlePong(message: WebSocketMessage) {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n // Keep only the last 100 samples for average calculation\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["ObservableQueryConnection","_socket","_disconnected","_unauthorized","_url","_pingInterval","_pingIntervalMs","_lastPingSentTime","_lastPongLatency","_latencySamples","_connectionStartTime","url","_microservice","pingIntervalMs","_reconnectPolicy","ReconnectPolicy","secure","protocol","indexOf","host","pathname","search","length","microserviceParam","Globals","microserviceWSQueryArgument","dispose","disconnect","lastPingLatency","averageLatency","sum","reduce","acc","val","connect","dataReceived","queryArguments","query","Object","keys","map","key","join","connectSocket","WebSocket","onopen","console","log","reset","Date","now","startPinging","onclose","stopPinging","schedule","onerror","error","onmessage","ev","handleMessage","data","cancel","close","undefined","setInterval","sendPing","clearInterval","readyState","OPEN","pingMessage","type","WebSocketMessageType","Ping","timestamp","send","JSON","stringify","rawData","message","parse","Pong","handlePong","Data","handleResult","result","isAuthorized","handleUnauthorized","isValid","warn","latency","push","shift"],"mappings":";;;;AAAA;AACA;AAWA;;AAEC,IACM,MAAMA,yBAAAA,CAAAA;;;IAEDC,OAAAA;AACAC,IAAAA,aAAAA,GAAgB,KAAA;AAChBC,IAAAA,aAAAA,GAAgB,KAAA;IAChBC,IAAAA;IACAC,aAAAA;AACAC,IAAAA,eAAAA,GAA0B,KAAA;IAC1BC,iBAAAA;AACAC,IAAAA,gBAAAA,GAA2B,CAAA;AAC3BC,IAAAA,eAAAA,GAA4B,EAAE;IAC9BC,oBAAAA;AAER;;;;;;AAMC,QACD,WAAA,CAAYC,GAAQ,EAAmBC,aAAqB,EAAEC,cAAAA,GAAyB,KAAK,EAAmBC,gBAAAA,GAAqC,IAAIC,iBAAiB,CAAE;aAApIH,aAAAA,GAAAA,aAAAA;aAAwEE,gBAAAA,GAAAA,gBAAAA;QAC3G,IAAI,CAACR,eAAe,GAAGO,cAAAA;AACvB,QAAA,MAAMG,SAASL,GAAAA,CAAIM,QAAQ,EAAEC,OAAAA,CAAQ,aAAa,CAAA,IAAK,KAAA;AAEvD,QAAA,IAAI,CAACd,IAAI,GAAG,CAAA,EAAGY,MAAAA,GAAS,QAAQ,IAAA,CAAK,GAAG,EAAEL,GAAAA,CAAIQ,IAAI,CAAA,EAAGR,GAAAA,CAAIS,QAAQ,CAAA,EAAGT,GAAAA,CAAIU,MAAM,CAAA,CAAE;AAChF,QAAA,IAAI,IAAI,CAACT,aAAa,EAAEU,SAAS,CAAA,EAAG;YAChC,MAAMC,iBAAAA,GAAoB,CAAA,EAAGC,OAAAA,CAAQC,2BAA2B,CAAC,CAAC,EAAE,IAAI,CAACb,aAAa,CAAA,CAAE;AACxF,YAAA,IAAI,IAAI,CAACR,IAAI,CAACc,OAAO,CAAC,OAAO,CAAA,EAAG;gBAC5B,IAAI,CAACd,IAAI,GAAG,CAAA,EAAG,IAAI,CAACA,IAAI,CAAC,CAAC,EAAEmB,iBAAAA,CAAAA,CAAmB;YACnD,CAAA,MAAO;gBACH,IAAI,CAACnB,IAAI,GAAG,CAAA,EAAG,IAAI,CAACA,IAAI,CAAC,CAAC,EAAEmB,iBAAAA,CAAAA,CAAmB;AACnD,YAAA;AACJ,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDG,OAAAA,GAAU;AACN,QAAA,IAAI,CAACC,UAAU,EAAA;AACnB,IAAA;AAEA;;AAEC,QACD,IAAIC,eAAAA,GAA0B;QAC1B,OAAO,IAAI,CAACpB,gBAAgB;AAChC,IAAA;AAEA;;AAEC,QACD,IAAIqB,cAAAA,GAAyB;AACzB,QAAA,IAAI,IAAI,CAACpB,eAAe,CAACa,MAAM,KAAK,CAAA,EAAG;YACnC,OAAO,CAAA;AACX,QAAA;QACA,MAAMQ,GAAAA,GAAM,IAAI,CAACrB,eAAe,CAACsB,MAAM,CAAC,CAACC,GAAAA,EAAKC,GAAAA,GAAQD,GAAAA,GAAMC,GAAAA,EAAK,CAAA,CAAA;AACjE,QAAA,OAAOH,GAAAA,GAAM,IAAI,CAACrB,eAAe,CAACa,MAAM;AAC5C,IAAA;AAEA,uBACAY,OAAAA,CAAQC,YAAqC,EAAEC,cAAuB,EAAE;QACpE,IAAIzB,GAAAA,GAAM,IAAI,CAACP,IAAI;AACnB,QAAA,IAAIgC,cAAAA,EAAgB;AAChB,YAAA,IAAIzB,GAAAA,CAAIO,OAAO,CAAC,GAAA,CAAA,GAAO,CAAA,EAAG;gBACtBP,GAAAA,GAAM,CAAA,EAAGA,GAAAA,CAAI,CAAC,CAAC;YACnB,CAAA,MAAO;gBACHA,GAAAA,GAAM,CAAA,EAAGA,GAAAA,CAAI,CAAC,CAAC;AACnB,YAAA;AACA,YAAA,MAAM0B,QAAQC,MAAAA,CAAOC,IAAI,CAACH,cAAAA,CAAAA,CAAgBI,GAAG,CAACC,CAAAA,GAAAA,GAAO,GAAGA,GAAAA,CAAI,CAAC,EAAEL,cAAc,CAACK,IAAI,CAAA,CAAE,CAAA,CAAEC,IAAI,CAAC,GAAA,CAAA;YAC3F/B,GAAAA,GAAM,CAAA,EAAGA,MAAM0B,KAAAA,CAAAA,CAAO;AAC1B,QAAA;AAEA,QAAA,MAAMM,aAAAA,GAAgB,IAAA;AAClB,YAAA,IAAI,CAAC1C,OAAO,GAAG,IAAI2C,SAAAA,CAAUjC,GAAAA,CAAAA;AAC7B,YAAA,IAAI,CAACV,OAAO,CAAC4C,MAAM,GAAG,IAAA;gBAClB,IAAI,IAAI,CAAC3C,aAAa,EAAE;AACxB4C,gBAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,gBAAgB,EAAEpC,GAAAA,CAAI,aAAa,CAAC,CAAA;gBACjD,IAAI,CAACG,gBAAgB,CAACkC,KAAK,EAAA;AAC3B,gBAAA,IAAI,CAACtC,oBAAoB,GAAGuC,IAAAA,CAAKC,GAAG,EAAA;AACpC,gBAAA,IAAI,CAACC,YAAY,EAAA;AACrB,YAAA,CAAA;AACA,YAAA,IAAI,CAAClD,OAAO,CAACmD,OAAO,GAAG,IAAA;AACnB,gBAAA,IAAI,IAAI,CAAClD,aAAa,IAAI,IAAI,CAACC,aAAa,EAAE;AAC9C2C,gBAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,wCAAwC,EAAEpC,GAAAA,CAAI,CAAC,CAAC,CAAA;AAC7D,gBAAA,IAAI,CAAC0C,WAAW,EAAA;AAChB,gBAAA,IAAI,CAACvC,gBAAgB,CAACwC,QAAQ,CAACX,aAAAA,EAAehC,GAAAA,CAAAA;AAClD,YAAA,CAAA;AACA,YAAA,IAAI,CAACV,OAAO,CAACsD,OAAO,GAAG,CAACC,KAAAA,GAAAA;AACpB,gBAAA,IAAI,IAAI,CAACtD,aAAa,IAAI,IAAI,CAACC,aAAa,EAAE;gBAC9C2C,OAAAA,CAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAEpC,GAAAA,CAAI,IAAI,EAAE6C,KAAAA,CAAAA,CAAO,CAAA;AAC3D,gBAAA,IAAI,CAACH,WAAW,EAAA;AAChB,gBAAA,IAAI,CAACvC,gBAAgB,CAACwC,QAAQ,CAACX,aAAAA,EAAehC,GAAAA,CAAAA;AAClD,YAAA,CAAA;AACA,YAAA,IAAI,CAACV,OAAO,CAACwD,SAAS,GAAG,CAACC,EAAAA,GAAAA;gBACtB,IAAI,IAAI,CAACxD,aAAa,EAAE;AACpB4C,oBAAAA,OAAAA,CAAQC,GAAG,CAAC,2CAAA,CAAA;AACZ,oBAAA;AACJ,gBAAA;AACA,gBAAA,IAAI,CAACY,aAAa,CAACD,EAAAA,CAAGE,IAAI,EAAEzB,YAAAA,CAAAA;AAChC,YAAA,CAAA;AACJ,QAAA,CAAA;AAEA,QAAA,IAAI,IAAI,CAACjC,aAAa,IAAI,IAAI,CAACC,aAAa,EAAE;AAC9CwC,QAAAA,aAAAA,EAAAA;AACJ,IAAA;AAEA,uBACAhB,UAAAA,GAAa;QACT,IAAI,IAAI,CAACzB,aAAa,EAAE;AACpB,YAAA;AACJ,QAAA;QACA4C,OAAAA,CAAQC,GAAG,CAAC,CAAC,eAAe,EAAE,IAAI,CAAC3C,IAAI,CAAC,CAAC,CAAC,CAAA;QAC1C,IAAI,CAACF,aAAa,GAAG,IAAA;QACrB,IAAI,CAACY,gBAAgB,CAAC+C,MAAM,EAAA;AAC5B,QAAA,IAAI,CAACR,WAAW,EAAA;QAChB,IAAI,CAACpD,OAAO,EAAE6D,KAAAA,EAAAA;QACdhB,OAAAA,CAAQC,GAAG,CAAC,CAAC,gBAAgB,EAAE,IAAI,CAAC3C,IAAI,CAAC,QAAQ,CAAC,CAAA;QAClD,IAAI,CAACH,OAAO,GAAG8D,SAAAA;AACnB,IAAA;IAEQZ,YAAAA,GAAe;AACnB,QAAA,IAAI,CAACE,WAAW,EAAA;QAChB,IAAI,CAAChD,aAAa,GAAG2D,WAAAA,CAAY,IAAA;AAC7B,YAAA,IAAI,CAACC,QAAQ,EAAA;QACjB,CAAA,EAAG,IAAI,CAAC3D,eAAe,CAAA;AAC3B,IAAA;IAEQ+C,WAAAA,GAAc;QAClB,IAAI,IAAI,CAAChD,aAAa,EAAE;YACpB6D,aAAAA,CAAc,IAAI,CAAC7D,aAAa,CAAA;YAChC,IAAI,CAACA,aAAa,GAAG0D,SAAAA;AACzB,QAAA;AACJ,IAAA;IAEQE,QAAAA,GAAW;AACf,QAAA,IAAI,IAAI,CAAC/D,aAAa,IAAI,CAAC,IAAI,CAACD,OAAO,IAAI,IAAI,CAACA,OAAO,CAACkE,UAAU,KAAKvB,SAAAA,CAAUwB,IAAI,EAAE;AACnF,YAAA;AACJ,QAAA;AAEA,QAAA,IAAI,CAAC7D,iBAAiB,GAAG0C,IAAAA,CAAKC,GAAG,EAAA;AACjC,QAAA,MAAMmB,WAAAA,GAAgC;AAClCC,YAAAA,IAAAA,EAAMC,qBAAqBC,IAAI;YAC/BC,SAAAA,EAAW,IAAI,CAAClE;AACpB,SAAA;AAEA,QAAA,IAAI,CAACN,OAAO,CAACyE,IAAI,CAACC,IAAAA,CAAKC,SAAS,CAACP,WAAAA,CAAAA,CAAAA;AACrC,IAAA;IAEQV,aAAAA,CAAckB,OAAe,EAAE1C,YAAqC,EAAE;QAC1E,IAAI;YACA,MAAM2C,OAAAA,GAAUH,IAAAA,CAAKI,KAAK,CAACF,OAAAA,CAAAA;;AAG3B,YAAA,IAAIC,OAAAA,CAAQR,IAAI,KAAKC,oBAAAA,CAAqBS,IAAI,EAAE;gBAC5C,IAAI,CAACC,UAAU,CAACH,OAAAA,CAAAA;YACpB,CAAA,MAAO,IAAIA,OAAAA,CAAQR,IAAI,KAAKC,oBAAAA,CAAqBW,IAAI,IAAI,CAACJ,OAAAA,CAAQR,IAAI,EAAE;;;gBAGpE,MAAMV,IAAAA,GAAOkB,QAAQR,IAAI,KAAKC,qBAAqBW,IAAI,GAAGJ,OAAAA,CAAQlB,IAAI,GAAGkB,OAAAA;gBACzE,IAAI,CAACK,YAAY,CAACvB,IAAAA,EAAgCzB,YAAAA,CAAAA;AACtD,YAAA;AACJ,QAAA,CAAA,CAAE,OAAOqB,KAAAA,EAAO;YACZV,OAAAA,CAAQU,KAAK,CAAC,kCAAA,EAAoCA,KAAAA,CAAAA;AACtD,QAAA;AACJ,IAAA;IAEQ2B,YAAAA,CAAaC,MAA8B,EAAEjD,YAAqC,EAAE;QACxF,IAAIiD,MAAAA,EAAQC,iBAAiB,KAAA,EAAO;YAChC,IAAI,CAACC,kBAAkB,CAACF,MAAAA,EAAQjD,YAAAA,CAAAA;AAChC,YAAA;AACJ,QAAA;QAEA,IAAIiD,MAAAA,EAAQG,YAAY,KAAA,EAAO;AAC3B,YAAA,IAAI,CAAC5D,UAAU,EAAA;AACnB,QAAA;QACAQ,YAAAA,CAAaiD,MAAAA,CAAAA;AACjB,IAAA;AAEA;;;;;;AAMC,QACD,kBAAQE,CAAmBF,MAA8B,EAAEjD,YAAqC,EAAE;QAC9FW,OAAAA,CAAQ0C,IAAI,CAAC,CAAC,gBAAgB,EAAE,IAAI,CAACpF,IAAI,CAAC,gDAAgD,CAAC,CAAA;QAC3F,IAAI,CAACD,aAAa,GAAG,IAAA;AACrB,QAAA,IAAI,CAACkD,WAAW,EAAA;QAChB,IAAI,CAACvC,gBAAgB,CAAC+C,MAAM,EAAA;QAC5B1B,YAAAA,CAAaiD,MAAAA,CAAAA;QACb,IAAI,CAACnF,OAAO,EAAE6D,KAAAA,EAAAA;AAClB,IAAA;AAEQmB,IAAAA,UAAAA,CAAWH,OAAyB,EAAE;AAC1C,QAAA,IAAIA,QAAQL,SAAS,IAAI,IAAI,CAAClE,iBAAiB,EAAE;AAC7C,YAAA,MAAMkF,OAAAA,GAAUxC,IAAAA,CAAKC,GAAG,EAAA,GAAK4B,QAAQL,SAAS;YAC9C,IAAI,CAACjE,gBAAgB,GAAGiF,OAAAA;AACxB,YAAA,IAAI,CAAChF,eAAe,CAACiF,IAAI,CAACD,OAAAA,CAAAA;;AAG1B,YAAA,IAAI,IAAI,CAAChF,eAAe,CAACa,MAAM,GAAG,GAAA,EAAK;gBACnC,IAAI,CAACb,eAAe,CAACkF,KAAK,EAAA;AAC9B,YAAA;AACJ,QAAA;AACJ,IAAA;AACJ;;"}
|
|
@@ -39,6 +39,7 @@ export declare class ServerSentEventHubConnection implements IObservableQueryHub
|
|
|
39
39
|
private applyServerKeepAliveInterval;
|
|
40
40
|
private handleQueryResult;
|
|
41
41
|
private handleUnauthorized;
|
|
42
|
+
private deliverResult;
|
|
42
43
|
private sendSubscribe;
|
|
43
44
|
private isMessageForCurrentSubscription;
|
|
44
45
|
private isCurrentSubscription;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,EAGH,KAAK,mBAAmB,EAC3B,MAAM,6BAA6B,CAAC;AA8BrC,qBAAa,4BAA6B,YAAW,6BAA6B;IA2B1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhC5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,8BAA8B,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IAepD,YACqB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC,EA4BrE;IAGD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,WAAW,IAAI,OAAO,CAKzB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAK3B;IAGD,SAAS,CACL,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAC5B,IAAI,CAgBN;IAGD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAYjC;IAGD,OAAO,IAAI,IAAI,CASd;IAED,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,eAAe;IAyDvB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,4BAA4B;IAgBpC,OAAO,CAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,OAAO,EAGH,KAAK,mBAAmB,EAC3B,MAAM,6BAA6B,CAAC;AA8BrC,qBAAa,4BAA6B,YAAW,6BAA6B;IA2B1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhC5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,8BAA8B,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IAepD,YACqB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC,EA4BrE;IAGD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,WAAW,IAAI,OAAO,CAKzB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAK3B;IAGD,SAAS,CACL,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAC5B,IAAI,CAgBN;IAGD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAYjC;IAGD,OAAO,IAAI,IAAI,CASd;IAED,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,eAAe;IAyDvB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,eAAe;IAgCvB,OAAO,CAAC,4BAA4B;IAgBpC,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,aAAa;IAmHrB,OAAO,CAAC,+BAA+B;IAgBvC,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;CAyB1B"}
|
|
@@ -288,19 +288,21 @@ import { HubMessageType } from './WebSocketHubConnection.js';
|
|
|
288
288
|
this._keepAlive.reconfigure(serverIntervalMs, serverIntervalMs * IDLE_THRESHOLD_FACTOR);
|
|
289
289
|
}
|
|
290
290
|
handleQueryResult(message) {
|
|
291
|
-
if (!message.queryId) return;
|
|
292
|
-
const sub = this._subscriptions.get(message.queryId);
|
|
293
|
-
if (!sub || !this.isMessageForCurrentSubscription(message)) return;
|
|
294
291
|
const result = message.payload;
|
|
295
|
-
|
|
292
|
+
this.deliverResult(message, result, result?.isValid === false);
|
|
296
293
|
}
|
|
297
294
|
handleUnauthorized(message) {
|
|
295
|
+
this.deliverResult(message, QueryResult.unauthorized(), true);
|
|
296
|
+
}
|
|
297
|
+
deliverResult(message, result, terminal) {
|
|
298
298
|
if (!message.queryId) return;
|
|
299
299
|
const sub = this._subscriptions.get(message.queryId);
|
|
300
300
|
if (!sub || !this.isMessageForCurrentSubscription(message)) return;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
301
|
+
if (terminal) {
|
|
302
|
+
this._subscriptions.delete(message.queryId);
|
|
303
|
+
this._pendingSubscriptions.delete(message.queryId);
|
|
304
|
+
}
|
|
305
|
+
sub.callback(result);
|
|
304
306
|
}
|
|
305
307
|
sendSubscribe(queryId, subscription, attempt = 0) {
|
|
306
308
|
if (!this._connectionId || this._disconnected) return;
|