@cratis/arc 22.13.1 → 22.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +5 -4
  2. package/dist/cjs/Globals.js.map +1 -1
  3. package/dist/cjs/UrlHelpers.js.map +1 -1
  4. package/dist/cjs/commands/Command.js.map +1 -1
  5. package/dist/cjs/commands/CommandResult.js.map +1 -1
  6. package/dist/cjs/commands/CommandResults.js.map +1 -1
  7. package/dist/cjs/commands/CommandValidator.js.map +1 -1
  8. package/dist/cjs/commands/index.js.map +1 -1
  9. package/dist/cjs/deepEqual.js.map +1 -1
  10. package/dist/cjs/identity/IIdentityProvider.js.map +1 -1
  11. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  12. package/dist/cjs/identity/index.js.map +1 -1
  13. package/dist/cjs/joinPaths.js.map +1 -1
  14. package/dist/cjs/messaging/IMessenger.js.map +1 -1
  15. package/dist/cjs/messaging/Message.js.map +1 -1
  16. package/dist/cjs/messaging/Messenger.js.map +1 -1
  17. package/dist/cjs/messaging/index.js.map +1 -1
  18. package/dist/cjs/queries/HubConnectionKeepAlive.js.map +1 -1
  19. package/dist/cjs/queries/IQueryProvider.js.map +1 -1
  20. package/dist/cjs/queries/NullObservableQueryConnection.js.map +1 -1
  21. package/dist/cjs/queries/ObservableQueryConnection.js.map +1 -1
  22. package/dist/cjs/queries/ObservableQueryConnectionFactory.js.map +1 -1
  23. package/dist/cjs/queries/ObservableQueryConnectionPool.js.map +1 -1
  24. package/dist/cjs/queries/ObservableQueryDiagnostics.js.map +1 -1
  25. package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
  26. package/dist/cjs/queries/ObservableQueryMultiplexer.js.map +1 -1
  27. package/dist/cjs/queries/ObservableQuerySubscription.js.map +1 -1
  28. package/dist/cjs/queries/Paging.js.map +1 -1
  29. package/dist/cjs/queries/PagingInfo.js.map +1 -1
  30. package/dist/cjs/queries/QueryFor.js.map +1 -1
  31. package/dist/cjs/queries/QueryHttpMethod.js.map +1 -1
  32. package/dist/cjs/queries/QueryHttpMethodResolver.js.map +1 -1
  33. package/dist/cjs/queries/QueryHttpRequest.js.map +1 -1
  34. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  35. package/dist/cjs/queries/QueryProvider.js.map +1 -1
  36. package/dist/cjs/queries/QueryResult.js.map +1 -1
  37. package/dist/cjs/queries/QueryResultWithState.js.map +1 -1
  38. package/dist/cjs/queries/QueryTransportMethod.js.map +1 -1
  39. package/dist/cjs/queries/QueryValidator.js.map +1 -1
  40. package/dist/cjs/queries/ReconnectPolicy.js.map +1 -1
  41. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  42. package/dist/cjs/queries/ServerSentEventQueryConnection.js.map +1 -1
  43. package/dist/cjs/queries/SortDirection.js.map +1 -1
  44. package/dist/cjs/queries/Sorting.js.map +1 -1
  45. package/dist/cjs/queries/SortingActions.js.map +1 -1
  46. package/dist/cjs/queries/SortingActionsForObservableQuery.js.map +1 -1
  47. package/dist/cjs/queries/SortingActionsForQuery.js.map +1 -1
  48. package/dist/cjs/queries/ValidateRequestArguments.js.map +1 -1
  49. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  50. package/dist/cjs/queries/WebSocketMessage.js.map +1 -1
  51. package/dist/cjs/queries/deserializeQueryModel.js.map +1 -1
  52. package/dist/cjs/queries/index.js.map +1 -1
  53. package/dist/cjs/queries/isAbortError.js.map +1 -1
  54. package/dist/cjs/queries/reconcileQueryData.js.map +1 -1
  55. package/dist/cjs/reflection/ParameterDescriptor.js.map +1 -1
  56. package/dist/cjs/reflection/ParametersHelper.js.map +1 -1
  57. package/dist/cjs/reflection/PropertyDescriptor.js.map +1 -1
  58. package/dist/cjs/reflection/index.js.map +1 -1
  59. package/dist/cjs/validation/PropertyRule.js.map +1 -1
  60. package/dist/cjs/validation/PropertyValidator.js.map +1 -1
  61. package/dist/cjs/validation/RuleBuilder.js.map +1 -1
  62. package/dist/cjs/validation/RuleBuilderExtensions.js.map +1 -1
  63. package/dist/cjs/validation/ValidationResult.js.map +1 -1
  64. package/dist/cjs/validation/ValidationResultReason.js.map +1 -1
  65. package/dist/cjs/validation/ValidationResultSeverity.js.map +1 -1
  66. package/dist/cjs/validation/Validator.js.map +1 -1
  67. package/dist/cjs/validation/index.js.map +1 -1
  68. package/dist/cjs/validation/rules/ComparisonRules.js.map +1 -1
  69. package/dist/cjs/validation/rules/EmailRule.js.map +1 -1
  70. package/dist/cjs/validation/rules/LengthRules.js.map +1 -1
  71. package/dist/cjs/validation/rules/NotEmptyRule.js.map +1 -1
  72. package/dist/cjs/validation/rules/PhoneRule.js.map +1 -1
  73. package/dist/cjs/validation/rules/RegexRule.js.map +1 -1
  74. package/dist/cjs/validation/rules/UrlRule.js.map +1 -1
  75. package/dist/esm/Globals.js.map +1 -1
  76. package/dist/esm/UrlHelpers.js.map +1 -1
  77. package/dist/esm/commands/Command.js.map +1 -1
  78. package/dist/esm/commands/CommandResult.js.map +1 -1
  79. package/dist/esm/commands/CommandResults.js.map +1 -1
  80. package/dist/esm/commands/CommandValidator.js.map +1 -1
  81. package/dist/esm/deepEqual.js.map +1 -1
  82. package/dist/esm/identity/IIdentityProvider.js.map +1 -1
  83. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  84. package/dist/esm/joinPaths.js.map +1 -1
  85. package/dist/esm/messaging/IMessenger.js.map +1 -1
  86. package/dist/esm/messaging/Message.js.map +1 -1
  87. package/dist/esm/messaging/Messenger.js.map +1 -1
  88. package/dist/esm/queries/HubConnectionKeepAlive.js.map +1 -1
  89. package/dist/esm/queries/IQueryProvider.js.map +1 -1
  90. package/dist/esm/queries/NullObservableQueryConnection.js.map +1 -1
  91. package/dist/esm/queries/ObservableQueryConnection.js.map +1 -1
  92. package/dist/esm/queries/ObservableQueryConnectionFactory.js.map +1 -1
  93. package/dist/esm/queries/ObservableQueryConnectionPool.js.map +1 -1
  94. package/dist/esm/queries/ObservableQueryDiagnostics.js.map +1 -1
  95. package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
  96. package/dist/esm/queries/ObservableQueryMultiplexer.js.map +1 -1
  97. package/dist/esm/queries/ObservableQuerySubscription.js.map +1 -1
  98. package/dist/esm/queries/Paging.js.map +1 -1
  99. package/dist/esm/queries/PagingInfo.js.map +1 -1
  100. package/dist/esm/queries/QueryFor.js.map +1 -1
  101. package/dist/esm/queries/QueryHttpMethod.js.map +1 -1
  102. package/dist/esm/queries/QueryHttpMethodResolver.js.map +1 -1
  103. package/dist/esm/queries/QueryHttpRequest.js.map +1 -1
  104. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  105. package/dist/esm/queries/QueryProvider.js.map +1 -1
  106. package/dist/esm/queries/QueryResult.js.map +1 -1
  107. package/dist/esm/queries/QueryResultWithState.js.map +1 -1
  108. package/dist/esm/queries/QueryTransportMethod.js.map +1 -1
  109. package/dist/esm/queries/QueryValidator.js.map +1 -1
  110. package/dist/esm/queries/ReconnectPolicy.js.map +1 -1
  111. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  112. package/dist/esm/queries/ServerSentEventQueryConnection.js.map +1 -1
  113. package/dist/esm/queries/SortDirection.js.map +1 -1
  114. package/dist/esm/queries/Sorting.js.map +1 -1
  115. package/dist/esm/queries/SortingActions.js.map +1 -1
  116. package/dist/esm/queries/SortingActionsForObservableQuery.js.map +1 -1
  117. package/dist/esm/queries/SortingActionsForQuery.js.map +1 -1
  118. package/dist/esm/queries/ValidateRequestArguments.js.map +1 -1
  119. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  120. package/dist/esm/queries/WebSocketMessage.js.map +1 -1
  121. package/dist/esm/queries/deserializeQueryModel.js.map +1 -1
  122. package/dist/esm/queries/isAbortError.js.map +1 -1
  123. package/dist/esm/queries/reconcileQueryData.js.map +1 -1
  124. package/dist/esm/reflection/ParameterDescriptor.js.map +1 -1
  125. package/dist/esm/reflection/ParametersHelper.js.map +1 -1
  126. package/dist/esm/reflection/PropertyDescriptor.js.map +1 -1
  127. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  128. package/dist/esm/validation/PropertyRule.js.map +1 -1
  129. package/dist/esm/validation/PropertyValidator.js.map +1 -1
  130. package/dist/esm/validation/RuleBuilder.js.map +1 -1
  131. package/dist/esm/validation/RuleBuilderExtensions.js.map +1 -1
  132. package/dist/esm/validation/ValidationResult.js.map +1 -1
  133. package/dist/esm/validation/ValidationResultReason.js.map +1 -1
  134. package/dist/esm/validation/ValidationResultSeverity.js.map +1 -1
  135. package/dist/esm/validation/Validator.js.map +1 -1
  136. package/dist/esm/validation/rules/ComparisonRules.js.map +1 -1
  137. package/dist/esm/validation/rules/EmailRule.js.map +1 -1
  138. package/dist/esm/validation/rules/LengthRules.js.map +1 -1
  139. package/dist/esm/validation/rules/NotEmptyRule.js.map +1 -1
  140. package/dist/esm/validation/rules/PhoneRule.js.map +1 -1
  141. package/dist/esm/validation/rules/RegexRule.js.map +1 -1
  142. package/dist/esm/validation/rules/UrlRule.js.map +1 -1
  143. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"QueryInstanceCache.js","sources":["../../../queries/QueryInstanceCache.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { QueryResultWithState } from './QueryResultWithState';\nimport type {\n CacheDiagnostics,\n CacheEntryDiagnostics,\n} from './ObservableQueryDiagnosticsSnapshot';\nimport { reconcileQueryData } from './reconcileQueryData';\n\n/**\n * Represents a key that uniquely identifies a query instance in the cache, based on the query type name and its serialized arguments.\n */\nexport type QueryCacheKey = string;\n\n/**\n * Callback invoked when the cached result for an entry changes.\n */\nexport type QueryCacheListener<TDataType> = (\n result: QueryResultWithState<TDataType>,\n) => void;\n\n/**\n * Represents a single entry in the {@link QueryInstanceCache}.\n * @template TDataType The type of data returned by the query.\n */\nexport interface QueryCacheEntry<TDataType> {\n /**\n * The cached query instance.\n */\n readonly instance: unknown;\n\n /**\n * The last result received from the query, if any.\n */\n lastResult?: QueryResultWithState<TDataType>;\n\n /**\n * The number of active subscribers holding a reference to this entry.\n */\n subscriberCount: number;\n\n /**\n * Set of listener callbacks that are notified when {@link lastResult} changes.\n */\n readonly listeners: Set<QueryCacheListener<TDataType>>;\n\n /**\n * Cleanup function returned by the first subscriber that starts the query connection.\n * Called when the last subscriber releases the entry.\n */\n teardown?: () => void;\n\n /**\n * Whether an active subscription has been established for this entry.\n */\n subscribed: boolean;\n\n /**\n * Timer handle for deferred cleanup. Allows React StrictMode re-mounts (in any build\n * environment) to cancel the pending teardown so the connection is reused instead of\n * torn down and recreated.\n */\n pendingCleanup?: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Provides a cache for query instances, keyed by query type and serialized arguments.\n *\n * Two callers requesting the same query type with identical arguments receive the same\n * cached instance and immediately see the last known result — without an additional\n * round trip to the server. When the last subscriber releases its reference the entry\n * is evicted.\n */\nexport class QueryInstanceCache {\n private readonly _entries = new Map<QueryCacheKey, QueryCacheEntry<unknown>>();\n private _pendingDispose?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link QueryInstanceCache}.\n * @param retentionMs How long in milliseconds to keep a cache entry alive after the last\n * subscriber releases it before evicting the subscription and cached data. A non-zero\n * value lets users navigate away and back without losing cached data. Defaults to\n * 30 000 ms. Pass 0 for immediate eviction.\n */\n constructor(private readonly _retentionMs: number = 30_000) {}\n\n /**\n * Builds the cache key for a query.\n * @param queryTypeName The stable type name for the query. Use the instance's `queryName`\n * (a hardcoded fully-qualified string in generated proxies) rather than {@link Function.name},\n * which is unstable under minification.\n * @param args Optional arguments supplied to the query.\n * @returns A stable string key.\n */\n buildKey(queryTypeName: string, args?: object): QueryCacheKey {\n if (!args || Object.keys(args).length === 0) {\n return `${queryTypeName}::`;\n }\n\n const sorted = Object.keys(args)\n .sort()\n .reduce<Record<string, unknown>>((accumulator, key) => {\n accumulator[key] = (args as Record<string, unknown>)[key];\n return accumulator;\n }, {});\n\n return `${queryTypeName}::${JSON.stringify(sorted)}`;\n }\n\n /**\n * Returns a cached instance for the given key, or creates a new one using the provided factory.\n * The subscriber count of the entry is incremented.\n * @template TInstance The type of the query instance.\n * @param key The cache key produced by {@link buildKey}.\n * @param factory A zero-argument factory that creates a fresh query instance when one is not yet cached.\n * @returns The cached (or newly created) instance and whether it was newly created.\n */\n getOrCreate<TInstance>(\n key: QueryCacheKey,\n factory: () => TInstance,\n ): { instance: TInstance; isNew: boolean } {\n if (!this._entries.has(key)) {\n const entry: QueryCacheEntry<unknown> = {\n instance: factory(),\n lastResult: undefined,\n subscriberCount: 0,\n listeners: new Set(),\n subscribed: false,\n };\n\n this._entries.set(key, entry);\n return { instance: entry.instance as TInstance, isNew: true };\n }\n\n const entry = this._entries.get(key)!;\n return { instance: entry.instance as TInstance, isNew: false };\n }\n\n /**\n * Increments the active subscriber count for the given key.\n * If a deferred cleanup was pending (from a recent {@link release}),\n * it is cancelled so the existing subscription is reused.\n * Call from `useEffect` setup to pair with {@link release} in the cleanup.\n * @param key The cache key produced by {@link buildKey}.\n */\n acquire(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscriberCount++;\n }\n }\n\n /**\n * Returns the last cached result for the given key, or `undefined` if no result has been stored yet.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @returns The last {@link QueryResultWithState}, or `undefined`.\n */\n getLastResult<TDataType>(\n key: QueryCacheKey,\n ): QueryResultWithState<TDataType> | undefined {\n return this._entries.get(key)?.lastResult as\n | QueryResultWithState<TDataType>\n | undefined;\n }\n\n /**\n * Stores the most recent result for the given key and notifies all registered listeners.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param result The result to store.\n */\n setLastResult<TDataType>(\n key: QueryCacheKey,\n result: QueryResultWithState<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (!entry) {\n return;\n }\n\n const previousResult = entry.lastResult as\n | QueryResultWithState<TDataType>\n | undefined;\n\n // Reconcile the incoming payload against the one already held so items that did not actually\n // change keep their previous references. A full snapshot — which is what the server re-sends\n // whenever a subscription is re-established — otherwise arrives as all-new references and\n // makes every consumer treat every item as changed.\n const reconciled =\n previousResult === undefined\n ? result\n : this.withReconciledData(previousResult, result);\n\n entry.lastResult = reconciled as QueryResultWithState<unknown>;\n\n // Reconciliation returns the previous data reference when nothing changed, so identity is\n // enough to detect it. Data, success, and readiness affect what the user sees; changeSet is\n // ephemeral and does not independently require a notification.\n if (\n previousResult !== undefined &&\n previousResult.isSuccess === reconciled.isSuccess &&\n previousResult.isReady === reconciled.isReady &&\n previousResult.data === reconciled.data\n ) {\n return;\n }\n\n for (const listener of entry.listeners) {\n (listener as QueryCacheListener<TDataType>)(reconciled);\n }\n }\n\n /**\n * Returns the incoming result with its data reconciled against the previous result, or the\n * incoming result unchanged when reconciliation found nothing to carry over.\n * @template TDataType The type of data returned by the query.\n * @param previous The previously held result.\n * @param next The freshly received result.\n * @returns A result whose data preserves references for everything that did not change.\n */\n private withReconciledData<TDataType>(\n previous: QueryResultWithState<TDataType>,\n next: QueryResultWithState<TDataType>,\n ): QueryResultWithState<TDataType> {\n const reconciledData = reconcileQueryData(previous.data, next.data);\n\n if (reconciledData === next.data) {\n return next;\n }\n\n return new QueryResultWithState<TDataType>(\n reconciledData,\n next.paging,\n next.isSuccess,\n next.isAuthorized,\n next.isValid,\n next.validationResults,\n next.hasExceptions,\n next.exceptionMessages,\n next.exceptionStackTrace,\n next.isPerforming,\n next.changeSet,\n next.isReady,\n );\n }\n\n /**\n * Registers a listener that is invoked whenever the cached result for the given key changes.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to register.\n */\n addListener<TDataType>(\n key: QueryCacheKey,\n listener: QueryCacheListener<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.add(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Removes a previously registered listener.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to remove.\n */\n removeListener<TDataType>(\n key: QueryCacheKey,\n listener: QueryCacheListener<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.delete(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Stores a teardown function for the given key and marks the entry as subscribed.\n * Called automatically when the last subscriber releases the entry.\n * @param key The cache key produced by {@link buildKey}.\n * @param teardown Cleanup function that disconnects the underlying query subscription.\n */\n setTeardown(key: QueryCacheKey, teardown: () => void): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.teardown = teardown;\n entry.subscribed = true;\n }\n }\n\n /**\n * Returns whether an active subscription exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if a subscription has been established; `false` otherwise.\n */\n isSubscribed(key: QueryCacheKey): boolean {\n return this._entries.get(key)?.subscribed ?? false;\n }\n\n /**\n * Decrements the subscriber count for the given key. When the count reaches zero, both teardown\n * and eviction are deferred by one microtask so that React StrictMode re-mounts — in any build\n * environment — can re-acquire the entry and cancel the cleanup before the timeout fires. This\n * prevents an unnecessary disconnect/reconnect cycle during the synthetic unmount/remount that\n * StrictMode performs.\n * @param key The cache key produced by {@link buildKey}.\n */\n release(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.subscriberCount--;\n\n if (entry.subscriberCount <= 0) {\n // Defer both teardown and eviction. React StrictMode re-mounts can cancel by\n // calling acquire() before the timeout fires. A non-zero _retentionMs keeps the\n // entry alive so users navigating back quickly see cached data immediately.\n entry.pendingCleanup = setTimeout(() => {\n const current = this._entries.get(key);\n\n if (current && current.subscriberCount <= 0) {\n current.subscribed = false;\n current.teardown?.();\n current.teardown = undefined;\n current.pendingCleanup = undefined;\n this._entries.delete(key);\n }\n }, this._retentionMs);\n }\n }\n }\n\n /**\n * Returns whether an entry exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if an entry exists; `false` otherwise.\n */\n has(key: QueryCacheKey): boolean {\n return this._entries.has(key);\n }\n\n /**\n * Tears down all active subscriptions and marks every entry as not subscribed,\n * but preserves entries, subscriber counts, and listeners. This allows\n * hooks whose effects re-run afterward to detect that the entry is no longer\n * subscribed and re-establish a fresh connection.\n *\n * Use this when the underlying transport must be replaced (e.g. after an\n * authentication change that requires new WebSocket connections with updated\n * credentials).\n */\n teardownAllSubscriptions(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n }\n\n /**\n * Immediately tears down all subscriptions, cancels any pending deferred cleanups,\n * and evicts all entries. Call when the owning component (e.g. the {@link Arc} provider)\n * unmounts permanently so that all query connections are closed synchronously.\n */\n dispose(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n\n this._entries.clear();\n }\n\n /**\n * Schedules a deferred {@link dispose} using {@code setTimeout(0)}.\n *\n * This allows React StrictMode re-mounts to call {@link cancelPendingDispose}\n * before the dispose fires, avoiding the destruction of cache entries that child\n * effects are about to re-acquire.\n *\n * If a deferred dispose is already pending, it is replaced.\n */\n deferDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n }\n\n this._pendingDispose = setTimeout(() => {\n this._pendingDispose = undefined;\n this.dispose();\n }, 0);\n }\n\n /**\n * Cancels a pending deferred dispose scheduled by {@link deferDispose}.\n *\n * Call from the {@code useEffect} setup phase so that a StrictMode re-mount\n * prevents the synthetic unmount's deferred dispose from firing.\n */\n cancelPendingDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n this._pendingDispose = undefined;\n }\n }\n\n /**\n * Returns a diagnostics snapshot of the current cache state.\n * @returns A {@link CacheDiagnostics} describing all entries.\n */\n getDiagnosticsSnapshot(): CacheDiagnostics {\n const entries: CacheEntryDiagnostics[] = [];\n let totalBytes = 0;\n let unhealthyCount = 0;\n\n for (const [key, entry] of this._entries) {\n const colonIndex = key.indexOf('::');\n const queryName = colonIndex >= 0 ? key.substring(0, colonIndex) : key;\n\n let estimatedBytes = 0;\n try {\n if (entry.lastResult !== undefined) {\n estimatedBytes = JSON.stringify(entry.lastResult).length;\n }\n } catch {\n // Ignore serialization errors\n }\n\n if (entry.subscriberCount > 0 && !entry.subscribed) {\n unhealthyCount++;\n }\n\n totalBytes += estimatedBytes;\n entries.push({\n key,\n queryName,\n subscriberCount: entry.subscriberCount,\n listenerCount: entry.listeners.size,\n subscribed: entry.subscribed,\n hasResult: entry.lastResult !== undefined,\n estimatedBytes,\n });\n }\n\n return {\n healthy: unhealthyCount === 0,\n entryCount: this._entries.size,\n estimatedBytes: totalBytes,\n entries,\n };\n }\n}\n"],"names":["QueryInstanceCache","_entries","Map","_pendingDispose","_retentionMs","buildKey","queryTypeName","args","Object","keys","length","sorted","sort","reduce","accumulator","key","JSON","stringify","getOrCreate","factory","has","entry","instance","lastResult","undefined","subscriberCount","listeners","Set","subscribed","set","isNew","get","acquire","pendingCleanup","clearTimeout","getLastResult","setLastResult","result","previousResult","reconciled","withReconciledData","isSuccess","isReady","data","listener","previous","next","reconciledData","reconcileQueryData","QueryResultWithState","paging","isAuthorized","isValid","validationResults","hasExceptions","exceptionMessages","exceptionStackTrace","isPerforming","changeSet","addListener","add","removeListener","delete","setTeardown","teardown","isSubscribed","release","setTimeout","current","teardownAllSubscriptions","dispose","clear","deferDispose","cancelPendingDispose","getDiagnosticsSnapshot","entries","totalBytes","unhealthyCount","colonIndex","indexOf","queryName","substring","estimatedBytes","push","listenerCount","size","hasResult","healthy","entryCount"],"mappings":"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"}
1
+ {"version":3,"file":"QueryInstanceCache.js","sources":["../../../queries/QueryInstanceCache.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { QueryResultWithState } from './QueryResultWithState';\nimport type {\n CacheDiagnostics,\n CacheEntryDiagnostics,\n} from './ObservableQueryDiagnosticsSnapshot';\nimport { reconcileQueryData } from './reconcileQueryData';\n\n/**\n * Represents a key that uniquely identifies a query instance in the cache, based on the query type name and its serialized arguments.\n */\nexport type QueryCacheKey = string;\n\n/**\n * Callback invoked when the cached result for an entry changes.\n */\nexport type QueryCacheListener<TDataType> = (\n result: QueryResultWithState<TDataType>,\n) => void;\n\n/**\n * Represents a single entry in the {@link QueryInstanceCache}.\n * @template TDataType The type of data returned by the query.\n */\nexport interface QueryCacheEntry<TDataType> {\n /**\n * The cached query instance.\n */\n readonly instance: unknown;\n\n /**\n * The last result received from the query, if any.\n */\n lastResult?: QueryResultWithState<TDataType>;\n\n /**\n * The number of active subscribers holding a reference to this entry.\n */\n subscriberCount: number;\n\n /**\n * Set of listener callbacks that are notified when {@link lastResult} changes.\n */\n readonly listeners: Set<QueryCacheListener<TDataType>>;\n\n /**\n * Cleanup function returned by the first subscriber that starts the query connection.\n * Called when the last subscriber releases the entry.\n */\n teardown?: () => void;\n\n /**\n * Whether an active subscription has been established for this entry.\n */\n subscribed: boolean;\n\n /**\n * Timer handle for deferred cleanup. Allows React StrictMode re-mounts (in any build\n * environment) to cancel the pending teardown so the connection is reused instead of\n * torn down and recreated.\n */\n pendingCleanup?: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Provides a cache for query instances, keyed by query type and serialized arguments.\n *\n * Two callers requesting the same query type with identical arguments receive the same\n * cached instance and immediately see the last known result — without an additional\n * round trip to the server. When the last subscriber releases its reference the entry\n * is evicted.\n */\nexport class QueryInstanceCache {\n private readonly _entries = new Map<QueryCacheKey, QueryCacheEntry<unknown>>();\n private _pendingDispose?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link QueryInstanceCache}.\n * @param retentionMs How long in milliseconds to keep a cache entry alive after the last\n * subscriber releases it before evicting the subscription and cached data. A non-zero\n * value lets users navigate away and back without losing cached data. Defaults to\n * 30 000 ms. Pass 0 for immediate eviction.\n */\n constructor(private readonly _retentionMs: number = 30_000) {}\n\n /**\n * Builds the cache key for a query.\n * @param queryTypeName The stable type name for the query. Use the instance's `queryName`\n * (a hardcoded fully-qualified string in generated proxies) rather than {@link Function.name},\n * which is unstable under minification.\n * @param args Optional arguments supplied to the query.\n * @returns A stable string key.\n */\n buildKey(queryTypeName: string, args?: object): QueryCacheKey {\n if (!args || Object.keys(args).length === 0) {\n return `${queryTypeName}::`;\n }\n\n const sorted = Object.keys(args)\n .sort()\n .reduce<Record<string, unknown>>((accumulator, key) => {\n accumulator[key] = (args as Record<string, unknown>)[key];\n return accumulator;\n }, {});\n\n return `${queryTypeName}::${JSON.stringify(sorted)}`;\n }\n\n /**\n * Returns a cached instance for the given key, or creates a new one using the provided factory.\n * The subscriber count of the entry is incremented.\n * @template TInstance The type of the query instance.\n * @param key The cache key produced by {@link buildKey}.\n * @param factory A zero-argument factory that creates a fresh query instance when one is not yet cached.\n * @returns The cached (or newly created) instance and whether it was newly created.\n */\n getOrCreate<TInstance>(\n key: QueryCacheKey,\n factory: () => TInstance,\n ): { instance: TInstance; isNew: boolean } {\n if (!this._entries.has(key)) {\n const entry: QueryCacheEntry<unknown> = {\n instance: factory(),\n lastResult: undefined,\n subscriberCount: 0,\n listeners: new Set(),\n subscribed: false,\n };\n\n this._entries.set(key, entry);\n return { instance: entry.instance as TInstance, isNew: true };\n }\n\n const entry = this._entries.get(key)!;\n return { instance: entry.instance as TInstance, isNew: false };\n }\n\n /**\n * Increments the active subscriber count for the given key.\n * If a deferred cleanup was pending (from a recent {@link release}),\n * it is cancelled so the existing subscription is reused.\n * Call from `useEffect` setup to pair with {@link release} in the cleanup.\n * @param key The cache key produced by {@link buildKey}.\n */\n acquire(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscriberCount++;\n }\n }\n\n /**\n * Returns the last cached result for the given key, or `undefined` if no result has been stored yet.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @returns The last {@link QueryResultWithState}, or `undefined`.\n */\n getLastResult<TDataType>(\n key: QueryCacheKey,\n ): QueryResultWithState<TDataType> | undefined {\n return this._entries.get(key)?.lastResult as\n | QueryResultWithState<TDataType>\n | undefined;\n }\n\n /**\n * Stores the most recent result for the given key and notifies all registered listeners.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param result The result to store.\n */\n setLastResult<TDataType>(\n key: QueryCacheKey,\n result: QueryResultWithState<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (!entry) {\n return;\n }\n\n const previousResult = entry.lastResult as\n | QueryResultWithState<TDataType>\n | undefined;\n\n // Reconcile the incoming payload against the one already held so items that did not actually\n // change keep their previous references. A full snapshot — which is what the server re-sends\n // whenever a subscription is re-established — otherwise arrives as all-new references and\n // makes every consumer treat every item as changed.\n const reconciled =\n previousResult === undefined\n ? result\n : this.withReconciledData(previousResult, result);\n\n entry.lastResult = reconciled as QueryResultWithState<unknown>;\n\n // Reconciliation returns the previous data reference when nothing changed, so identity is\n // enough to detect it. Data, success, and readiness affect what the user sees; changeSet is\n // ephemeral and does not independently require a notification.\n if (\n previousResult !== undefined &&\n previousResult.isSuccess === reconciled.isSuccess &&\n previousResult.isReady === reconciled.isReady &&\n previousResult.data === reconciled.data\n ) {\n return;\n }\n\n for (const listener of entry.listeners) {\n (listener as QueryCacheListener<TDataType>)(reconciled);\n }\n }\n\n /**\n * Returns the incoming result with its data reconciled against the previous result, or the\n * incoming result unchanged when reconciliation found nothing to carry over.\n * @template TDataType The type of data returned by the query.\n * @param previous The previously held result.\n * @param next The freshly received result.\n * @returns A result whose data preserves references for everything that did not change.\n */\n private withReconciledData<TDataType>(\n previous: QueryResultWithState<TDataType>,\n next: QueryResultWithState<TDataType>,\n ): QueryResultWithState<TDataType> {\n const reconciledData = reconcileQueryData(previous.data, next.data);\n\n if (reconciledData === next.data) {\n return next;\n }\n\n return new QueryResultWithState<TDataType>(\n reconciledData,\n next.paging,\n next.isSuccess,\n next.isAuthorized,\n next.isValid,\n next.validationResults,\n next.hasExceptions,\n next.exceptionMessages,\n next.exceptionStackTrace,\n next.isPerforming,\n next.changeSet,\n next.isReady,\n );\n }\n\n /**\n * Registers a listener that is invoked whenever the cached result for the given key changes.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to register.\n */\n addListener<TDataType>(\n key: QueryCacheKey,\n listener: QueryCacheListener<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.add(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Removes a previously registered listener.\n * @template TDataType The type of data returned by the query.\n * @param key The cache key produced by {@link buildKey}.\n * @param listener The callback to remove.\n */\n removeListener<TDataType>(\n key: QueryCacheKey,\n listener: QueryCacheListener<TDataType>,\n ): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.listeners.delete(listener as QueryCacheListener<unknown>);\n }\n }\n\n /**\n * Stores a teardown function for the given key and marks the entry as subscribed.\n * Called automatically when the last subscriber releases the entry.\n * @param key The cache key produced by {@link buildKey}.\n * @param teardown Cleanup function that disconnects the underlying query subscription.\n */\n setTeardown(key: QueryCacheKey, teardown: () => void): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.teardown = teardown;\n entry.subscribed = true;\n }\n }\n\n /**\n * Returns whether an active subscription exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if a subscription has been established; `false` otherwise.\n */\n isSubscribed(key: QueryCacheKey): boolean {\n return this._entries.get(key)?.subscribed ?? false;\n }\n\n /**\n * Decrements the subscriber count for the given key. When the count reaches zero, both teardown\n * and eviction are deferred by one microtask so that React StrictMode re-mounts — in any build\n * environment — can re-acquire the entry and cancel the cleanup before the timeout fires. This\n * prevents an unnecessary disconnect/reconnect cycle during the synthetic unmount/remount that\n * StrictMode performs.\n * @param key The cache key produced by {@link buildKey}.\n */\n release(key: QueryCacheKey): void {\n const entry = this._entries.get(key);\n\n if (entry) {\n entry.subscriberCount--;\n\n if (entry.subscriberCount <= 0) {\n // Defer both teardown and eviction. React StrictMode re-mounts can cancel by\n // calling acquire() before the timeout fires. A non-zero _retentionMs keeps the\n // entry alive so users navigating back quickly see cached data immediately.\n entry.pendingCleanup = setTimeout(() => {\n const current = this._entries.get(key);\n\n if (current && current.subscriberCount <= 0) {\n current.subscribed = false;\n current.teardown?.();\n current.teardown = undefined;\n current.pendingCleanup = undefined;\n this._entries.delete(key);\n }\n }, this._retentionMs);\n }\n }\n }\n\n /**\n * Returns whether an entry exists for the given key.\n * @param key The cache key to check.\n * @returns `true` if an entry exists; `false` otherwise.\n */\n has(key: QueryCacheKey): boolean {\n return this._entries.has(key);\n }\n\n /**\n * Tears down all active subscriptions and marks every entry as not subscribed,\n * but preserves entries, subscriber counts, and listeners. This allows\n * hooks whose effects re-run afterward to detect that the entry is no longer\n * subscribed and re-establish a fresh connection.\n *\n * Use this when the underlying transport must be replaced (e.g. after an\n * authentication change that requires new WebSocket connections with updated\n * credentials).\n */\n teardownAllSubscriptions(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n }\n\n /**\n * Immediately tears down all subscriptions, cancels any pending deferred cleanups,\n * and evicts all entries. Call when the owning component (e.g. the {@link Arc} provider)\n * unmounts permanently so that all query connections are closed synchronously.\n */\n dispose(): void {\n for (const [, entry] of this._entries) {\n if (entry.pendingCleanup !== undefined) {\n clearTimeout(entry.pendingCleanup);\n entry.pendingCleanup = undefined;\n }\n\n entry.subscribed = false;\n entry.teardown?.();\n entry.teardown = undefined;\n }\n\n this._entries.clear();\n }\n\n /**\n * Schedules a deferred {@link dispose} using {@code setTimeout(0)}.\n *\n * This allows React StrictMode re-mounts to call {@link cancelPendingDispose}\n * before the dispose fires, avoiding the destruction of cache entries that child\n * effects are about to re-acquire.\n *\n * If a deferred dispose is already pending, it is replaced.\n */\n deferDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n }\n\n this._pendingDispose = setTimeout(() => {\n this._pendingDispose = undefined;\n this.dispose();\n }, 0);\n }\n\n /**\n * Cancels a pending deferred dispose scheduled by {@link deferDispose}.\n *\n * Call from the {@code useEffect} setup phase so that a StrictMode re-mount\n * prevents the synthetic unmount's deferred dispose from firing.\n */\n cancelPendingDispose(): void {\n if (this._pendingDispose !== undefined) {\n clearTimeout(this._pendingDispose);\n this._pendingDispose = undefined;\n }\n }\n\n /**\n * Returns a diagnostics snapshot of the current cache state.\n * @returns A {@link CacheDiagnostics} describing all entries.\n */\n getDiagnosticsSnapshot(): CacheDiagnostics {\n const entries: CacheEntryDiagnostics[] = [];\n let totalBytes = 0;\n let unhealthyCount = 0;\n\n for (const [key, entry] of this._entries) {\n const colonIndex = key.indexOf('::');\n const queryName = colonIndex >= 0 ? key.substring(0, colonIndex) : key;\n\n let estimatedBytes = 0;\n try {\n if (entry.lastResult !== undefined) {\n estimatedBytes = JSON.stringify(entry.lastResult).length;\n }\n } catch {\n // Ignore serialization errors\n }\n\n if (entry.subscriberCount > 0 && !entry.subscribed) {\n unhealthyCount++;\n }\n\n totalBytes += estimatedBytes;\n entries.push({\n key,\n queryName,\n subscriberCount: entry.subscriberCount,\n listenerCount: entry.listeners.size,\n subscribed: entry.subscribed,\n hasResult: entry.lastResult !== undefined,\n estimatedBytes,\n });\n }\n\n return {\n healthy: unhealthyCount === 0,\n entryCount: this._entries.size,\n estimatedBytes: totalBytes,\n entries,\n };\n }\n}\n"],"names":["QueryInstanceCache","_entries","Map","_pendingDispose","_retentionMs","buildKey","queryTypeName","args","Object","keys","length","sorted","sort","reduce","accumulator","key","JSON","stringify","getOrCreate","factory","has","entry","instance","lastResult","undefined","subscriberCount","listeners","Set","subscribed","set","isNew","get","acquire","pendingCleanup","clearTimeout","getLastResult","setLastResult","result","previousResult","reconciled","withReconciledData","isSuccess","isReady","data","listener","previous","next","reconciledData","reconcileQueryData","QueryResultWithState","paging","isAuthorized","isValid","validationResults","hasExceptions","exceptionMessages","exceptionStackTrace","isPerforming","changeSet","addListener","add","removeListener","delete","setTeardown","teardown","isSubscribed","release","setTimeout","current","teardownAllSubscriptions","dispose","clear","deferDispose","cancelPendingDispose","getDiagnosticsSnapshot","entries","totalBytes","unhealthyCount","colonIndex","indexOf","queryName","substring","estimatedBytes","push","listenerCount","size","hasResult","healthy","entryCount"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryProvider.js","sources":["../../../queries/QueryProvider.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 } from '@cratis/fundamentals';\nimport { IQueryProvider } from './IQueryProvider';\nimport { IQuery } from './IQuery';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\n\n/**\n * Represents an implementation of {@link IQueryProvider}\n */\nexport class QueryProvider implements IQueryProvider {\n\n /**\n * Initializes a new instance of {@link QueryProvider}\n * @param _microservice Name of the microservice to provide queries for.\n * @param _apiBasePath Base path for the API to use for the query.\n * @param _origin Origin to use for the query.\n * @param _httpHeadersCallback Callback to get HTTP headers for the query.\n */\n constructor(\n private readonly _microservice: string,\n private readonly _apiBasePath: string,\n private readonly _origin: string,\n private readonly _httpHeadersCallback: GetHttpHeaders) { }\n\n /** @inheritdoc */\n get<T extends IQuery>(queryType: Constructor<T>): T {\n const query = new queryType();\n query.setMicroservice(this._microservice);\n query.setApiBasePath(this._apiBasePath);\n query.setOrigin(this._origin);\n query.setHttpHeadersCallback(this._httpHeadersCallback);\n return query;\n }\n}"],"names":["QueryProvider","_microservice","_origin","_apiBasePath","_httpHeadersCallback","get","queryType","query","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback"],"mappings":"AAAA;AACA;AAOA;;AAEC,IACM,MAAMA,aAAAA,CAAAA;;;;;AAET;;;;;;AAMC,QACD,WAAA,CACqBC,aAAqB,EACtC,YAAqC,EACpBC,OAAe,EAChC,oBAAqD,CAAE;aAHtCD,aAAAA,GAAAA,aAAAA;aACAE,YAAAA,GAAAA,YAAAA;aACAD,OAAAA,GAAAA,OAAAA;aACAE,oBAAAA,GAAAA,oBAAAA;AAAwC,IAAA;uBAG7DC,GAAAA,CAAsBC,SAAyB,EAAK;AAChD,QAAA,MAAMC,QAAQ,IAAID,SAAAA,EAAAA;AAClBC,QAAAA,KAAAA,CAAMC,eAAe,CAAC,IAAI,CAACP,aAAa,CAAA;AACxCM,QAAAA,KAAAA,CAAME,cAAc,CAAC,IAAI,CAACN,YAAY,CAAA;AACtCI,QAAAA,KAAAA,CAAMG,SAAS,CAAC,IAAI,CAACR,OAAO,CAAA;AAC5BK,QAAAA,KAAAA,CAAMI,sBAAsB,CAAC,IAAI,CAACP,oBAAoB,CAAA;QACtD,OAAOG,KAAAA;AACX,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"QueryProvider.js","sources":["../../../queries/QueryProvider.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 } from '@cratis/fundamentals';\nimport { IQueryProvider } from './IQueryProvider';\nimport { IQuery } from './IQuery';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\n\n/**\n * Represents an implementation of {@link IQueryProvider}\n */\nexport class QueryProvider implements IQueryProvider {\n\n /**\n * Initializes a new instance of {@link QueryProvider}\n * @param _microservice Name of the microservice to provide queries for.\n * @param _apiBasePath Base path for the API to use for the query.\n * @param _origin Origin to use for the query.\n * @param _httpHeadersCallback Callback to get HTTP headers for the query.\n */\n constructor(\n private readonly _microservice: string,\n private readonly _apiBasePath: string,\n private readonly _origin: string,\n private readonly _httpHeadersCallback: GetHttpHeaders) { }\n\n /** @inheritdoc */\n get<T extends IQuery>(queryType: Constructor<T>): T {\n const query = new queryType();\n query.setMicroservice(this._microservice);\n query.setApiBasePath(this._apiBasePath);\n query.setOrigin(this._origin);\n query.setHttpHeadersCallback(this._httpHeadersCallback);\n return query;\n }\n}"],"names":["QueryProvider","_microservice","_origin","_apiBasePath","_httpHeadersCallback","get","queryType","query","setMicroservice","setApiBasePath","setOrigin","setHttpHeadersCallback"],"mappings":"AAAA;AACA;AAOA;;AAEC,IACM,MAAMA,aAAAA,CAAAA;;;;;AAET;;;;;;AAMC,QACD,WAAA,CACqBC,aAAqB,EACtC,YAAqC,EACpBC,OAAe,EAChC,oBAAqD,CAAE;aAHtCD,aAAAA,GAAAA,aAAAA;aACAE,YAAAA,GAAAA,YAAAA;aACAD,OAAAA,GAAAA,OAAAA;aACAE,oBAAAA,GAAAA,oBAAAA;AAAwC,IAAA;uBAG7DC,GAAAA,CAAsBC,SAAyB,EAAK;AAChD,QAAA,MAAMC,QAAQ,IAAID,SAAAA,EAAAA;AAClBC,QAAAA,KAAAA,CAAMC,eAAe,CAAC,IAAI,CAACP,aAAa,CAAA;AACxCM,QAAAA,KAAAA,CAAME,cAAc,CAAC,IAAI,CAACN,YAAY,CAAA;AACtCI,QAAAA,KAAAA,CAAMG,SAAS,CAAC,IAAI,CAACR,OAAO,CAAA;AAC5BK,QAAAA,KAAAA,CAAMI,sBAAsB,CAAC,IAAI,CAACP,oBAAoB,CAAA;QACtD,OAAOG,KAAAA;AACX,IAAA;AACJ;;"}
@@ -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 } from '@cratis/fundamentals';\nimport { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\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 isReady?: 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 reason?: string;\n reasonDetail?: string;\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 * Creates a settled empty result. It is ready because no server result is pending.\n * @param defaultValue The query's empty data value.\n * @returns A ready empty result.\n */\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult(\n {\n data: defaultValue as object,\n isSuccess: true,\n isReady: 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,\n false,\n );\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 ready result that is neither successful nor valid.\n */\n static validationFailed<TDataType>(\n validationResults: ValidationResult[],\n query: {\n readonly defaultValue: TDataType;\n readonly modelType: Constructor;\n readonly enumerable: boolean;\n },\n ): QueryResult<TDataType> {\n const { defaultValue, modelType, enumerable } = query;\n return new QueryResult(\n {\n data: defaultValue as object,\n isSuccess: false,\n isReady: true,\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 reason: _.reason,\n reasonDetail: _.reasonDetail,\n })),\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0,\n },\n },\n modelType,\n enumerable,\n ) as QueryResult<TDataType>;\n }\n\n /**\n * Creates a settled unauthorized result. Authorization rejection is terminal, so the result is ready.\n * @returns A ready unauthorized result.\n */\n static unauthorized<TDataType>(): QueryResult<TDataType> {\n return new QueryResult(\n {\n // SAFETY: An unauthorized result intentionally has no data, while the wire envelope uses object.\n data: null as unknown as object,\n isSuccess: false,\n isReady: true,\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 },\n Object,\n false,\n );\n }\n\n /**\n * A settled unsuccessful result used for client-side and transport failures. These failures are ready because\n * the client has completed the attempt; they are not the server's transient not-ready state.\n */\n static noSuccess: QueryResult = new QueryResult(\n {\n data: {},\n isSuccess: false,\n isReady: 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,\n false,\n );\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(\n result: ServerQueryResult,\n instanceType: Constructor,\n enumerable: boolean,\n ) {\n this.isSuccess = result.isSuccess;\n // Older servers and hand-built envelopes do not carry readiness. Those results predate\n // the transient not-ready state and are therefore complete from the client's perspective.\n this.isReady = result.isReady ?? true;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(\n (_) =>\n new ValidationResult(\n _.severity,\n _.message,\n _.members,\n _.state,\n _.reason,\n _.reasonDetail,\n ),\n );\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 this.data = (\n enumerable\n ? deserializeQueryModels(instanceType, result.data)\n : deserializeQueryModel(instanceType, result.data)\n ) as TDataType;\n } else {\n this.data = (enumerable ? [] : null) as TDataType;\n }\n\n if (enumerable && result.changeSet) {\n this.changeSet = {\n added: deserializeQueryModels(instanceType, result.changeSet.added ?? []),\n replaced: deserializeQueryModels(\n instanceType,\n result.changeSet.replaced ?? [],\n ),\n removed: deserializeQueryModels(\n instanceType,\n result.changeSet.removed ?? [],\n ),\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 isReady: 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","isReady","isAuthorized","isValid","hasExceptions","validationResults","exceptionMessages","exceptionStackTrace","paging","totalItems","totalPages","page","size","Object","validationFailed","query","modelType","enumerable","map","_","severity","message","members","state","reason","reasonDetail","unauthorized","noSuccess","result","instanceType","ValidationResult","PagingInfo","deserializeQueryModels","deserializeQueryModel","changeSet","added","replaced","removed","hasData","Array","isArray","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 } from '@cratis/fundamentals';\nimport { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\nimport { deserializeQueryModel, deserializeQueryModels } from './deserializeQueryModel';\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 isReady?: 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 reason?: string;\n reasonDetail?: string;\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 * Creates a settled empty result. It is ready because no server result is pending.\n * @param defaultValue The query's empty data value.\n * @returns A ready empty result.\n */\n static empty<TDataType>(defaultValue: TDataType): QueryResult<TDataType> {\n return new QueryResult(\n {\n data: defaultValue as object,\n isSuccess: true,\n isReady: 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,\n false,\n );\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 ready result that is neither successful nor valid.\n */\n static validationFailed<TDataType>(\n validationResults: ValidationResult[],\n query: {\n readonly defaultValue: TDataType;\n readonly modelType: Constructor;\n readonly enumerable: boolean;\n },\n ): QueryResult<TDataType> {\n const { defaultValue, modelType, enumerable } = query;\n return new QueryResult(\n {\n data: defaultValue as object,\n isSuccess: false,\n isReady: true,\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 reason: _.reason,\n reasonDetail: _.reasonDetail,\n })),\n exceptionMessages: [],\n exceptionStackTrace: '',\n paging: {\n totalItems: 0,\n totalPages: 0,\n page: 0,\n size: 0,\n },\n },\n modelType,\n enumerable,\n ) as QueryResult<TDataType>;\n }\n\n /**\n * Creates a settled unauthorized result. Authorization rejection is terminal, so the result is ready.\n * @returns A ready unauthorized result.\n */\n static unauthorized<TDataType>(): QueryResult<TDataType> {\n return new QueryResult(\n {\n // SAFETY: An unauthorized result intentionally has no data, while the wire envelope uses object.\n data: null as unknown as object,\n isSuccess: false,\n isReady: true,\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 },\n Object,\n false,\n );\n }\n\n /**\n * A settled unsuccessful result used for client-side and transport failures. These failures are ready because\n * the client has completed the attempt; they are not the server's transient not-ready state.\n */\n static noSuccess: QueryResult = new QueryResult(\n {\n data: {},\n isSuccess: false,\n isReady: 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,\n false,\n );\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(\n result: ServerQueryResult,\n instanceType: Constructor,\n enumerable: boolean,\n ) {\n this.isSuccess = result.isSuccess;\n // Older servers and hand-built envelopes do not carry readiness. Those results predate\n // the transient not-ready state and are therefore complete from the client's perspective.\n this.isReady = result.isReady ?? true;\n this.isAuthorized = result.isAuthorized;\n this.isValid = result.isValid;\n this.hasExceptions = result.hasExceptions;\n this.validationResults = result.validationResults.map(\n (_) =>\n new ValidationResult(\n _.severity,\n _.message,\n _.members,\n _.state,\n _.reason,\n _.reasonDetail,\n ),\n );\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 this.data = (\n enumerable\n ? deserializeQueryModels(instanceType, result.data)\n : deserializeQueryModel(instanceType, result.data)\n ) as TDataType;\n } else {\n this.data = (enumerable ? [] : null) as TDataType;\n }\n\n if (enumerable && result.changeSet) {\n this.changeSet = {\n added: deserializeQueryModels(instanceType, result.changeSet.added ?? []),\n replaced: deserializeQueryModels(\n instanceType,\n result.changeSet.replaced ?? [],\n ),\n removed: deserializeQueryModels(\n instanceType,\n result.changeSet.removed ?? [],\n ),\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 isReady: 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","isReady","isAuthorized","isValid","hasExceptions","validationResults","exceptionMessages","exceptionStackTrace","paging","totalItems","totalPages","page","size","Object","validationFailed","query","modelType","enumerable","map","_","severity","message","members","state","reason","reasonDetail","unauthorized","noSuccess","result","instanceType","ValidationResult","PagingInfo","deserializeQueryModels","deserializeQueryModel","changeSet","added","replaced","removed","hasData","Array","isArray","length"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResultWithState.js","sources":["../../../queries/QueryResultWithState.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 { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\n\n/**\n * Represents a specialized {@link QueryResult<TDataType>} that holds state for its execution\n */\nexport class QueryResultWithState<TDataType> implements IQueryResult<TDataType> {\n /**\n * Creates a settled empty state, such as the state returned by a disabled query.\n * @param defaultValue The query's empty data value.\n * @returns A ready state that is not performing.\n */\n static empty<TDataType>(defaultValue: TDataType): QueryResultWithState<TDataType> {\n return new QueryResultWithState(\n defaultValue,\n PagingInfo.noPaging,\n true,\n true,\n true,\n [],\n false,\n [],\n '',\n false,\n undefined,\n true,\n );\n }\n\n /**\n * Creates the local initial state before any server result has been received. This state is not ready because\n * no result exists yet; its performing state independently describes the active client request.\n * @param defaultValue The query's initial data value.\n * @returns A not-ready state that is performing.\n */\n static initial<TDataType>(defaultValue: TDataType): QueryResultWithState<TDataType> {\n return new QueryResultWithState(\n defaultValue,\n PagingInfo.noPaging,\n true,\n true,\n true,\n [],\n false,\n [],\n '',\n true,\n undefined,\n false,\n );\n }\n\n /**\n * Initializes an instance of {@link QueryResultWithState<TDataType>}.\n * @param {TDataType} data The items returned, if any - can be empty.\n * @param {PagingInfo} paging The paging info.\n * @param {boolean} isSuccess Whether or not the query was successful.\n * @param {boolean} isAuthorized Whether or not the query was authorized.\n * @param {boolean} isValid Whether or not it is valid.\n * @param {ValidationResult[]} validationResults Any validation errors.\n * @param {boolean} hasExceptions Whether or not it has exceptions.\n * @param {string[]} exceptionMessages Any exception messages.\n * @param {string} exceptionStackTrace Exception stack trace, if any.\n * @param {boolean} isPerforming Whether or not the query is being performed. True if its performing, false if it is done.\n * @param {ChangeSet<unknown> | undefined} changeSet Optional change set from the server describing the delta since the last update.\n * @param {boolean} isReady Whether the query has produced a result. Defaults to true so existing constructor calls\n * represent settled synthetic states; {@link initial} explicitly uses false because no server result exists yet.\n */\n constructor(\n readonly data: TDataType,\n readonly paging: PagingInfo,\n readonly isSuccess: boolean,\n readonly isAuthorized: boolean,\n readonly isValid: boolean,\n readonly validationResults: ValidationResult[],\n readonly hasExceptions: boolean,\n readonly exceptionMessages: string[],\n readonly exceptionStackTrace: string,\n readonly isPerforming: boolean,\n readonly changeSet?: ChangeSet<unknown>,\n readonly isReady: boolean = true,\n ) {}\n\n /** @inheritdoc */\n get hasData(): boolean {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return !!this.data;\n }\n\n /**\n * Create a new {@link QueryResultWithState<TDataType>} from an {@link IQueryResult<TDataType>}.\n * @param queryResult The original query result.\n * @param isPerforming Whether or not the query is performing.\n * @returns A new {@link QueryResultWithState<TDataType>}\n */\n static fromQueryResult<TDataType>(\n queryResult: IQueryResult<TDataType>,\n isPerforming: boolean,\n ) {\n return new QueryResultWithState<TDataType>(\n queryResult.data,\n queryResult.paging,\n queryResult.isSuccess,\n queryResult.isAuthorized,\n queryResult.isValid,\n queryResult.validationResults,\n queryResult.hasExceptions,\n queryResult.exceptionMessages,\n queryResult.exceptionStackTrace,\n isPerforming,\n queryResult.changeSet,\n queryResult.isReady ?? true,\n );\n }\n}\n"],"names":["QueryResultWithState","empty","defaultValue","PagingInfo","noPaging","undefined","initial","paging","isSuccess","hasExceptions","exceptionMessages","isReady","data","isAuthorized","isValid","validationResults","exceptionStackTrace","isPerforming","changeSet","hasData","Array","isArray","length","fromQueryResult","queryResult"],"mappings":";;AAAA;AACA;AAOA;;AAEC,IACM,MAAMA,oBAAAA,CAAAA;;;;;;;;;;;;;AACT;;;;QAKA,OAAOC,KAAAA,CAAiBC,YAAuB,EAAmC;AAC9E,QAAA,OAAO,IAAIF,oBAAAA,CACPE,YAAAA,EACAC,UAAAA,CAAWC,QAAQ,EACnB,IAAA,EACA,IAAA,EACA,IAAA,EACA,EAAE,EACF,KAAA,EACA,EAAE,EACF,EAAA,EACA,OACAC,SAAAA,EACA,IAAA,CAAA;AAER,IAAA;AAEA;;;;;QAMA,OAAOC,OAAAA,CAAmBJ,YAAuB,EAAmC;AAChF,QAAA,OAAO,IAAIF,oBAAAA,CACPE,YAAAA,EACAC,UAAAA,CAAWC,QAAQ,EACnB,IAAA,EACA,IAAA,EACA,IAAA,EACA,EAAE,EACF,KAAA,EACA,EAAE,EACF,EAAA,EACA,MACAC,SAAAA,EACA,KAAA,CAAA;AAER,IAAA;AAEA;;;;;;;;;;;;;;;AAeC,QACD,YACI,IAAwB,EACfE,MAAkB,EAClBC,SAAkB,EAC3B,YAA8B,EAC9B,OAAyB,EACzB,iBAA8C,EACrCC,aAAsB,EACtBC,iBAA2B,EACpC,mBAAoC,EACpC,YAA8B,EAC9B,SAAuC,EACvC,OAASC,GAAmB,IAAI,CAClC;aAZWC,IAAAA,GAAAA,IAAAA;aACAL,MAAAA,GAAAA,MAAAA;aACAC,SAAAA,GAAAA,SAAAA;aACAK,YAAAA,GAAAA,YAAAA;aACAC,OAAAA,GAAAA,OAAAA;aACAC,iBAAAA,GAAAA,iBAAAA;aACAN,aAAAA,GAAAA,aAAAA;aACAC,iBAAAA,GAAAA,iBAAAA;aACAM,mBAAAA,GAAAA,mBAAAA;aACAC,YAAAA,GAAAA,YAAAA;aACAC,SAAAA,GAAAA,SAAAA;aACAP,OAAAA,GAAAA,OAAAA;AACV,IAAA;uBAGH,IAAIQ,OAAAA,GAAmB;AACnB,QAAA,IAAIC,MAAMC,OAAO,CAAC,IAAI,CAACT,IAAI,CAAA,EAAG;AAC1B,YAAA,OAAO,IAAI,CAACA,IAAI,CAACU,MAAM,GAAG,CAAA;AAC9B,QAAA;AACA,QAAA,OAAO,CAAC,CAAC,IAAI,CAACV,IAAI;AACtB,IAAA;AAEA;;;;;AAKC,QACD,OAAOW,eAAAA,CACHC,WAAoC,EACpCP,YAAqB,EACvB;AACE,QAAA,OAAO,IAAIjB,oBAAAA,CACPwB,WAAAA,CAAYZ,IAAI,EAChBY,WAAAA,CAAYjB,MAAM,EAClBiB,WAAAA,CAAYhB,SAAS,EACrBgB,WAAAA,CAAYX,YAAY,EACxBW,YAAYV,OAAO,EACnBU,WAAAA,CAAYT,iBAAiB,EAC7BS,WAAAA,CAAYf,aAAa,EACzBe,WAAAA,CAAYd,iBAAiB,EAC7Bc,WAAAA,CAAYR,mBAAmB,EAC/BC,cACAO,WAAAA,CAAYN,SAAS,EACrBM,WAAAA,CAAYb,OAAO,IAAI,IAAA,CAAA;AAE/B,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"QueryResultWithState.js","sources":["../../../queries/QueryResultWithState.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 { ValidationResult } from '../validation/ValidationResult';\nimport { IQueryResult } from './IQueryResult';\nimport { PagingInfo } from './PagingInfo';\nimport { ChangeSet } from './ChangeSet';\n\n/**\n * Represents a specialized {@link QueryResult<TDataType>} that holds state for its execution\n */\nexport class QueryResultWithState<TDataType> implements IQueryResult<TDataType> {\n /**\n * Creates a settled empty state, such as the state returned by a disabled query.\n * @param defaultValue The query's empty data value.\n * @returns A ready state that is not performing.\n */\n static empty<TDataType>(defaultValue: TDataType): QueryResultWithState<TDataType> {\n return new QueryResultWithState(\n defaultValue,\n PagingInfo.noPaging,\n true,\n true,\n true,\n [],\n false,\n [],\n '',\n false,\n undefined,\n true,\n );\n }\n\n /**\n * Creates the local initial state before any server result has been received. This state is not ready because\n * no result exists yet; its performing state independently describes the active client request.\n * @param defaultValue The query's initial data value.\n * @returns A not-ready state that is performing.\n */\n static initial<TDataType>(defaultValue: TDataType): QueryResultWithState<TDataType> {\n return new QueryResultWithState(\n defaultValue,\n PagingInfo.noPaging,\n true,\n true,\n true,\n [],\n false,\n [],\n '',\n true,\n undefined,\n false,\n );\n }\n\n /**\n * Initializes an instance of {@link QueryResultWithState<TDataType>}.\n * @param {TDataType} data The items returned, if any - can be empty.\n * @param {PagingInfo} paging The paging info.\n * @param {boolean} isSuccess Whether or not the query was successful.\n * @param {boolean} isAuthorized Whether or not the query was authorized.\n * @param {boolean} isValid Whether or not it is valid.\n * @param {ValidationResult[]} validationResults Any validation errors.\n * @param {boolean} hasExceptions Whether or not it has exceptions.\n * @param {string[]} exceptionMessages Any exception messages.\n * @param {string} exceptionStackTrace Exception stack trace, if any.\n * @param {boolean} isPerforming Whether or not the query is being performed. True if its performing, false if it is done.\n * @param {ChangeSet<unknown> | undefined} changeSet Optional change set from the server describing the delta since the last update.\n * @param {boolean} isReady Whether the query has produced a result. Defaults to true so existing constructor calls\n * represent settled synthetic states; {@link initial} explicitly uses false because no server result exists yet.\n */\n constructor(\n readonly data: TDataType,\n readonly paging: PagingInfo,\n readonly isSuccess: boolean,\n readonly isAuthorized: boolean,\n readonly isValid: boolean,\n readonly validationResults: ValidationResult[],\n readonly hasExceptions: boolean,\n readonly exceptionMessages: string[],\n readonly exceptionStackTrace: string,\n readonly isPerforming: boolean,\n readonly changeSet?: ChangeSet<unknown>,\n readonly isReady: boolean = true,\n ) {}\n\n /** @inheritdoc */\n get hasData(): boolean {\n if (Array.isArray(this.data)) {\n return this.data.length > 0;\n }\n return !!this.data;\n }\n\n /**\n * Create a new {@link QueryResultWithState<TDataType>} from an {@link IQueryResult<TDataType>}.\n * @param queryResult The original query result.\n * @param isPerforming Whether or not the query is performing.\n * @returns A new {@link QueryResultWithState<TDataType>}\n */\n static fromQueryResult<TDataType>(\n queryResult: IQueryResult<TDataType>,\n isPerforming: boolean,\n ) {\n return new QueryResultWithState<TDataType>(\n queryResult.data,\n queryResult.paging,\n queryResult.isSuccess,\n queryResult.isAuthorized,\n queryResult.isValid,\n queryResult.validationResults,\n queryResult.hasExceptions,\n queryResult.exceptionMessages,\n queryResult.exceptionStackTrace,\n isPerforming,\n queryResult.changeSet,\n queryResult.isReady ?? true,\n );\n }\n}\n"],"names":["QueryResultWithState","empty","defaultValue","PagingInfo","noPaging","undefined","initial","paging","isSuccess","hasExceptions","exceptionMessages","isReady","data","isAuthorized","isValid","validationResults","exceptionStackTrace","isPerforming","changeSet","hasData","Array","isArray","length","fromQueryResult","queryResult"],"mappings":";;AAAA;AACA;AAOA;;AAEC,IACM,MAAMA,oBAAAA,CAAAA;;;;;;;;;;;;;AACT;;;;QAKA,OAAOC,KAAAA,CAAiBC,YAAuB,EAAmC;AAC9E,QAAA,OAAO,IAAIF,oBAAAA,CACPE,YAAAA,EACAC,UAAAA,CAAWC,QAAQ,EACnB,IAAA,EACA,IAAA,EACA,IAAA,EACA,EAAE,EACF,KAAA,EACA,EAAE,EACF,EAAA,EACA,OACAC,SAAAA,EACA,IAAA,CAAA;AAER,IAAA;AAEA;;;;;QAMA,OAAOC,OAAAA,CAAmBJ,YAAuB,EAAmC;AAChF,QAAA,OAAO,IAAIF,oBAAAA,CACPE,YAAAA,EACAC,UAAAA,CAAWC,QAAQ,EACnB,IAAA,EACA,IAAA,EACA,IAAA,EACA,EAAE,EACF,KAAA,EACA,EAAE,EACF,EAAA,EACA,MACAC,SAAAA,EACA,KAAA,CAAA;AAER,IAAA;AAEA;;;;;;;;;;;;;;;AAeC,QACD,YACI,IAAwB,EACfE,MAAkB,EAClBC,SAAkB,EAC3B,YAA8B,EAC9B,OAAyB,EACzB,iBAA8C,EACrCC,aAAsB,EACtBC,iBAA2B,EACpC,mBAAoC,EACpC,YAA8B,EAC9B,SAAuC,EACvC,OAASC,GAAmB,IAAI,CAClC;aAZWC,IAAAA,GAAAA,IAAAA;aACAL,MAAAA,GAAAA,MAAAA;aACAC,SAAAA,GAAAA,SAAAA;aACAK,YAAAA,GAAAA,YAAAA;aACAC,OAAAA,GAAAA,OAAAA;aACAC,iBAAAA,GAAAA,iBAAAA;aACAN,aAAAA,GAAAA,aAAAA;aACAC,iBAAAA,GAAAA,iBAAAA;aACAM,mBAAAA,GAAAA,mBAAAA;aACAC,YAAAA,GAAAA,YAAAA;aACAC,SAAAA,GAAAA,SAAAA;aACAP,OAAAA,GAAAA,OAAAA;AACV,IAAA;uBAGH,IAAIQ,OAAAA,GAAmB;AACnB,QAAA,IAAIC,MAAMC,OAAO,CAAC,IAAI,CAACT,IAAI,CAAA,EAAG;AAC1B,YAAA,OAAO,IAAI,CAACA,IAAI,CAACU,MAAM,GAAG,CAAA;AAC9B,QAAA;AACA,QAAA,OAAO,CAAC,CAAC,IAAI,CAACV,IAAI;AACtB,IAAA;AAEA;;;;;AAKC,QACD,OAAOW,eAAAA,CACHC,WAAoC,EACpCP,YAAqB,EACvB;AACE,QAAA,OAAO,IAAIjB,oBAAAA,CACPwB,WAAAA,CAAYZ,IAAI,EAChBY,WAAAA,CAAYjB,MAAM,EAClBiB,WAAAA,CAAYhB,SAAS,EACrBgB,WAAAA,CAAYX,YAAY,EACxBW,YAAYV,OAAO,EACnBU,WAAAA,CAAYT,iBAAiB,EAC7BS,WAAAA,CAAYf,aAAa,EACzBe,WAAAA,CAAYd,iBAAiB,EAC7Bc,WAAAA,CAAYR,mBAAmB,EAC/BC,cACAO,WAAAA,CAAYN,SAAS,EACrBM,WAAAA,CAAYb,OAAO,IAAI,IAAA,CAAA;AAE/B,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryTransportMethod.js","sources":["../../../queries/QueryTransportMethod.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Defines the transport method used for observable query connections.\n */\nexport enum QueryTransportMethod {\n /**\n * Use WebSocket for real-time data streaming.\n */\n WebSocket = 'webSocket',\n\n /**\n * Use Server-Sent Events (SSE) for real-time data streaming.\n */\n ServerSentEvents = 'serverSentEvents',\n}\n"],"names":["QueryTransportMethod"],"mappings":"AAAA;AACA;AAEA;;IAGO,IAAKA,oBAAAA,iBAAAA,SAAAA,oBAAAA,EAAAA;AACR;;AAEC,QAAA,oBAAA,CAAA,WAAA,CAAA,GAAA,WAAA;AAGD;;AAEC,QAAA,oBAAA,CAAA,kBAAA,CAAA,GAAA,kBAAA;AAROA,IAAAA,OAAAA,oBAAAA;AAUX,CAAA,CAAA,EAAA;;;;"}
1
+ {"version":3,"file":"QueryTransportMethod.js","sources":["../../../queries/QueryTransportMethod.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Defines the transport method used for observable query connections.\n */\nexport enum QueryTransportMethod {\n /**\n * Use WebSocket for real-time data streaming.\n */\n WebSocket = 'webSocket',\n\n /**\n * Use Server-Sent Events (SSE) for real-time data streaming.\n */\n ServerSentEvents = 'serverSentEvents',\n}\n"],"names":["QueryTransportMethod"],"mappings":"AAAA;AACA;AAEA;;IAGO,IAAKA,oBAAAA,iBAAAA,SAAAA,oBAAAA,EAAAA;AACR;;AAEC,QAAA,oBAAA,CAAA,WAAA,CAAA,GAAA,WAAA;AAGD;;AAEC,QAAA,oBAAA,CAAA,kBAAA,CAAA,GAAA,kBAAA;AAROA,IAAAA,OAAAA,oBAAAA;AAUX,CAAA,CAAA,EAAA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryValidator.js","sources":["../../../queries/QueryValidator.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 { Validator } from '../validation/Validator';\nimport { ValidationResult } from '../validation/ValidationResult';\n\n/**\n * Represents the query validator\n */\nexport abstract class QueryValidator<T = object> extends Validator<T> {\n /**\n * Validate the query parameters.\n * @param query The query to validate.\n * @returns An array of validation results, empty if valid.\n */\n validate(query: T): ValidationResult[] {\n return super.validate(query);\n }\n}\n"],"names":["QueryValidator","Validator","validate","query"],"mappings":";;AAAA;AACA;AAKA;;IAGO,MAAeA,cAAAA,SAAmCC,SAAAA,CAAAA;AACrD;;;;QAKAC,QAAAA,CAASC,KAAQ,EAAsB;QACnC,OAAO,KAAK,CAACD,QAAAA,CAASC,KAAAA,CAAAA;AAC1B,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"QueryValidator.js","sources":["../../../queries/QueryValidator.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 { Validator } from '../validation/Validator';\nimport { ValidationResult } from '../validation/ValidationResult';\n\n/**\n * Represents the query validator\n */\nexport abstract class QueryValidator<T = object> extends Validator<T> {\n /**\n * Validate the query parameters.\n * @param query The query to validate.\n * @returns An array of validation results, empty if valid.\n */\n validate(query: T): ValidationResult[] {\n return super.validate(query);\n }\n}\n"],"names":["QueryValidator","Validator","validate","query"],"mappings":";;AAAA;AACA;AAKA;;IAGO,MAAeA,cAAAA,SAAmCC,SAAAA,CAAAA;AACrD;;;;QAKAC,QAAAA,CAASC,KAAQ,EAAsB;QACnC,OAAO,KAAK,CAACD,QAAAA,CAASC,KAAAA,CAAAA;AAC1B,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectPolicy.js","sources":["../../../queries/ReconnectPolicy.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 { IReconnectPolicy, ReconnectCallback } from './IReconnectPolicy';\n\n/**\n * Default exponential back-off reconnect policy shared by all observable query connections.\n *\n * Delay formula: `Math.min(initialDelayMs + delayStepMs * attempt, maxDelayMs)`\n *\n * With the default parameters:\n * - Attempt 1 → 1 000 ms\n * - Attempt 2 → 1 500 ms\n * - …\n * - Attempt 19+ → 10 000 ms (capped)\n * - After 100 attempts → abandoned (returns `false`)\n */\nexport class ReconnectPolicy implements IReconnectPolicy {\n private _attempt = 0;\n private _timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link ReconnectPolicy}.\n * @param {number} maxAttempts Maximum number of reconnect attempts before giving up (default: 100).\n * @param {number} initialDelayMs Base delay in milliseconds added to every attempt (default: 500).\n * @param {number} delayStepMs Additional delay per attempt in milliseconds (default: 500).\n * @param {number} maxDelayMs Upper bound on the computed delay in milliseconds (default: 10 000).\n */\n constructor(\n private readonly _maxAttempts: number = 100,\n private readonly _initialDelayMs: number = 500,\n private readonly _delayStepMs: number = 500,\n private readonly _maxDelayMs: number = 10_000,\n ) {}\n\n /** @inheritdoc */\n get attempt(): number {\n return this._attempt;\n }\n\n /** @inheritdoc */\n schedule(onReconnect: ReconnectCallback, label: string): boolean {\n if (this._attempt >= this._maxAttempts) {\n console.log(`Reconnect: abandoned after ${this._maxAttempts} attempts for '${label}'`);\n return false;\n }\n\n // Cancel any pending reconnect timer so we don't fire multiple\n // concurrent reconnect attempts when schedule() is called rapidly.\n this.cancel();\n\n this._attempt++;\n const delay = Math.min(this._initialDelayMs + this._delayStepMs * this._attempt, this._maxDelayMs);\n console.log(`Reconnect: attempt ${this._attempt} in ${delay}ms for '${label}'`);\n this._timer = setTimeout(onReconnect, delay);\n return true;\n }\n\n /** @inheritdoc */\n reset(): void {\n this._attempt = 0;\n this.cancel();\n }\n\n /** @inheritdoc */\n cancel(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n"],"names":["ReconnectPolicy","_attempt","_timer","_maxAttempts","_initialDelayMs","_delayStepMs","_maxDelayMs","attempt","schedule","onReconnect","label","console","log","cancel","delay","Math","min","setTimeout","reset","clearTimeout","undefined"],"mappings":"AAAA;AACA;AAIA;;;;;;;;;;;AAWC,IACM,MAAMA,eAAAA,CAAAA;;;;;AACDC,IAAAA,QAAAA,GAAW,CAAA;IACXC,MAAAA;AAER;;;;;;AAMC,QACD,YACI,YAAiBC,GAAuB,GAAG,EAC3C,eAAiBC,GAA0B,GAAG,EAC7BC,eAAuB,GAAG,EAC3C,WAAiBC,GAAsB,MAAM,CAC/C;aAJmBH,YAAAA,GAAAA,YAAAA;aACAC,eAAAA,GAAAA,eAAAA;aACAC,YAAAA,GAAAA,YAAAA;aACAC,WAAAA,GAAAA,WAAAA;AAClB,IAAA;uBAGH,IAAIC,OAAAA,GAAkB;QAClB,OAAO,IAAI,CAACN,QAAQ;AACxB,IAAA;AAEA,uBACAO,QAAAA,CAASC,WAA8B,EAAEC,KAAa,EAAW;AAC7D,QAAA,IAAI,IAAI,CAACT,QAAQ,IAAI,IAAI,CAACE,YAAY,EAAE;AACpCQ,YAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAE,IAAI,CAACT,YAAY,CAAC,eAAe,EAAEO,KAAAA,CAAM,CAAC,CAAC,CAAA;YACrF,OAAO,KAAA;AACX,QAAA;;;AAIA,QAAA,IAAI,CAACG,MAAM,EAAA;AAEX,QAAA,IAAI,CAACZ,QAAQ,EAAA;AACb,QAAA,MAAMa,QAAQC,IAAAA,CAAKC,GAAG,CAAC,IAAI,CAACZ,eAAe,GAAG,IAAI,CAACC,YAAY,GAAG,IAAI,CAACJ,QAAQ,EAAE,IAAI,CAACK,WAAW,CAAA;AACjGK,QAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,mBAAmB,EAAE,IAAI,CAACX,QAAQ,CAAC,IAAI,EAAEa,KAAAA,CAAM,QAAQ,EAAEJ,KAAAA,CAAM,CAAC,CAAC,CAAA;AAC9E,QAAA,IAAI,CAACR,MAAM,GAAGe,UAAAA,CAAWR,WAAAA,EAAaK,KAAAA,CAAAA;QACtC,OAAO,IAAA;AACX,IAAA;AAEA,uBACAI,KAAAA,GAAc;QACV,IAAI,CAACjB,QAAQ,GAAG,CAAA;AAChB,QAAA,IAAI,CAACY,MAAM,EAAA;AACf,IAAA;AAEA,uBACAA,MAAAA,GAAe;QACX,IAAI,IAAI,CAACX,MAAM,EAAE;YACbiB,YAAAA,CAAa,IAAI,CAACjB,MAAM,CAAA;YACxB,IAAI,CAACA,MAAM,GAAGkB,SAAAA;AAClB,QAAA;AACJ,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"ReconnectPolicy.js","sources":["../../../queries/ReconnectPolicy.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 { IReconnectPolicy, ReconnectCallback } from './IReconnectPolicy';\n\n/**\n * Default exponential back-off reconnect policy shared by all observable query connections.\n *\n * Delay formula: `Math.min(initialDelayMs + delayStepMs * attempt, maxDelayMs)`\n *\n * With the default parameters:\n * - Attempt 1 → 1 000 ms\n * - Attempt 2 → 1 500 ms\n * - …\n * - Attempt 19+ → 10 000 ms (capped)\n * - After 100 attempts → abandoned (returns `false`)\n */\nexport class ReconnectPolicy implements IReconnectPolicy {\n private _attempt = 0;\n private _timer?: ReturnType<typeof setTimeout>;\n\n /**\n * Initializes a new instance of {@link ReconnectPolicy}.\n * @param {number} maxAttempts Maximum number of reconnect attempts before giving up (default: 100).\n * @param {number} initialDelayMs Base delay in milliseconds added to every attempt (default: 500).\n * @param {number} delayStepMs Additional delay per attempt in milliseconds (default: 500).\n * @param {number} maxDelayMs Upper bound on the computed delay in milliseconds (default: 10 000).\n */\n constructor(\n private readonly _maxAttempts: number = 100,\n private readonly _initialDelayMs: number = 500,\n private readonly _delayStepMs: number = 500,\n private readonly _maxDelayMs: number = 10_000,\n ) {}\n\n /** @inheritdoc */\n get attempt(): number {\n return this._attempt;\n }\n\n /** @inheritdoc */\n schedule(onReconnect: ReconnectCallback, label: string): boolean {\n if (this._attempt >= this._maxAttempts) {\n console.log(`Reconnect: abandoned after ${this._maxAttempts} attempts for '${label}'`);\n return false;\n }\n\n // Cancel any pending reconnect timer so we don't fire multiple\n // concurrent reconnect attempts when schedule() is called rapidly.\n this.cancel();\n\n this._attempt++;\n const delay = Math.min(this._initialDelayMs + this._delayStepMs * this._attempt, this._maxDelayMs);\n console.log(`Reconnect: attempt ${this._attempt} in ${delay}ms for '${label}'`);\n this._timer = setTimeout(onReconnect, delay);\n return true;\n }\n\n /** @inheritdoc */\n reset(): void {\n this._attempt = 0;\n this.cancel();\n }\n\n /** @inheritdoc */\n cancel(): void {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n"],"names":["ReconnectPolicy","_attempt","_timer","_maxAttempts","_initialDelayMs","_delayStepMs","_maxDelayMs","attempt","schedule","onReconnect","label","console","log","cancel","delay","Math","min","setTimeout","reset","clearTimeout","undefined"],"mappings":"AAAA;AACA;AAIA;;;;;;;;;;;AAWC,IACM,MAAMA,eAAAA,CAAAA;;;;;AACDC,IAAAA,QAAAA,GAAW,CAAA;IACXC,MAAAA;AAER;;;;;;AAMC,QACD,YACI,YAAiBC,GAAuB,GAAG,EAC3C,eAAiBC,GAA0B,GAAG,EAC7BC,eAAuB,GAAG,EAC3C,WAAiBC,GAAsB,MAAM,CAC/C;aAJmBH,YAAAA,GAAAA,YAAAA;aACAC,eAAAA,GAAAA,eAAAA;aACAC,YAAAA,GAAAA,YAAAA;aACAC,WAAAA,GAAAA,WAAAA;AAClB,IAAA;uBAGH,IAAIC,OAAAA,GAAkB;QAClB,OAAO,IAAI,CAACN,QAAQ;AACxB,IAAA;AAEA,uBACAO,QAAAA,CAASC,WAA8B,EAAEC,KAAa,EAAW;AAC7D,QAAA,IAAI,IAAI,CAACT,QAAQ,IAAI,IAAI,CAACE,YAAY,EAAE;AACpCQ,YAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAE,IAAI,CAACT,YAAY,CAAC,eAAe,EAAEO,KAAAA,CAAM,CAAC,CAAC,CAAA;YACrF,OAAO,KAAA;AACX,QAAA;;;AAIA,QAAA,IAAI,CAACG,MAAM,EAAA;AAEX,QAAA,IAAI,CAACZ,QAAQ,EAAA;AACb,QAAA,MAAMa,QAAQC,IAAAA,CAAKC,GAAG,CAAC,IAAI,CAACZ,eAAe,GAAG,IAAI,CAACC,YAAY,GAAG,IAAI,CAACJ,QAAQ,EAAE,IAAI,CAACK,WAAW,CAAA;AACjGK,QAAAA,OAAAA,CAAQC,GAAG,CAAC,CAAC,mBAAmB,EAAE,IAAI,CAACX,QAAQ,CAAC,IAAI,EAAEa,KAAAA,CAAM,QAAQ,EAAEJ,KAAAA,CAAM,CAAC,CAAC,CAAA;AAC9E,QAAA,IAAI,CAACR,MAAM,GAAGe,UAAAA,CAAWR,WAAAA,EAAaK,KAAAA,CAAAA;QACtC,OAAO,IAAA;AACX,IAAA;AAEA,uBACAI,KAAAA,GAAc;QACV,IAAI,CAACjB,QAAQ,GAAG,CAAA;AAChB,QAAA,IAAI,CAACY,MAAM,EAAA;AACf,IAAA;AAEA,uBACAA,MAAAA,GAAe;QACX,IAAI,IAAI,CAACX,MAAM,EAAE;YACbiB,YAAAA,CAAa,IAAI,CAACjB,MAAM,CAAA;YACxB,IAAI,CAACA,MAAM,GAAGkB,SAAAA;AAClB,QAAA;AACJ,IAAA;AACJ;;"}
@@ -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 type { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport type { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport type { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport {\n type HubMessage,\n HubMessageType,\n type SubscriptionRequest,\n} from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n revision: number;\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 _nextRevision = 0;\n private _supportsSubscriptionRevisions = false;\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(\n keepAliveIntervalMs,\n () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(\n 'SSE hub: no messages received; reconnecting',\n this._keepAlive.idleThresholdMs,\n this._sseUrl,\n );\n this.reconnect();\n }\n },\n keepAliveIntervalMs * IDLE_THRESHOLD_FACTOR,\n );\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get isConnected(): boolean {\n return (\n this._connectionId !== undefined &&\n this._eventSource?.readyState === EventSource.OPEN\n );\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 (\n this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length\n );\n }\n\n /** @inheritdoc */\n subscribe(\n queryId: string,\n request: SubscriptionRequest,\n callback: DataReceived<any>,\n ): void {\n const sub: ActiveSubscription = {\n request,\n callback,\n revision: this.getNextRevision(),\n };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, sub);\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 const subscription = this._subscriptions.get(queryId);\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId && subscription) {\n this.sendUnsubscribe(queryId, subscription.revision);\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.detachAndCloseEventSource();\n this._connectionId = undefined;\n }\n\n private detachAndCloseEventSource(): void {\n const eventSource = this._eventSource;\n if (!eventSource) return;\n\n eventSource.onopen = null;\n eventSource.onmessage = null;\n eventSource.onerror = null;\n eventSource.close();\n\n if (this._eventSource === eventSource) {\n this._eventSource = undefined;\n }\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 // An immediate subscription can win while a back-off callback is pending. Cancel that callback before\n // opening, and let openEventSource perform the same live-source guard for already-queued callbacks.\n this._policy.cancel();\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 this.detachAndCloseEventSource();\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this._policy.cancel();\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._supportsSubscriptionRevisions = false;\n const eventSource = Globals.eventSourceFactory\n ? Globals.eventSourceFactory(url)\n : new EventSource(url);\n this._eventSource = eventSource;\n\n eventSource.onopen = () => {\n if (this._disconnected || this._eventSource !== eventSource) 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 (\n !this._disconnected &&\n this._eventSource === eventSource &&\n !this._connectionId\n ) {\n console.warn(\n 'SSE hub: no Connected message within timeout; retrying',\n this._connectTimeoutMs,\n url,\n );\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected || this._eventSource !== eventSource) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n eventSource.onerror = () => {\n if (this._disconnected || this._eventSource !== eventSource) 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 // Detach before closing so callbacks already queued by the retired source are inert.\n this.detachAndCloseEventSource();\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.ensureConnected();\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 if (this.isMessageForCurrentSubscription(message)) {\n console.warn('SSE hub: query unauthorized', message.queryId);\n this.handleUnauthorized(message);\n }\n break;\n case HubMessageType.Error:\n if (this.isMessageForCurrentSubscription(message)) {\n console.error(\n 'SSE hub: query error',\n message.queryId,\n message.payload,\n );\n }\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 const connectionId = message.payload as string;\n const connectionIdChanged = this._connectionId !== connectionId;\n this._connectionId = connectionId;\n this._supportsSubscriptionRevisions =\n message.supportsSubscriptionRevisions === true;\n console.log('SSE hub: connected', this._connectionId);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n this.applyServerKeepAliveInterval(message.keepAliveIntervalMs);\n\n // The active collection is authoritative. A previous connection's subscribe POST may\n // still be in flight, so relying only on pending subscriptions can orphan a query when\n // the server assigns a new connection ID before that POST completes.\n if (connectionIdChanged) {\n for (const [queryId, subscription] of this._subscriptions) {\n this.sendSubscribe(queryId, subscription);\n }\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(\n serverIntervalMs,\n serverIntervalMs * IDLE_THRESHOLD_FACTOR,\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 || !this.isMessageForCurrentSubscription(message)) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n this._subscriptions.delete(message.queryId);\n this._pendingSubscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private sendSubscribe(\n queryId: string,\n subscription: ActiveSubscription,\n attempt: number = 0,\n ): void {\n if (!this._connectionId || this._disconnected) return;\n\n // Capture the connection ID and subscription instance so retries can detect whether\n // either has been replaced while this request is in flight.\n const connectionId = this._connectionId;\n\n const body: {\n connectionId: string;\n queryId: string;\n request: SubscriptionRequest;\n revision?: number;\n } = {\n connectionId,\n queryId,\n request: subscription.request,\n };\n if (this._supportsSubscriptionRevisions) {\n body.revision = subscription.revision;\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 })\n .then((response) => {\n if (!response.ok) {\n if (\n !this.isCurrentSubscription(queryId, subscription, connectionId)\n ) {\n console.warn(\n 'SSE hub: subscribe POST returned a failure for an obsolete connection or subscription; ignoring',\n queryId,\n response.status,\n );\n } else if (attempt < maxRetries) {\n setTimeout(\n () => {\n if (\n this.isCurrentSubscription(\n queryId,\n subscription,\n connectionId,\n )\n ) {\n this.sendSubscribe(\n queryId,\n subscription,\n attempt + 1,\n );\n }\n },\n retryDelayMs * (attempt + 1),\n );\n } else {\n console.warn(\n 'SSE hub: subscribe POST failed after retries; reconnecting',\n queryId,\n response.status,\n attempt + 1,\n );\n this.reconnect();\n }\n }\n })\n .catch((error) => {\n if (!this.isCurrentSubscription(queryId, subscription, connectionId)) {\n console.warn(\n 'SSE hub: subscribe POST failed for an obsolete connection or subscription; ignoring',\n queryId,\n error,\n );\n } else if (attempt < maxRetries) {\n setTimeout(\n () => {\n if (\n this.isCurrentSubscription(\n queryId,\n subscription,\n connectionId,\n )\n ) {\n this.sendSubscribe(queryId, subscription, attempt + 1);\n }\n },\n retryDelayMs * (attempt + 1),\n );\n } else {\n console.error(\n 'SSE hub: subscribe POST failed after retries; reconnecting',\n queryId,\n attempt + 1,\n error,\n );\n this.reconnect();\n }\n });\n }\n\n private isMessageForCurrentSubscription(message: HubMessage): boolean {\n if (!message.queryId) return false;\n\n const subscription = this._subscriptions.get(message.queryId);\n if (!subscription) return false;\n\n if (!this._supportsSubscriptionRevisions) {\n return message.revision === undefined;\n }\n\n return (\n this.isValidRevision(message.revision) &&\n message.revision === subscription.revision\n );\n }\n\n private isCurrentSubscription(\n queryId: string,\n subscription: ActiveSubscription,\n connectionId: string,\n ): boolean {\n return (\n !this._disconnected &&\n this._connectionId === connectionId &&\n this._subscriptions.get(queryId) === subscription\n );\n }\n\n private getNextRevision(): number {\n if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n 'SSE hub subscription revision exhausted the safe integer range',\n );\n }\n\n return ++this._nextRevision;\n }\n\n private isValidRevision(revision: number | undefined): revision is number {\n return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;\n }\n\n private sendUnsubscribe(queryId: string, revision: number): void {\n if (!this._connectionId) return;\n\n const body: {\n connectionId: string;\n queryId: string;\n revision?: number;\n } = {\n connectionId: this._connectionId,\n queryId,\n };\n if (this._supportsSubscriptionRevisions) {\n body.revision = revision;\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', queryId, error);\n });\n }\n}\n"],"names":["IDLE_THRESHOLD_FACTOR","ServerSentEventHubConnection","_eventSource","_connectionId","_disconnected","_subscriptions","Map","_pendingSubscriptions","_lastPongLatency","_latencySamples","_connectTimeoutTimer","_nextRevision","_supportsSubscriptionRevisions","_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","revision","getNextRevision","set","ensureConnected","sendSubscribe","unsubscribe","subscription","get","delete","sendUnsubscribe","close","dispose","clear","cancel","stop","clearConnectTimeout","detachAndCloseEventSource","eventSource","onopen","onmessage","onerror","CLOSED","openEventSource","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","eventSourceFactory","log","reset","start","setTimeout","event","recordActivity","handleMessage","data","schedule","clearTimeout","rawData","message","JSON","parse","type","HubMessageType","Connected","handleConnected","QueryResult","handleQueryResult","Ping","Unauthorized","isMessageForCurrentSubscription","handleUnauthorized","Error","error","payload","connectionId","connectionIdChanged","supportsSubscriptionRevisions","applyServerKeepAliveInterval","serverIntervalMs","reconfigure","result","unauthorized","attempt","body","customHeaders","httpHeadersCallback","maxRetries","retryDelayMs","fetch","method","headers","stringify","then","response","ok","isCurrentSubscription","status","catch","isValidRevision","Number","MAX_SAFE_INTEGER","RangeError","isSafeInteger"],"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 type { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport type { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport type { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport {\n type HubMessage,\n HubMessageType,\n type SubscriptionRequest,\n} from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n revision: number;\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 _nextRevision = 0;\n private _supportsSubscriptionRevisions = false;\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(\n keepAliveIntervalMs,\n () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(\n 'SSE hub: no messages received; reconnecting',\n this._keepAlive.idleThresholdMs,\n this._sseUrl,\n );\n this.reconnect();\n }\n },\n keepAliveIntervalMs * IDLE_THRESHOLD_FACTOR,\n );\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get isConnected(): boolean {\n return (\n this._connectionId !== undefined &&\n this._eventSource?.readyState === EventSource.OPEN\n );\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 (\n this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length\n );\n }\n\n /** @inheritdoc */\n subscribe(\n queryId: string,\n request: SubscriptionRequest,\n callback: DataReceived<any>,\n ): void {\n const sub: ActiveSubscription = {\n request,\n callback,\n revision: this.getNextRevision(),\n };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, sub);\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 const subscription = this._subscriptions.get(queryId);\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId && subscription) {\n this.sendUnsubscribe(queryId, subscription.revision);\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.detachAndCloseEventSource();\n this._connectionId = undefined;\n }\n\n private detachAndCloseEventSource(): void {\n const eventSource = this._eventSource;\n if (!eventSource) return;\n\n eventSource.onopen = null;\n eventSource.onmessage = null;\n eventSource.onerror = null;\n eventSource.close();\n\n if (this._eventSource === eventSource) {\n this._eventSource = undefined;\n }\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 // An immediate subscription can win while a back-off callback is pending. Cancel that callback before\n // opening, and let openEventSource perform the same live-source guard for already-queued callbacks.\n this._policy.cancel();\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 this.detachAndCloseEventSource();\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this._policy.cancel();\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._supportsSubscriptionRevisions = false;\n const eventSource = Globals.eventSourceFactory\n ? Globals.eventSourceFactory(url)\n : new EventSource(url);\n this._eventSource = eventSource;\n\n eventSource.onopen = () => {\n if (this._disconnected || this._eventSource !== eventSource) 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 (\n !this._disconnected &&\n this._eventSource === eventSource &&\n !this._connectionId\n ) {\n console.warn(\n 'SSE hub: no Connected message within timeout; retrying',\n this._connectTimeoutMs,\n url,\n );\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected || this._eventSource !== eventSource) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n eventSource.onerror = () => {\n if (this._disconnected || this._eventSource !== eventSource) 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 // Detach before closing so callbacks already queued by the retired source are inert.\n this.detachAndCloseEventSource();\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.ensureConnected();\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 if (this.isMessageForCurrentSubscription(message)) {\n console.warn('SSE hub: query unauthorized', message.queryId);\n this.handleUnauthorized(message);\n }\n break;\n case HubMessageType.Error:\n if (this.isMessageForCurrentSubscription(message)) {\n console.error(\n 'SSE hub: query error',\n message.queryId,\n message.payload,\n );\n }\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 const connectionId = message.payload as string;\n const connectionIdChanged = this._connectionId !== connectionId;\n this._connectionId = connectionId;\n this._supportsSubscriptionRevisions =\n message.supportsSubscriptionRevisions === true;\n console.log('SSE hub: connected', this._connectionId);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n this.applyServerKeepAliveInterval(message.keepAliveIntervalMs);\n\n // The active collection is authoritative. A previous connection's subscribe POST may\n // still be in flight, so relying only on pending subscriptions can orphan a query when\n // the server assigns a new connection ID before that POST completes.\n if (connectionIdChanged) {\n for (const [queryId, subscription] of this._subscriptions) {\n this.sendSubscribe(queryId, subscription);\n }\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(\n serverIntervalMs,\n serverIntervalMs * IDLE_THRESHOLD_FACTOR,\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 || !this.isMessageForCurrentSubscription(message)) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private handleUnauthorized(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub || !this.isMessageForCurrentSubscription(message)) return;\n\n this._subscriptions.delete(message.queryId);\n this._pendingSubscriptions.delete(message.queryId);\n sub.callback(QueryResult.unauthorized());\n }\n\n private sendSubscribe(\n queryId: string,\n subscription: ActiveSubscription,\n attempt: number = 0,\n ): void {\n if (!this._connectionId || this._disconnected) return;\n\n // Capture the connection ID and subscription instance so retries can detect whether\n // either has been replaced while this request is in flight.\n const connectionId = this._connectionId;\n\n const body: {\n connectionId: string;\n queryId: string;\n request: SubscriptionRequest;\n revision?: number;\n } = {\n connectionId,\n queryId,\n request: subscription.request,\n };\n if (this._supportsSubscriptionRevisions) {\n body.revision = subscription.revision;\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 })\n .then((response) => {\n if (!response.ok) {\n if (\n !this.isCurrentSubscription(queryId, subscription, connectionId)\n ) {\n console.warn(\n 'SSE hub: subscribe POST returned a failure for an obsolete connection or subscription; ignoring',\n queryId,\n response.status,\n );\n } else if (attempt < maxRetries) {\n setTimeout(\n () => {\n if (\n this.isCurrentSubscription(\n queryId,\n subscription,\n connectionId,\n )\n ) {\n this.sendSubscribe(\n queryId,\n subscription,\n attempt + 1,\n );\n }\n },\n retryDelayMs * (attempt + 1),\n );\n } else {\n console.warn(\n 'SSE hub: subscribe POST failed after retries; reconnecting',\n queryId,\n response.status,\n attempt + 1,\n );\n this.reconnect();\n }\n }\n })\n .catch((error) => {\n if (!this.isCurrentSubscription(queryId, subscription, connectionId)) {\n console.warn(\n 'SSE hub: subscribe POST failed for an obsolete connection or subscription; ignoring',\n queryId,\n error,\n );\n } else if (attempt < maxRetries) {\n setTimeout(\n () => {\n if (\n this.isCurrentSubscription(\n queryId,\n subscription,\n connectionId,\n )\n ) {\n this.sendSubscribe(queryId, subscription, attempt + 1);\n }\n },\n retryDelayMs * (attempt + 1),\n );\n } else {\n console.error(\n 'SSE hub: subscribe POST failed after retries; reconnecting',\n queryId,\n attempt + 1,\n error,\n );\n this.reconnect();\n }\n });\n }\n\n private isMessageForCurrentSubscription(message: HubMessage): boolean {\n if (!message.queryId) return false;\n\n const subscription = this._subscriptions.get(message.queryId);\n if (!subscription) return false;\n\n if (!this._supportsSubscriptionRevisions) {\n return message.revision === undefined;\n }\n\n return (\n this.isValidRevision(message.revision) &&\n message.revision === subscription.revision\n );\n }\n\n private isCurrentSubscription(\n queryId: string,\n subscription: ActiveSubscription,\n connectionId: string,\n ): boolean {\n return (\n !this._disconnected &&\n this._connectionId === connectionId &&\n this._subscriptions.get(queryId) === subscription\n );\n }\n\n private getNextRevision(): number {\n if (this._nextRevision >= Number.MAX_SAFE_INTEGER) {\n throw new RangeError(\n 'SSE hub subscription revision exhausted the safe integer range',\n );\n }\n\n return ++this._nextRevision;\n }\n\n private isValidRevision(revision: number | undefined): revision is number {\n return revision !== undefined && Number.isSafeInteger(revision) && revision > 0;\n }\n\n private sendUnsubscribe(queryId: string, revision: number): void {\n if (!this._connectionId) return;\n\n const body: {\n connectionId: string;\n queryId: string;\n revision?: number;\n } = {\n connectionId: this._connectionId,\n queryId,\n };\n if (this._supportsSubscriptionRevisions) {\n body.revision = revision;\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', queryId, error);\n });\n }\n}\n"],"names":["IDLE_THRESHOLD_FACTOR","ServerSentEventHubConnection","_eventSource","_connectionId","_disconnected","_subscriptions","Map","_pendingSubscriptions","_lastPongLatency","_latencySamples","_connectTimeoutTimer","_nextRevision","_supportsSubscriptionRevisions","_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","revision","getNextRevision","set","ensureConnected","sendSubscribe","unsubscribe","subscription","get","delete","sendUnsubscribe","close","dispose","clear","cancel","stop","clearConnectTimeout","detachAndCloseEventSource","eventSource","onopen","onmessage","onerror","CLOSED","openEventSource","url","param","Globals","microserviceWSQueryArgument","encodeURIComponent","includes","eventSourceFactory","log","reset","start","setTimeout","event","recordActivity","handleMessage","data","schedule","clearTimeout","rawData","message","JSON","parse","type","HubMessageType","Connected","handleConnected","QueryResult","handleQueryResult","Ping","Unauthorized","isMessageForCurrentSubscription","handleUnauthorized","Error","error","payload","connectionId","connectionIdChanged","supportsSubscriptionRevisions","applyServerKeepAliveInterval","serverIntervalMs","reconfigure","result","unauthorized","attempt","body","customHeaders","httpHeadersCallback","maxRetries","retryDelayMs","fetch","method","headers","stringify","then","response","ok","isCurrentSubscription","status","catch","isValidRevision","Number","MAX_SAFE_INTEGER","RangeError","isSafeInteger"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServerSentEventQueryConnection.js","sources":["../../../queries/ServerSentEventQueryConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { QueryResult } from './QueryResult';\n\n/**\n * The SSE demultiplexer route used when connecting through the multiplexed observable query endpoint.\n */\nexport const SSE_HUB_ROUTE = '/.cratis/queries/sse';\n\n/**\n * Represents a direct Server-Sent Events (SSE) connection for a single observable query.\n *\n * In direct mode the URL points to the per-query endpoint (e.g. `/api/queries/latest`).\n * The backend detects the `Accept: text/event-stream` header and streams results directly.\n *\n * The caller (typically {@link createObservableQueryConnection}) decides which URL to use;\n * this class is transport-agnostic beyond being SSE.\n */\nexport class ServerSentEventQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n private _eventSource?: EventSource;\n private _disconnected = false;\n private _unauthorized = false;\n\n /** @inheritdoc */\n readonly lastPingLatency: number = 0;\n\n /** @inheritdoc */\n readonly averageLatency: number = 0;\n\n /**\n * Initializes a new instance of {@link ServerSentEventQueryConnection}.\n * @param {URL} url The fully qualified URL of the SSE endpoint (including query parameters).\n */\n constructor(private readonly _url: URL) {}\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object): void {\n if (this._disconnected || this._unauthorized) return;\n\n // Guard against environments where EventSource is not available (e.g. Node.js, SSR)\n // and no custom factory has been supplied to substitute it.\n if (!Globals.eventSourceFactory && typeof EventSource === 'undefined') {\n return;\n }\n\n let url = this._url.toString();\n if (queryArguments) {\n const separator = url.includes('?') ? '&' : '?';\n const query = Object.entries(queryArguments)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)\n .join('&');\n if (query) {\n url = `${url}${separator}${query}`;\n }\n }\n\n this._eventSource = Globals.eventSourceFactory ? Globals.eventSourceFactory(url) : new EventSource(url);\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n try {\n const result = JSON.parse(event.data as string) as QueryResult<TDataType>;\n if ((result as unknown as { isAuthorized?: boolean })?.isAuthorized === false) {\n this.handleUnauthorized(url, result, dataReceived);\n return;\n }\n dataReceived(result);\n } catch (error) {\n console.error('SSE: error parsing message', error);\n }\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected || this._unauthorized) return;\n console.warn(`SSE: connection error for '${url}', EventSource will retry automatically.`);\n };\n }\n\n /** @inheritdoc */\n disconnect(): void {\n if (this._disconnected) return;\n this._disconnected = true;\n this._eventSource?.close();\n this._eventSource = undefined;\n }\n\n /**\n * Handles the terminal result the server sends when the caller is no longer authorized for the query it is\n * subscribed to.\n *\n * Unlike a WebSocket, an `EventSource` re-establishes a stream the server ended - the server closing its response\n * is precisely the signal the browser retries on, roughly every three seconds. Each retry re-runs the whole query\n * pipeline server side just to be denied again, so the stream is only actually terminal if this client closes it.\n * @param {string} url The stream url, for diagnostics.\n * @param {QueryResult<TDataType>} result The unauthorized result to deliver.\n * @param {DataReceived<TDataType>} dataReceived Callback that receives the result.\n */\n private handleUnauthorized(url: string, result: QueryResult<TDataType>, dataReceived: DataReceived<TDataType>): void {\n console.warn(`SSE: stream for '${url}' was ended by the server - no longer authorized`);\n this._unauthorized = true;\n this._eventSource?.close();\n this._eventSource = undefined;\n dataReceived(result);\n }\n}\n"],"names":["SSE_HUB_ROUTE","ServerSentEventQueryConnection","_eventSource","_disconnected","_unauthorized","lastPingLatency","averageLatency","_url","connect","dataReceived","queryArguments","Globals","eventSourceFactory","EventSource","url","toString","separator","includes","query","Object","entries","filter","value","undefined","map","key","encodeURIComponent","String","join","onmessage","event","result","JSON","parse","data","isAuthorized","handleUnauthorized","error","console","onerror","warn","disconnect","close"],"mappings":";;AAAA;AACA;AAOA;;IAGO,MAAMA,aAAAA,GAAgB;AAE7B;;;;;;;;AAQC,IACM,MAAMC,8BAAAA,CAAAA;;IACDC,YAAAA;AACAC,IAAAA,aAAAA,GAAgB,KAAA;AAChBC,IAAAA,aAAAA,GAAgB,KAAA;uBAGxB,eAASC,GAA0B,CAAA;uBAGnC,cAASC,GAAyB,CAAA;AAElC;;;QAIA,WAAA,CAAY,IAA0B,CAAE;aAAXC,IAAAA,GAAAA,IAAAA;AAAY,IAAA;AAEzC,uBACAC,OAAAA,CAAQC,YAAqC,EAAEC,cAAuB,EAAQ;AAC1E,QAAA,IAAI,IAAI,CAACP,aAAa,IAAI,IAAI,CAACC,aAAa,EAAE;;;AAI9C,QAAA,IAAI,CAACO,OAAAA,CAAQC,kBAAkB,IAAI,OAAOC,gBAAgB,WAAA,EAAa;AACnE,YAAA;AACJ,QAAA;AAEA,QAAA,IAAIC,GAAAA,GAAM,IAAI,CAACP,IAAI,CAACQ,QAAQ,EAAA;AAC5B,QAAA,IAAIL,cAAAA,EAAgB;AAChB,YAAA,MAAMM,SAAAA,GAAYF,GAAAA,CAAIG,QAAQ,CAAC,OAAO,GAAA,GAAM,GAAA;AAC5C,YAAA,MAAMC,KAAAA,GAAQC,MAAAA,CAAOC,OAAO,CAACV,gBACxBW,MAAM,CAAC,CAAC,GAAGC,KAAAA,CAAM,GAAKA,KAAAA,KAAUC,SAAAA,IAAaD,UAAU,IAAA,CAAA,CACvDE,GAAG,CAAC,CAAC,CAACC,GAAAA,EAAKH,KAAAA,CAAM,GAAK,GAAGI,kBAAAA,CAAmBD,GAAAA,CAAAA,CAAK,CAAC,EAAEC,kBAAAA,CAAmBC,MAAAA,CAAOL,KAAAA,CAAAA,CAAAA,CAAAA,CAAS,CAAA,CACvFM,IAAI,CAAC,GAAA,CAAA;AACV,YAAA,IAAIV,KAAAA,EAAO;gBACPJ,GAAAA,GAAM,CAAA,EAAGA,GAAAA,CAAAA,EAAME,SAAAA,CAAAA,EAAYE,KAAAA,CAAAA,CAAO;AACtC,YAAA;AACJ,QAAA;QAEA,IAAI,CAAChB,YAAY,GAAGS,OAAAA,CAAQC,kBAAkB,GAAGD,OAAAA,CAAQC,kBAAkB,CAACE,GAAAA,CAAAA,GAAO,IAAID,WAAAA,CAAYC,GAAAA,CAAAA;AAEnG,QAAA,IAAI,CAACZ,YAAY,CAAC2B,SAAS,GAAG,CAACC,KAAAA,GAAAA;YAC3B,IAAI,IAAI,CAAC3B,aAAa,EAAE;YACxB,IAAI;AACA,gBAAA,MAAM4B,MAAAA,GAASC,IAAAA,CAAKC,KAAK,CAACH,MAAMI,IAAI,CAAA;gBACpC,IAAKH,MAAAA,EAAkDI,YAAAA,KAAiB,KAAA,EAAO;AAC3E,oBAAA,IAAI,CAACC,kBAAkB,CAACtB,GAAAA,EAAKiB,MAAAA,EAAQtB,YAAAA,CAAAA;AACrC,oBAAA;AACJ,gBAAA;gBACAA,YAAAA,CAAasB,MAAAA,CAAAA;AACjB,YAAA,CAAA,CAAE,OAAOM,KAAAA,EAAO;gBACZC,OAAAA,CAAQD,KAAK,CAAC,4BAAA,EAA8BA,KAAAA,CAAAA;AAChD,YAAA;AACJ,QAAA,CAAA;AAEA,QAAA,IAAI,CAACnC,YAAY,CAACqC,OAAO,GAAG,IAAA;AACxB,YAAA,IAAI,IAAI,CAACpC,aAAa,IAAI,IAAI,CAACC,aAAa,EAAE;AAC9CkC,YAAAA,OAAAA,CAAQE,IAAI,CAAC,CAAC,2BAA2B,EAAE1B,GAAAA,CAAI,wCAAwC,CAAC,CAAA;AAC5F,QAAA,CAAA;AACJ,IAAA;AAEA,uBACA2B,UAAAA,GAAmB;QACf,IAAI,IAAI,CAACtC,aAAa,EAAE;QACxB,IAAI,CAACA,aAAa,GAAG,IAAA;QACrB,IAAI,CAACD,YAAY,EAAEwC,KAAAA,EAAAA;QACnB,IAAI,CAACxC,YAAY,GAAGqB,SAAAA;AACxB,IAAA;AAEA;;;;;;;;;;AAUC,QACD,kBAAQa,CAAmBtB,GAAW,EAAEiB,MAA8B,EAAEtB,YAAqC,EAAQ;AACjH6B,QAAAA,OAAAA,CAAQE,IAAI,CAAC,CAAC,iBAAiB,EAAE1B,GAAAA,CAAI,gDAAgD,CAAC,CAAA;QACtF,IAAI,CAACV,aAAa,GAAG,IAAA;QACrB,IAAI,CAACF,YAAY,EAAEwC,KAAAA,EAAAA;QACnB,IAAI,CAACxC,YAAY,GAAGqB,SAAAA;QACpBd,YAAAA,CAAasB,MAAAA,CAAAA;AACjB,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"ServerSentEventQueryConnection.js","sources":["../../../queries/ServerSentEventQueryConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryConnection } from './IObservableQueryConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { QueryResult } from './QueryResult';\n\n/**\n * The SSE demultiplexer route used when connecting through the multiplexed observable query endpoint.\n */\nexport const SSE_HUB_ROUTE = '/.cratis/queries/sse';\n\n/**\n * Represents a direct Server-Sent Events (SSE) connection for a single observable query.\n *\n * In direct mode the URL points to the per-query endpoint (e.g. `/api/queries/latest`).\n * The backend detects the `Accept: text/event-stream` header and streams results directly.\n *\n * The caller (typically {@link createObservableQueryConnection}) decides which URL to use;\n * this class is transport-agnostic beyond being SSE.\n */\nexport class ServerSentEventQueryConnection<TDataType> implements IObservableQueryConnection<TDataType> {\n private _eventSource?: EventSource;\n private _disconnected = false;\n private _unauthorized = false;\n\n /** @inheritdoc */\n readonly lastPingLatency: number = 0;\n\n /** @inheritdoc */\n readonly averageLatency: number = 0;\n\n /**\n * Initializes a new instance of {@link ServerSentEventQueryConnection}.\n * @param {URL} url The fully qualified URL of the SSE endpoint (including query parameters).\n */\n constructor(private readonly _url: URL) {}\n\n /** @inheritdoc */\n connect(dataReceived: DataReceived<TDataType>, queryArguments?: object): void {\n if (this._disconnected || this._unauthorized) return;\n\n // Guard against environments where EventSource is not available (e.g. Node.js, SSR)\n // and no custom factory has been supplied to substitute it.\n if (!Globals.eventSourceFactory && typeof EventSource === 'undefined') {\n return;\n }\n\n let url = this._url.toString();\n if (queryArguments) {\n const separator = url.includes('?') ? '&' : '?';\n const query = Object.entries(queryArguments)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)\n .join('&');\n if (query) {\n url = `${url}${separator}${query}`;\n }\n }\n\n this._eventSource = Globals.eventSourceFactory ? Globals.eventSourceFactory(url) : new EventSource(url);\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n try {\n const result = JSON.parse(event.data as string) as QueryResult<TDataType>;\n if ((result as unknown as { isAuthorized?: boolean })?.isAuthorized === false) {\n this.handleUnauthorized(url, result, dataReceived);\n return;\n }\n dataReceived(result);\n } catch (error) {\n console.error('SSE: error parsing message', error);\n }\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected || this._unauthorized) return;\n console.warn(`SSE: connection error for '${url}', EventSource will retry automatically.`);\n };\n }\n\n /** @inheritdoc */\n disconnect(): void {\n if (this._disconnected) return;\n this._disconnected = true;\n this._eventSource?.close();\n this._eventSource = undefined;\n }\n\n /**\n * Handles the terminal result the server sends when the caller is no longer authorized for the query it is\n * subscribed to.\n *\n * Unlike a WebSocket, an `EventSource` re-establishes a stream the server ended - the server closing its response\n * is precisely the signal the browser retries on, roughly every three seconds. Each retry re-runs the whole query\n * pipeline server side just to be denied again, so the stream is only actually terminal if this client closes it.\n * @param {string} url The stream url, for diagnostics.\n * @param {QueryResult<TDataType>} result The unauthorized result to deliver.\n * @param {DataReceived<TDataType>} dataReceived Callback that receives the result.\n */\n private handleUnauthorized(url: string, result: QueryResult<TDataType>, dataReceived: DataReceived<TDataType>): void {\n console.warn(`SSE: stream for '${url}' was ended by the server - no longer authorized`);\n this._unauthorized = true;\n this._eventSource?.close();\n this._eventSource = undefined;\n dataReceived(result);\n }\n}\n"],"names":["SSE_HUB_ROUTE","ServerSentEventQueryConnection","_eventSource","_disconnected","_unauthorized","lastPingLatency","averageLatency","_url","connect","dataReceived","queryArguments","Globals","eventSourceFactory","EventSource","url","toString","separator","includes","query","Object","entries","filter","value","undefined","map","key","encodeURIComponent","String","join","onmessage","event","result","JSON","parse","data","isAuthorized","handleUnauthorized","error","console","onerror","warn","disconnect","close"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SortDirection.js","sources":["../../../queries/SortDirection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Defines the direction of sorting.\n */\nexport enum SortDirection {\n /**\n * Unspecified sort direction.\n */\n unspecified = 0,\n\n /**\n * Sort in ascending order.\n */\n ascending = 1,\n\n /**\n * Sort in descending order.\n */\n descending = 2,\n}"],"names":["SortDirection"],"mappings":"AAAA;AACA;AAEA;;IAGO,IAAKA,aAAAA,iBAAAA,SAAAA,aAAAA,EAAAA;AACR;;QAEC,aAAA,CAAA,aAAA,CAAA,aAAA,CAAA,GACa,CAAA,CAAA,GAAA,aAAA;AAEd;;QAEC,aAAA,CAAA,aAAA,CAAA,WAAA,CAAA,GACW,CAAA,CAAA,GAAA,WAAA;AAEZ;;QAEC,aAAA,CAAA,aAAA,CAAA,YAAA,CAAA,GACY,CAAA,CAAA,GAAA,YAAA;AAdLA,IAAAA,OAAAA,aAAAA;AAeX,CAAA,CAAA,EAAA;;;;"}
1
+ {"version":3,"file":"SortDirection.js","sources":["../../../queries/SortDirection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * Defines the direction of sorting.\n */\nexport enum SortDirection {\n /**\n * Unspecified sort direction.\n */\n unspecified = 0,\n\n /**\n * Sort in ascending order.\n */\n ascending = 1,\n\n /**\n * Sort in descending order.\n */\n descending = 2,\n}"],"names":["SortDirection"],"mappings":"AAAA;AACA;AAEA;;IAGO,IAAKA,aAAAA,iBAAAA,SAAAA,aAAAA,EAAAA;AACR;;QAEC,aAAA,CAAA,aAAA,CAAA,aAAA,CAAA,GACa,CAAA,CAAA,GAAA,aAAA;AAEd;;QAEC,aAAA,CAAA,aAAA,CAAA,WAAA,CAAA,GACW,CAAA,CAAA,GAAA,WAAA;AAEZ;;QAEC,aAAA,CAAA,aAAA,CAAA,YAAA,CAAA,GACY,CAAA,CAAA,GAAA,YAAA;AAdLA,IAAAA,OAAAA,aAAAA;AAeX,CAAA,CAAA,EAAA;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sorting.js","sources":["../../../queries/Sorting.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 { SortDirection } from './SortDirection';\n\n/**\n * Represents sorting for a query.\n */\nexport class Sorting {\n\n /**\n * No sorting.\n */\n static none: Sorting = new Sorting('', SortDirection.ascending);\n\n /**\n * Initializes a new instance of the {@link Sorting} class.\n * @param {string} field The field to sort by.\n * @param {SortDirection} direction The {@link SortDirection} to sort by.\n */\n constructor(readonly field: string, readonly direction: SortDirection) {\n }\n\n /**\n * Gets whether sorting is enabled.\n */\n get hasSorting(): boolean {\n return this.field !== '';\n }\n}"],"names":["Sorting","none","SortDirection","ascending","direction","field","hasSorting"],"mappings":";;AAAA;AACA;AAIA;;AAEC,IACM,MAAMA,OAAAA,CAAAA;;;AAET;;AAEC,QACD,OAAOC,IAAAA,GAAgB,IAAID,QAAQ,EAAA,EAAIE,aAAAA,CAAcC,SAAS,CAAA;AAE9D;;;;AAIC,QACD,YAAY,KAAsB,EAAWC,SAAwB,CAAE;aAAlDC,KAAAA,GAAAA,KAAAA;aAAwBD,SAAAA,GAAAA,SAAAA;AAC7C,IAAA;AAEA;;AAEC,QACD,IAAIE,UAAAA,GAAsB;QACtB,OAAO,IAAI,CAACD,KAAK,KAAK,EAAA;AAC1B,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"Sorting.js","sources":["../../../queries/Sorting.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 { SortDirection } from './SortDirection';\n\n/**\n * Represents sorting for a query.\n */\nexport class Sorting {\n\n /**\n * No sorting.\n */\n static none: Sorting = new Sorting('', SortDirection.ascending);\n\n /**\n * Initializes a new instance of the {@link Sorting} class.\n * @param {string} field The field to sort by.\n * @param {SortDirection} direction The {@link SortDirection} to sort by.\n */\n constructor(readonly field: string, readonly direction: SortDirection) {\n }\n\n /**\n * Gets whether sorting is enabled.\n */\n get hasSorting(): boolean {\n return this.field !== '';\n }\n}"],"names":["Sorting","none","SortDirection","ascending","direction","field","hasSorting"],"mappings":";;AAAA;AACA;AAIA;;AAEC,IACM,MAAMA,OAAAA,CAAAA;;;AAET;;AAEC,QACD,OAAOC,IAAAA,GAAgB,IAAID,QAAQ,EAAA,EAAIE,aAAAA,CAAcC,SAAS,CAAA;AAE9D;;;;AAIC,QACD,YAAY,KAAsB,EAAWC,SAAwB,CAAE;aAAlDC,KAAAA,GAAAA,KAAAA;aAAwBD,SAAAA,GAAAA,SAAAA;AAC7C,IAAA;AAEA;;AAEC,QACD,IAAIE,UAAAA,GAAsB;QACtB,OAAO,IAAI,CAACD,KAAK,KAAK,EAAA;AAC1B,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SortingActions.js","sources":["../../../queries/SortingActions.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 { SortDirection } from './SortDirection';\nimport { Sorting } from './Sorting';\n\n/**\n * Represents sorting for a query.\n */\nexport class SortingActions {\n private readonly _ascending: Sorting;\n private readonly _descending: Sorting;\n\n /**\n * Initializes a new instance of {@link SortingActions}.\n * @param {string} field The field that the sorting represents.\n */\n constructor(readonly field: string) { \n this._ascending = new Sorting(this.field, SortDirection.ascending);\n this._descending = new Sorting(this.field, SortDirection.descending);\n }\n\n /**\n * Returns ascending sort for the field.\n */\n get ascending(): Sorting {\n return this._ascending;\n }\n\n /**\n * Returns ascending sort for the field.\n */\n get descending(): Sorting {\n return this._descending;\n }\n}\n"],"names":["SortingActions","_ascending","_descending","field","Sorting","SortDirection","ascending","descending"],"mappings":";;;AAAA;AACA;AAKA;;AAEC,IACM,MAAMA,cAAAA,CAAAA;;IACQC,UAAAA;IACAC,WAAAA;AAEjB;;;QAIA,WAAA,CAAY,KAAsB,CAAE;aAAfC,KAAAA,GAAAA,KAAAA;QACjB,IAAI,CAACF,UAAU,GAAG,IAAIG,OAAAA,CAAQ,IAAI,CAACD,KAAK,EAAEE,aAAAA,CAAcC,SAAS,CAAA;QACjE,IAAI,CAACJ,WAAW,GAAG,IAAIE,OAAAA,CAAQ,IAAI,CAACD,KAAK,EAAEE,aAAAA,CAAcE,UAAU,CAAA;AACvE,IAAA;AAEA;;AAEE,SACF,IAAID,SAAAA,GAAqB;QACrB,OAAO,IAAI,CAACL,UAAU;AAC1B,IAAA;AAEA;;AAEE,SACF,IAAIM,UAAAA,GAAsB;QACtB,OAAO,IAAI,CAACL,WAAW;AAC3B,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"SortingActions.js","sources":["../../../queries/SortingActions.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 { SortDirection } from './SortDirection';\nimport { Sorting } from './Sorting';\n\n/**\n * Represents sorting for a query.\n */\nexport class SortingActions {\n private readonly _ascending: Sorting;\n private readonly _descending: Sorting;\n\n /**\n * Initializes a new instance of {@link SortingActions}.\n * @param {string} field The field that the sorting represents.\n */\n constructor(readonly field: string) { \n this._ascending = new Sorting(this.field, SortDirection.ascending);\n this._descending = new Sorting(this.field, SortDirection.descending);\n }\n\n /**\n * Returns ascending sort for the field.\n */\n get ascending(): Sorting {\n return this._ascending;\n }\n\n /**\n * Returns ascending sort for the field.\n */\n get descending(): Sorting {\n return this._descending;\n }\n}\n"],"names":["SortingActions","_ascending","_descending","field","Sorting","SortDirection","ascending","descending"],"mappings":";;;AAAA;AACA;AAKA;;AAEC,IACM,MAAMA,cAAAA,CAAAA;;IACQC,UAAAA;IACAC,WAAAA;AAEjB;;;QAIA,WAAA,CAAY,KAAsB,CAAE;aAAfC,KAAAA,GAAAA,KAAAA;QACjB,IAAI,CAACF,UAAU,GAAG,IAAIG,OAAAA,CAAQ,IAAI,CAACD,KAAK,EAAEE,aAAAA,CAAcC,SAAS,CAAA;QACjE,IAAI,CAACJ,WAAW,GAAG,IAAIE,OAAAA,CAAQ,IAAI,CAACD,KAAK,EAAEE,aAAAA,CAAcE,UAAU,CAAA;AACvE,IAAA;AAEA;;AAEE,SACF,IAAID,SAAAA,GAAqB;QACrB,OAAO,IAAI,CAACL,UAAU;AAC1B,IAAA;AAEA;;AAEE,SACF,IAAIM,UAAAA,GAAsB;QACtB,OAAO,IAAI,CAACL,WAAW;AAC3B,IAAA;AACJ;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SortingActionsForObservableQuery.js","sources":["../../../queries/SortingActionsForObservableQuery.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 { IObservableQueryFor } from './IObservableQueryFor';\nimport { SortDirection } from './SortDirection';\nimport { Sorting } from './Sorting';\n\n/**\n * Represents sorting for an observable query.\n */\nexport class SortingActionsForObservableQuery<TDataType, TArguments = object> {\n\n /**\n * Initializes a new instance of {@link SortingActionsForQuery}.\n * @param {string} field The field that the sorting represents.\n * @param {IQueryFor<TDataType, TArguments>} query The query that holds the field.\n */\n constructor(readonly field: string, readonly query: IObservableQueryFor<TDataType, TArguments>) {\n }\n\n /**\n * Instructs query to sort ascending for the field.\n */\n ascending(): Sorting {\n this.query.sorting = new Sorting(this.field, SortDirection.ascending);\n return this.query.sorting;\n }\n\n /**\n * Instructs query to sort ascending for the field.\n */\n descending(): Sorting {\n this.query.sorting = new Sorting(this.field, SortDirection.descending);\n return this.query.sorting;\n }\n}\n"],"names":["SortingActionsForObservableQuery","query","field","ascending","sorting","Sorting","SortDirection","descending"],"mappings":";;;AAAA;AACA;AAMA;;AAEC,IACM,MAAMA,gCAAAA,CAAAA;;;AAET;;;;AAIC,QACD,YAAY,KAAsB,EAAWC,KAAiD,CAAE;aAA3EC,KAAAA,GAAAA,KAAAA;aAAwBD,KAAAA,GAAAA,KAAAA;AAC7C,IAAA;AAEA;;AAEE,SACFE,SAAAA,GAAqB;AACjB,QAAA,IAAI,CAACF,KAAK,CAACG,OAAO,GAAG,IAAIC,OAAAA,CAAQ,IAAI,CAACH,KAAK,EAAEI,aAAAA,CAAcH,SAAS,CAAA;AACpE,QAAA,OAAO,IAAI,CAACF,KAAK,CAACG,OAAO;AAC7B,IAAA;AAEA;;AAEE,SACFG,UAAAA,GAAsB;AAClB,QAAA,IAAI,CAACN,KAAK,CAACG,OAAO,GAAG,IAAIC,OAAAA,CAAQ,IAAI,CAACH,KAAK,EAAEI,aAAAA,CAAcC,UAAU,CAAA;AACrE,QAAA,OAAO,IAAI,CAACN,KAAK,CAACG,OAAO;AAC7B,IAAA;AACJ;;;;"}
1
+ {"version":3,"file":"SortingActionsForObservableQuery.js","sources":["../../../queries/SortingActionsForObservableQuery.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 { IObservableQueryFor } from './IObservableQueryFor';\nimport { SortDirection } from './SortDirection';\nimport { Sorting } from './Sorting';\n\n/**\n * Represents sorting for an observable query.\n */\nexport class SortingActionsForObservableQuery<TDataType, TArguments = object> {\n\n /**\n * Initializes a new instance of {@link SortingActionsForQuery}.\n * @param {string} field The field that the sorting represents.\n * @param {IQueryFor<TDataType, TArguments>} query The query that holds the field.\n */\n constructor(readonly field: string, readonly query: IObservableQueryFor<TDataType, TArguments>) {\n }\n\n /**\n * Instructs query to sort ascending for the field.\n */\n ascending(): Sorting {\n this.query.sorting = new Sorting(this.field, SortDirection.ascending);\n return this.query.sorting;\n }\n\n /**\n * Instructs query to sort ascending for the field.\n */\n descending(): Sorting {\n this.query.sorting = new Sorting(this.field, SortDirection.descending);\n return this.query.sorting;\n }\n}\n"],"names":["SortingActionsForObservableQuery","query","field","ascending","sorting","Sorting","SortDirection","descending"],"mappings":";;;AAAA;AACA;AAMA;;AAEC,IACM,MAAMA,gCAAAA,CAAAA;;;AAET;;;;AAIC,QACD,YAAY,KAAsB,EAAWC,KAAiD,CAAE;aAA3EC,KAAAA,GAAAA,KAAAA;aAAwBD,KAAAA,GAAAA,KAAAA;AAC7C,IAAA;AAEA;;AAEE,SACFE,SAAAA,GAAqB;AACjB,QAAA,IAAI,CAACF,KAAK,CAACG,OAAO,GAAG,IAAIC,OAAAA,CAAQ,IAAI,CAACH,KAAK,EAAEI,aAAAA,CAAcH,SAAS,CAAA;AACpE,QAAA,OAAO,IAAI,CAACF,KAAK,CAACG,OAAO;AAC7B,IAAA;AAEA;;AAEE,SACFG,UAAAA,GAAsB;AAClB,QAAA,IAAI,CAACN,KAAK,CAACG,OAAO,GAAG,IAAIC,OAAAA,CAAQ,IAAI,CAACH,KAAK,EAAEI,aAAAA,CAAcC,UAAU,CAAA;AACrE,QAAA,OAAO,IAAI,CAACN,KAAK,CAACG,OAAO;AAC7B,IAAA;AACJ;;"}