@cratis/arc 22.13.1 → 22.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +5 -4
  2. package/dist/cjs/Globals.js.map +1 -1
  3. package/dist/cjs/UrlHelpers.js.map +1 -1
  4. package/dist/cjs/commands/Command.js.map +1 -1
  5. package/dist/cjs/commands/CommandResult.js.map +1 -1
  6. package/dist/cjs/commands/CommandResults.js.map +1 -1
  7. package/dist/cjs/commands/CommandValidator.js.map +1 -1
  8. package/dist/cjs/commands/index.js.map +1 -1
  9. package/dist/cjs/deepEqual.js.map +1 -1
  10. package/dist/cjs/identity/IIdentityProvider.js.map +1 -1
  11. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  12. package/dist/cjs/identity/index.js.map +1 -1
  13. package/dist/cjs/joinPaths.js.map +1 -1
  14. package/dist/cjs/messaging/IMessenger.js.map +1 -1
  15. package/dist/cjs/messaging/Message.js.map +1 -1
  16. package/dist/cjs/messaging/Messenger.js.map +1 -1
  17. package/dist/cjs/messaging/index.js.map +1 -1
  18. package/dist/cjs/queries/HubConnectionKeepAlive.js.map +1 -1
  19. package/dist/cjs/queries/IQueryProvider.js.map +1 -1
  20. package/dist/cjs/queries/NullObservableQueryConnection.js.map +1 -1
  21. package/dist/cjs/queries/ObservableQueryConnection.js.map +1 -1
  22. package/dist/cjs/queries/ObservableQueryConnectionFactory.js.map +1 -1
  23. package/dist/cjs/queries/ObservableQueryConnectionPool.js.map +1 -1
  24. package/dist/cjs/queries/ObservableQueryDiagnostics.js.map +1 -1
  25. package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
  26. package/dist/cjs/queries/ObservableQueryMultiplexer.js.map +1 -1
  27. package/dist/cjs/queries/ObservableQuerySubscription.js.map +1 -1
  28. package/dist/cjs/queries/Paging.js.map +1 -1
  29. package/dist/cjs/queries/PagingInfo.js.map +1 -1
  30. package/dist/cjs/queries/QueryFor.js.map +1 -1
  31. package/dist/cjs/queries/QueryHttpMethod.js.map +1 -1
  32. package/dist/cjs/queries/QueryHttpMethodResolver.js.map +1 -1
  33. package/dist/cjs/queries/QueryHttpRequest.js.map +1 -1
  34. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  35. package/dist/cjs/queries/QueryProvider.js.map +1 -1
  36. package/dist/cjs/queries/QueryResult.js.map +1 -1
  37. package/dist/cjs/queries/QueryResultWithState.js.map +1 -1
  38. package/dist/cjs/queries/QueryTransportMethod.js.map +1 -1
  39. package/dist/cjs/queries/QueryValidator.js.map +1 -1
  40. package/dist/cjs/queries/ReconnectPolicy.js.map +1 -1
  41. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  42. package/dist/cjs/queries/ServerSentEventQueryConnection.js.map +1 -1
  43. package/dist/cjs/queries/SortDirection.js.map +1 -1
  44. package/dist/cjs/queries/Sorting.js.map +1 -1
  45. package/dist/cjs/queries/SortingActions.js.map +1 -1
  46. package/dist/cjs/queries/SortingActionsForObservableQuery.js.map +1 -1
  47. package/dist/cjs/queries/SortingActionsForQuery.js.map +1 -1
  48. package/dist/cjs/queries/ValidateRequestArguments.js.map +1 -1
  49. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  50. package/dist/cjs/queries/WebSocketMessage.js.map +1 -1
  51. package/dist/cjs/queries/deserializeQueryModel.js.map +1 -1
  52. package/dist/cjs/queries/index.js.map +1 -1
  53. package/dist/cjs/queries/isAbortError.js.map +1 -1
  54. package/dist/cjs/queries/reconcileQueryData.js.map +1 -1
  55. package/dist/cjs/reflection/ParameterDescriptor.js.map +1 -1
  56. package/dist/cjs/reflection/ParametersHelper.js.map +1 -1
  57. package/dist/cjs/reflection/PropertyDescriptor.js.map +1 -1
  58. package/dist/cjs/reflection/index.js.map +1 -1
  59. package/dist/cjs/validation/PropertyRule.js.map +1 -1
  60. package/dist/cjs/validation/PropertyValidator.js.map +1 -1
  61. package/dist/cjs/validation/RuleBuilder.js.map +1 -1
  62. package/dist/cjs/validation/RuleBuilderExtensions.js.map +1 -1
  63. package/dist/cjs/validation/ValidationResult.js.map +1 -1
  64. package/dist/cjs/validation/ValidationResultReason.js.map +1 -1
  65. package/dist/cjs/validation/ValidationResultSeverity.js.map +1 -1
  66. package/dist/cjs/validation/Validator.js.map +1 -1
  67. package/dist/cjs/validation/index.js.map +1 -1
  68. package/dist/cjs/validation/rules/ComparisonRules.js.map +1 -1
  69. package/dist/cjs/validation/rules/EmailRule.js.map +1 -1
  70. package/dist/cjs/validation/rules/LengthRules.js.map +1 -1
  71. package/dist/cjs/validation/rules/NotEmptyRule.js.map +1 -1
  72. package/dist/cjs/validation/rules/PhoneRule.js.map +1 -1
  73. package/dist/cjs/validation/rules/RegexRule.js.map +1 -1
  74. package/dist/cjs/validation/rules/UrlRule.js.map +1 -1
  75. package/dist/esm/Globals.js.map +1 -1
  76. package/dist/esm/UrlHelpers.js.map +1 -1
  77. package/dist/esm/commands/Command.js.map +1 -1
  78. package/dist/esm/commands/CommandResult.js.map +1 -1
  79. package/dist/esm/commands/CommandResults.js.map +1 -1
  80. package/dist/esm/commands/CommandValidator.js.map +1 -1
  81. package/dist/esm/deepEqual.js.map +1 -1
  82. package/dist/esm/identity/IIdentityProvider.js.map +1 -1
  83. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  84. package/dist/esm/joinPaths.js.map +1 -1
  85. package/dist/esm/messaging/IMessenger.js.map +1 -1
  86. package/dist/esm/messaging/Message.js.map +1 -1
  87. package/dist/esm/messaging/Messenger.js.map +1 -1
  88. package/dist/esm/queries/HubConnectionKeepAlive.js.map +1 -1
  89. package/dist/esm/queries/IQueryProvider.js.map +1 -1
  90. package/dist/esm/queries/NullObservableQueryConnection.js.map +1 -1
  91. package/dist/esm/queries/ObservableQueryConnection.js.map +1 -1
  92. package/dist/esm/queries/ObservableQueryConnectionFactory.js.map +1 -1
  93. package/dist/esm/queries/ObservableQueryConnectionPool.js.map +1 -1
  94. package/dist/esm/queries/ObservableQueryDiagnostics.js.map +1 -1
  95. package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
  96. package/dist/esm/queries/ObservableQueryMultiplexer.js.map +1 -1
  97. package/dist/esm/queries/ObservableQuerySubscription.js.map +1 -1
  98. package/dist/esm/queries/Paging.js.map +1 -1
  99. package/dist/esm/queries/PagingInfo.js.map +1 -1
  100. package/dist/esm/queries/QueryFor.js.map +1 -1
  101. package/dist/esm/queries/QueryHttpMethod.js.map +1 -1
  102. package/dist/esm/queries/QueryHttpMethodResolver.js.map +1 -1
  103. package/dist/esm/queries/QueryHttpRequest.js.map +1 -1
  104. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  105. package/dist/esm/queries/QueryProvider.js.map +1 -1
  106. package/dist/esm/queries/QueryResult.js.map +1 -1
  107. package/dist/esm/queries/QueryResultWithState.js.map +1 -1
  108. package/dist/esm/queries/QueryTransportMethod.js.map +1 -1
  109. package/dist/esm/queries/QueryValidator.js.map +1 -1
  110. package/dist/esm/queries/ReconnectPolicy.js.map +1 -1
  111. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  112. package/dist/esm/queries/ServerSentEventQueryConnection.js.map +1 -1
  113. package/dist/esm/queries/SortDirection.js.map +1 -1
  114. package/dist/esm/queries/Sorting.js.map +1 -1
  115. package/dist/esm/queries/SortingActions.js.map +1 -1
  116. package/dist/esm/queries/SortingActionsForObservableQuery.js.map +1 -1
  117. package/dist/esm/queries/SortingActionsForQuery.js.map +1 -1
  118. package/dist/esm/queries/ValidateRequestArguments.js.map +1 -1
  119. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  120. package/dist/esm/queries/WebSocketMessage.js.map +1 -1
  121. package/dist/esm/queries/deserializeQueryModel.js.map +1 -1
  122. package/dist/esm/queries/isAbortError.js.map +1 -1
  123. package/dist/esm/queries/reconcileQueryData.js.map +1 -1
  124. package/dist/esm/reflection/ParameterDescriptor.js.map +1 -1
  125. package/dist/esm/reflection/ParametersHelper.js.map +1 -1
  126. package/dist/esm/reflection/PropertyDescriptor.js.map +1 -1
  127. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  128. package/dist/esm/validation/PropertyRule.js.map +1 -1
  129. package/dist/esm/validation/PropertyValidator.js.map +1 -1
  130. package/dist/esm/validation/RuleBuilder.js.map +1 -1
  131. package/dist/esm/validation/RuleBuilderExtensions.js.map +1 -1
  132. package/dist/esm/validation/ValidationResult.js.map +1 -1
  133. package/dist/esm/validation/ValidationResultReason.js.map +1 -1
  134. package/dist/esm/validation/ValidationResultSeverity.js.map +1 -1
  135. package/dist/esm/validation/Validator.js.map +1 -1
  136. package/dist/esm/validation/rules/ComparisonRules.js.map +1 -1
  137. package/dist/esm/validation/rules/EmailRule.js.map +1 -1
  138. package/dist/esm/validation/rules/LengthRules.js.map +1 -1
  139. package/dist/esm/validation/rules/NotEmptyRule.js.map +1 -1
  140. package/dist/esm/validation/rules/PhoneRule.js.map +1 -1
  141. package/dist/esm/validation/rules/RegexRule.js.map +1 -1
  142. package/dist/esm/validation/rules/UrlRule.js.map +1 -1
  143. package/package.json +3 -3
@@ -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';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { WebSocketMessage, WebSocketMessageType } from './WebSocketMessage';\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';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { WebSocketMessage, WebSocketMessageType } from './WebSocketMessage';\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 +1 @@
1
- {"version":3,"file":"ObservableQueryConnectionFactory.js","sources":["../../../queries/ObservableQueryConnectionFactory.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 { joinPaths } from '../joinPaths';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { ObservableQueryConnection } from './ObservableQueryConnection';\nimport { QueryTransportMethod } from './QueryTransportMethod';\nimport { ServerSentEventQueryConnection, SSE_HUB_ROUTE } from './ServerSentEventQueryConnection';\nimport { ServerSentEventHubConnection } from './ServerSentEventHubConnection';\nimport { WebSocketHubConnection } from './WebSocketHubConnection';\nimport { MultiplexedObservableQueryConnection, WS_HUB_ROUTE, getOrCreateMultiplexer } from './ObservableQueryMultiplexer';\n\n/**\n * The SSE subscribe POST endpoint route.\n */\nexport const SSE_SUBSCRIBE_ROUTE = '/.cratis/queries/sse/subscribe';\n\n/**\n * The SSE unsubscribe POST endpoint route.\n */\nexport const SSE_UNSUBSCRIBE_ROUTE = '/.cratis/queries/sse/unsubscribe';\n\n/**\n * Describes what the factory needs to know about a query in order to create\n * the right connection. Transport details are intentionally absent — the\n * factory reads those from {@link Globals}.\n */\nexport interface QueryConnectionDescriptor {\n /** The route template (e.g. `/api/accounts/debit/all-accounts`). */\n route: string;\n /** Fully-qualified backend query name used by hub transports. */\n queryName: string;\n /** Origin base URL (e.g. `http://localhost:5000`). */\n origin: string;\n /** API base path prefix. */\n apiBasePath: string;\n /** Microservice identifier. */\n microservice: string;\n /** Route/query arguments for the current subscription. */\n args?: object;\n}\n\n/**\n * Single entry-point for creating observable query connections.\n *\n * The transport is chosen as a 2x2 matrix of (direct | hub) x (WebSocket | SSE):\n *\n * | | Direct (per-query URL) | Hub (centralized endpoint) |\n * |----------------|-------------------------------|-------------------------------|\n * | **WebSocket** | ObservableQueryConnection | MultiplexedObservableQueryConnection |\n * | **SSE** | ServerSentEventQueryConnection | MultiplexedObservableQueryConnection |\n *\n * In multiplexed mode, both transports share the same multiplexer — it creates either\n * WebSocket or SSE connections depending on the transport setting.\n *\n * {@link ObservableQueryFor} never needs to know which transport is in use.\n */\nexport function createObservableQueryConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n const isSSE = Globals.queryTransportMethod === QueryTransportMethod.ServerSentEvents;\n\n if (Globals.queryDirectMode) {\n return isSSE\n ? createDirectSSEConnection<TDataType>(descriptor)\n : createDirectWebSocketConnection<TDataType>(descriptor);\n }\n\n return createMultiplexedConnection<TDataType>(descriptor, isSSE);\n}\n\n// ---- Direct mode: one connection per query, hitting the query's own URL ----\n\nfunction buildDirectUrl(descriptor: QueryConnectionDescriptor): URL {\n const { route } = UrlHelpers.replaceRouteParameters(descriptor.route, descriptor.args as object);\n const actualRoute = joinPaths(descriptor.apiBasePath, route);\n return UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, actualRoute);\n}\n\nfunction createDirectWebSocketConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n return new ObservableQueryConnection<TDataType>(buildDirectUrl(descriptor), descriptor.microservice);\n}\n\nfunction createDirectSSEConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n return new ServerSentEventQueryConnection<TDataType>(buildDirectUrl(descriptor));\n}\n\n// ---- Multiplexed mode: centralized endpoint, multiple queries share connections ----\n\n/**\n * Maximum number of SSE hub connections that fits safely within the HTTP/1.1 browser\n * per-origin connection limit (typically 6 for Chrome/Firefox). Each SSE EventSource\n * occupies one persistent connection slot indefinitely. Exceeding this cap blocks the\n * subscribe/unsubscribe POST requests that share the same pool, causing queries to hang.\n * Servers configured for HTTP/2 do not have this restriction.\n */\nconst MAX_SAFE_SSE_CONNECTIONS = 4;\n\nfunction createMultiplexedConnection<TDataType>(descriptor: QueryConnectionDescriptor, isSSE: boolean): IObservableQueryConnection<TDataType> {\n const transport = isSSE ? 'sse' : 'ws';\n const requestedCount = Globals.queryConnectionCount;\n const effectiveCount = isSSE ? Math.min(requestedCount, MAX_SAFE_SSE_CONNECTIONS) : requestedCount;\n\n if (isSSE && requestedCount > MAX_SAFE_SSE_CONNECTIONS) {\n console.warn(\n `[Arc] queryConnectionCount (${requestedCount}) exceeds the safe limit for SSE transport (${MAX_SAFE_SSE_CONNECTIONS}). ` +\n `HTTP/1.1 browsers allow at most 6 concurrent connections per origin; ` +\n `using more SSE connections blocks subscribe/unsubscribe requests, causing queries to hang. ` +\n `Capping at ${MAX_SAFE_SSE_CONNECTIONS}. Enable HTTP/2 on your server to use a higher connection count.`\n );\n }\n\n const cacheKey = `${requestedCount}|${transport}|${descriptor.origin}|${descriptor.apiBasePath}|${descriptor.microservice}`;\n\n const multiplexer = getOrCreateMultiplexer(() => {\n if (isSSE) {\n const sseRoute = joinPaths(descriptor.apiBasePath, SSE_HUB_ROUTE);\n const sseUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, sseRoute);\n const subscribeRoute = joinPaths(descriptor.apiBasePath, SSE_SUBSCRIBE_ROUTE);\n const subscribeUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, subscribeRoute);\n const unsubscribeRoute = joinPaths(descriptor.apiBasePath, SSE_UNSUBSCRIBE_ROUTE);\n const unsubscribeUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, unsubscribeRoute);\n return new ServerSentEventHubConnection(\n sseUrl.toString(),\n subscribeUrl.toString(),\n unsubscribeUrl.toString(),\n descriptor.microservice,\n );\n } else {\n const hubRoute = joinPaths(descriptor.apiBasePath, WS_HUB_ROUTE);\n const hubUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, hubRoute);\n const secure = hubUrl.protocol?.indexOf('https') === 0;\n const wsUrl = `${secure ? 'wss' : 'ws'}://${hubUrl.host}${hubUrl.pathname}${hubUrl.search}`;\n return new WebSocketHubConnection(wsUrl, descriptor.microservice);\n }\n }, cacheKey, effectiveCount);\n\n return new MultiplexedObservableQueryConnection<TDataType>(multiplexer, descriptor.queryName);\n}\n"],"names":["SSE_SUBSCRIBE_ROUTE","SSE_UNSUBSCRIBE_ROUTE","createObservableQueryConnection","descriptor","isSSE","Globals","queryTransportMethod","QueryTransportMethod","ServerSentEvents","queryDirectMode","createDirectSSEConnection","createDirectWebSocketConnection","createMultiplexedConnection","buildDirectUrl","route","UrlHelpers","replaceRouteParameters","args","actualRoute","joinPaths","apiBasePath","createUrlFrom","origin","ObservableQueryConnection","microservice","ServerSentEventQueryConnection","MAX_SAFE_SSE_CONNECTIONS","transport","requestedCount","queryConnectionCount","effectiveCount","Math","min","console","warn","cacheKey","multiplexer","getOrCreateMultiplexer","sseRoute","SSE_HUB_ROUTE","sseUrl","subscribeRoute","subscribeUrl","unsubscribeRoute","unsubscribeUrl","ServerSentEventHubConnection","toString","hubRoute","WS_HUB_ROUTE","hubUrl","secure","protocol","indexOf","wsUrl","host","pathname","search","WebSocketHubConnection","MultiplexedObservableQueryConnection","queryName"],"mappings":"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"}
1
+ {"version":3,"file":"ObservableQueryConnectionFactory.js","sources":["../../../queries/ObservableQueryConnectionFactory.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 { joinPaths } from '../joinPaths';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { ObservableQueryConnection } from './ObservableQueryConnection';\nimport { QueryTransportMethod } from './QueryTransportMethod';\nimport { ServerSentEventQueryConnection, SSE_HUB_ROUTE } from './ServerSentEventQueryConnection';\nimport { ServerSentEventHubConnection } from './ServerSentEventHubConnection';\nimport { WebSocketHubConnection } from './WebSocketHubConnection';\nimport { MultiplexedObservableQueryConnection, WS_HUB_ROUTE, getOrCreateMultiplexer } from './ObservableQueryMultiplexer';\n\n/**\n * The SSE subscribe POST endpoint route.\n */\nexport const SSE_SUBSCRIBE_ROUTE = '/.cratis/queries/sse/subscribe';\n\n/**\n * The SSE unsubscribe POST endpoint route.\n */\nexport const SSE_UNSUBSCRIBE_ROUTE = '/.cratis/queries/sse/unsubscribe';\n\n/**\n * Describes what the factory needs to know about a query in order to create\n * the right connection. Transport details are intentionally absent — the\n * factory reads those from {@link Globals}.\n */\nexport interface QueryConnectionDescriptor {\n /** The route template (e.g. `/api/accounts/debit/all-accounts`). */\n route: string;\n /** Fully-qualified backend query name used by hub transports. */\n queryName: string;\n /** Origin base URL (e.g. `http://localhost:5000`). */\n origin: string;\n /** API base path prefix. */\n apiBasePath: string;\n /** Microservice identifier. */\n microservice: string;\n /** Route/query arguments for the current subscription. */\n args?: object;\n}\n\n/**\n * Single entry-point for creating observable query connections.\n *\n * The transport is chosen as a 2x2 matrix of (direct | hub) x (WebSocket | SSE):\n *\n * | | Direct (per-query URL) | Hub (centralized endpoint) |\n * |----------------|-------------------------------|-------------------------------|\n * | **WebSocket** | ObservableQueryConnection | MultiplexedObservableQueryConnection |\n * | **SSE** | ServerSentEventQueryConnection | MultiplexedObservableQueryConnection |\n *\n * In multiplexed mode, both transports share the same multiplexer — it creates either\n * WebSocket or SSE connections depending on the transport setting.\n *\n * {@link ObservableQueryFor} never needs to know which transport is in use.\n */\nexport function createObservableQueryConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n const isSSE = Globals.queryTransportMethod === QueryTransportMethod.ServerSentEvents;\n\n if (Globals.queryDirectMode) {\n return isSSE\n ? createDirectSSEConnection<TDataType>(descriptor)\n : createDirectWebSocketConnection<TDataType>(descriptor);\n }\n\n return createMultiplexedConnection<TDataType>(descriptor, isSSE);\n}\n\n// ---- Direct mode: one connection per query, hitting the query's own URL ----\n\nfunction buildDirectUrl(descriptor: QueryConnectionDescriptor): URL {\n const { route } = UrlHelpers.replaceRouteParameters(descriptor.route, descriptor.args as object);\n const actualRoute = joinPaths(descriptor.apiBasePath, route);\n return UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, actualRoute);\n}\n\nfunction createDirectWebSocketConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n return new ObservableQueryConnection<TDataType>(buildDirectUrl(descriptor), descriptor.microservice);\n}\n\nfunction createDirectSSEConnection<TDataType>(descriptor: QueryConnectionDescriptor): IObservableQueryConnection<TDataType> {\n return new ServerSentEventQueryConnection<TDataType>(buildDirectUrl(descriptor));\n}\n\n// ---- Multiplexed mode: centralized endpoint, multiple queries share connections ----\n\n/**\n * Maximum number of SSE hub connections that fits safely within the HTTP/1.1 browser\n * per-origin connection limit (typically 6 for Chrome/Firefox). Each SSE EventSource\n * occupies one persistent connection slot indefinitely. Exceeding this cap blocks the\n * subscribe/unsubscribe POST requests that share the same pool, causing queries to hang.\n * Servers configured for HTTP/2 do not have this restriction.\n */\nconst MAX_SAFE_SSE_CONNECTIONS = 4;\n\nfunction createMultiplexedConnection<TDataType>(descriptor: QueryConnectionDescriptor, isSSE: boolean): IObservableQueryConnection<TDataType> {\n const transport = isSSE ? 'sse' : 'ws';\n const requestedCount = Globals.queryConnectionCount;\n const effectiveCount = isSSE ? Math.min(requestedCount, MAX_SAFE_SSE_CONNECTIONS) : requestedCount;\n\n if (isSSE && requestedCount > MAX_SAFE_SSE_CONNECTIONS) {\n console.warn(\n `[Arc] queryConnectionCount (${requestedCount}) exceeds the safe limit for SSE transport (${MAX_SAFE_SSE_CONNECTIONS}). ` +\n `HTTP/1.1 browsers allow at most 6 concurrent connections per origin; ` +\n `using more SSE connections blocks subscribe/unsubscribe requests, causing queries to hang. ` +\n `Capping at ${MAX_SAFE_SSE_CONNECTIONS}. Enable HTTP/2 on your server to use a higher connection count.`\n );\n }\n\n const cacheKey = `${requestedCount}|${transport}|${descriptor.origin}|${descriptor.apiBasePath}|${descriptor.microservice}`;\n\n const multiplexer = getOrCreateMultiplexer(() => {\n if (isSSE) {\n const sseRoute = joinPaths(descriptor.apiBasePath, SSE_HUB_ROUTE);\n const sseUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, sseRoute);\n const subscribeRoute = joinPaths(descriptor.apiBasePath, SSE_SUBSCRIBE_ROUTE);\n const subscribeUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, subscribeRoute);\n const unsubscribeRoute = joinPaths(descriptor.apiBasePath, SSE_UNSUBSCRIBE_ROUTE);\n const unsubscribeUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, unsubscribeRoute);\n return new ServerSentEventHubConnection(\n sseUrl.toString(),\n subscribeUrl.toString(),\n unsubscribeUrl.toString(),\n descriptor.microservice,\n );\n } else {\n const hubRoute = joinPaths(descriptor.apiBasePath, WS_HUB_ROUTE);\n const hubUrl = UrlHelpers.createUrlFrom(descriptor.origin, descriptor.apiBasePath, hubRoute);\n const secure = hubUrl.protocol?.indexOf('https') === 0;\n const wsUrl = `${secure ? 'wss' : 'ws'}://${hubUrl.host}${hubUrl.pathname}${hubUrl.search}`;\n return new WebSocketHubConnection(wsUrl, descriptor.microservice);\n }\n }, cacheKey, effectiveCount);\n\n return new MultiplexedObservableQueryConnection<TDataType>(multiplexer, descriptor.queryName);\n}\n"],"names":["SSE_SUBSCRIBE_ROUTE","SSE_UNSUBSCRIBE_ROUTE","createObservableQueryConnection","descriptor","isSSE","Globals","queryTransportMethod","QueryTransportMethod","ServerSentEvents","queryDirectMode","createDirectSSEConnection","createDirectWebSocketConnection","createMultiplexedConnection","buildDirectUrl","route","UrlHelpers","replaceRouteParameters","args","actualRoute","joinPaths","apiBasePath","createUrlFrom","origin","ObservableQueryConnection","microservice","ServerSentEventQueryConnection","MAX_SAFE_SSE_CONNECTIONS","transport","requestedCount","queryConnectionCount","effectiveCount","Math","min","console","warn","cacheKey","multiplexer","getOrCreateMultiplexer","sseRoute","SSE_HUB_ROUTE","sseUrl","subscribeRoute","subscribeUrl","unsubscribeRoute","unsubscribeUrl","ServerSentEventHubConnection","toString","hubRoute","WS_HUB_ROUTE","hubUrl","secure","protocol","indexOf","wsUrl","host","pathname","search","WebSocketHubConnection","MultiplexedObservableQueryConnection","queryName"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryConnectionPool.js","sources":["../../../queries/ObservableQueryConnectionPool.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 { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { DataReceived } from './ObservableQueryConnection';\n\n/**\n * Tracks the number of active subscribers assigned to each pool slot.\n */\ninterface PoolSlot {\n queryCount: number;\n}\n\n/**\n * Represents a pool of observable query connection factories distributed round-robin across N slots.\n *\n * Each call to {@link acquire} picks the slot with the fewest active queries (falling back to\n * round-robin when counts are equal) and creates a fresh connection for that subscriber via the\n * provided factory. The connection is a dedicated instance per subscriber; the pool only tracks\n * slot utilization so future multiplexed transports (e.g. WebSocket) can share connections\n * across a fixed number of physical hub connections.\n *\n * When {@link size} is 1 (the default), all queries are counted against a single slot — the\n * natural behavior for a single multiplexed connection.\n *\n * @template TDataType The type of data received from the connections.\n */\nexport class ObservableQueryConnectionPool<TDataType> {\n private readonly _slots: PoolSlot[];\n\n /**\n * Initializes a new {@link ObservableQueryConnectionPool}.\n * @param {number} size Number of logical slots (hub connections) in the pool.\n * @param {() => IObservableQueryConnection<TDataType>} factory Factory that produces a new connection instance per subscriber.\n */\n constructor(\n size: number,\n private readonly _factory: () => IObservableQueryConnection<TDataType>\n ) {\n this._slots = Array.from({ length: Math.max(1, size) }, () => ({ queryCount: 0 }));\n }\n\n /**\n * Picks the least-loaded pool slot, creates a fresh connection via the factory, and starts\n * delivering data to the provided callback.\n * @param {DataReceived<TDataType>} dataReceived Callback invoked for each message.\n * @param {object} queryArguments Arguments forwarded to the connection.\n * @returns A cleanup function that decrements the slot counter and disconnects the connection.\n */\n acquire(dataReceived: DataReceived<TDataType>, queryArguments?: object): () => void {\n // Pick the slot with the fewest active queries.\n const slot = this._slots.reduce((min, current) => current.queryCount < min.queryCount ? current : min, this._slots[0]);\n slot.queryCount++;\n\n // Each subscriber gets its own dedicated connection instance.\n const connection = this._factory();\n connection.connect(dataReceived, queryArguments);\n\n return () => {\n connection.disconnect();\n slot.queryCount = Math.max(0, slot.queryCount - 1);\n };\n }\n}\n"],"names":["ObservableQueryConnectionPool","_slots","size","_factory","Array","from","length","Math","max","queryCount","acquire","dataReceived","queryArguments","slot","reduce","min","current","connection","connect","disconnect"],"mappings":";;AAAA;AACA;AAYA;;;;;;;;;;;;;AAaC,IACM,MAAMA,6BAAAA,CAAAA;;IACQC,MAAAA;AAEjB;;;;AAIC,QACD,WAAA,CACIC,IAAY,EACKC,QAAqD,CACxE;aADmBA,QAAAA,GAAAA,QAAAA;AAEjB,QAAA,IAAI,CAACF,MAAM,GAAGG,KAAAA,CAAMC,IAAI,CAAC;YAAEC,MAAAA,EAAQC,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGN,IAAAA;AAAM,SAAA,EAAG,KAAO;gBAAEO,UAAAA,EAAY;aAAE,CAAA,CAAA;AACnF,IAAA;AAEA;;;;;;AAMC,QACDC,OAAAA,CAAQC,YAAqC,EAAEC,cAAuB,EAAc;;QAEhF,MAAMC,IAAAA,GAAO,IAAI,CAACZ,MAAM,CAACa,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAAA,GAAYA,OAAAA,CAAQP,UAAU,GAAGM,GAAAA,CAAIN,UAAU,GAAGO,OAAAA,GAAUD,KAAK,IAAI,CAACd,MAAM,CAAC,CAAA,CAAE,CAAA;AACrHY,QAAAA,IAAAA,CAAKJ,UAAU,EAAA;;QAGf,MAAMQ,UAAAA,GAAa,IAAI,CAACd,QAAQ,EAAA;QAChCc,UAAAA,CAAWC,OAAO,CAACP,YAAAA,EAAcC,cAAAA,CAAAA;QAEjC,OAAO,IAAA;AACHK,YAAAA,UAAAA,CAAWE,UAAU,EAAA;YACrBN,IAAAA,CAAKJ,UAAU,GAAGF,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGK,IAAAA,CAAKJ,UAAU,GAAG,CAAA,CAAA;AACpD,QAAA,CAAA;AACJ,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"ObservableQueryConnectionPool.js","sources":["../../../queries/ObservableQueryConnectionPool.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 { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { DataReceived } from './ObservableQueryConnection';\n\n/**\n * Tracks the number of active subscribers assigned to each pool slot.\n */\ninterface PoolSlot {\n queryCount: number;\n}\n\n/**\n * Represents a pool of observable query connection factories distributed round-robin across N slots.\n *\n * Each call to {@link acquire} picks the slot with the fewest active queries (falling back to\n * round-robin when counts are equal) and creates a fresh connection for that subscriber via the\n * provided factory. The connection is a dedicated instance per subscriber; the pool only tracks\n * slot utilization so future multiplexed transports (e.g. WebSocket) can share connections\n * across a fixed number of physical hub connections.\n *\n * When {@link size} is 1 (the default), all queries are counted against a single slot — the\n * natural behavior for a single multiplexed connection.\n *\n * @template TDataType The type of data received from the connections.\n */\nexport class ObservableQueryConnectionPool<TDataType> {\n private readonly _slots: PoolSlot[];\n\n /**\n * Initializes a new {@link ObservableQueryConnectionPool}.\n * @param {number} size Number of logical slots (hub connections) in the pool.\n * @param {() => IObservableQueryConnection<TDataType>} factory Factory that produces a new connection instance per subscriber.\n */\n constructor(\n size: number,\n private readonly _factory: () => IObservableQueryConnection<TDataType>\n ) {\n this._slots = Array.from({ length: Math.max(1, size) }, () => ({ queryCount: 0 }));\n }\n\n /**\n * Picks the least-loaded pool slot, creates a fresh connection via the factory, and starts\n * delivering data to the provided callback.\n * @param {DataReceived<TDataType>} dataReceived Callback invoked for each message.\n * @param {object} queryArguments Arguments forwarded to the connection.\n * @returns A cleanup function that decrements the slot counter and disconnects the connection.\n */\n acquire(dataReceived: DataReceived<TDataType>, queryArguments?: object): () => void {\n // Pick the slot with the fewest active queries.\n const slot = this._slots.reduce((min, current) => current.queryCount < min.queryCount ? current : min, this._slots[0]);\n slot.queryCount++;\n\n // Each subscriber gets its own dedicated connection instance.\n const connection = this._factory();\n connection.connect(dataReceived, queryArguments);\n\n return () => {\n connection.disconnect();\n slot.queryCount = Math.max(0, slot.queryCount - 1);\n };\n }\n}\n"],"names":["ObservableQueryConnectionPool","_slots","size","_factory","Array","from","length","Math","max","queryCount","acquire","dataReceived","queryArguments","slot","reduce","min","current","connection","connect","disconnect"],"mappings":";;AAAA;AACA;AAYA;;;;;;;;;;;;;AAaC,IACM,MAAMA,6BAAAA,CAAAA;;IACQC,MAAAA;AAEjB;;;;AAIC,QACD,WAAA,CACIC,IAAY,EACKC,QAAqD,CACxE;aADmBA,QAAAA,GAAAA,QAAAA;AAEjB,QAAA,IAAI,CAACF,MAAM,GAAGG,KAAAA,CAAMC,IAAI,CAAC;YAAEC,MAAAA,EAAQC,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGN,IAAAA;AAAM,SAAA,EAAG,KAAO;gBAAEO,UAAAA,EAAY;aAAE,CAAA,CAAA;AACnF,IAAA;AAEA;;;;;;AAMC,QACDC,OAAAA,CAAQC,YAAqC,EAAEC,cAAuB,EAAc;;QAEhF,MAAMC,IAAAA,GAAO,IAAI,CAACZ,MAAM,CAACa,MAAM,CAAC,CAACC,GAAAA,EAAKC,OAAAA,GAAYA,OAAAA,CAAQP,UAAU,GAAGM,GAAAA,CAAIN,UAAU,GAAGO,OAAAA,GAAUD,KAAK,IAAI,CAACd,MAAM,CAAC,CAAA,CAAE,CAAA;AACrHY,QAAAA,IAAAA,CAAKJ,UAAU,EAAA;;QAGf,MAAMQ,UAAAA,GAAa,IAAI,CAACd,QAAQ,EAAA;QAChCc,UAAAA,CAAWC,OAAO,CAACP,YAAAA,EAAcC,cAAAA,CAAAA;QAEjC,OAAO,IAAA;AACHK,YAAAA,UAAAA,CAAWE,UAAU,EAAA;YACrBN,IAAAA,CAAKJ,UAAU,GAAGF,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGK,IAAAA,CAAKJ,UAAU,GAAG,CAAA,CAAA;AACpD,QAAA,CAAA;AACJ,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryDiagnostics.js","sources":["../../../queries/ObservableQueryDiagnostics.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 { Observable, Subject } from 'rxjs';\nimport { QueryInstanceCache } from './QueryInstanceCache';\nimport { ObservableQueryMultiplexer } from './ObservableQueryMultiplexer';\nimport { IObservableQueryDiagnostics } from './IObservableQueryDiagnostics';\nimport {\n ObservableQueryDiagnosticsSnapshot,\n MultiplexerDiagnostics,\n TransportDiagnostics,\n HealthDiagnostics,\n OwnershipDiagnostics,\n} from './ObservableQueryDiagnosticsSnapshot';\n\n/**\n * Implements the {@link IObservableQueryDiagnostics} contract by collecting live state from\n * the {@link QueryInstanceCache} and the shared {@link ObservableQueryMultiplexer}.\n */\nexport class ObservableQueryDiagnostics implements IObservableQueryDiagnostics {\n private readonly _snapshots = new Subject<ObservableQueryDiagnosticsSnapshot>();\n private readonly _ownersByKey = new Map<string, string>();\n\n /**\n * Initializes a new instance of {@link ObservableQueryDiagnostics}.\n * @param _cache The {@link QueryInstanceCache} whose state will be reflected.\n * @param _getMultiplexer Factory that returns the current shared multiplexer, or {@code undefined}.\n * @param _getTransportConfig Factory that returns the current transport diagnostics.\n */\n constructor(\n private readonly _cache: QueryInstanceCache,\n private readonly _getMultiplexer: () => ObservableQueryMultiplexer | undefined,\n private readonly _getTransportConfig: () => TransportDiagnostics,\n ) {}\n\n /**\n * Stream of diagnostics snapshots.\n */\n get snapshots$(): Observable<ObservableQueryDiagnosticsSnapshot> {\n return this._snapshots.asObservable();\n }\n\n /** @inheritdoc */\n getSnapshot(): ObservableQueryDiagnosticsSnapshot {\n const snapshot = this._createSnapshot();\n this._publishSnapshot(snapshot);\n return snapshot;\n }\n\n /** @inheritdoc */\n beginTracking(cacheKey: string, owner: string): void {\n this._ownersByKey.set(cacheKey, owner);\n this._publishSnapshot(this._createSnapshot());\n }\n\n /** @inheritdoc */\n endTracking(cacheKey: string): void {\n this._ownersByKey.delete(cacheKey);\n this._publishSnapshot(this._createSnapshot());\n }\n\n private _buildMultiplexerDiagnostics(): MultiplexerDiagnostics {\n const mux = this._getMultiplexer();\n if (!mux) {\n return {\n isConnected: false,\n configuredConnectionCount: 0,\n effectiveConnectionCount: 0,\n activeConnectionCount: 0,\n connections: [],\n };\n }\n\n const connections = mux.getConnectionsSnapshot();\n const activeConnectionCount = connections.filter(c => c.isConnected).length;\n\n return {\n isConnected: activeConnectionCount > 0,\n configuredConnectionCount: connections.length,\n effectiveConnectionCount: connections.length,\n activeConnectionCount,\n connections,\n };\n }\n\n private _createSnapshot(): ObservableQueryDiagnosticsSnapshot {\n const transport = this._getTransportConfig();\n const multiplexer = this._buildMultiplexerDiagnostics();\n const cache = this._cache.getDiagnosticsSnapshot();\n\n const ownersByQueryKey: Record<string, string> = {};\n const queriesByOwner: Record<string, string[]> = {};\n\n for (const [key, owner] of this._ownersByKey) {\n ownersByQueryKey[key] = owner;\n if (!queriesByOwner[owner]) {\n queriesByOwner[owner] = [];\n }\n queriesByOwner[owner].push(key);\n }\n\n const ownership: OwnershipDiagnostics = { ownersByQueryKey, queriesByOwner };\n\n const disconnectedQueryCount = multiplexer.connections.filter(c => !c.isConnected).length;\n const health: HealthDiagnostics = {\n allQueriesConnected: multiplexer.isConnected && cache.healthy,\n disconnectedQueryCount,\n };\n\n return {\n health,\n transport,\n multiplexer,\n cache,\n ownership,\n timestamp: new Date().toISOString(),\n };\n }\n\n private _publishSnapshot(snapshot: ObservableQueryDiagnosticsSnapshot): void {\n this._snapshots.next(snapshot);\n }\n}\n"],"names":["ObservableQueryDiagnostics","_snapshots","Subject","_ownersByKey","Map","_cache","_getMultiplexer","_getTransportConfig","snapshots$","asObservable","getSnapshot","snapshot","_createSnapshot","_publishSnapshot","beginTracking","cacheKey","owner","set","endTracking","delete","_buildMultiplexerDiagnostics","mux","isConnected","configuredConnectionCount","effectiveConnectionCount","activeConnectionCount","connections","getConnectionsSnapshot","filter","c","length","transport","multiplexer","cache","getDiagnosticsSnapshot","ownersByQueryKey","queriesByOwner","key","push","ownership","disconnectedQueryCount","health","allQueriesConnected","healthy","timestamp","Date","toISOString","next"],"mappings":"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"}
1
+ {"version":3,"file":"ObservableQueryDiagnostics.js","sources":["../../../queries/ObservableQueryDiagnostics.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 { Observable, Subject } from 'rxjs';\nimport { QueryInstanceCache } from './QueryInstanceCache';\nimport { ObservableQueryMultiplexer } from './ObservableQueryMultiplexer';\nimport { IObservableQueryDiagnostics } from './IObservableQueryDiagnostics';\nimport {\n ObservableQueryDiagnosticsSnapshot,\n MultiplexerDiagnostics,\n TransportDiagnostics,\n HealthDiagnostics,\n OwnershipDiagnostics,\n} from './ObservableQueryDiagnosticsSnapshot';\n\n/**\n * Implements the {@link IObservableQueryDiagnostics} contract by collecting live state from\n * the {@link QueryInstanceCache} and the shared {@link ObservableQueryMultiplexer}.\n */\nexport class ObservableQueryDiagnostics implements IObservableQueryDiagnostics {\n private readonly _snapshots = new Subject<ObservableQueryDiagnosticsSnapshot>();\n private readonly _ownersByKey = new Map<string, string>();\n\n /**\n * Initializes a new instance of {@link ObservableQueryDiagnostics}.\n * @param _cache The {@link QueryInstanceCache} whose state will be reflected.\n * @param _getMultiplexer Factory that returns the current shared multiplexer, or {@code undefined}.\n * @param _getTransportConfig Factory that returns the current transport diagnostics.\n */\n constructor(\n private readonly _cache: QueryInstanceCache,\n private readonly _getMultiplexer: () => ObservableQueryMultiplexer | undefined,\n private readonly _getTransportConfig: () => TransportDiagnostics,\n ) {}\n\n /**\n * Stream of diagnostics snapshots.\n */\n get snapshots$(): Observable<ObservableQueryDiagnosticsSnapshot> {\n return this._snapshots.asObservable();\n }\n\n /** @inheritdoc */\n getSnapshot(): ObservableQueryDiagnosticsSnapshot {\n const snapshot = this._createSnapshot();\n this._publishSnapshot(snapshot);\n return snapshot;\n }\n\n /** @inheritdoc */\n beginTracking(cacheKey: string, owner: string): void {\n this._ownersByKey.set(cacheKey, owner);\n this._publishSnapshot(this._createSnapshot());\n }\n\n /** @inheritdoc */\n endTracking(cacheKey: string): void {\n this._ownersByKey.delete(cacheKey);\n this._publishSnapshot(this._createSnapshot());\n }\n\n private _buildMultiplexerDiagnostics(): MultiplexerDiagnostics {\n const mux = this._getMultiplexer();\n if (!mux) {\n return {\n isConnected: false,\n configuredConnectionCount: 0,\n effectiveConnectionCount: 0,\n activeConnectionCount: 0,\n connections: [],\n };\n }\n\n const connections = mux.getConnectionsSnapshot();\n const activeConnectionCount = connections.filter(c => c.isConnected).length;\n\n return {\n isConnected: activeConnectionCount > 0,\n configuredConnectionCount: connections.length,\n effectiveConnectionCount: connections.length,\n activeConnectionCount,\n connections,\n };\n }\n\n private _createSnapshot(): ObservableQueryDiagnosticsSnapshot {\n const transport = this._getTransportConfig();\n const multiplexer = this._buildMultiplexerDiagnostics();\n const cache = this._cache.getDiagnosticsSnapshot();\n\n const ownersByQueryKey: Record<string, string> = {};\n const queriesByOwner: Record<string, string[]> = {};\n\n for (const [key, owner] of this._ownersByKey) {\n ownersByQueryKey[key] = owner;\n if (!queriesByOwner[owner]) {\n queriesByOwner[owner] = [];\n }\n queriesByOwner[owner].push(key);\n }\n\n const ownership: OwnershipDiagnostics = { ownersByQueryKey, queriesByOwner };\n\n const disconnectedQueryCount = multiplexer.connections.filter(c => !c.isConnected).length;\n const health: HealthDiagnostics = {\n allQueriesConnected: multiplexer.isConnected && cache.healthy,\n disconnectedQueryCount,\n };\n\n return {\n health,\n transport,\n multiplexer,\n cache,\n ownership,\n timestamp: new Date().toISOString(),\n };\n }\n\n private _publishSnapshot(snapshot: ObservableQueryDiagnosticsSnapshot): void {\n this._snapshots.next(snapshot);\n }\n}\n"],"names":["ObservableQueryDiagnostics","_snapshots","Subject","_ownersByKey","Map","_cache","_getMultiplexer","_getTransportConfig","snapshots$","asObservable","getSnapshot","snapshot","_createSnapshot","_publishSnapshot","beginTracking","cacheKey","owner","set","endTracking","delete","_buildMultiplexerDiagnostics","mux","isConnected","configuredConnectionCount","effectiveConnectionCount","activeConnectionCount","connections","getConnectionsSnapshot","filter","c","length","transport","multiplexer","cache","getDiagnosticsSnapshot","ownersByQueryKey","queriesByOwner","key","push","ownership","disconnectedQueryCount","health","allQueriesConnected","healthy","timestamp","Date","toISOString","next"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryFor.js","sources":["../../../queries/ObservableQueryFor.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 type { IObservableQueryFor, OnNextResult } from './IObservableQueryFor';\nimport { ObservableQuerySubscription } from './ObservableQuerySubscription';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport type { QueryValidator } from './QueryValidator';\nimport type { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { NullObservableQueryConnection } from './NullObservableQueryConnection';\nimport { createObservableQueryConnection } from './ObservableQueryConnectionFactory';\nimport type { Constructor } from '@cratis/fundamentals';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\nimport { QueryResult } from './QueryResult';\nimport { Sorting } from './Sorting';\nimport { Paging } from './Paging';\nimport { SortDirection } from './SortDirection';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport type { GetHttpHeaders } from '../GetHttpHeaders';\nimport type { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport type { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class ObservableQueryFor<\n TDataType,\n TParameters = object,\n> implements IObservableQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _connection?: IObservableQueryConnection<TDataType>;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n\n abstract readonly route: string;\n abstract readonly defaultValue: TDataType;\n readonly roles: string[] = [];\n readonly validation?: QueryValidator<any>;\n /** Backend fully-qualified query name used when subscribing via the SSE hub. Overridden in generated proxies. */\n readonly queryName?: string;\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n sorting: Sorting;\n paging: Paging;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(\n readonly modelType: Constructor,\n readonly enumerable: boolean,\n ) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /**\n * Disposes the query.\n */\n dispose() {\n this._connection?.disconnect();\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n subscribe(\n callback: OnNextResult<QueryResult<TDataType>>,\n args?: TParameters,\n ): ObservableQuerySubscription<TDataType> {\n if (this._connection) {\n this._connection.disconnect();\n }\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n // Serve the failure through the connection rather than throwing, so a subscriber sees an invalid result\n // on its normal callback path instead of the empty result an unestablished connection would emit.\n this._connection = new NullObservableQueryConnection(\n this.defaultValue,\n QueryResult.validationFailed(clientValidationErrors, this),\n );\n } else if (this.validateArguments(args)) {\n this._connection = createObservableQueryConnection({\n route: this.route,\n queryName: this.queryName ?? this.constructor.name,\n origin: this._origin,\n apiBasePath: this._apiBasePath,\n microservice: this._microservice,\n args: args as object,\n });\n } else {\n this._connection = new NullObservableQueryConnection(this.defaultValue);\n }\n\n // Descriptor-backed instance properties provide defaults; fresh args passed to subscribe()\n // must take precedence over any stale instance property values. Spread parameterValues\n // first so that the caller-supplied args can override them.\n //\n // In direct mode the route arguments are already embedded in the URL path, so only\n // the unused (non-route) parameters are appended as additional query arguments.\n // In multiplexed mode ALL arguments — including route-derived ones — must be included\n // in the subscribe payload so the server can execute the query correctly.\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const { unusedParameters } = UrlHelpers.replaceRouteParameters(\n this.route,\n args as object,\n );\n const connectionQueryArguments: any = {\n ...parameterValues,\n ...(Globals.queryDirectMode ? unusedParameters : (args as object) || {}),\n ...this.buildQueryArguments(),\n };\n\n const subscriber = new ObservableQuerySubscription(this._connection);\n this._connection.connect((data) => {\n const result: any = data;\n try {\n // Observable transports deliver structural query-result envelopes directly instead of\n // constructing QueryResult. Servers predating readiness therefore omit the member;\n // those results are complete by definition and must be normalized before subscribers\n // observe them. Preserve an explicit false transient state from newer servers.\n result.isReady ??= true;\n this.deserializeResult(result);\n callback(result);\n } catch (ex) {\n console.log(ex);\n }\n }, connectionQueryArguments);\n return subscriber;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = {\n ...QueryResult.noSuccess,\n ...{ data: this.defaultValue },\n } as QueryResult<TDataType>;\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!this.validateArguments(args)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ...(this._httpHeadersCallback?.() || {}),\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n const response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers,\n });\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n\n private validateArguments(args?: TParameters): boolean {\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const combinedArgs = { ...((args as object) || {}), ...parameterValues };\n return ValidateRequestArguments(\n this.constructor.name,\n this.requiredRequestParameters,\n combinedArgs as object,\n );\n }\n\n private buildQueryArguments(): any {\n const queryArguments: any = {};\n\n if (this.paging && this.paging.pageSize > 0) {\n queryArguments.pageSize = this.paging.pageSize;\n queryArguments.page = this.paging.page;\n }\n\n if (this.sorting.hasSorting) {\n queryArguments.sortBy = this.sorting.field;\n queryArguments.sortDirection =\n this.sorting.direction === SortDirection.descending ? 'desc' : 'asc';\n }\n\n return queryArguments;\n }\n\n private deserializeResult(result: any): void {\n if (this.enumerable) {\n result.data = deserializeQueryModels(this.modelType, result.data);\n } else if (result.data) {\n result.data = deserializeQueryModel(this.modelType, result.data);\n }\n }\n}\n"],"names":["ObservableQueryFor","_microservice","_apiBasePath","_origin","_connection","_httpHeadersCallback","_httpMethod","roles","validation","queryName","sorting","paging","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","dispose","disconnect","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","subscribe","args","clientValidationErrors","validate","length","NullObservableQueryConnection","defaultValue","QueryResult","validationFailed","validateArguments","createObservableQueryConnection","route","name","parameterValues","ParametersHelper","collectParameterValues","unusedParameters","UrlHelpers","replaceRouteParameters","connectionQueryArguments","queryDirectMode","buildQueryArguments","subscriber","ObservableQuerySubscription","connect","data","result","isReady","deserializeResult","ex","console","log","perform","noSuccess","Promise","resolve","headers","Accept","microserviceHttpHeader","response","executeQueryHttpRequest","json","combinedArgs","ValidateRequestArguments","requiredRequestParameters","queryArguments","pageSize","page","hasSorting","sortBy","field","sortDirection","direction","SortDirection","descending","deserializeQueryModels","deserializeQueryModel"],"mappings":"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"}
1
+ {"version":3,"file":"ObservableQueryFor.js","sources":["../../../queries/ObservableQueryFor.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 type { IObservableQueryFor, OnNextResult } from './IObservableQueryFor';\nimport { ObservableQuerySubscription } from './ObservableQuerySubscription';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport type { QueryValidator } from './QueryValidator';\nimport type { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { NullObservableQueryConnection } from './NullObservableQueryConnection';\nimport { createObservableQueryConnection } from './ObservableQueryConnectionFactory';\nimport type { Constructor } from '@cratis/fundamentals';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\nimport { QueryResult } from './QueryResult';\nimport { Sorting } from './Sorting';\nimport { Paging } from './Paging';\nimport { SortDirection } from './SortDirection';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport type { GetHttpHeaders } from '../GetHttpHeaders';\nimport type { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport type { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class ObservableQueryFor<\n TDataType,\n TParameters = object,\n> implements IObservableQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _connection?: IObservableQueryConnection<TDataType>;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n\n abstract readonly route: string;\n abstract readonly defaultValue: TDataType;\n readonly roles: string[] = [];\n readonly validation?: QueryValidator<any>;\n /** Backend fully-qualified query name used when subscribing via the SSE hub. Overridden in generated proxies. */\n readonly queryName?: string;\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n sorting: Sorting;\n paging: Paging;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(\n readonly modelType: Constructor,\n readonly enumerable: boolean,\n ) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /**\n * Disposes the query.\n */\n dispose() {\n this._connection?.disconnect();\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n subscribe(\n callback: OnNextResult<QueryResult<TDataType>>,\n args?: TParameters,\n ): ObservableQuerySubscription<TDataType> {\n if (this._connection) {\n this._connection.disconnect();\n }\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n // Serve the failure through the connection rather than throwing, so a subscriber sees an invalid result\n // on its normal callback path instead of the empty result an unestablished connection would emit.\n this._connection = new NullObservableQueryConnection(\n this.defaultValue,\n QueryResult.validationFailed(clientValidationErrors, this),\n );\n } else if (this.validateArguments(args)) {\n this._connection = createObservableQueryConnection({\n route: this.route,\n queryName: this.queryName ?? this.constructor.name,\n origin: this._origin,\n apiBasePath: this._apiBasePath,\n microservice: this._microservice,\n args: args as object,\n });\n } else {\n this._connection = new NullObservableQueryConnection(this.defaultValue);\n }\n\n // Descriptor-backed instance properties provide defaults; fresh args passed to subscribe()\n // must take precedence over any stale instance property values. Spread parameterValues\n // first so that the caller-supplied args can override them.\n //\n // In direct mode the route arguments are already embedded in the URL path, so only\n // the unused (non-route) parameters are appended as additional query arguments.\n // In multiplexed mode ALL arguments — including route-derived ones — must be included\n // in the subscribe payload so the server can execute the query correctly.\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const { unusedParameters } = UrlHelpers.replaceRouteParameters(\n this.route,\n args as object,\n );\n const connectionQueryArguments: any = {\n ...parameterValues,\n ...(Globals.queryDirectMode ? unusedParameters : (args as object) || {}),\n ...this.buildQueryArguments(),\n };\n\n const subscriber = new ObservableQuerySubscription(this._connection);\n this._connection.connect((data) => {\n const result: any = data;\n try {\n // Observable transports deliver structural query-result envelopes directly instead of\n // constructing QueryResult. Servers predating readiness therefore omit the member;\n // those results are complete by definition and must be normalized before subscribers\n // observe them. Preserve an explicit false transient state from newer servers.\n result.isReady ??= true;\n this.deserializeResult(result);\n callback(result);\n } catch (ex) {\n console.log(ex);\n }\n }, connectionQueryArguments);\n return subscriber;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = {\n ...QueryResult.noSuccess,\n ...{ data: this.defaultValue },\n } as QueryResult<TDataType>;\n\n const clientValidationErrors =\n this.validation?.validate((args as object) || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!this.validateArguments(args)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ...(this._httpHeadersCallback?.() || {}),\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n const response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers,\n });\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n\n private validateArguments(args?: TParameters): boolean {\n const parameterValues = ParametersHelper.collectParameterValues(this);\n const combinedArgs = { ...((args as object) || {}), ...parameterValues };\n return ValidateRequestArguments(\n this.constructor.name,\n this.requiredRequestParameters,\n combinedArgs as object,\n );\n }\n\n private buildQueryArguments(): any {\n const queryArguments: any = {};\n\n if (this.paging && this.paging.pageSize > 0) {\n queryArguments.pageSize = this.paging.pageSize;\n queryArguments.page = this.paging.page;\n }\n\n if (this.sorting.hasSorting) {\n queryArguments.sortBy = this.sorting.field;\n queryArguments.sortDirection =\n this.sorting.direction === SortDirection.descending ? 'desc' : 'asc';\n }\n\n return queryArguments;\n }\n\n private deserializeResult(result: any): void {\n if (this.enumerable) {\n result.data = deserializeQueryModels(this.modelType, result.data);\n } else if (result.data) {\n result.data = deserializeQueryModel(this.modelType, result.data);\n }\n }\n}\n"],"names":["ObservableQueryFor","_microservice","_apiBasePath","_origin","_connection","_httpHeadersCallback","_httpMethod","roles","validation","queryName","sorting","paging","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","dispose","disconnect","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","subscribe","args","clientValidationErrors","validate","length","NullObservableQueryConnection","defaultValue","QueryResult","validationFailed","validateArguments","createObservableQueryConnection","route","name","parameterValues","ParametersHelper","collectParameterValues","unusedParameters","UrlHelpers","replaceRouteParameters","connectionQueryArguments","queryDirectMode","buildQueryArguments","subscriber","ObservableQuerySubscription","connect","data","result","isReady","deserializeResult","ex","console","log","perform","noSuccess","Promise","resolve","headers","Accept","microserviceHttpHeader","response","executeQueryHttpRequest","json","combinedArgs","ValidateRequestArguments","requiredRequestParameters","queryArguments","pageSize","page","hasSorting","sortBy","field","sortDirection","direction","SortDirection","descending","deserializeQueryModels","deserializeQueryModel"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQueryMultiplexer.js","sources":["../../../queries/ObservableQueryMultiplexer.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 { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { SubscriptionRequest } from './WebSocketHubConnection';\nimport { Globals } from '../Globals';\nimport { MultiplexerConnectionState } from './ObservableQueryDiagnosticsSnapshot';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * The WebSocket demultiplexer route used when connecting through the multiplexed observable query endpoint.\n */\nexport const WS_HUB_ROUTE = '/.cratis/queries/ws';\n\n/**\n * Multiplexes multiple observable query subscriptions across a bounded pool of physical\n * connections (WebSocket or SSE) to the backend demultiplexer.\n *\n * Each pool slot is a single multiplexed connection. When a new subscription is requested,\n * the slot with the fewest active queries is chosen. This balances load across N physical\n * connections while keeping the total connection count bounded.\n */\nexport class ObservableQueryMultiplexer {\n private readonly _connections: IObservableQueryHubConnection[];\n private readonly _size: number;\n\n /**\n * Initializes a new {@link ObservableQueryMultiplexer}.\n * @param {number} size Number of physical connections (pool slots).\n * @param {() => IObservableQueryHubConnection} connectionFactory Factory function to create each connection.\n */\n constructor(size: number, connectionFactory: () => IObservableQueryHubConnection) {\n this._size = Math.max(1, size);\n this._connections = Array.from({ length: this._size }, () => connectionFactory());\n }\n\n /**\n * Gets the pool size.\n */\n get size(): number {\n return this._size;\n }\n\n /**\n * Gets the best available ping latency across all connections.\n */\n get lastPingLatency(): number {\n return this._connections.reduce((min, c) =>\n c.lastPingLatency > 0 && c.lastPingLatency < min ? c.lastPingLatency : min,\n Number.MAX_SAFE_INTEGER\n );\n }\n\n /**\n * Gets the average latency across all connections.\n */\n get averageLatency(): number {\n const active = this._connections.filter(c => c.averageLatency > 0);\n if (active.length === 0) return 0;\n return active.reduce((sum, c) => sum + c.averageLatency, 0) / active.length;\n }\n\n /**\n * Subscribe to a query through the multiplexer. Picks the least-loaded connection\n * and sends a Subscribe message on it.\n * @param {string} queryName Fully qualified backend query name.\n * @param {object} queryArguments Flat query arguments (incl. page, pageSize, sortBy, sortDirection).\n * @param {DataReceived<any>} callback Callback invoked for each result.\n * @returns A cleanup function that unsubscribes from the query.\n */\n subscribe(queryName: string, queryArguments: object | undefined, callback: DataReceived<any>): () => void {\n const request = this.buildSubscriptionRequest(queryName, queryArguments);\n const conn = this.leastLoaded();\n const queryId = this.generateQueryId();\n\n conn.subscribe(queryId, request, callback);\n\n return () => {\n conn.unsubscribe(queryId);\n };\n }\n\n /**\n * Dispose all connections in the multiplexer.\n */\n dispose(): void {\n for (const conn of this._connections) {\n conn.dispose();\n }\n }\n\n private leastLoaded(): IObservableQueryHubConnection {\n return this._connections.reduce((min, c) =>\n c.queryCount < min.queryCount ? c : min, this._connections[0]);\n }\n\n private generateQueryId(): string {\n // Use crypto.randomUUID when available, fall back to timestamp + random\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private buildSubscriptionRequest(queryName: string, args?: object): SubscriptionRequest {\n const request: SubscriptionRequest = { queryName };\n\n // Always include the transfer mode so the server knows which emission strategy to use.\n request.transferMode = Globals.observableQueryTransferMode;\n\n if (!args) return request;\n\n const a = args as Record<string, any>;\n const pagingAndSortingKeys = new Set(['page', 'pageSize', 'sortBy', 'sortDirection']);\n\n if (a.page !== undefined && a.page !== null) request.page = Number(a.page);\n if (a.pageSize !== undefined && a.pageSize !== null) request.pageSize = Number(a.pageSize);\n if (a.sortBy !== undefined && a.sortBy !== null) request.sortBy = String(a.sortBy);\n if (a.sortDirection !== undefined && a.sortDirection !== null) request.sortDirection = String(a.sortDirection);\n\n // Everything else goes into arguments as string key-value pairs\n const remaining: Record<string, string | null> = {};\n let hasRemaining = false;\n\n for (const [key, value] of Object.entries(a)) {\n if (pagingAndSortingKeys.has(key)) continue;\n if (value === undefined || value === null) continue;\n remaining[key] = String(value);\n hasRemaining = true;\n }\n\n if (hasRemaining) {\n request.arguments = remaining;\n }\n\n return request;\n }\n\n /**\n * Returns a snapshot of the per-connection state for diagnostics.\n * @returns An array describing each slot in the connection pool.\n */\n getConnectionsSnapshot(): MultiplexerConnectionState[] {\n return this._connections.map((conn, index) => ({\n index,\n isConnected: conn.isConnected,\n queryCount: conn.queryCount,\n }));\n }\n}\n\n/**\n * Wraps an {@link ObservableQueryMultiplexer} subscription as an {@link IObservableQueryConnection},\n * allowing the multiplexed transport to plug into the existing query subscription pipeline\n * without changes to callers.\n */\nexport class MultiplexedObservableQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n private _cleanup?: () => void;\n\n /**\n * Initializes a new {@link MultiplexedObservableQueryConnection}.\n * @param {ObservableQueryMultiplexer} multiplexer The shared multiplexer.\n * @param {string} queryName The fully qualified backend query name.\n */\n constructor(\n private readonly _pool: ObservableQueryMultiplexer,\n private readonly _queryName: string,\n ) {\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._pool.lastPingLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n return this._pool.averageLatency;\n }\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object): void {\n this._cleanup = this._pool.subscribe(\n this._queryName,\n queryArguments,\n dataReceived as DataReceived<any>,\n );\n }\n\n /** @inheritdoc */\n disconnect(): void {\n this._cleanup?.();\n this._cleanup = undefined;\n }\n}\n\n// ----- Shared pool singleton management -----\n\nlet _sharedMultiplexer: ObservableQueryMultiplexer | undefined;\nlet _sharedMultiplexerKey = '';\n\n/**\n * Returns the shared {@link ObservableQueryMultiplexer}, creating or re-creating it when the\n * configuration (connection count, origin, base path, microservice, transport) changes.\n * @param {() => IObservableQueryHubConnection} connectionFactory Factory to create individual connections.\n * @param {string} cacheKey A string that identifies the current configuration for invalidation.\n * @param {number} size Number of physical connections to create. Defaults to {@link Globals.queryConnectionCount}.\n * @returns The shared multiplexer instance.\n */\nexport function getOrCreateMultiplexer(connectionFactory: () => IObservableQueryHubConnection, cacheKey: string, size: number = Globals.queryConnectionCount): ObservableQueryMultiplexer {\n if (_sharedMultiplexer && _sharedMultiplexerKey === cacheKey) {\n return _sharedMultiplexer;\n }\n\n _sharedMultiplexer?.dispose();\n _sharedMultiplexer = new ObservableQueryMultiplexer(size, connectionFactory);\n _sharedMultiplexerKey = cacheKey;\n return _sharedMultiplexer;\n}\n\n/**\n * Disposes and clears the shared multiplexer singleton.\n * Intended for use in test teardown to prevent state leakage across tests.\n */\nexport function resetSharedMultiplexer(): void {\n _sharedMultiplexer?.dispose();\n _sharedMultiplexer = undefined;\n _sharedMultiplexerKey = '';\n}\n\n/**\n * Returns the current shared multiplexer instance, or {@code undefined} if none has been created yet.\n */\nexport function getSharedMultiplexer(): ObservableQueryMultiplexer | undefined {\n return _sharedMultiplexer;\n}\n"],"names":["WS_HUB_ROUTE","ObservableQueryMultiplexer","_connections","_size","size","connectionFactory","Math","max","Array","from","length","lastPingLatency","reduce","min","c","Number","MAX_SAFE_INTEGER","averageLatency","active","filter","sum","subscribe","queryName","queryArguments","callback","request","buildSubscriptionRequest","conn","leastLoaded","queryId","generateQueryId","unsubscribe","dispose","queryCount","crypto","randomUUID","Date","now","random","toString","substring","args","transferMode","Globals","observableQueryTransferMode","a","pagingAndSortingKeys","Set","page","undefined","pageSize","sortBy","String","sortDirection","remaining","hasRemaining","key","value","Object","entries","has","arguments","getConnectionsSnapshot","map","index","isConnected","MultiplexedObservableQueryConnection","_cleanup","_queryName","_pool","connect","dataReceived","disconnect","_sharedMultiplexer","_sharedMultiplexerKey","getOrCreateMultiplexer","cacheKey","queryConnectionCount","resetSharedMultiplexer","getSharedMultiplexer"],"mappings":"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"}
1
+ {"version":3,"file":"ObservableQueryMultiplexer.js","sources":["../../../queries/ObservableQueryMultiplexer.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 { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { SubscriptionRequest } from './WebSocketHubConnection';\nimport { Globals } from '../Globals';\nimport { MultiplexerConnectionState } from './ObservableQueryDiagnosticsSnapshot';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * The WebSocket demultiplexer route used when connecting through the multiplexed observable query endpoint.\n */\nexport const WS_HUB_ROUTE = '/.cratis/queries/ws';\n\n/**\n * Multiplexes multiple observable query subscriptions across a bounded pool of physical\n * connections (WebSocket or SSE) to the backend demultiplexer.\n *\n * Each pool slot is a single multiplexed connection. When a new subscription is requested,\n * the slot with the fewest active queries is chosen. This balances load across N physical\n * connections while keeping the total connection count bounded.\n */\nexport class ObservableQueryMultiplexer {\n private readonly _connections: IObservableQueryHubConnection[];\n private readonly _size: number;\n\n /**\n * Initializes a new {@link ObservableQueryMultiplexer}.\n * @param {number} size Number of physical connections (pool slots).\n * @param {() => IObservableQueryHubConnection} connectionFactory Factory function to create each connection.\n */\n constructor(size: number, connectionFactory: () => IObservableQueryHubConnection) {\n this._size = Math.max(1, size);\n this._connections = Array.from({ length: this._size }, () => connectionFactory());\n }\n\n /**\n * Gets the pool size.\n */\n get size(): number {\n return this._size;\n }\n\n /**\n * Gets the best available ping latency across all connections.\n */\n get lastPingLatency(): number {\n return this._connections.reduce((min, c) =>\n c.lastPingLatency > 0 && c.lastPingLatency < min ? c.lastPingLatency : min,\n Number.MAX_SAFE_INTEGER\n );\n }\n\n /**\n * Gets the average latency across all connections.\n */\n get averageLatency(): number {\n const active = this._connections.filter(c => c.averageLatency > 0);\n if (active.length === 0) return 0;\n return active.reduce((sum, c) => sum + c.averageLatency, 0) / active.length;\n }\n\n /**\n * Subscribe to a query through the multiplexer. Picks the least-loaded connection\n * and sends a Subscribe message on it.\n * @param {string} queryName Fully qualified backend query name.\n * @param {object} queryArguments Flat query arguments (incl. page, pageSize, sortBy, sortDirection).\n * @param {DataReceived<any>} callback Callback invoked for each result.\n * @returns A cleanup function that unsubscribes from the query.\n */\n subscribe(queryName: string, queryArguments: object | undefined, callback: DataReceived<any>): () => void {\n const request = this.buildSubscriptionRequest(queryName, queryArguments);\n const conn = this.leastLoaded();\n const queryId = this.generateQueryId();\n\n conn.subscribe(queryId, request, callback);\n\n return () => {\n conn.unsubscribe(queryId);\n };\n }\n\n /**\n * Dispose all connections in the multiplexer.\n */\n dispose(): void {\n for (const conn of this._connections) {\n conn.dispose();\n }\n }\n\n private leastLoaded(): IObservableQueryHubConnection {\n return this._connections.reduce((min, c) =>\n c.queryCount < min.queryCount ? c : min, this._connections[0]);\n }\n\n private generateQueryId(): string {\n // Use crypto.randomUUID when available, fall back to timestamp + random\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private buildSubscriptionRequest(queryName: string, args?: object): SubscriptionRequest {\n const request: SubscriptionRequest = { queryName };\n\n // Always include the transfer mode so the server knows which emission strategy to use.\n request.transferMode = Globals.observableQueryTransferMode;\n\n if (!args) return request;\n\n const a = args as Record<string, any>;\n const pagingAndSortingKeys = new Set(['page', 'pageSize', 'sortBy', 'sortDirection']);\n\n if (a.page !== undefined && a.page !== null) request.page = Number(a.page);\n if (a.pageSize !== undefined && a.pageSize !== null) request.pageSize = Number(a.pageSize);\n if (a.sortBy !== undefined && a.sortBy !== null) request.sortBy = String(a.sortBy);\n if (a.sortDirection !== undefined && a.sortDirection !== null) request.sortDirection = String(a.sortDirection);\n\n // Everything else goes into arguments as string key-value pairs\n const remaining: Record<string, string | null> = {};\n let hasRemaining = false;\n\n for (const [key, value] of Object.entries(a)) {\n if (pagingAndSortingKeys.has(key)) continue;\n if (value === undefined || value === null) continue;\n remaining[key] = String(value);\n hasRemaining = true;\n }\n\n if (hasRemaining) {\n request.arguments = remaining;\n }\n\n return request;\n }\n\n /**\n * Returns a snapshot of the per-connection state for diagnostics.\n * @returns An array describing each slot in the connection pool.\n */\n getConnectionsSnapshot(): MultiplexerConnectionState[] {\n return this._connections.map((conn, index) => ({\n index,\n isConnected: conn.isConnected,\n queryCount: conn.queryCount,\n }));\n }\n}\n\n/**\n * Wraps an {@link ObservableQueryMultiplexer} subscription as an {@link IObservableQueryConnection},\n * allowing the multiplexed transport to plug into the existing query subscription pipeline\n * without changes to callers.\n */\nexport class MultiplexedObservableQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n private _cleanup?: () => void;\n\n /**\n * Initializes a new {@link MultiplexedObservableQueryConnection}.\n * @param {ObservableQueryMultiplexer} multiplexer The shared multiplexer.\n * @param {string} queryName The fully qualified backend query name.\n */\n constructor(\n private readonly _pool: ObservableQueryMultiplexer,\n private readonly _queryName: string,\n ) {\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._pool.lastPingLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n return this._pool.averageLatency;\n }\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object): void {\n this._cleanup = this._pool.subscribe(\n this._queryName,\n queryArguments,\n dataReceived as DataReceived<any>,\n );\n }\n\n /** @inheritdoc */\n disconnect(): void {\n this._cleanup?.();\n this._cleanup = undefined;\n }\n}\n\n// ----- Shared pool singleton management -----\n\nlet _sharedMultiplexer: ObservableQueryMultiplexer | undefined;\nlet _sharedMultiplexerKey = '';\n\n/**\n * Returns the shared {@link ObservableQueryMultiplexer}, creating or re-creating it when the\n * configuration (connection count, origin, base path, microservice, transport) changes.\n * @param {() => IObservableQueryHubConnection} connectionFactory Factory to create individual connections.\n * @param {string} cacheKey A string that identifies the current configuration for invalidation.\n * @param {number} size Number of physical connections to create. Defaults to {@link Globals.queryConnectionCount}.\n * @returns The shared multiplexer instance.\n */\nexport function getOrCreateMultiplexer(connectionFactory: () => IObservableQueryHubConnection, cacheKey: string, size: number = Globals.queryConnectionCount): ObservableQueryMultiplexer {\n if (_sharedMultiplexer && _sharedMultiplexerKey === cacheKey) {\n return _sharedMultiplexer;\n }\n\n _sharedMultiplexer?.dispose();\n _sharedMultiplexer = new ObservableQueryMultiplexer(size, connectionFactory);\n _sharedMultiplexerKey = cacheKey;\n return _sharedMultiplexer;\n}\n\n/**\n * Disposes and clears the shared multiplexer singleton.\n * Intended for use in test teardown to prevent state leakage across tests.\n */\nexport function resetSharedMultiplexer(): void {\n _sharedMultiplexer?.dispose();\n _sharedMultiplexer = undefined;\n _sharedMultiplexerKey = '';\n}\n\n/**\n * Returns the current shared multiplexer instance, or {@code undefined} if none has been created yet.\n */\nexport function getSharedMultiplexer(): ObservableQueryMultiplexer | undefined {\n return _sharedMultiplexer;\n}\n"],"names":["WS_HUB_ROUTE","ObservableQueryMultiplexer","_connections","_size","size","connectionFactory","Math","max","Array","from","length","lastPingLatency","reduce","min","c","Number","MAX_SAFE_INTEGER","averageLatency","active","filter","sum","subscribe","queryName","queryArguments","callback","request","buildSubscriptionRequest","conn","leastLoaded","queryId","generateQueryId","unsubscribe","dispose","queryCount","crypto","randomUUID","Date","now","random","toString","substring","args","transferMode","Globals","observableQueryTransferMode","a","pagingAndSortingKeys","Set","page","undefined","pageSize","sortBy","String","sortDirection","remaining","hasRemaining","key","value","Object","entries","has","arguments","getConnectionsSnapshot","map","index","isConnected","MultiplexedObservableQueryConnection","_cleanup","_queryName","_pool","connect","dataReceived","disconnect","_sharedMultiplexer","_sharedMultiplexerKey","getOrCreateMultiplexer","cacheKey","queryConnectionCount","resetSharedMultiplexer","getSharedMultiplexer"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableQuerySubscription.js","sources":["../../../queries/ObservableQuerySubscription.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 { IObservableQueryConnection } from './IObservableQueryConnection';\n\n/**\n * Represents a subscription for an observable query.\n */\nexport class ObservableQuerySubscription<TDataType> {\n\n /**\n * Initializes a new instance of the {@link ObservableQuerySubscription} class.\n * @param {ObservableQueryConnection<TDataType> _connection The connection to use.\n */\n constructor(private _connection: IObservableQueryConnection<TDataType>) {\n }\n\n /**\n * Unsubscribe subscription.\n */\n unsubscribe() {\n if (this._connection) {\n this._connection.disconnect();\n this._connection = undefined!;\n }\n }\n}\n"],"names":["ObservableQuerySubscription","_connection","unsubscribe","disconnect","undefined"],"mappings":";;AAAA;AACA;AAIA;;AAEC,IACM,MAAMA,2BAAAA,CAAAA;;AAET;;;QAIA,WAAA,CAAY,WAA0D,CAAE;aAApDC,WAAAA,GAAAA,WAAAA;AACpB,IAAA;AAEA;;AAEC,QACDC,WAAAA,GAAc;QACV,IAAI,IAAI,CAACD,WAAW,EAAE;YAClB,IAAI,CAACA,WAAW,CAACE,UAAU,EAAA;YAC3B,IAAI,CAACF,WAAW,GAAGG,SAAAA;AACvB,QAAA;AACJ,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"ObservableQuerySubscription.js","sources":["../../../queries/ObservableQuerySubscription.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 { IObservableQueryConnection } from './IObservableQueryConnection';\n\n/**\n * Represents a subscription for an observable query.\n */\nexport class ObservableQuerySubscription<TDataType> {\n\n /**\n * Initializes a new instance of the {@link ObservableQuerySubscription} class.\n * @param {ObservableQueryConnection<TDataType> _connection The connection to use.\n */\n constructor(private _connection: IObservableQueryConnection<TDataType>) {\n }\n\n /**\n * Unsubscribe subscription.\n */\n unsubscribe() {\n if (this._connection) {\n this._connection.disconnect();\n this._connection = undefined!;\n }\n }\n}\n"],"names":["ObservableQuerySubscription","_connection","unsubscribe","disconnect","undefined"],"mappings":";;AAAA;AACA;AAIA;;AAEC,IACM,MAAMA,2BAAAA,CAAAA;;AAET;;;QAIA,WAAA,CAAY,WAA0D,CAAE;aAApDC,WAAAA,GAAAA,WAAAA;AACpB,IAAA;AAEA;;AAEC,QACDC,WAAAA,GAAc;QACV,IAAI,IAAI,CAACD,WAAW,EAAE;YAClB,IAAI,CAACA,WAAW,CAACE,UAAU,EAAA;YAC3B,IAAI,CAACF,WAAW,GAAGG,SAAAA;AACvB,QAAA;AACJ,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Paging.js","sources":["../../../queries/Paging.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 * Represents the paging information for a query.\n */\nexport class Paging {\n\n /**\n * No paging.\n */\n static noPaging: Paging = new Paging(0, 0);\n\n /**\n * Initializes a new instance of {@link Paging}.\n */\n constructor(page?: number, pageSize?: number) {\n this.page = page ?? 0;\n this.pageSize = pageSize ?? 0;\n }\n\n /**\n * Page of paging\n */\n page: number;\n\n /**\n * Page size of paging\n */\n pageSize: number;\n\n /**\n * Gets whether or not there is paging.\n */\n get hasPaging(): boolean {\n return this.page > 0 || this.pageSize > 0;\n }\n}"],"names":["Paging","noPaging","page","pageSize","hasPaging"],"mappings":";;AAAA;AACA;AAEA;;AAEC,IACM,MAAMA,MAAAA,CAAAA;AAET;;AAEC,QACD,OAAOC,QAAAA,GAAmB,IAAID,MAAAA,CAAO,GAAG,CAAA,CAAA;AAExC;;AAEC,QACD,WAAA,CAAYE,IAAa,EAAEC,QAAiB,CAAE;QAC1C,IAAI,CAACD,IAAI,GAAGA,IAAAA,IAAQ,CAAA;QACpB,IAAI,CAACC,QAAQ,GAAGA,QAAAA,IAAY,CAAA;AAChC,IAAA;AAEA;;AAEC,QACDD,IAAAA;AAEA;;AAEC,QACDC,QAAAA;AAEA;;AAEC,QACD,IAAIC,SAAAA,GAAqB;QACrB,OAAO,IAAI,CAACF,IAAI,GAAG,KAAK,IAAI,CAACC,QAAQ,GAAG,CAAA;AAC5C,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"Paging.js","sources":["../../../queries/Paging.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 * Represents the paging information for a query.\n */\nexport class Paging {\n\n /**\n * No paging.\n */\n static noPaging: Paging = new Paging(0, 0);\n\n /**\n * Initializes a new instance of {@link Paging}.\n */\n constructor(page?: number, pageSize?: number) {\n this.page = page ?? 0;\n this.pageSize = pageSize ?? 0;\n }\n\n /**\n * Page of paging\n */\n page: number;\n\n /**\n * Page size of paging\n */\n pageSize: number;\n\n /**\n * Gets whether or not there is paging.\n */\n get hasPaging(): boolean {\n return this.page > 0 || this.pageSize > 0;\n }\n}"],"names":["Paging","noPaging","page","pageSize","hasPaging"],"mappings":";;AAAA;AACA;AAEA;;AAEC,IACM,MAAMA,MAAAA,CAAAA;AAET;;AAEC,QACD,OAAOC,QAAAA,GAAmB,IAAID,MAAAA,CAAO,GAAG,CAAA,CAAA;AAExC;;AAEC,QACD,WAAA,CAAYE,IAAa,EAAEC,QAAiB,CAAE;QAC1C,IAAI,CAACD,IAAI,GAAGA,IAAAA,IAAQ,CAAA;QACpB,IAAI,CAACC,QAAQ,GAAGA,QAAAA,IAAY,CAAA;AAChC,IAAA;AAEA;;AAEC,QACDD,IAAAA;AAEA;;AAEC,QACDC,QAAAA;AAEA;;AAEC,QACD,IAAIC,SAAAA,GAAqB;QACrB,OAAO,IAAI,CAACF,IAAI,GAAG,KAAK,IAAI,CAACC,QAAQ,GAAG,CAAA;AAC5C,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"PagingInfo.js","sources":["../../../queries/PagingInfo.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 * Represents the paging information for a query.\n */\nexport class PagingInfo {\n\n /**\n * No paging paging info.\n */\n static readonly noPaging = new PagingInfo();\n\n /**\n * Initializes a new instance of the {@link PagingInfo} class.\n */\n constructor() {\n this.page = 0;\n this.size = 0;\n this.totalItems = 0;\n this.totalPages = 0;\n }\n\n /**\n * Current page.\n */\n page: number;\n\n /**\n * Page size.\n */\n size: number;\n\n /**\n * Total number items.\n */\n totalItems: number;\n\n /**\n * Total number of pages.\n */\n totalPages: number;\n}\n"],"names":["PagingInfo","noPaging","page","size","totalItems","totalPages"],"mappings":";;AAAA;AACA;AAEA;;AAEC,IACM,MAAMA,UAAAA,CAAAA;AAET;;QAGA,OAAgBC,QAAAA,GAAW,IAAID,UAAAA,EAAAA;AAE/B;;AAEC,QACD,WAAA,EAAc;QACV,IAAI,CAACE,IAAI,GAAG,CAAA;QACZ,IAAI,CAACC,IAAI,GAAG,CAAA;QACZ,IAAI,CAACC,UAAU,GAAG,CAAA;QAClB,IAAI,CAACC,UAAU,GAAG,CAAA;AACtB,IAAA;AAEA;;AAEC,QACDH,IAAAA;AAEA;;AAEC,QACDC,IAAAA;AAEA;;AAEC,QACDC,UAAAA;AAEA;;AAEC,QACDC,UAAAA;AACJ;;;;"}
1
+ {"version":3,"file":"PagingInfo.js","sources":["../../../queries/PagingInfo.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 * Represents the paging information for a query.\n */\nexport class PagingInfo {\n\n /**\n * No paging paging info.\n */\n static readonly noPaging = new PagingInfo();\n\n /**\n * Initializes a new instance of the {@link PagingInfo} class.\n */\n constructor() {\n this.page = 0;\n this.size = 0;\n this.totalItems = 0;\n this.totalPages = 0;\n }\n\n /**\n * Current page.\n */\n page: number;\n\n /**\n * Page size.\n */\n size: number;\n\n /**\n * Total number items.\n */\n totalItems: number;\n\n /**\n * Total number of pages.\n */\n totalPages: number;\n}\n"],"names":["PagingInfo","noPaging","page","size","totalItems","totalPages"],"mappings":";;AAAA;AACA;AAEA;;AAEC,IACM,MAAMA,UAAAA,CAAAA;AAET;;QAGA,OAAgBC,QAAAA,GAAW,IAAID,UAAAA,EAAAA;AAE/B;;AAEC,QACD,WAAA,EAAc;QACV,IAAI,CAACE,IAAI,GAAG,CAAA;QACZ,IAAI,CAACC,IAAI,GAAG,CAAA;QACZ,IAAI,CAACC,UAAU,GAAG,CAAA;QAClB,IAAI,CAACC,UAAU,GAAG,CAAA;AACtB,IAAA;AAEA;;AAEC,QACDH,IAAAA;AAEA;;AAEC,QACDC,IAAAA;AAEA;;AAEC,QACDC,UAAAA;AAEA;;AAEC,QACDC,UAAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryFor.js","sources":["../../../queries/QueryFor.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 { IQueryFor } from './IQueryFor';\nimport { QueryResult } from \"./QueryResult\";\nimport { QueryValidator } from './QueryValidator';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport { Constructor } from '@cratis/fundamentals';\nimport { Paging } from './Paging';\nimport { Globals } from '../Globals';\nimport { Sorting } from './Sorting';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\nimport { isAbortError } from './isAbortError';\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class QueryFor<TDataType, TParameters = object> implements IQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n abstract readonly route: string;\n /** Backend fully-qualified query name used as cache key. Overridden in generated proxies. */\n readonly queryName?: string;\n /* eslint-disable @typescript-eslint/no-explicit-any */\n readonly validation?: QueryValidator<any>;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n readonly roles: string[] = [];\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n abstract defaultValue: TDataType;\n abortController?: AbortController;\n sorting: Sorting;\n paging: Paging;\n parameters: TParameters | undefined;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(readonly modelType: Constructor, readonly enumerable: boolean) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = { ...QueryResult.noSuccess, ...{ data: this.defaultValue } } as QueryResult<TDataType>;\n\n args = args || this.parameters;\n\n const clientValidationErrors = this.validation?.validate(args as object || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!ValidateRequestArguments(this.constructor.name, this.requiredRequestParameters, args as object)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n if (this.abortController) {\n this.abortController.abort();\n }\n\n this.abortController = new AbortController();\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ... this._httpHeadersCallback?.(), ...\n {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n }\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n let response: Response;\n\n try {\n response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers,\n signal: this.abortController.signal\n });\n } catch (error) {\n // An abort is not a failure - it is this query superseding its own in-flight request above.\n // Rethrowing lets the caller discard the superseded request so it cannot settle over the\n // newer one that now owns the result.\n if (isAbortError(error)) {\n throw error;\n }\n\n // A dead network, a CORS rejection or a DNS failure never reaches the server, so it is\n // neither an authorization nor a validation outcome - it is reported as an exception, with\n // the default value as data, exactly as every other unsuccessful result from here does.\n // Destructuring a nullish rejection value throws, which would make the `String(error)`\n // fallback written for exactly that case unreachable - so it is coerced to an object first.\n const { message } = (error ?? {}) as { message?: string };\n const failure = {\n ...QueryResult.noSuccess,\n data: this.defaultValue,\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: true,\n exceptionMessages: [message ?? String(error)],\n // Left empty on purpose. Every result the server returns has its stack trace blanked\n // unless exception detail is explicitly exposed, and consumers are told to forward\n // this field to a logger - so filling it in here would make a failure that never\n // reached the server the one case that escapes that policy. The message is what\n // diagnoses a transport failure; the browser's own frames add nothing.\n exceptionStackTrace: ''\n };\n\n // `hasData` is a prototype getter, and a spread copies own properties only - so the literal\n // above would hand every consumer of this public `IQueryResult` member `undefined` instead\n // of a boolean. Restoring the prototype makes it a real {@link QueryResult} again while\n // leaving every field value exactly as it is.\n return Object.setPrototypeOf(failure, QueryResult.prototype) as QueryResult<TDataType>;\n }\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n}\n"],"names":["QueryFor","_microservice","_apiBasePath","_origin","_httpHeadersCallback","_httpMethod","queryName","validation","roles","abortController","sorting","paging","parameters","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","perform","args","noSuccess","QueryResult","data","defaultValue","clientValidationErrors","validate","length","validationFailed","ValidateRequestArguments","name","requiredRequestParameters","Promise","resolve","abort","AbortController","parameterValues","ParametersHelper","collectParameterValues","headers","microserviceHttpHeader","response","executeQueryHttpRequest","route","signal","error","isAbortError","message","failure","isSuccess","isAuthorized","isValid","hasExceptions","exceptionMessages","String","exceptionStackTrace","Object","setPrototypeOf","prototype","result","json"],"mappings":"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"}
1
+ {"version":3,"file":"QueryFor.js","sources":["../../../queries/QueryFor.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 { IQueryFor } from './IQueryFor';\nimport { QueryResult } from \"./QueryResult\";\nimport { QueryValidator } from './QueryValidator';\nimport { ValidateRequestArguments } from './ValidateRequestArguments';\nimport { Constructor } from '@cratis/fundamentals';\nimport { Paging } from './Paging';\nimport { Globals } from '../Globals';\nimport { Sorting } from './Sorting';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { ParameterDescriptor } from '../reflection/ParameterDescriptor';\nimport { ParametersHelper } from '../reflection/ParametersHelper';\nimport { QueryHttpMethod } from './QueryHttpMethod';\nimport { executeQueryHttpRequest } from './QueryHttpRequest';\nimport { isAbortError } from './isAbortError';\n\n/**\n * Represents an implementation of {@link IQueryFor}.\n * @template TDataType Type of data returned by the query.\n */\nexport abstract class QueryFor<TDataType, TParameters = object> implements IQueryFor<TDataType, TParameters> {\n private _microservice: string;\n private _apiBasePath: string;\n private _origin: string;\n private _httpHeadersCallback: GetHttpHeaders;\n private _httpMethod?: QueryHttpMethod;\n abstract readonly route: string;\n /** Backend fully-qualified query name used as cache key. Overridden in generated proxies. */\n readonly queryName?: string;\n /* eslint-disable @typescript-eslint/no-explicit-any */\n readonly validation?: QueryValidator<any>;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n readonly roles: string[] = [];\n abstract readonly parameterDescriptors: ParameterDescriptor[];\n abstract get requiredRequestParameters(): string[];\n abstract defaultValue: TDataType;\n abortController?: AbortController;\n sorting: Sorting;\n paging: Paging;\n parameters: TParameters | undefined;\n\n /**\n * Initializes a new instance of the {@link ObservableQueryFor<,>}} class.\n * @param modelType Type of model, if an enumerable, this is the instance type.\n * @param enumerable Whether or not it is an enumerable.\n */\n constructor(readonly modelType: Constructor, readonly enumerable: boolean) {\n this.sorting = Sorting.none;\n this.paging = Paging.noPaging;\n this._microservice = Globals.microservice ?? '';\n this._apiBasePath = Globals.apiBasePath ?? '';\n this._origin = Globals.origin ?? '';\n this._httpHeadersCallback = () => ({});\n }\n\n /** @inheritdoc */\n setMicroservice(microservice: string) {\n this._microservice = microservice;\n }\n\n /** @inheritdoc */\n setApiBasePath(apiBasePath: string): void {\n this._apiBasePath = apiBasePath;\n }\n\n /** @inheritdoc */\n setOrigin(origin: string): void {\n this._origin = origin;\n }\n\n /** @inheritdoc */\n setHttpHeadersCallback(callback: GetHttpHeaders): void {\n this._httpHeadersCallback = callback;\n }\n\n /** @inheritdoc */\n setHttpMethod(method: QueryHttpMethod): void {\n this._httpMethod = method;\n }\n\n /** @inheritdoc */\n async perform(args?: TParameters): Promise<QueryResult<TDataType>> {\n const noSuccess = { ...QueryResult.noSuccess, ...{ data: this.defaultValue } } as QueryResult<TDataType>;\n\n args = args || this.parameters;\n\n const clientValidationErrors = this.validation?.validate(args as object || {}) || [];\n if (clientValidationErrors.length > 0) {\n return QueryResult.validationFailed(clientValidationErrors, this);\n }\n\n if (!ValidateRequestArguments(this.constructor.name, this.requiredRequestParameters, args as object)) {\n return new Promise<QueryResult<TDataType>>((resolve) => {\n resolve(noSuccess);\n });\n }\n\n if (this.abortController) {\n this.abortController.abort();\n }\n\n this.abortController = new AbortController();\n\n // Collect parameter values from parameterDescriptors that are set\n const parameterValues = ParametersHelper.collectParameterValues(this);\n\n const headers = {\n ... this._httpHeadersCallback?.(), ...\n {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n }\n };\n\n if (this._microservice?.length > 0) {\n headers[Globals.microserviceHttpHeader] = this._microservice;\n }\n\n let response: Response;\n\n try {\n response = await executeQueryHttpRequest(this._httpMethod, {\n route: this.route,\n apiBasePath: this._apiBasePath,\n origin: this._origin,\n args: (args as object) ?? {},\n parameterValues,\n paging: this.paging,\n sorting: this.sorting,\n headers,\n signal: this.abortController.signal\n });\n } catch (error) {\n // An abort is not a failure - it is this query superseding its own in-flight request above.\n // Rethrowing lets the caller discard the superseded request so it cannot settle over the\n // newer one that now owns the result.\n if (isAbortError(error)) {\n throw error;\n }\n\n // A dead network, a CORS rejection or a DNS failure never reaches the server, so it is\n // neither an authorization nor a validation outcome - it is reported as an exception, with\n // the default value as data, exactly as every other unsuccessful result from here does.\n // Destructuring a nullish rejection value throws, which would make the `String(error)`\n // fallback written for exactly that case unreachable - so it is coerced to an object first.\n const { message } = (error ?? {}) as { message?: string };\n const failure = {\n ...QueryResult.noSuccess,\n data: this.defaultValue,\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: true,\n exceptionMessages: [message ?? String(error)],\n // Left empty on purpose. Every result the server returns has its stack trace blanked\n // unless exception detail is explicitly exposed, and consumers are told to forward\n // this field to a logger - so filling it in here would make a failure that never\n // reached the server the one case that escapes that policy. The message is what\n // diagnoses a transport failure; the browser's own frames add nothing.\n exceptionStackTrace: ''\n };\n\n // `hasData` is a prototype getter, and a spread copies own properties only - so the literal\n // above would hand every consumer of this public `IQueryResult` member `undefined` instead\n // of a boolean. Restoring the prototype makes it a real {@link QueryResult} again while\n // leaving every field value exactly as it is.\n return Object.setPrototypeOf(failure, QueryResult.prototype) as QueryResult<TDataType>;\n }\n\n try {\n const result = await response.json();\n return new QueryResult(result, this.modelType, this.enumerable);\n } catch {\n return noSuccess;\n }\n }\n}\n"],"names":["QueryFor","_microservice","_apiBasePath","_origin","_httpHeadersCallback","_httpMethod","queryName","validation","roles","abortController","sorting","paging","parameters","enumerable","modelType","Sorting","none","Paging","noPaging","Globals","microservice","apiBasePath","origin","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback","callback","setHttpMethod","method","perform","args","noSuccess","QueryResult","data","defaultValue","clientValidationErrors","validate","length","validationFailed","ValidateRequestArguments","name","requiredRequestParameters","Promise","resolve","abort","AbortController","parameterValues","ParametersHelper","collectParameterValues","headers","microserviceHttpHeader","response","executeQueryHttpRequest","route","signal","error","isAbortError","message","failure","isSuccess","isAuthorized","isValid","hasExceptions","exceptionMessages","String","exceptionStackTrace","Object","setPrototypeOf","prototype","result","json"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryHttpMethod.js","sources":["../../../queries/QueryHttpMethod.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 * Defines the HTTP method used to perform a query over HTTP.\n */\nexport enum QueryHttpMethod {\n /**\n * Use the GET method, carrying arguments in the URL query string (default).\n */\n Get = 'GET',\n\n /**\n * Use the QUERY method (RFC 10008), carrying arguments in a JSON request body.\n */\n Query = 'QUERY',\n\n /**\n * Prefer the QUERY method and automatically fall back to GET when the server or network path\n * does not support it. The outcome is remembered for the rest of the session so subsequent\n * queries go straight to the working transport.\n */\n Auto = 'AUTO',\n}\n"],"names":["QueryHttpMethod"],"mappings":";;AAAA;AACA;AAEA;;IAGO,IAAKA,eAAAA,iBAAAA,SAAAA,eAAAA,EAAAA;AACR;;AAEC,QAAA,eAAA,CAAA,KAAA,CAAA,GAAA,KAAA;AAGD;;AAEC,QAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAA;AAGD;;;;AAIC,QAAA,eAAA,CAAA,MAAA,CAAA,GAAA,MAAA;AAfOA,IAAAA,OAAAA,eAAAA;AAiBX,CAAA,CAAA,EAAA;;;;"}
1
+ {"version":3,"file":"QueryHttpMethod.js","sources":["../../../queries/QueryHttpMethod.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 * Defines the HTTP method used to perform a query over HTTP.\n */\nexport enum QueryHttpMethod {\n /**\n * Use the GET method, carrying arguments in the URL query string (default).\n */\n Get = 'GET',\n\n /**\n * Use the QUERY method (RFC 10008), carrying arguments in a JSON request body.\n */\n Query = 'QUERY',\n\n /**\n * Prefer the QUERY method and automatically fall back to GET when the server or network path\n * does not support it. The outcome is remembered for the rest of the session so subsequent\n * queries go straight to the working transport.\n */\n Auto = 'AUTO',\n}\n"],"names":["QueryHttpMethod"],"mappings":";;AAAA;AACA;AAEA;;IAGO,IAAKA,eAAAA,iBAAAA,SAAAA,eAAAA,EAAAA;AACR;;AAEC,QAAA,eAAA,CAAA,KAAA,CAAA,GAAA,KAAA;AAGD;;AAEC,QAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAA;AAGD;;;;AAIC,QAAA,eAAA,CAAA,MAAA,CAAA,GAAA,MAAA;AAfOA,IAAAA,OAAAA,eAAAA;AAiBX,CAAA,CAAA,EAAA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryHttpMethodResolver.js","sources":["../../../queries/QueryHttpMethodResolver.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 { QueryHttpMethod } from './QueryHttpMethod';\n\n/**\n * The information a {@link QueryHttpMethodResolver} uses to decide the HTTP method for a query.\n */\nexport interface QueryHttpMethodResolverContext {\n /** The URL the query would use as a GET request (arguments in the query string). */\n readonly url: URL;\n /** The route template for the query. */\n readonly route: string;\n /** The arguments for the query. */\n readonly args: object;\n}\n\n/**\n * A policy that decides, per query, which {@link QueryHttpMethod} to use.\n * Consulted only when the query has no explicit method set via {@code setHttpMethod}.\n */\nexport type QueryHttpMethodResolver = (context: QueryHttpMethodResolverContext) => QueryHttpMethod;\n\n/**\n * The default URL length, in characters, above which {@link lengthBasedQueryHttpMethod} prefers QUERY.\n * 2000 is the widely-safe URL length across browsers, servers and proxies.\n */\nexport const defaultQueryHttpMethodUrlThreshold = 2000;\n\n/**\n * Options for {@link lengthBasedQueryHttpMethod}.\n */\nexport interface LengthBasedQueryHttpMethodOptions {\n /** URL length (in characters) above which QUERY is preferred. Defaults to {@link defaultQueryHttpMethodUrlThreshold}. */\n threshold?: number;\n /** The method to use when the URL exceeds the threshold. Defaults to {@link QueryHttpMethod.Auto} so it still falls back to GET. */\n whenLong?: QueryHttpMethod;\n}\n\n/**\n * Creates a {@link QueryHttpMethodResolver} that keeps short queries on GET and prefers QUERY only when\n * the GET URL would exceed a threshold — targeting the arguments-too-large-for-a-URL case while leaving\n * small, cacheable queries on GET.\n * @param options Optional {@link LengthBasedQueryHttpMethodOptions}.\n * @returns A {@link QueryHttpMethodResolver}.\n */\nexport function lengthBasedQueryHttpMethod(options?: LengthBasedQueryHttpMethodOptions): QueryHttpMethodResolver {\n const threshold = options?.threshold ?? defaultQueryHttpMethodUrlThreshold;\n const whenLong = options?.whenLong ?? QueryHttpMethod.Auto;\n return context => (context.url.href.length > threshold ? whenLong : QueryHttpMethod.Get);\n}\n"],"names":["defaultQueryHttpMethodUrlThreshold","lengthBasedQueryHttpMethod","options","threshold","whenLong","QueryHttpMethod","Auto","context","url","href","length","Get"],"mappings":";;;;AAAA;AACA;AAsBA;;;IAIO,MAAMA,kCAAAA,GAAqC;AAYlD;;;;;;IAOO,SAASC,0BAAAA,CAA2BC,OAA2C,EAAA;IAClF,MAAMC,SAAAA,GAAYD,SAASC,SAAAA,IAAaH,kCAAAA;AACxC,IAAA,MAAMI,QAAAA,GAAWF,OAAAA,EAASE,QAAAA,IAAYC,+BAAAA,CAAgBC,IAAI;AAC1D,IAAA,OAAOC,CAAAA,OAAAA,GAAYA,OAAAA,CAAQC,GAAG,CAACC,IAAI,CAACC,MAAM,GAAGP,SAAAA,GAAYC,QAAAA,GAAWC,+BAAAA,CAAgBM,GAAG;AAC3F;;;;;"}
1
+ {"version":3,"file":"QueryHttpMethodResolver.js","sources":["../../../queries/QueryHttpMethodResolver.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 { QueryHttpMethod } from './QueryHttpMethod';\n\n/**\n * The information a {@link QueryHttpMethodResolver} uses to decide the HTTP method for a query.\n */\nexport interface QueryHttpMethodResolverContext {\n /** The URL the query would use as a GET request (arguments in the query string). */\n readonly url: URL;\n /** The route template for the query. */\n readonly route: string;\n /** The arguments for the query. */\n readonly args: object;\n}\n\n/**\n * A policy that decides, per query, which {@link QueryHttpMethod} to use.\n * Consulted only when the query has no explicit method set via {@code setHttpMethod}.\n */\nexport type QueryHttpMethodResolver = (context: QueryHttpMethodResolverContext) => QueryHttpMethod;\n\n/**\n * The default URL length, in characters, above which {@link lengthBasedQueryHttpMethod} prefers QUERY.\n * 2000 is the widely-safe URL length across browsers, servers and proxies.\n */\nexport const defaultQueryHttpMethodUrlThreshold = 2000;\n\n/**\n * Options for {@link lengthBasedQueryHttpMethod}.\n */\nexport interface LengthBasedQueryHttpMethodOptions {\n /** URL length (in characters) above which QUERY is preferred. Defaults to {@link defaultQueryHttpMethodUrlThreshold}. */\n threshold?: number;\n /** The method to use when the URL exceeds the threshold. Defaults to {@link QueryHttpMethod.Auto} so it still falls back to GET. */\n whenLong?: QueryHttpMethod;\n}\n\n/**\n * Creates a {@link QueryHttpMethodResolver} that keeps short queries on GET and prefers QUERY only when\n * the GET URL would exceed a threshold — targeting the arguments-too-large-for-a-URL case while leaving\n * small, cacheable queries on GET.\n * @param options Optional {@link LengthBasedQueryHttpMethodOptions}.\n * @returns A {@link QueryHttpMethodResolver}.\n */\nexport function lengthBasedQueryHttpMethod(options?: LengthBasedQueryHttpMethodOptions): QueryHttpMethodResolver {\n const threshold = options?.threshold ?? defaultQueryHttpMethodUrlThreshold;\n const whenLong = options?.whenLong ?? QueryHttpMethod.Auto;\n return context => (context.url.href.length > threshold ? whenLong : QueryHttpMethod.Get);\n}\n"],"names":["defaultQueryHttpMethodUrlThreshold","lengthBasedQueryHttpMethod","options","threshold","whenLong","QueryHttpMethod","Auto","context","url","href","length","Get"],"mappings":";;;;AAAA;AACA;AAsBA;;;IAIO,MAAMA,kCAAAA,GAAqC;AAYlD;;;;;;IAOO,SAASC,0BAAAA,CAA2BC,OAA2C,EAAA;IAClF,MAAMC,SAAAA,GAAYD,SAASC,SAAAA,IAAaH,kCAAAA;AACxC,IAAA,MAAMI,QAAAA,GAAWF,OAAAA,EAASE,QAAAA,IAAYC,+BAAAA,CAAgBC,IAAI;AAC1D,IAAA,OAAOC,CAAAA,OAAAA,GAAYA,OAAAA,CAAQC,GAAG,CAACC,IAAI,CAACC,MAAM,GAAGP,SAAAA,GAAYC,QAAAA,GAAWC,+BAAAA,CAAgBM,GAAG;AAC3F;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryHttpRequest.js","sources":["../../../queries/QueryHttpRequest.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 { Paging } from './Paging';\nimport { Sorting } from './Sorting';\nimport { SortDirection } from './SortDirection';\nimport { QueryHttpMethod } from './QueryHttpMethod';\nimport { joinPaths } from '../joinPaths';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { Globals } from '../Globals';\nimport { isAbortError } from './isAbortError';\n\n/**\n * Options for building an HTTP request for a query.\n */\nexport interface BuildQueryHttpRequestOptions {\n /** The route template for the query, possibly containing route parameters. */\n route: string;\n /** The base path for the API. */\n apiBasePath: string;\n /** The origin for the API. */\n origin: string;\n /** The arguments used for route-parameter substitution and as query arguments. */\n args: object;\n /** Descriptor-collected parameter values that also form query arguments. */\n parameterValues: object;\n /** The paging for the query. */\n paging: Paging;\n /** The sorting for the query. */\n sorting: Sorting;\n /** The HTTP headers to include. */\n headers: HeadersInit;\n /** Optional abort signal for the request. */\n signal?: AbortSignal;\n}\n\ninterface QueryRequestPayload {\n arguments: object;\n paging?: { page: number; pageSize: number };\n sorting?: { field: string; direction: string };\n}\n\nfunction directionToString(sorting: Sorting): string {\n return sorting.direction === SortDirection.descending ? 'desc' : 'asc';\n}\n\n/**\n * Builds the URL and {@link RequestInit} for performing a query with the given HTTP method.\n *\n * For {@link QueryHttpMethod.Get}, arguments, paging and sorting are placed in the URL query string.\n * For {@link QueryHttpMethod.Query}, route parameters remain in the path while the arguments, paging\n * and sorting are carried in a JSON body envelope.\n * @param method The {@link QueryHttpMethod} to use.\n * @param options The {@link BuildQueryHttpRequestOptions} describing the request.\n * @returns The URL and {@link RequestInit} to pass to {@link fetch}.\n */\nexport function buildQueryHttpRequest(method: QueryHttpMethod, options: BuildQueryHttpRequestOptions): { url: URL; init: RequestInit } {\n const { route, apiBasePath, origin, args, parameterValues, paging, sorting, headers, signal } = options;\n\n const { route: replacedRoute, unusedParameters } = UrlHelpers.replaceRouteParameters(route, args);\n const argumentValues = { ...unusedParameters, ...parameterValues };\n let actualRoute = joinPaths(apiBasePath, replacedRoute);\n\n if (method === QueryHttpMethod.Query) {\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, actualRoute);\n const payload: QueryRequestPayload = { arguments: argumentValues };\n if (paging.hasPaging) {\n payload.paging = { page: paging.page, pageSize: paging.pageSize };\n }\n if (sorting.hasSorting) {\n payload.sorting = { field: sorting.field, direction: directionToString(sorting) };\n }\n\n const requestHeaders = new Headers(headers);\n if (!requestHeaders.has('Content-Type')) {\n requestHeaders.set('Content-Type', 'application/json');\n }\n\n const init: RequestInit = {\n method: QueryHttpMethod.Query,\n headers: requestHeaders,\n body: JSON.stringify(payload),\n signal\n };\n return { url, init };\n }\n\n const additionalParams: Record<string, string | number> = {};\n if (paging.hasPaging) {\n additionalParams.page = paging.page;\n additionalParams.pageSize = paging.pageSize;\n }\n if (sorting.hasSorting) {\n additionalParams.sortBy = sorting.field;\n additionalParams.sortDirection = directionToString(sorting);\n }\n\n const queryParams = UrlHelpers.buildQueryParams(argumentValues, additionalParams);\n const queryString = queryParams.toString();\n if (queryString) {\n actualRoute += (actualRoute.includes('?') ? '&' : '?') + queryString;\n }\n\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, actualRoute);\n const init: RequestInit = {\n method: QueryHttpMethod.Get,\n headers,\n signal\n };\n return { url, init };\n}\n\n/**\n * The transport learned for {@link QueryHttpMethod.Auto}, keyed by backend (origin + API base path).\n * Once QUERY is found to be unsupported for a backend it is pinned to GET for the rest of the session;\n * while QUERY works the backend stays absent so each attempt keeps verifying cheaply. Keying by backend\n * means one backend rejecting QUERY does not downgrade queries to other backends.\n */\nconst autoResolvedMethods = new Map<string, QueryHttpMethod>();\n\n// A NUL separator cannot occur in an origin or an API base path, so no pair of backends can\n// produce the same composite key. Written as an escape rather than a literal control byte,\n// which would make git classify this file as binary and hide every diff of it from review.\nfunction backendKey(options: BuildQueryHttpRequestOptions): string {\n return `${options.origin}\\0${options.apiBasePath}`;\n}\n\n/**\n * Resets the transport learned for {@link QueryHttpMethod.Auto} for every backend, so the next Auto\n * query re-probes for QUERY support. Useful after a network change, or between tests.\n */\nexport function resetQueryHttpMethodResolution(): void {\n autoResolvedMethods.clear();\n}\n\nfunction isMethodUnsupported(status: number): boolean {\n // 405 Method Not Allowed / 501 Not Implemented — the server received the request but will not\n // handle the verb (e.g. QUERY disabled). A missing intermediary surfaces as a thrown TypeError.\n return status === 405 || status === 501;\n}\n\n/**\n * Performs the query HTTP request for the given method, resolving {@link QueryHttpMethod.Auto} by\n * preferring QUERY and falling back to GET when the server or network path does not support it.\n *\n * Explicit {@link QueryHttpMethod.Get} and {@link QueryHttpMethod.Query} are honored exactly, with no\n * fallback. For Auto, a transport-level failure — a `405`/`501` response, or a network/CORS error from\n * {@link fetch} — falls back to GET and pins the session to GET. Application-level errors (any other\n * status, returned as a normal {@link Response}) are never treated as a fallback signal.\n *\n * The method is resolved in order of precedence: an explicit per-query {@code override}, then\n * {@link Globals.queryHttpMethodResolver} (given the built GET URL), then {@link Globals.queryHttpMethod}.\n * @param override The explicit per-query {@link QueryHttpMethod}, or `undefined` to resolve from globals.\n * @param options The {@link BuildQueryHttpRequestOptions} describing the request.\n * @returns The {@link Response} from the request that was ultimately sent.\n */\nexport async function executeQueryHttpRequest(override: QueryHttpMethod | undefined, options: BuildQueryHttpRequestOptions): Promise<Response> {\n // The GET request is built up front when a resolver needs the URL, and reused if GET is chosen.\n let getRequest: { url: URL; init: RequestInit } | undefined;\n let method: QueryHttpMethod;\n if (override !== undefined) {\n method = override;\n } else if (Globals.queryHttpMethodResolver) {\n getRequest = buildQueryHttpRequest(QueryHttpMethod.Get, options);\n method = Globals.queryHttpMethodResolver({ url: getRequest.url, route: options.route, args: options.args });\n } else {\n method = Globals.queryHttpMethod;\n }\n\n const send = (httpMethod: QueryHttpMethod): Promise<Response> => {\n if (httpMethod === QueryHttpMethod.Get && getRequest) {\n return fetch(getRequest.url, getRequest.init);\n }\n const { url, init } = buildQueryHttpRequest(httpMethod, options);\n return fetch(url, init);\n };\n\n if (method !== QueryHttpMethod.Auto) {\n return send(method);\n }\n\n const key = backendKey(options);\n if (autoResolvedMethods.get(key) === QueryHttpMethod.Get) {\n return send(QueryHttpMethod.Get);\n }\n\n try {\n const response = await send(QueryHttpMethod.Query);\n if (isMethodUnsupported(response.status)) {\n autoResolvedMethods.set(key, QueryHttpMethod.Get);\n return send(QueryHttpMethod.Get);\n }\n autoResolvedMethods.set(key, QueryHttpMethod.Query);\n return response;\n } catch (error) {\n if (isAbortError(error)) {\n throw error;\n }\n autoResolvedMethods.set(key, QueryHttpMethod.Get);\n return send(QueryHttpMethod.Get);\n }\n}\n"],"names":["directionToString","sorting","direction","SortDirection","descending","buildQueryHttpRequest","method","options","route","apiBasePath","origin","args","parameterValues","paging","headers","signal","replacedRoute","unusedParameters","UrlHelpers","replaceRouteParameters","argumentValues","actualRoute","joinPaths","QueryHttpMethod","Query","url","createUrlFrom","payload","arguments","hasPaging","page","pageSize","hasSorting","field","requestHeaders","Headers","has","set","init","body","JSON","stringify","additionalParams","sortBy","sortDirection","queryParams","buildQueryParams","queryString","toString","includes","Get","autoResolvedMethods","Map","backendKey","resetQueryHttpMethodResolution","clear","isMethodUnsupported","status","executeQueryHttpRequest","override","getRequest","undefined","Globals","queryHttpMethodResolver","queryHttpMethod","send","httpMethod","fetch","Auto","key","get","response","error","isAbortError"],"mappings":"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"}
1
+ {"version":3,"file":"QueryHttpRequest.js","sources":["../../../queries/QueryHttpRequest.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 { Paging } from './Paging';\nimport { Sorting } from './Sorting';\nimport { SortDirection } from './SortDirection';\nimport { QueryHttpMethod } from './QueryHttpMethod';\nimport { joinPaths } from '../joinPaths';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { Globals } from '../Globals';\nimport { isAbortError } from './isAbortError';\n\n/**\n * Options for building an HTTP request for a query.\n */\nexport interface BuildQueryHttpRequestOptions {\n /** The route template for the query, possibly containing route parameters. */\n route: string;\n /** The base path for the API. */\n apiBasePath: string;\n /** The origin for the API. */\n origin: string;\n /** The arguments used for route-parameter substitution and as query arguments. */\n args: object;\n /** Descriptor-collected parameter values that also form query arguments. */\n parameterValues: object;\n /** The paging for the query. */\n paging: Paging;\n /** The sorting for the query. */\n sorting: Sorting;\n /** The HTTP headers to include. */\n headers: HeadersInit;\n /** Optional abort signal for the request. */\n signal?: AbortSignal;\n}\n\ninterface QueryRequestPayload {\n arguments: object;\n paging?: { page: number; pageSize: number };\n sorting?: { field: string; direction: string };\n}\n\nfunction directionToString(sorting: Sorting): string {\n return sorting.direction === SortDirection.descending ? 'desc' : 'asc';\n}\n\n/**\n * Builds the URL and {@link RequestInit} for performing a query with the given HTTP method.\n *\n * For {@link QueryHttpMethod.Get}, arguments, paging and sorting are placed in the URL query string.\n * For {@link QueryHttpMethod.Query}, route parameters remain in the path while the arguments, paging\n * and sorting are carried in a JSON body envelope.\n * @param method The {@link QueryHttpMethod} to use.\n * @param options The {@link BuildQueryHttpRequestOptions} describing the request.\n * @returns The URL and {@link RequestInit} to pass to {@link fetch}.\n */\nexport function buildQueryHttpRequest(method: QueryHttpMethod, options: BuildQueryHttpRequestOptions): { url: URL; init: RequestInit } {\n const { route, apiBasePath, origin, args, parameterValues, paging, sorting, headers, signal } = options;\n\n const { route: replacedRoute, unusedParameters } = UrlHelpers.replaceRouteParameters(route, args);\n const argumentValues = { ...unusedParameters, ...parameterValues };\n let actualRoute = joinPaths(apiBasePath, replacedRoute);\n\n if (method === QueryHttpMethod.Query) {\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, actualRoute);\n const payload: QueryRequestPayload = { arguments: argumentValues };\n if (paging.hasPaging) {\n payload.paging = { page: paging.page, pageSize: paging.pageSize };\n }\n if (sorting.hasSorting) {\n payload.sorting = { field: sorting.field, direction: directionToString(sorting) };\n }\n\n const requestHeaders = new Headers(headers);\n if (!requestHeaders.has('Content-Type')) {\n requestHeaders.set('Content-Type', 'application/json');\n }\n\n const init: RequestInit = {\n method: QueryHttpMethod.Query,\n headers: requestHeaders,\n body: JSON.stringify(payload),\n signal\n };\n return { url, init };\n }\n\n const additionalParams: Record<string, string | number> = {};\n if (paging.hasPaging) {\n additionalParams.page = paging.page;\n additionalParams.pageSize = paging.pageSize;\n }\n if (sorting.hasSorting) {\n additionalParams.sortBy = sorting.field;\n additionalParams.sortDirection = directionToString(sorting);\n }\n\n const queryParams = UrlHelpers.buildQueryParams(argumentValues, additionalParams);\n const queryString = queryParams.toString();\n if (queryString) {\n actualRoute += (actualRoute.includes('?') ? '&' : '?') + queryString;\n }\n\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, actualRoute);\n const init: RequestInit = {\n method: QueryHttpMethod.Get,\n headers,\n signal\n };\n return { url, init };\n}\n\n/**\n * The transport learned for {@link QueryHttpMethod.Auto}, keyed by backend (origin + API base path).\n * Once QUERY is found to be unsupported for a backend it is pinned to GET for the rest of the session;\n * while QUERY works the backend stays absent so each attempt keeps verifying cheaply. Keying by backend\n * means one backend rejecting QUERY does not downgrade queries to other backends.\n */\nconst autoResolvedMethods = new Map<string, QueryHttpMethod>();\n\n// A NUL separator cannot occur in an origin or an API base path, so no pair of backends can\n// produce the same composite key. Written as an escape rather than a literal control byte,\n// which would make git classify this file as binary and hide every diff of it from review.\nfunction backendKey(options: BuildQueryHttpRequestOptions): string {\n return `${options.origin}\\0${options.apiBasePath}`;\n}\n\n/**\n * Resets the transport learned for {@link QueryHttpMethod.Auto} for every backend, so the next Auto\n * query re-probes for QUERY support. Useful after a network change, or between tests.\n */\nexport function resetQueryHttpMethodResolution(): void {\n autoResolvedMethods.clear();\n}\n\nfunction isMethodUnsupported(status: number): boolean {\n // 405 Method Not Allowed / 501 Not Implemented — the server received the request but will not\n // handle the verb (e.g. QUERY disabled). A missing intermediary surfaces as a thrown TypeError.\n return status === 405 || status === 501;\n}\n\n/**\n * Performs the query HTTP request for the given method, resolving {@link QueryHttpMethod.Auto} by\n * preferring QUERY and falling back to GET when the server or network path does not support it.\n *\n * Explicit {@link QueryHttpMethod.Get} and {@link QueryHttpMethod.Query} are honored exactly, with no\n * fallback. For Auto, a transport-level failure — a `405`/`501` response, or a network/CORS error from\n * {@link fetch} — falls back to GET and pins the session to GET. Application-level errors (any other\n * status, returned as a normal {@link Response}) are never treated as a fallback signal.\n *\n * The method is resolved in order of precedence: an explicit per-query {@code override}, then\n * {@link Globals.queryHttpMethodResolver} (given the built GET URL), then {@link Globals.queryHttpMethod}.\n * @param override The explicit per-query {@link QueryHttpMethod}, or `undefined` to resolve from globals.\n * @param options The {@link BuildQueryHttpRequestOptions} describing the request.\n * @returns The {@link Response} from the request that was ultimately sent.\n */\nexport async function executeQueryHttpRequest(override: QueryHttpMethod | undefined, options: BuildQueryHttpRequestOptions): Promise<Response> {\n // The GET request is built up front when a resolver needs the URL, and reused if GET is chosen.\n let getRequest: { url: URL; init: RequestInit } | undefined;\n let method: QueryHttpMethod;\n if (override !== undefined) {\n method = override;\n } else if (Globals.queryHttpMethodResolver) {\n getRequest = buildQueryHttpRequest(QueryHttpMethod.Get, options);\n method = Globals.queryHttpMethodResolver({ url: getRequest.url, route: options.route, args: options.args });\n } else {\n method = Globals.queryHttpMethod;\n }\n\n const send = (httpMethod: QueryHttpMethod): Promise<Response> => {\n if (httpMethod === QueryHttpMethod.Get && getRequest) {\n return fetch(getRequest.url, getRequest.init);\n }\n const { url, init } = buildQueryHttpRequest(httpMethod, options);\n return fetch(url, init);\n };\n\n if (method !== QueryHttpMethod.Auto) {\n return send(method);\n }\n\n const key = backendKey(options);\n if (autoResolvedMethods.get(key) === QueryHttpMethod.Get) {\n return send(QueryHttpMethod.Get);\n }\n\n try {\n const response = await send(QueryHttpMethod.Query);\n if (isMethodUnsupported(response.status)) {\n autoResolvedMethods.set(key, QueryHttpMethod.Get);\n return send(QueryHttpMethod.Get);\n }\n autoResolvedMethods.set(key, QueryHttpMethod.Query);\n return response;\n } catch (error) {\n if (isAbortError(error)) {\n throw error;\n }\n autoResolvedMethods.set(key, QueryHttpMethod.Get);\n return send(QueryHttpMethod.Get);\n }\n}\n"],"names":["directionToString","sorting","direction","SortDirection","descending","buildQueryHttpRequest","method","options","route","apiBasePath","origin","args","parameterValues","paging","headers","signal","replacedRoute","unusedParameters","UrlHelpers","replaceRouteParameters","argumentValues","actualRoute","joinPaths","QueryHttpMethod","Query","url","createUrlFrom","payload","arguments","hasPaging","page","pageSize","hasSorting","field","requestHeaders","Headers","has","set","init","body","JSON","stringify","additionalParams","sortBy","sortDirection","queryParams","buildQueryParams","queryString","toString","includes","Get","autoResolvedMethods","Map","backendKey","resetQueryHttpMethodResolution","clear","isMethodUnsupported","status","executeQueryHttpRequest","override","getRequest","undefined","Globals","queryHttpMethodResolver","queryHttpMethod","send","httpMethod","fetch","Auto","key","get","response","error","isAbortError"],"mappings":"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"}