@cratis/arc 20.60.0 → 20.60.2

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 (140) hide show
  1. package/dist/cjs/queries/HubConnectionKeepAlive.js +24 -4
  2. package/dist/cjs/queries/HubConnectionKeepAlive.js.map +1 -1
  3. package/dist/cjs/queries/NullObservableQueryConnection.js +7 -2
  4. package/dist/cjs/queries/NullObservableQueryConnection.js.map +1 -1
  5. package/dist/cjs/queries/ObservableQueryFor.js +11 -1
  6. package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
  7. package/dist/cjs/queries/QueryFor.js +1 -21
  8. package/dist/cjs/queries/QueryFor.js.map +1 -1
  9. package/dist/cjs/queries/QueryInstanceCache.js +35 -12
  10. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  11. package/dist/cjs/queries/QueryResult.js +30 -0
  12. package/dist/cjs/queries/QueryResult.js.map +1 -1
  13. package/dist/cjs/queries/ServerSentEventHubConnection.js +38 -10
  14. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  15. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  16. package/dist/cjs/queries/index.js +2 -0
  17. package/dist/cjs/queries/index.js.map +1 -1
  18. package/dist/cjs/queries/reconcileQueryData.js +84 -0
  19. package/dist/cjs/queries/reconcileQueryData.js.map +1 -0
  20. package/dist/esm/queries/HubConnectionKeepAlive.d.ts +5 -3
  21. package/dist/esm/queries/HubConnectionKeepAlive.d.ts.map +1 -1
  22. package/dist/esm/queries/HubConnectionKeepAlive.js +24 -4
  23. package/dist/esm/queries/HubConnectionKeepAlive.js.map +1 -1
  24. package/dist/esm/queries/NullObservableQueryConnection.d.ts +3 -1
  25. package/dist/esm/queries/NullObservableQueryConnection.d.ts.map +1 -1
  26. package/dist/esm/queries/NullObservableQueryConnection.js +7 -2
  27. package/dist/esm/queries/NullObservableQueryConnection.js.map +1 -1
  28. package/dist/esm/queries/ObservableQueryFor.d.ts +2 -0
  29. package/dist/esm/queries/ObservableQueryFor.d.ts.map +1 -1
  30. package/dist/esm/queries/ObservableQueryFor.js +11 -1
  31. package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
  32. package/dist/esm/queries/QueryFor.d.ts.map +1 -1
  33. package/dist/esm/queries/QueryFor.js +1 -21
  34. package/dist/esm/queries/QueryFor.js.map +1 -1
  35. package/dist/esm/queries/QueryInstanceCache.d.ts +1 -0
  36. package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
  37. package/dist/esm/queries/QueryInstanceCache.js +35 -12
  38. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  39. package/dist/esm/queries/QueryResult.d.ts +5 -0
  40. package/dist/esm/queries/QueryResult.d.ts.map +1 -1
  41. package/dist/esm/queries/QueryResult.js +30 -0
  42. package/dist/esm/queries/QueryResult.js.map +1 -1
  43. package/dist/esm/queries/ServerSentEventHubConnection.d.ts +1 -0
  44. package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
  45. package/dist/esm/queries/ServerSentEventHubConnection.js +38 -10
  46. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  47. package/dist/esm/queries/WebSocketHubConnection.d.ts +1 -0
  48. package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
  49. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  50. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.d.ts +2 -0
  51. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.d.ts.map +1 -0
  52. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.js +37 -0
  53. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.js.map +1 -0
  54. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.d.ts +2 -0
  55. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.d.ts.map +1 -0
  56. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.js +22 -0
  57. package/dist/esm/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.js.map +1 -0
  58. package/dist/esm/queries/for_ObservableQueryFor/given/an_observable_query_with_validator.d.ts +23 -0
  59. package/dist/esm/queries/for_ObservableQueryFor/given/an_observable_query_with_validator.d.ts.map +1 -0
  60. package/dist/esm/queries/for_ObservableQueryFor/given/an_observable_query_with_validator.js +28 -0
  61. package/dist/esm/queries/for_ObservableQueryFor/given/an_observable_query_with_validator.js.map +1 -0
  62. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.d.ts +2 -0
  63. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.d.ts.map +1 -0
  64. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.js +21 -0
  65. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.js.map +1 -0
  66. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_failing.d.ts +2 -0
  67. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_failing.d.ts.map +1 -0
  68. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_failing.js +18 -0
  69. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_failing.js.map +1 -0
  70. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_passing.d.ts +2 -0
  71. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_passing.d.ts.map +1 -0
  72. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_passing.js +21 -0
  73. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_passing.js.map +1 -0
  74. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_partially_changed_result.d.ts +2 -0
  75. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_partially_changed_result.d.ts.map +1 -0
  76. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_partially_changed_result.js +32 -0
  77. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_partially_changed_result.js.map +1 -0
  78. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_re_delivered_identical_result.d.ts +2 -0
  79. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_re_delivered_identical_result.d.ts.map +1 -0
  80. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_re_delivered_identical_result.js +22 -0
  81. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_a_re_delivered_identical_result.js.map +1 -0
  82. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_advertises_a_longer_keep_alive_interval/does_not_reconnect_at_the_assumed_threshold.d.ts +2 -0
  83. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_advertises_a_longer_keep_alive_interval/does_not_reconnect_at_the_assumed_threshold.d.ts.map +1 -0
  84. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_advertises_a_longer_keep_alive_interval/does_not_reconnect_at_the_assumed_threshold.js +39 -0
  85. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_advertises_a_longer_keep_alive_interval/does_not_reconnect_at_the_assumed_threshold.js.map +1 -0
  86. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_reports_keep_alive_disabled/never_reconnects_from_idle.d.ts +2 -0
  87. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_reports_keep_alive_disabled/never_reconnects_from_idle.d.ts.map +1 -0
  88. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_reports_keep_alive_disabled/never_reconnects_from_idle.js +28 -0
  89. package/dist/esm/queries/for_ServerSentEventHubConnection/when_server_reports_keep_alive_disabled/never_reconnects_from_idle.js.map +1 -0
  90. package/dist/esm/queries/for_reconcileQueryData/when_items_are_added_or_removed/reuses_the_surviving_items.d.ts +2 -0
  91. package/dist/esm/queries/for_reconcileQueryData/when_items_are_added_or_removed/reuses_the_surviving_items.d.ts.map +1 -0
  92. package/dist/esm/queries/for_reconcileQueryData/when_items_are_added_or_removed/reuses_the_surviving_items.js +36 -0
  93. package/dist/esm/queries/for_reconcileQueryData/when_items_are_added_or_removed/reuses_the_surviving_items.js.map +1 -0
  94. package/dist/esm/queries/for_reconcileQueryData/when_one_item_changed/only_the_changed_item_gets_a_new_reference.d.ts +2 -0
  95. package/dist/esm/queries/for_reconcileQueryData/when_one_item_changed/only_the_changed_item_gets_a_new_reference.d.ts.map +1 -0
  96. package/dist/esm/queries/for_reconcileQueryData/when_one_item_changed/only_the_changed_item_gets_a_new_reference.js +20 -0
  97. package/dist/esm/queries/for_reconcileQueryData/when_one_item_changed/only_the_changed_item_gets_a_new_reference.js.map +1 -0
  98. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_an_unchanged_collection/preserves_all_references.d.ts +2 -0
  99. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_an_unchanged_collection/preserves_all_references.d.ts.map +1 -0
  100. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_an_unchanged_collection/preserves_all_references.js +15 -0
  101. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_an_unchanged_collection/preserves_all_references.js.map +1 -0
  102. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_non_collection_payloads/compares_by_value.d.ts +2 -0
  103. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_non_collection_payloads/compares_by_value.d.ts.map +1 -0
  104. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_non_collection_payloads/compares_by_value.js +20 -0
  105. package/dist/esm/queries/for_reconcileQueryData/when_reconciling_non_collection_payloads/compares_by_value.js.map +1 -0
  106. package/dist/esm/queries/index.d.ts +1 -0
  107. package/dist/esm/queries/index.d.ts.map +1 -1
  108. package/dist/esm/queries/index.js +1 -0
  109. package/dist/esm/queries/index.js.map +1 -1
  110. package/dist/esm/queries/reconcileQueryData.d.ts +2 -0
  111. package/dist/esm/queries/reconcileQueryData.d.ts.map +1 -0
  112. package/dist/esm/queries/reconcileQueryData.js +82 -0
  113. package/dist/esm/queries/reconcileQueryData.js.map +1 -0
  114. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  115. package/package.json +1 -1
  116. package/queries/HubConnectionKeepAlive.ts +30 -3
  117. package/queries/NullObservableQueryConnection.ts +5 -2
  118. package/queries/ObservableQueryFor.ts +15 -1
  119. package/queries/QueryFor.ts +1 -21
  120. package/queries/QueryInstanceCache.ts +61 -17
  121. package/queries/QueryResult.ts +34 -0
  122. package/queries/ServerSentEventHubConnection.ts +45 -10
  123. package/queries/WebSocketHubConnection.ts +6 -0
  124. package/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.ts +50 -0
  125. package/queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.ts +28 -0
  126. package/queries/for_ObservableQueryFor/given/an_observable_query_with_validator.ts +41 -0
  127. package/queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.ts +30 -0
  128. package/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_failing.ts +26 -0
  129. package/queries/for_ObservableQueryFor/when_subscribing/with_client_validation_passing.ts +32 -0
  130. package/queries/for_QueryInstanceCache/when_setting_last_result/with_a_partially_changed_result.ts +43 -0
  131. package/queries/for_QueryInstanceCache/when_setting_last_result/with_a_re_delivered_identical_result.ts +34 -0
  132. package/queries/for_ServerSentEventHubConnection/when_keep_alive_is_idle/triggers_reconnect.ts +4 -4
  133. package/queries/for_ServerSentEventHubConnection/when_server_advertises_a_longer_keep_alive_interval/does_not_reconnect_at_the_assumed_threshold.ts +64 -0
  134. package/queries/for_ServerSentEventHubConnection/when_server_reports_keep_alive_disabled/never_reconnects_from_idle.ts +50 -0
  135. package/queries/for_reconcileQueryData/when_items_are_added_or_removed/reuses_the_surviving_items.ts +46 -0
  136. package/queries/for_reconcileQueryData/when_one_item_changed/only_the_changed_item_gets_a_new_reference.ts +26 -0
  137. package/queries/for_reconcileQueryData/when_reconciling_an_unchanged_collection/preserves_all_references.ts +22 -0
  138. package/queries/for_reconcileQueryData/when_reconciling_non_collection_payloads/compares_by_value.ts +31 -0
  139. package/queries/index.ts +1 -0
  140. package/queries/reconcileQueryData.ts +98 -0
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.js","sources":["../../../queries/QueryResult.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\n\ntype ServerQueryResult = {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n data: any;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n isSuccess: boolean;\n isAuthorized: boolean;\n isValid: boolean;\n hasExceptions: boolean;\n validationResults: ServerValidationResult[];\n exceptionMessages: string[];\n exceptionStackTrace: string;\n paging: ServerPagingInfo;\n changeSet?: ServerChangeSet;\n}\n\ntype ServerChangeSet = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n added: any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n replaced: any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n removed: any[];\n}\n\ntype ServerValidationResult = {\n severity: number;\n message: string;\n members: string[];\n state: object;\n}\n\ntype ServerPagingInfo = {\n page: number;\n size: number; \n totalItems: number;\n totalPages: number;\n}\n\n/**\n * Represents the result from executing a {@link IQueryFor}.\n * @template TDataType The data type.\n */\nexport class QueryResult<TDataType = object> implements IQueryResult<TDataType> {\n\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult({\n data: defaultValue as object,\n isSuccess: true,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n\n }, Object, false);\n }\n\n static unauthorized<TDataType>(): QueryResult<TDataType> {\n return new QueryResult({\n data: null as unknown as object,\n isSuccess: false,\n isAuthorized: false,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n }\n\n static noSuccess: QueryResult = new QueryResult({\n data: {},\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n\n /**\n * Creates an instance of query result.\n * @param {*} result The raw result from the backend.\n * @param {Constructor} instanceType The type of instance to deserialize.\n * @param {boolean} enumerable Whether or not the result is supposed be an enumerable or not.\n */\n constructor(result: ServerQueryResult, instanceType: Constructor, enumerable: boolean) {\n this.isSuccess = result.isSuccess;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(_ => new ValidationResult(_.severity, _.message, _.members, _.state));\n this.exceptionMessages = result.exceptionMessages;\n this.exceptionStackTrace = result.exceptionStackTrace;\n this.paging = new PagingInfo();\n this.paging.page = result.paging.page;\n this.paging.size = result.paging.size;\n this.paging.totalItems = result.paging.totalItems;\n this.paging.totalPages = result.paging.totalPages;\n\n if (result.data) {\n let data: object = result.data;\n const isPrimitive = instanceType === String || instanceType === Number || instanceType === Boolean;\n if (enumerable) {\n if (Array.isArray(result.data)) {\n data = isPrimitive\n ? Array.from(result.data)\n : JsonSerializer.deserializeArrayFromInstance(instanceType, data);\n } else {\n data = [];\n }\n } else {\n data = isPrimitive ? data : JsonSerializer.deserializeFromInstance(instanceType, data);\n }\n\n this.data = data as TDataType;\n } else {\n this.data = (enumerable ? [] : null) as TDataType;\n }\n\n if (enumerable && result.changeSet) {\n const isPrimitive = instanceType === String || instanceType === Number || instanceType === Boolean;\n this.changeSet = {\n added: isPrimitive\n ? Array.from(result.changeSet.added ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.added ?? []),\n replaced: isPrimitive\n ? Array.from(result.changeSet.replaced ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.replaced ?? []),\n removed: isPrimitive\n ? Array.from(result.changeSet.removed ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.removed ?? []),\n } as ChangeSet<unknown>;\n }\n }\n\n /** @inheritdoc */\n readonly data: TDataType;\n\n /** @inheritdoc */\n readonly paging: PagingInfo;\n\n /** @inheritdoc */\n readonly isSuccess: boolean;\n\n /** @inheritdoc */\n readonly isAuthorized: boolean;\n\n /** @inheritdoc */\n readonly isValid: boolean;\n\n /** @inheritdoc */\n readonly hasExceptions: boolean;\n\n /** @inheritdoc */\n readonly validationResults: ValidationResult[];\n\n /** @inheritdoc */\n readonly exceptionMessages: string[];\n\n /** @inheritdoc */\n readonly exceptionStackTrace: string;\n\n /**\n * Gets the optional change set describing what changed since the previous update.\n * Set by the server when the delta transfer mode is active.\n * When present, clients can apply the delta to their local state rather than replacing\n * the full dataset.\n */\n readonly changeSet?: ChangeSet<unknown>;\n\n /**\n * Gets whether or not the query has data.\n */\n get hasData(): boolean {\n if (this.data) {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return true;\n }\n return false;\n }\n}\n"],"names":["QueryResult","empty","defaultValue","data","isSuccess","isAuthorized","isValid","hasExceptions","validationResults","exceptionMessages","exceptionStackTrace","paging","totalItems","totalPages","page","size","Object","unauthorized","noSuccess","result","instanceType","enumerable","map","_","ValidationResult","severity","message","members","state","PagingInfo","isPrimitive","String","Number","Boolean","Array","isArray","from","JsonSerializer","deserializeArrayFromInstance","deserializeFromInstance","changeSet","added","replaced","removed","hasData","length"],"mappings":"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"}
1
+ {"version":3,"file":"QueryResult.js","sources":["../../../queries/QueryResult.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\n\ntype ServerQueryResult = {\n /* eslint-disable @typescript-eslint/no-explicit-any */\n data: any;\n /* eslint-enable @typescript-eslint/no-explicit-any */\n isSuccess: boolean;\n isAuthorized: boolean;\n isValid: boolean;\n hasExceptions: boolean;\n validationResults: ServerValidationResult[];\n exceptionMessages: string[];\n exceptionStackTrace: string;\n paging: ServerPagingInfo;\n changeSet?: ServerChangeSet;\n}\n\ntype ServerChangeSet = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n added: any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n replaced: any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n removed: any[];\n}\n\ntype ServerValidationResult = {\n severity: number;\n message: string;\n members: string[];\n state: object;\n}\n\ntype ServerPagingInfo = {\n page: number;\n size: number; \n totalItems: number;\n totalPages: number;\n}\n\n/**\n * Represents the result from executing a {@link IQueryFor}.\n * @template TDataType The data type.\n */\nexport class QueryResult<TDataType = object> implements IQueryResult<TDataType> {\n\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult({\n data: defaultValue as object,\n isSuccess: true,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n\n }, Object, false);\n }\n\n /**\n * Creates a {@link QueryResult} representing a query rejected by client-side validation, mirroring\n * {@link CommandResult.validationFailed} so a caller reads a failed query the same way it reads a failed command.\n * @param {ValidationResult[]} validationResults The validation results that caused the failure.\n * @param {object} query The query being rejected, which describes how to shape its own result.\n * @returns {QueryResult<TDataType>} A result that is neither successful nor valid.\n */\n static validationFailed<TDataType>(\n validationResults: ValidationResult[],\n query: { readonly defaultValue: TDataType; readonly modelType: Constructor; readonly enumerable: boolean }): QueryResult<TDataType> {\n const { defaultValue, modelType, enumerable } = query;\n return new QueryResult({\n data: defaultValue as object,\n isSuccess: false,\n isAuthorized: true,\n isValid: false,\n hasExceptions: false,\n validationResults: validationResults.map(_ => ({\n severity: _.severity,\n message: _.message,\n members: _.members,\n state: _.state\n })),\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, modelType, enumerable) as QueryResult<TDataType>;\n }\n\n static unauthorized<TDataType>(): QueryResult<TDataType> {\n return new QueryResult({\n data: null as unknown as object,\n isSuccess: false,\n isAuthorized: false,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n }\n\n static noSuccess: QueryResult = new QueryResult({\n data: {},\n isSuccess: false,\n isAuthorized: true,\n isValid: true,\n hasExceptions: false,\n validationResults: [],\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0\n }\n }, Object, false);\n\n /**\n * Creates an instance of query result.\n * @param {*} result The raw result from the backend.\n * @param {Constructor} instanceType The type of instance to deserialize.\n * @param {boolean} enumerable Whether or not the result is supposed be an enumerable or not.\n */\n constructor(result: ServerQueryResult, instanceType: Constructor, enumerable: boolean) {\n this.isSuccess = result.isSuccess;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(_ => new ValidationResult(_.severity, _.message, _.members, _.state));\n this.exceptionMessages = result.exceptionMessages;\n this.exceptionStackTrace = result.exceptionStackTrace;\n this.paging = new PagingInfo();\n this.paging.page = result.paging.page;\n this.paging.size = result.paging.size;\n this.paging.totalItems = result.paging.totalItems;\n this.paging.totalPages = result.paging.totalPages;\n\n if (result.data) {\n let data: object = result.data;\n const isPrimitive = instanceType === String || instanceType === Number || instanceType === Boolean;\n if (enumerable) {\n if (Array.isArray(result.data)) {\n data = isPrimitive\n ? Array.from(result.data)\n : JsonSerializer.deserializeArrayFromInstance(instanceType, data);\n } else {\n data = [];\n }\n } else {\n data = isPrimitive ? data : JsonSerializer.deserializeFromInstance(instanceType, data);\n }\n\n this.data = data as TDataType;\n } else {\n this.data = (enumerable ? [] : null) as TDataType;\n }\n\n if (enumerable && result.changeSet) {\n const isPrimitive = instanceType === String || instanceType === Number || instanceType === Boolean;\n this.changeSet = {\n added: isPrimitive\n ? Array.from(result.changeSet.added ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.added ?? []),\n replaced: isPrimitive\n ? Array.from(result.changeSet.replaced ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.replaced ?? []),\n removed: isPrimitive\n ? Array.from(result.changeSet.removed ?? [])\n : JsonSerializer.deserializeArrayFromInstance(instanceType, result.changeSet.removed ?? []),\n } as ChangeSet<unknown>;\n }\n }\n\n /** @inheritdoc */\n readonly data: TDataType;\n\n /** @inheritdoc */\n readonly paging: PagingInfo;\n\n /** @inheritdoc */\n readonly isSuccess: boolean;\n\n /** @inheritdoc */\n readonly isAuthorized: boolean;\n\n /** @inheritdoc */\n readonly isValid: boolean;\n\n /** @inheritdoc */\n readonly hasExceptions: boolean;\n\n /** @inheritdoc */\n readonly validationResults: ValidationResult[];\n\n /** @inheritdoc */\n readonly exceptionMessages: string[];\n\n /** @inheritdoc */\n readonly exceptionStackTrace: string;\n\n /**\n * Gets the optional change set describing what changed since the previous update.\n * Set by the server when the delta transfer mode is active.\n * When present, clients can apply the delta to their local state rather than replacing\n * the full dataset.\n */\n readonly changeSet?: ChangeSet<unknown>;\n\n /**\n * Gets whether or not the query has data.\n */\n get hasData(): boolean {\n if (this.data) {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return true;\n }\n return false;\n }\n}\n"],"names":["QueryResult","empty","defaultValue","data","isSuccess","isAuthorized","isValid","hasExceptions","validationResults","exceptionMessages","exceptionStackTrace","paging","totalItems","totalPages","page","size","Object","validationFailed","query","modelType","enumerable","map","_","severity","message","members","state","unauthorized","noSuccess","result","instanceType","ValidationResult","PagingInfo","isPrimitive","String","Number","Boolean","Array","isArray","from","JsonSerializer","deserializeArrayFromInstance","deserializeFromInstance","changeSet","added","replaced","removed","hasData","length"],"mappings":"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"}
@@ -33,6 +33,7 @@ export declare class ServerSentEventHubConnection implements IObservableQueryHub
33
33
  private clearConnectTimeout;
34
34
  private handleMessage;
35
35
  private handleConnected;
36
+ private applyServerKeepAliveInterval;
36
37
  private handleQueryResult;
37
38
  private handleUnauthorized;
38
39
  private sendSubscribe;
@@ -1 +1 @@
1
- {"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAwB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IAcpD,YACqB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC,EAkBrE;IAGD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,CAY1F;IAGD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAWjC;IAGD,OAAO,IAAI,IAAI,CAUd;IAED,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAmBb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;IA+CrB,OAAO,CAAC,eAAe;CAkB1B"}
1
+ {"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AA6B3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAyB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA9B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IAepD,YACqB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC,EAoBrE;IAGD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,CAY1F;IAGD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAWjC;IAGD,OAAO,IAAI,IAAI,CAUd;IAED,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAmBb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;IA+CrB,OAAO,CAAC,eAAe;CAkB1B"}
@@ -6,6 +6,13 @@ import { HubMessageType } from './WebSocketHubConnection.js';
6
6
 
7
7
  // Copyright (c) Cratis. All rights reserved.
8
8
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
9
+ /**
10
+ * How many keep-alive intervals of silence are tolerated before the connection is considered dead.
11
+ *
12
+ * The server guarantees a message every interval, so this is pure slack for latency and jitter.
13
+ * It must stay above 1 — a threshold at or below the server's own cadence makes the client and
14
+ * server timers race, and the client tears down connections the server considers healthy.
15
+ */ const IDLE_THRESHOLD_FACTOR = 2;
9
16
  /**
10
17
  * A multiplexed SSE hub connection that uses EventSource for server→client streaming
11
18
  * and fetch POST requests for client→server subscribe/unsubscribe commands.
@@ -38,8 +45,9 @@ import { HubMessageType } from './WebSocketHubConnection.js';
38
45
  * @param {string} _subscribeUrl The subscribe POST endpoint URL.
39
46
  * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.
40
47
  * @param {string} _microservice The microservice name to pass as a query argument.
41
- * @param {number} keepAliveIntervalMs How long without any server message before the connection
42
- * is considered stale and a reconnect is forced (default: 30 000 ms).
48
+ * @param {number} keepAliveIntervalMs The keep-alive cadence to assume until the server advertises
49
+ * its own on the {@link HubMessageType.Connected} message (default: 30 000 ms). The connection is
50
+ * considered stale after {@link IDLE_THRESHOLD_FACTOR} times this without any server message.
43
51
  * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}
44
52
  * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).
45
53
  * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).
@@ -54,18 +62,20 @@ import { HubMessageType } from './WebSocketHubConnection.js';
54
62
  // inactivity — if the server stops sending messages (including its own keep-alive
55
63
  // pings) for the entire idle threshold, the connection is stale and we reconnect.
56
64
  //
57
- // The idle threshold is set to 1.5× the check interval so the server's keep-alive
58
- // ping (which fires on the same cadence) has time to arrive over the network before
59
- // the client declares the connection dead. Without this tolerance the client's timer
60
- // and the server's timer race the client often fires first and reconnects
61
- // unnecessarily.
62
- const idleThresholdMs = Math.round(keepAliveIntervalMs * 1.5);
65
+ // The server guarantees a message at least every keep-alive interval, so the threshold
66
+ // only has to absorb network latency, timer jitter and server-side scheduling hiccups.
67
+ // A hard TCP drop surfaces immediately through `onerror`, so this watchdog only needs to
68
+ // catch silent black-holes that makes a generous tolerance strictly better than a tight
69
+ // one, which would tear down healthy connections.
70
+ //
71
+ // The interval below is only the starting assumption; the server advertises its real
72
+ // cadence on the Connected message and {@link handleConnected} reconfigures from it.
63
73
  this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, ()=>{
64
74
  if (!this._disconnected && this._subscriptions.size > 0) {
65
- console.warn(`SSE hub: no messages received for ${idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);
75
+ console.warn(`SSE hub: no messages received for ${this._keepAlive.idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);
66
76
  this.reconnect();
67
77
  }
68
- }, idleThresholdMs);
78
+ }, keepAliveIntervalMs * IDLE_THRESHOLD_FACTOR);
69
79
  }
70
80
  /** @inheritdoc */ get queryCount() {
71
81
  return this._subscriptions.size;
@@ -230,12 +240,30 @@ import { HubMessageType } from './WebSocketHubConnection.js';
230
240
  console.log(`SSE hub: connected with id '${this._connectionId}'`);
231
241
  // Connected message arrived — cancel the connect timeout.
232
242
  this.clearConnectTimeout();
243
+ this.applyServerKeepAliveInterval(message.keepAliveIntervalMs);
233
244
  // Send all pending subscriptions now that we have a connection ID.
234
245
  for (const [queryId, sub] of this._pendingSubscriptions){
235
246
  this.sendSubscribe(queryId, sub.request);
236
247
  }
237
248
  this._pendingSubscriptions.clear();
238
249
  }
250
+ /**
251
+ * Align the idle watchdog with the keep-alive cadence the server actually runs on.
252
+ *
253
+ * Without this the client assumes the default interval, so a server configured with a longer
254
+ * interval — or with keep-alive switched off entirely — would look silent and be reconnected
255
+ * on a loop even though it is perfectly healthy.
256
+ * @param {number | undefined} serverIntervalMs The interval advertised by the server, if any.
257
+ */ applyServerKeepAliveInterval(serverIntervalMs) {
258
+ if (serverIntervalMs === undefined) return;
259
+ // Keep-alive disabled server-side: silence is expected, so watching for it would guarantee
260
+ // an endless reconnect loop. Hard drops still surface through `onerror`.
261
+ if (serverIntervalMs <= 0) {
262
+ this._keepAlive.stop();
263
+ return;
264
+ }
265
+ this._keepAlive.reconfigure(serverIntervalMs, serverIntervalMs * IDLE_THRESHOLD_FACTOR);
266
+ }
239
267
  handleQueryResult(message) {
240
268
  if (!message.queryId) return;
241
269
  const sub = this._subscriptions.get(message.queryId);
@@ -1 +1 @@
1
- {"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs How long without any server message before the connection\n * is considered stale and a reconnect is forced (default: 30 000 ms).\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire idle threshold, the connection is stale and we reconnect.\n //\n // The idle threshold is set to 1.5× the check interval so the server's keep-alive\n // ping (which fires on the same cadence) has time to arrive over the network before\n // the client declares the connection dead. Without this tolerance the client's timer\n // and the server's timer race — the client often fires first and reconnects\n // unnecessarily.\n const idleThresholdMs = Math.round(keepAliveIntervalMs * 1.5);\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n }, idleThresholdMs);\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get isConnected(): boolean {\n return this._connectionId !== undefined && this._eventSource?.readyState === EventSource.OPEN;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n if (this._eventSource) {\n // Detach all handlers BEFORE closing so that the async onerror / onmessage\n // events that fire after close() cannot observe the new _disconnected=false\n // state set by an immediately following ensureConnected() call. Without this,\n // a stale onerror triggers an unintended reconnect with exponential back-off.\n this._eventSource.onopen = null;\n this._eventSource.onmessage = null;\n this._eventSource.onerror = null;\n this._eventSource.close();\n }\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n this._pendingSubscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private sendSubscribe(queryId: string, request: SubscriptionRequest, attempt: number = 0): void {\n if (!this._connectionId || this._disconnected) return;\n\n // Capture the connection ID so retries can detect if a reconnect has already fired\n // for a different reason and made this retry obsolete.\n const connectionId = this._connectionId;\n\n const body = {\n connectionId,\n queryId,\n request,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n // Maximum number of subscribe retries before falling back to a full SSE reconnect.\n // In a round-robin load-balanced deployment the subscribe POST may land on a different\n // backend instance than the one holding the SSE connection. Retrying gives the load\n // balancer the chance to route a subsequent attempt to the correct instance without\n // tearing down the SSE connection unnecessarily. With N backend instances at most\n // N-1 retries are needed, so 3 retries covers deployments with up to 4 replicas.\n const maxRetries = 3;\n const retryDelayMs = 200;\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).then(response => {\n if (!response.ok) {\n if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {\n setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));\n } else if (this._connectionId === connectionId && !this._disconnected) {\n console.warn(`SSE hub: subscribe POST for '${queryId}' returned ${response.status} after ${attempt + 1} attempt(s), reconnecting`);\n this.reconnect();\n }\n }\n }).catch(error => {\n if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {\n setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));\n } else if (this._connectionId === connectionId && !this._disconnected) {\n console.error(`SSE hub: subscribe POST failed for '${queryId}' after ${attempt + 1} attempt(s), reconnecting`, error);\n this.reconnect();\n }\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["ServerSentEventHubConnection","_eventSource","_connectionId","_disconnected","_subscriptions","Map","_pendingSubscriptions","_lastPongLatency","_latencySamples","_connectTimeoutTimer","_keepAlive","_subscribeUrl","_unsubscribeUrl","keepAliveIntervalMs","_connectTimeoutMs","_policy","ReconnectPolicy","_sseUrl","_microservice","idleThresholdMs","Math","round","HubConnectionKeepAlive","size","console","warn","reconnect","queryCount","isConnected","undefined","readyState","EventSource","OPEN","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","sub","set","ensureConnected","sendSubscribe","unsubscribe","delete","sendUnsubscribe","close","dispose","clear","cancel","stop","clearConnectTimeout","CLOSED","openEventSource","onopen","onmessage","onerror","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","log","reset","start","setTimeout","event","recordActivity","handleMessage","data","schedule","clearTimeout","rawData","message","JSON","parse","type","HubMessageType","Connected","handleConnected","QueryResult","handleQueryResult","Ping","Unauthorized","handleUnauthorized","Error","error","payload","get","result","unauthorized","attempt","connectionId","body","customHeaders","httpHeadersCallback","maxRetries","retryDelayMs","fetch","method","headers","stringify","then","response","ok","status","catch"],"mappings":"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"}
1
+ {"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * How many keep-alive intervals of silence are tolerated before the connection is considered dead.\n *\n * The server guarantees a message every interval, so this is pure slack for latency and jitter.\n * It must stay above 1 — a threshold at or below the server's own cadence makes the client and\n * server timers race, and the client tears down connections the server considers healthy.\n */\nconst IDLE_THRESHOLD_FACTOR = 2;\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs The keep-alive cadence to assume until the server advertises\n * its own on the {@link HubMessageType.Connected} message (default: 30 000 ms). The connection is\n * considered stale after {@link IDLE_THRESHOLD_FACTOR} times this without any server message.\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire idle threshold, the connection is stale and we reconnect.\n //\n // The server guarantees a message at least every keep-alive interval, so the threshold\n // only has to absorb network latency, timer jitter and server-side scheduling hiccups.\n // A hard TCP drop surfaces immediately through `onerror`, so this watchdog only needs to\n // catch silent black-holes — that makes a generous tolerance strictly better than a tight\n // one, which would tear down healthy connections.\n //\n // The interval below is only the starting assumption; the server advertises its real\n // cadence on the Connected message and {@link handleConnected} reconfigures from it.\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${this._keepAlive.idleThresholdMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n }, keepAliveIntervalMs * IDLE_THRESHOLD_FACTOR);\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get isConnected(): boolean {\n return this._connectionId !== undefined && this._eventSource?.readyState === EventSource.OPEN;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n if (this._eventSource) {\n // Detach all handlers BEFORE closing so that the async onerror / onmessage\n // events that fire after close() cannot observe the new _disconnected=false\n // state set by an immediately following ensureConnected() call. Without this,\n // a stale onerror triggers an unintended reconnect with exponential back-off.\n this._eventSource.onopen = null;\n this._eventSource.onmessage = null;\n this._eventSource.onerror = null;\n this._eventSource.close();\n }\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n this.applyServerKeepAliveInterval(message.keepAliveIntervalMs);\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\n }\n\n /**\n * Align the idle watchdog with the keep-alive cadence the server actually runs on.\n *\n * Without this the client assumes the default interval, so a server configured with a longer\n * interval — or with keep-alive switched off entirely — would look silent and be reconnected\n * on a loop even though it is perfectly healthy.\n * @param {number | undefined} serverIntervalMs The interval advertised by the server, if any.\n */\n private applyServerKeepAliveInterval(serverIntervalMs?: number): void {\n if (serverIntervalMs === undefined) return;\n\n // Keep-alive disabled server-side: silence is expected, so watching for it would guarantee\n // an endless reconnect loop. Hard drops still surface through `onerror`.\n if (serverIntervalMs <= 0) {\n this._keepAlive.stop();\n return;\n }\n\n this._keepAlive.reconfigure(serverIntervalMs, serverIntervalMs * IDLE_THRESHOLD_FACTOR);\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n this._pendingSubscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private sendSubscribe(queryId: string, request: SubscriptionRequest, attempt: number = 0): void {\n if (!this._connectionId || this._disconnected) return;\n\n // Capture the connection ID so retries can detect if a reconnect has already fired\n // for a different reason and made this retry obsolete.\n const connectionId = this._connectionId;\n\n const body = {\n connectionId,\n queryId,\n request,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n // Maximum number of subscribe retries before falling back to a full SSE reconnect.\n // In a round-robin load-balanced deployment the subscribe POST may land on a different\n // backend instance than the one holding the SSE connection. Retrying gives the load\n // balancer the chance to route a subsequent attempt to the correct instance without\n // tearing down the SSE connection unnecessarily. With N backend instances at most\n // N-1 retries are needed, so 3 retries covers deployments with up to 4 replicas.\n const maxRetries = 3;\n const retryDelayMs = 200;\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).then(response => {\n if (!response.ok) {\n if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {\n setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));\n } else if (this._connectionId === connectionId && !this._disconnected) {\n console.warn(`SSE hub: subscribe POST for '${queryId}' returned ${response.status} after ${attempt + 1} attempt(s), reconnecting`);\n this.reconnect();\n }\n }\n }).catch(error => {\n if (attempt < maxRetries && this._connectionId === connectionId && !this._disconnected) {\n setTimeout(() => this.sendSubscribe(queryId, request, attempt + 1), retryDelayMs * (attempt + 1));\n } else if (this._connectionId === connectionId && !this._disconnected) {\n console.error(`SSE hub: subscribe POST failed for '${queryId}' after ${attempt + 1} attempt(s), reconnecting`, error);\n this.reconnect();\n }\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["IDLE_THRESHOLD_FACTOR","ServerSentEventHubConnection","_eventSource","_connectionId","_disconnected","_subscriptions","Map","_pendingSubscriptions","_lastPongLatency","_latencySamples","_connectTimeoutTimer","_keepAlive","_subscribeUrl","_unsubscribeUrl","keepAliveIntervalMs","_connectTimeoutMs","_policy","ReconnectPolicy","_sseUrl","_microservice","HubConnectionKeepAlive","size","console","warn","idleThresholdMs","reconnect","queryCount","isConnected","undefined","readyState","EventSource","OPEN","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","sub","set","ensureConnected","sendSubscribe","unsubscribe","delete","sendUnsubscribe","close","dispose","clear","cancel","stop","clearConnectTimeout","CLOSED","openEventSource","onopen","onmessage","onerror","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","log","reset","start","setTimeout","event","recordActivity","handleMessage","data","schedule","clearTimeout","rawData","message","JSON","parse","type","HubMessageType","Connected","handleConnected","QueryResult","handleQueryResult","Ping","Unauthorized","handleUnauthorized","Error","error","payload","applyServerKeepAliveInterval","serverIntervalMs","reconfigure","get","result","unauthorized","attempt","connectionId","body","customHeaders","httpHeadersCallback","maxRetries","retryDelayMs","fetch","method","headers","stringify","then","response","ok","status","catch"],"mappings":"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"}
@@ -15,6 +15,7 @@ export interface HubMessage {
15
15
  queryId?: string;
16
16
  payload?: any;
17
17
  timestamp?: number;
18
+ keepAliveIntervalMs?: number;
18
19
  }
19
20
  export interface SubscriptionRequest {
20
21
  queryName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/WebSocketHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUtD,oBAAY,cAAc;IACtB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,KAAK,UAAU;IACf,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,cAAc;CAC1B;AAKD,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD,qBAAa,sBAAsB;IAiB3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAnB5B,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IASvC,YACqB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACtC,cAAc,GAAE,MAAc,EACb,OAAO,GAAE,gBAAwC,EAQrE;IAKD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAG3B;IASD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,CAQ1F;IAMD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAWjC;IAKD,OAAO,IAAI,IAAI,CAOd;IAED,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,KAAK;IAmBb,OAAO,CAAC,UAAU;IA0ClB,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,UAAU;CAWrB"}
1
+ {"version":3,"file":"WebSocketHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/WebSocketHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUtD,oBAAY,cAAc;IACtB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,KAAK,UAAU;IACf,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,cAAc;CAC1B;AAKD,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAKD,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD,qBAAa,sBAAsB;IAiB3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAnB5B,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IASvC,YACqB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACtC,cAAc,GAAE,MAAc,EACb,OAAO,GAAE,gBAAwC,EAQrE;IAKD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAKD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAKD,IAAI,cAAc,IAAI,MAAM,CAG3B;IASD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,CAQ1F;IAMD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAWjC;IAKD,OAAO,IAAI,IAAI,CAOd;IAED,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,KAAK;IAmBb,OAAO,CAAC,UAAU;IA0ClB,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,UAAU;CAWrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the {@link WebSocketHubConnection}.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n payload?: any;\n timestamp?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({ type: HubMessageType.Ping, timestamp: this._lastPingSentTime });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n this._subscriptions.set(queryId, { request, callback });\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, request);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendMessage({ type: HubMessageType.Unsubscribe, queryId });\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {\n return;\n }\n\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n if (this._socket) {\n // Detach all handlers BEFORE closing so that the async onclose event cannot\n // fire after a new subscription has reset _disconnected to false and opened a\n // fresh socket. Without this, the stale onclose triggers an unintended\n // reconnect via the back-off policy, causing a 1-10 second delay before the\n // new page's queries receive their first data.\n this._socket.onopen = null;\n this._socket.onclose = null;\n this._socket.onerror = null;\n this._socket.onmessage = null;\n this._socket.close();\n }\n this._socket = undefined;\n }\n\n private openSocket(): void {\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._socket = new WebSocket(url);\n\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n this._socket.onclose = () => {\n if (this._disconnected) return;\n console.log(`Hub connection closed: '${url}'`);\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openSocket();\n }\n }, this._url);\n };\n\n this._socket.onerror = (error) => {\n if (this._disconnected) return;\n console.error(`Hub connection error: '${url}'`, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n this._socket.onmessage = (ev) => {\n if (this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub.request);\n }\n }\n\n private sendSubscribeMessage(queryId: string, request: SubscriptionRequest): void {\n this.sendMessage({\n type: HubMessageType.Subscribe,\n queryId,\n payload: request,\n });\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn(`Hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`Hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","set","ensureConnected","sendSubscribeMessage","unsubscribe","delete","close","dispose","clear","stop","cancel","undefined","CONNECTING","openSocket","onopen","onclose","onerror","onmessage","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","console","log","reset","start","sendAllSubscriptions","schedule","error","ev","handleMessage","data","sub","payload","message","send","JSON","stringify","rawData","parse","recordActivity","handleQueryResult","handlePong","warn","handleUnauthorized","get","result","QueryResult","unauthorized","latency","push","shift"],"mappings":"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"}
1
+ {"version":3,"file":"WebSocketHubConnection.js","sources":["../../../queries/WebSocketHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Message types matching the backend {@link ObservableQueryHubMessageType} enum.\n * Serialized as strings by the JsonStringEnumConverter on the server.\n */\nexport enum HubMessageType {\n Subscribe = 'Subscribe',\n Unsubscribe = 'Unsubscribe',\n QueryResult = 'QueryResult',\n Unauthorized = 'Unauthorized',\n Error = 'Error',\n Ping = 'Ping',\n Pong = 'Pong',\n Connected = 'Connected',\n}\n\n/**\n * Wire format for messages exchanged over the {@link WebSocketHubConnection}.\n */\nexport interface HubMessage {\n type: HubMessageType;\n queryId?: string;\n payload?: any;\n timestamp?: number;\n\n /**\n * The server's keep-alive interval in milliseconds, or 0 when keep-alive is disabled.\n * Only present on {@link HubMessageType.Connected} messages.\n */\n keepAliveIntervalMs?: number;\n}\n\n/**\n * Matches the backend {@link ObservableQuerySubscriptionRequest} record.\n */\nexport interface SubscriptionRequest {\n queryName: string;\n arguments?: Record<string, string | null>;\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortDirection?: string;\n transferMode?: string;\n}\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * Represents a single multiplexed WebSocket connection to the observable query hub\n * at {@code /.cratis/queries/ws}.\n *\n * Multiple query subscriptions are carried over the same physical WebSocket. Each subscription\n * is identified by a client-generated {@code queryId}; the server tags every result message with\n * the same id so responses can be routed to the correct callback.\n */\nexport class WebSocketHubConnection {\n private _socket?: WebSocket;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private readonly _keepAlive: HubConnectionKeepAlive;\n private _lastPingSentTime?: number;\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n\n /**\n * Initializes a new instance of {@link WebSocketHubConnection}.\n * @param {string} url The WebSocket URL of the hub endpoint (e.g. {@code ws://localhost:5000/.cratis/queries/ws}).\n * @param {string} microservice The microservice name to pass as a query argument.\n * @param {number} pingIntervalMs How often to send keep-alive pings when the connection is idle (default: 10 000 ms).\n * @param {IReconnectPolicy} reconnectPolicy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _url: string,\n private readonly _microservice: string,\n pingIntervalMs: number = 10000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n this._keepAlive = new HubConnectionKeepAlive(pingIntervalMs, () => {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._lastPingSentTime = Date.now();\n this.sendMessage({ type: HubMessageType.Ping, timestamp: this._lastPingSentTime });\n }\n });\n }\n\n /**\n * Gets the number of active query subscriptions on this connection.\n */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /**\n * Gets whether the WebSocket connection is currently open.\n */\n get isConnected(): boolean {\n return this._socket?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Gets the latency of the last ping/pong sequence in milliseconds.\n */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /**\n * Gets the rolling average latency in milliseconds.\n */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /**\n * Subscribe to a query on this hub connection.\n * If the WebSocket is not yet open, the subscribe message will be sent once the connection is established.\n * @param {string} queryId Client-generated unique identifier for this subscription.\n * @param {SubscriptionRequest} request The subscription request payload.\n * @param {DataReceived<any>} callback Callback invoked whenever the server pushes a result for this query.\n */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n this._subscriptions.set(queryId, { request, callback });\n this.ensureConnected();\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendSubscribeMessage(queryId, request);\n }\n // If not yet open, sendAllSubscriptions will fire in onopen.\n }\n\n /**\n * Unsubscribe from a query on this hub connection.\n * @param {string} queryId The identifier of the subscription to cancel.\n */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n\n if (this._socket?.readyState === WebSocket.OPEN) {\n this.sendMessage({ type: HubMessageType.Unsubscribe, queryId });\n }\n\n // If no subscriptions remain, close the connection to free resources.\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /**\n * Permanently close this hub connection and clean up all subscriptions.\n */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._keepAlive.stop();\n this._policy.cancel();\n this._socket?.close();\n this._socket = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n // Reset disconnected flag when a new subscription comes in\n this._disconnected = false;\n }\n\n if (this._socket && (this._socket.readyState === WebSocket.OPEN || this._socket.readyState === WebSocket.CONNECTING)) {\n return;\n }\n\n this.openSocket();\n }\n\n private close(): void {\n this._disconnected = true;\n this._keepAlive.stop();\n this._policy.cancel();\n if (this._socket) {\n // Detach all handlers BEFORE closing so that the async onclose event cannot\n // fire after a new subscription has reset _disconnected to false and opened a\n // fresh socket. Without this, the stale onclose triggers an unintended\n // reconnect via the back-off policy, causing a 1-10 second delay before the\n // new page's queries receive their first data.\n this._socket.onopen = null;\n this._socket.onclose = null;\n this._socket.onerror = null;\n this._socket.onmessage = null;\n this._socket.close();\n }\n this._socket = undefined;\n }\n\n private openSocket(): void {\n let url = this._url;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._socket = new WebSocket(url);\n\n this._socket.onopen = () => {\n if (this._disconnected) return;\n console.log(`Hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n this.sendAllSubscriptions();\n };\n\n this._socket.onclose = () => {\n if (this._disconnected) return;\n console.log(`Hub connection closed: '${url}'`);\n this._keepAlive.stop();\n if (this._subscriptions.size === 0) return;\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openSocket();\n }\n }, this._url);\n };\n\n this._socket.onerror = (error) => {\n if (this._disconnected) return;\n console.error(`Hub connection error: '${url}'`, error);\n this._keepAlive.stop();\n // onclose will fire after onerror, triggering reconnect\n };\n\n this._socket.onmessage = (ev) => {\n if (this._disconnected) return;\n this.handleMessage(ev.data as string);\n };\n }\n\n private sendAllSubscriptions(): void {\n for (const [queryId, sub] of this._subscriptions) {\n this.sendSubscribeMessage(queryId, sub.request);\n }\n }\n\n private sendSubscribeMessage(queryId: string, request: SubscriptionRequest): void {\n this.sendMessage({\n type: HubMessageType.Subscribe,\n queryId,\n payload: request,\n });\n }\n\n private sendMessage(message: HubMessage): void {\n if (this._socket?.readyState === WebSocket.OPEN) {\n this._socket.send(JSON.stringify(message));\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n // Every received message is activity — skip keep-alive ping if data is flowing.\n this._keepAlive.recordActivity();\n\n switch (message.type) {\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Pong:\n this.handlePong(message);\n break;\n case HubMessageType.Unauthorized:\n console.warn(`Hub: query '${message.queryId}' unauthorized`);\n this.handleUnauthorized(message);\n break;\n case HubMessageType.Error:\n console.error(`Hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('Hub: error parsing message', error);\n }\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n this._subscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private handlePong(message: HubMessage): void {\n if (message.timestamp && this._lastPingSentTime) {\n const latency = Date.now() - message.timestamp;\n this._lastPongLatency = latency;\n this._latencySamples.push(latency);\n\n if (this._latencySamples.length > 100) {\n this._latencySamples.shift();\n }\n }\n }\n}\n"],"names":["HubMessageType","WebSocketHubConnection","_socket","_disconnected","_subscriptions","Map","_keepAlive","_lastPingSentTime","_lastPongLatency","_latencySamples","_url","pingIntervalMs","_policy","ReconnectPolicy","_microservice","HubConnectionKeepAlive","readyState","WebSocket","OPEN","Date","now","sendMessage","type","timestamp","queryCount","size","isConnected","lastPingLatency","averageLatency","length","reduce","a","b","subscribe","queryId","request","callback","set","ensureConnected","sendSubscribeMessage","unsubscribe","delete","close","dispose","clear","stop","cancel","undefined","CONNECTING","openSocket","onopen","onclose","onerror","onmessage","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","console","log","reset","start","sendAllSubscriptions","schedule","error","ev","handleMessage","data","sub","payload","message","send","JSON","stringify","rawData","parse","recordActivity","handleQueryResult","handlePong","warn","handleUnauthorized","get","result","QueryResult","unauthorized","latency","push","shift"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=while_running.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"while_running.d.ts","sourceRoot":"","sources":["../../../../../queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import sinon from 'sinon';
2
+ import { HubConnectionKeepAlive } from '../../HubConnectionKeepAlive';
3
+ describe('when reconfiguring a running keep-alive', () => {
4
+ let clock;
5
+ let onIdle;
6
+ let keepAlive;
7
+ const originalIntervalMs = 500;
8
+ const originalThresholdMs = 750;
9
+ const newIntervalMs = 1000;
10
+ const newThresholdMs = 2000;
11
+ beforeEach(() => {
12
+ clock = sinon.useFakeTimers();
13
+ onIdle = sinon.stub();
14
+ keepAlive = new HubConnectionKeepAlive(originalIntervalMs, onIdle, originalThresholdMs);
15
+ keepAlive.start();
16
+ keepAlive.reconfigure(newIntervalMs, newThresholdMs);
17
+ });
18
+ afterEach(() => {
19
+ keepAlive.stop();
20
+ clock.restore();
21
+ sinon.restore();
22
+ });
23
+ it('should expose the new idle threshold', () => keepAlive.idleThresholdMs.should.equal(newThresholdMs));
24
+ describe('and the original threshold elapses', () => {
25
+ beforeEach(() => {
26
+ clock.tick(originalThresholdMs + 1);
27
+ });
28
+ it('should not invoke the onIdle callback', () => onIdle.called.should.be.false);
29
+ });
30
+ describe('and the new threshold elapses', () => {
31
+ beforeEach(() => {
32
+ clock.tick(newThresholdMs + 1);
33
+ });
34
+ it('should invoke the onIdle callback', () => onIdle.calledOnce.should.be.true);
35
+ });
36
+ });
37
+ //# sourceMappingURL=while_running.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"while_running.js","sourceRoot":"","sources":["../../../../../queries/for_HubConnectionKeepAlive/when_reconfiguring/while_running.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACrD,IAAI,KAA4B,CAAC;IACjC,IAAI,MAAuB,CAAC;IAC5B,IAAI,SAAiC,CAAC;IAEtC,MAAM,kBAAkB,GAAG,GAAG,CAAC;IAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC;IAChC,MAAM,aAAa,GAAG,IAAI,CAAC;IAC3B,MAAM,cAAc,GAAG,IAAI,CAAC;IAE5B,UAAU,CAAC,GAAG,EAAE;QACZ,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACtB,SAAS,GAAG,IAAI,sBAAsB,CAAC,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC;QACxF,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,SAAS,CAAC,WAAW,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,SAAS,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,KAAK,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAEzG,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAChD,UAAU,CAAC,GAAG,EAAE;YAEZ,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;QAC3C,UAAU,CAAC,GAAG,EAAE;YAEZ,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=while_stopped.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"while_stopped.d.ts","sourceRoot":"","sources":["../../../../../queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import sinon from 'sinon';
2
+ import { HubConnectionKeepAlive } from '../../HubConnectionKeepAlive';
3
+ describe('when reconfiguring a keep-alive that has not been started', () => {
4
+ let clock;
5
+ let onIdle;
6
+ let keepAlive;
7
+ beforeEach(() => {
8
+ clock = sinon.useFakeTimers();
9
+ onIdle = sinon.stub();
10
+ keepAlive = new HubConnectionKeepAlive(500, onIdle, 750);
11
+ keepAlive.reconfigure(1000, 2000);
12
+ clock.tick(10000);
13
+ });
14
+ afterEach(() => {
15
+ keepAlive.stop();
16
+ clock.restore();
17
+ sinon.restore();
18
+ });
19
+ it('should not start the timer', () => onIdle.called.should.be.false);
20
+ it('should still apply the new idle threshold', () => keepAlive.idleThresholdMs.should.equal(2000));
21
+ });
22
+ //# sourceMappingURL=while_stopped.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"while_stopped.js","sourceRoot":"","sources":["../../../../../queries/for_HubConnectionKeepAlive/when_reconfiguring/while_stopped.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAEtE,QAAQ,CAAC,2DAA2D,EAAE,GAAG,EAAE;IACvE,IAAI,KAA4B,CAAC;IACjC,IAAI,MAAuB,CAAC;IAC5B,IAAI,SAAiC,CAAC;IAEtC,UAAU,CAAC,GAAG,EAAE;QACZ,KAAK,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACtB,SAAS,GAAG,IAAI,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACzD,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,SAAS,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,KAAK,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACtE,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACxG,CAAC,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { ObservableQueryFor } from '../../ObservableQueryFor';
2
+ import { QueryValidator } from '../../QueryValidator';
3
+ import { ParameterDescriptor } from '../../../reflection/ParameterDescriptor';
4
+ import '../../../validation/RuleBuilderExtensions';
5
+ export interface ITestParams {
6
+ minAge: number;
7
+ }
8
+ export declare class TestObservableQueryValidator extends QueryValidator<ITestParams> {
9
+ constructor();
10
+ }
11
+ export declare class TestObservableQuery extends ObservableQueryFor<string, ITestParams> {
12
+ readonly route = "/test";
13
+ readonly validation: TestObservableQueryValidator;
14
+ readonly parameterDescriptors: ParameterDescriptor[];
15
+ readonly defaultValue = "";
16
+ constructor();
17
+ get requiredRequestParameters(): string[];
18
+ }
19
+ export declare class an_observable_query_with_validator {
20
+ query: TestObservableQuery;
21
+ constructor();
22
+ }
23
+ //# sourceMappingURL=an_observable_query_with_validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"an_observable_query_with_validator.d.ts","sourceRoot":"","sources":["../../../../../queries/for_ObservableQueryFor/given/an_observable_query_with_validator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,2CAA2C,CAAC;AAEnD,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,4BAA6B,SAAQ,cAAc,CAAC,WAAW,CAAC;IACzE,cAGC;CACJ;AAED,qBAAa,mBAAoB,SAAQ,kBAAkB,CAAC,MAAM,EAAE,WAAW,CAAC;IAC5E,QAAQ,CAAC,KAAK,WAAW;IACzB,QAAQ,CAAC,UAAU,+BAAsC;IACzD,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAAM;IAC1D,QAAQ,CAAC,YAAY,MAAM;IAE3B,cAEC;IAED,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;CACJ;AAED,qBAAa,kCAAkC;IAC3C,KAAK,EAAE,mBAAmB,CAAC;IAE3B,cAEC;CACJ"}
@@ -0,0 +1,28 @@
1
+ import { ObservableQueryFor } from '../../ObservableQueryFor';
2
+ import { QueryValidator } from '../../QueryValidator';
3
+ import '../../../validation/RuleBuilderExtensions';
4
+ export class TestObservableQueryValidator extends QueryValidator {
5
+ constructor() {
6
+ super();
7
+ this.ruleFor((c) => c.minAge).greaterThanOrEqual(0).withMessage('Age must be positive');
8
+ }
9
+ }
10
+ export class TestObservableQuery extends ObservableQueryFor {
11
+ route = '/test';
12
+ validation = new TestObservableQueryValidator();
13
+ parameterDescriptors = [];
14
+ defaultValue = '';
15
+ constructor() {
16
+ super(String, false);
17
+ }
18
+ get requiredRequestParameters() {
19
+ return [];
20
+ }
21
+ }
22
+ export class an_observable_query_with_validator {
23
+ query;
24
+ constructor() {
25
+ this.query = new TestObservableQuery();
26
+ }
27
+ }
28
+ //# sourceMappingURL=an_observable_query_with_validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"an_observable_query_with_validator.js","sourceRoot":"","sources":["../../../../../queries/for_ObservableQueryFor/given/an_observable_query_with_validator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,2CAA2C,CAAC;AAMnD,MAAM,OAAO,4BAA6B,SAAQ,cAA2B;IACzE;QACI,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IACzG,CAAC;CACJ;AAED,MAAM,OAAO,mBAAoB,SAAQ,kBAAuC;IACnE,KAAK,GAAG,OAAO,CAAC;IAChB,UAAU,GAAG,IAAI,4BAA4B,EAAE,CAAC;IAChD,oBAAoB,GAA0B,EAAE,CAAC;IACjD,YAAY,GAAG,EAAE,CAAC;IAE3B;QACI,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,yBAAyB;QACzB,OAAO,EAAE,CAAC;IACd,CAAC;CACJ;AAED,MAAM,OAAO,kCAAkC;IAC3C,KAAK,CAAsB;IAE3B;QACI,IAAI,CAAC,KAAK,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAC3C,CAAC;CACJ"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=with_client_validation_failing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with_client_validation_failing.d.ts","sourceRoot":"","sources":["../../../../../queries/for_ObservableQueryFor/when_performing/with_client_validation_failing.ts"],"names":[],"mappings":""}