@equinor/fusion-framework-vite-plugin-spa 5.1.0 → 5.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
- import { c as createErrorClass, _ as __extends, e as errorContext, E as EMPTY_SUBSCRIPTION, S as Subscription, a as arrRemove, O as Observable, b as __values, d as __spreadArray, f as __read, i as isFunction$1, g as SafeSubscriber, h as EmptyError, o as operate, j as executeSchedule, k as innerFrom, l as createOperatorSubscriber, m as map, n as mergeMap, p as identity, q as isArrayLike, r as isScheduler, s as popScheduler, t as popNumber, u as EMPTY, v as from, w as mergeInternals, x as scanInternals, y as noop, z as popResultSelector, A as reduce, B as lastValueFrom, M as ModuleEventLevel, C as filter, D as BaseModuleProvider, F as catchError, G as of, H as object, I as _instanceof, J as _enum, K as string, L as boolean, N as record, P as union, Q as __rest, R as __assign, T as switchMap, U as observeOn, V as deepmerge, W as BaseConfigBuilder, X as TelemetryExceptionSchema, Y as TelemetryItemNames, Z as TelemetryType, $ as TelemetryEventSchema, a0 as TelemetryMetricSchema, a1 as TelemetryCustomEventSchema, a2 as array, a3 as TelemetryLevel, a4 as enableMSAL } from '../module-DzjJ4gjy.js';
1
+ import { c as createErrorClass, _ as __extends, e as errorContext, E as EMPTY_SUBSCRIPTION, S as Subscription, O as Observable, a as __values, b as arrRemove, d as __spreadArray, f as __read, i as isFunction$1, g as SafeSubscriber, h as EmptyError, o as operate, j as executeSchedule, k as innerFrom, l as createOperatorSubscriber, m as map, n as mergeMap, p as identity, q as isArrayLike, r as isScheduler, s as popScheduler, t as popNumber, u as EMPTY, v as from, w as mergeInternals, x as scanInternals, y as noop, z as popResultSelector, A as reduce, B as lastValueFrom, M as ModuleEventLevel, C as filter, D as BaseModuleProvider, F as catchError, G as of, H as object, I as _instanceof, J as _enum, K as string, L as boolean, N as record, P as union, Q as __rest, R as __assign, T as switchMap, U as observeOn, V as deepmerge, W as BaseConfigBuilder, X as TelemetryExceptionSchema, Y as TelemetryItemNames, Z as TelemetryType, $ as TelemetryEventSchema, a0 as TelemetryMetricSchema, a1 as TelemetryCustomEventSchema, a2 as array, a3 as TelemetryLevel, a4 as enableMSAL } from '../module-BR47HvRl.js';
2
+ import { B as BaseTelemetryAdapter } from '../TelemetryAdapter-B6JH_RXA.js';
2
3
 
3
4
  var ObjectUnsubscribedError = createErrorClass(function (_super) {
4
5
  return function ObjectUnsubscribedErrorImpl() {
@@ -1830,7 +1831,7 @@ async function runDisposePhase(ctx, instance, ref) {
1830
1831
  }
1831
1832
 
1832
1833
  // Generated by genversion.
1833
- const version$4 = '6.1.4';
1834
+ const version$4 = '6.1.5';
1834
1835
 
1835
1836
  // biome-ignore-all lint/suspicious/noExplicitAny: internal type-erased dispatch arrays — callbacks are registered with concrete module types but stored erased; the orchestrator never inspects these shapes itself
1836
1837
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -2993,7 +2994,7 @@ class HttpClientConfigurator {
2993
2994
  }
2994
2995
 
2995
2996
  // Generated by genversion.
2996
- const version$3 = '8.1.2';
2997
+ const version$3 = '8.1.3';
2997
2998
 
2998
2999
  /** URL protocols accepted as valid ad-hoc base URIs. */
2999
3000
  const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ws:', 'wss:'];
@@ -4273,7 +4274,7 @@ var objectTraps = {
4273
4274
  const currentState = current2?.[DRAFT_STATE];
4274
4275
  if (currentState && currentState.base_ === value) {
4275
4276
  state.copy_[prop] = value;
4276
- state.assigned_.set(prop, false);
4277
+ state.assigned_.delete(prop);
4277
4278
  return true;
4278
4279
  }
4279
4280
  if (is(value, current2) && (value !== void 0 || has(state.base_, prop, state.type_)))
@@ -5354,7 +5355,7 @@ class TelemetryConfigurator extends BaseConfigBuilder {
5354
5355
  }
5355
5356
 
5356
5357
  // Generated by genversion.
5357
- const version$2 = '7.1.2';
5358
+ const version$2 = '7.2.1';
5358
5359
 
5359
5360
  /**
5360
5361
  * Represents a framework event with customizable details and behavior.
@@ -5745,7 +5746,9 @@ const applyMetadata = (metadata, args) => {
5745
5746
  class TelemetryProvider extends BaseModuleProvider {
5746
5747
  #items = new Subject();
5747
5748
  #initialized = false;
5749
+ #disposal;
5748
5750
  #adapters = {};
5751
+ #handledByChild = new WeakSet();
5749
5752
  #filters;
5750
5753
  #defaultScope;
5751
5754
  #eventProvider;
@@ -5830,6 +5833,51 @@ class TelemetryProvider extends BaseModuleProvider {
5830
5833
  this.#items.complete();
5831
5834
  });
5832
5835
  }
5836
+ /**
5837
+ * Stops telemetry subscriptions and waits for every adapter to flush and shut down.
5838
+ *
5839
+ * Repeated calls share the same completion promise so exporters are shut down only once.
5840
+ * The telemetry module awaits this promise during framework module disposal.
5841
+ *
5842
+ * @returns Resolves after all adapter shutdowns settle.
5843
+ * @throws {AggregateError} When any adapter fails to shut down; all adapters are still attempted.
5844
+ * @example
5845
+ * ```ts
5846
+ * await provider.dispose();
5847
+ * ```
5848
+ */
5849
+ dispose() {
5850
+ // Direct disposal and module disposal must join the same pending shutdown.
5851
+ if (this.#disposal) {
5852
+ return this.#disposal;
5853
+ }
5854
+ super.dispose();
5855
+ // Defer adapter callbacks until the shared promise is assigned, including reentrant disposal.
5856
+ this.#disposal = Promise.resolve().then(async () => {
5857
+ // Shut down all exporters even when one rejects or throws synchronously.
5858
+ const results = await Promise.allSettled(Object.entries(this.#adapters).map(async ([identifier, adapter]) => {
5859
+ try {
5860
+ await adapter.shutdown?.();
5861
+ }
5862
+ catch (cause) {
5863
+ throw new Error(`Failed to shut down telemetry adapter "${identifier}"`, { cause });
5864
+ }
5865
+ }));
5866
+ const errors = [];
5867
+ // Retain each failure for the module lifecycle's structured disposal error event.
5868
+ for (const result of results) {
5869
+ // Successful shutdowns must not obscure another exporter's failure.
5870
+ if (result.status === 'rejected') {
5871
+ errors.push(result.reason);
5872
+ }
5873
+ }
5874
+ // Reject only after all exporters have had a chance to release their resources.
5875
+ if (errors.length) {
5876
+ throw new AggregateError(errors, 'Failed to shut down telemetry adapters');
5877
+ }
5878
+ });
5879
+ return this.#disposal;
5880
+ }
5833
5881
  /**
5834
5882
  * Initializes all telemetry adapters that support async initialization.
5835
5883
  * Uses Promise.allSettled to ensure all adapters attempt initialization,
@@ -5879,6 +5927,11 @@ class TelemetryProvider extends BaseModuleProvider {
5879
5927
  }
5880
5928
  // Iterate through all registered adapters
5881
5929
  for (const [identifier, adapter] of Object.entries(this.#adapters)) {
5930
+ // Explicit child exporters take precedence over inherited development exporters.
5931
+ if (adapter.fallback && this.#handledByChild.has(item)) {
5932
+ // Keep application-owned records out of parent fallback exporters.
5933
+ continue;
5934
+ }
5882
5935
  try {
5883
5936
  // Let the adapter process the telemetry item
5884
5937
  Promise.resolve(adapter.processItem(item));
@@ -5910,7 +5963,16 @@ class TelemetryProvider extends BaseModuleProvider {
5910
5963
  if (relayFilter && !relayFilter(item)) {
5911
5964
  return;
5912
5965
  }
5913
- target.track(item);
5966
+ // Older/custom providers retain the original track-only relay contract.
5967
+ if (target.trackRelayed) {
5968
+ // Carry exporter ownership across intermediate providers without changing record metadata.
5969
+ const hasAdapters = this.#handledByChild.has(item) ||
5970
+ Object.values(this.#adapters).some((adapter) => !adapter.fallback);
5971
+ target.trackRelayed(item, hasAdapters);
5972
+ }
5973
+ else {
5974
+ target.track(item);
5975
+ }
5914
5976
  });
5915
5977
  }
5916
5978
  /**
@@ -5967,16 +6029,26 @@ class TelemetryProvider extends BaseModuleProvider {
5967
6029
  break;
5968
6030
  }
5969
6031
  }
6032
+ /**
6033
+ * Tracks an already validated child record, suppressing fallback exporters when appropriate.
6034
+ *
6035
+ * @param item - Record emitted by a child telemetry provider.
6036
+ * @param hasAdapters - Whether an explicit child adapter has already handled this record.
6037
+ */
6038
+ trackRelayed(item, hasAdapters) {
6039
+ this._track(item, hasAdapters);
6040
+ }
5970
6041
  /**
5971
6042
  * Tracks a telemetry item by merging the default scope with the item's scope (if provided),
5972
6043
  * ensuring that all telemetry items have the correct scope context. The merged item is then
5973
6044
  * emitted to downstream handlers.
5974
6045
  *
5975
6046
  * @param item - The telemetry item to be tracked, conforming to the input schema of `TelemetryItemSchema`.
6047
+ * @param handledByChild - Whether fallback adapters should skip this relayed item.
5976
6048
  *
5977
6049
  * @protected
5978
6050
  */
5979
- async _track(item) {
6051
+ async _track(item, handledByChild = false) {
5980
6052
  const mergedItem = mergeTelemetryItem(item, {
5981
6053
  scope: this.#defaultScope,
5982
6054
  });
@@ -5986,11 +6058,19 @@ class TelemetryProvider extends BaseModuleProvider {
5986
6058
  modules: this.#modules,
5987
6059
  item: mergedItem,
5988
6060
  }).subscribe((nextItem) => {
6061
+ // Async metadata resolution creates new objects; retain ownership on the emitted record.
6062
+ if (handledByChild) {
6063
+ this.#handledByChild.add(nextItem);
6064
+ }
5989
6065
  // Emit the item after applying metadata
5990
6066
  this.#items.next(nextItem);
5991
6067
  });
5992
6068
  }
5993
6069
  else {
6070
+ // Providers without metadata still need the same fallback precedence.
6071
+ if (handledByChild) {
6072
+ this.#handledByChild.add(mergedItem);
6073
+ }
5994
6074
  // If no metadata extractor is provided or item is TelemetryMetadataError, emit directly
5995
6075
  this.#items.next(mergedItem);
5996
6076
  }
@@ -6114,6 +6194,15 @@ const module$2 = {
6114
6194
  });
6115
6195
  return provider;
6116
6196
  },
6197
+ /**
6198
+ * Joins exporter shutdown before the framework completes module disposal.
6199
+ * @param args - Module disposal context.
6200
+ * @param args.instance - Telemetry provider whose subscriptions and exporters must be released.
6201
+ * @returns Resolves after the provider finishes disposal.
6202
+ */
6203
+ dispose: async ({ instance }) => {
6204
+ await instance.dispose?.();
6205
+ },
6117
6206
  };
6118
6207
 
6119
6208
  /**
@@ -8409,6 +8498,51 @@ class Query {
8409
8498
  }
8410
8499
  }
8411
8500
 
8501
+ /**
8502
+ * Error thrown by {@link ServiceDiscoveryClient} while service discovery is in a
8503
+ * failure cooldown and no recent service list is available as a fallback.
8504
+ *
8505
+ * After a failed service discovery request the client pauses outgoing requests
8506
+ * for a growing backoff period instead of calling the API again immediately.
8507
+ * Calls made during that pause fail fast with this error, so a misbehaving caller
8508
+ * (retry loop, reload loop, render loop) cannot flood the service discovery API.
8509
+ *
8510
+ * @remarks
8511
+ * Use `cause` to inspect the original failure (for example an
8512
+ * `HttpJsonResponseError` with status `401`) and `retryAt` to decide when it is
8513
+ * worth trying again.
8514
+ *
8515
+ * @example
8516
+ * ```ts
8517
+ * try {
8518
+ * await serviceDiscovery.resolveService('people');
8519
+ * } catch (error) {
8520
+ * if (error instanceof ServiceDiscoveryUnavailableError) {
8521
+ * console.warn(`service discovery paused until ${new Date(error.retryAt).toISOString()}`);
8522
+ * }
8523
+ * }
8524
+ * ```
8525
+ */
8526
+ class ServiceDiscoveryUnavailableError extends Error {
8527
+ /** Epoch milliseconds when the client will attempt a new service discovery request. */
8528
+ retryAt;
8529
+ /** Number of consecutive failed service discovery requests in the current failure streak. */
8530
+ attempt;
8531
+ /**
8532
+ * @param args - Failure details for the current cooldown.
8533
+ * @param args.cause - The error from the last failed service discovery request.
8534
+ * @param args.retryAt - Epoch milliseconds when requests resume.
8535
+ * @param args.attempt - Number of consecutive failures in the current streak.
8536
+ */
8537
+ constructor(args) {
8538
+ const seconds = Math.max(0, Math.ceil((args.retryAt - Date.now()) / 1000));
8539
+ super(`Service discovery is unavailable after ${args.attempt} failed attempt(s); requests are paused for ${seconds}s`, { cause: args.cause });
8540
+ this.name = 'ServiceDiscoveryUnavailableError';
8541
+ this.retryAt = args.retryAt;
8542
+ this.attempt = args.attempt;
8543
+ }
8544
+ }
8545
+
8412
8546
  /**
8413
8547
  * Zod schema for a single service object returned by the service
8414
8548
  * discovery API.
@@ -8446,6 +8580,12 @@ const ApiServices = array(ApiService)
8446
8580
 
8447
8581
  /** Cache key used by the internal {@link Query} instance. */
8448
8582
  const queryKey = 'services';
8583
+ /** Pause after the first failed request; doubles per consecutive failure. */
8584
+ const failureBackoffInitialMs = 1_000;
8585
+ /** Upper bound for the pause between failed requests. */
8586
+ const failureBackoffMaxMs = 30_000;
8587
+ /** Maximum age of the last successful service list that may be returned when a refresh fails. */
8588
+ const staleIfErrorMs = 24 * 60 * 60 * 1_000;
8449
8589
  /**
8450
8590
  * Transforms a fetch {@link Response} into an observable that emits a
8451
8591
  * validated array of {@link Service} objects.
@@ -8479,9 +8619,20 @@ const serviceResponseSelector = (response, postProcess) => {
8479
8619
  * Results are cached for 5 minutes. When `allow_cache` is `true`,
8480
8620
  * {@link resolveServices} returns the first cached value immediately;
8481
8621
  * otherwise it waits for the latest API response.
8622
+ *
8623
+ * Failures are hardened so a broken caller cannot flood the service discovery API:
8624
+ * - After a failed request the client pauses outgoing requests with exponential
8625
+ * backoff (1s, 2s, 4s … capped at 30s). The pause resets on the first
8626
+ * successful response.
8627
+ * - When a refresh fails, or a call arrives during the pause, the last successful
8628
+ * service list is returned if it is younger than 24 hours.
8629
+ * - Without a usable fallback, the request that failed rethrows the original error,
8630
+ * and calls made during the pause throw {@link ServiceDiscoveryUnavailableError}.
8482
8631
  */
8483
8632
  class ServiceDiscoveryClient {
8484
8633
  #query;
8634
+ #failure;
8635
+ #lastKnownGood;
8485
8636
  /** Sub-path appended to the HTTP client's base URI when fetching services. */
8486
8637
  endpoint;
8487
8638
  /** HTTP client used to call the service discovery API. */
@@ -8507,11 +8658,75 @@ class ServiceDiscoveryClient {
8507
8658
  });
8508
8659
  }
8509
8660
  /** {@inheritDoc IServiceDiscoveryClient.resolveServices} */
8510
- resolveServices(allow_cache) {
8511
- // firstValueFrom returns the cached snapshot; lastValueFrom waits for
8512
- // the freshest value from the query
8513
- const fn = allow_cache ? firstValueFrom : lastValueFrom;
8514
- return fn(Query.extractQueryValue(this.#query.query()));
8661
+ async resolveServices(allow_cache) {
8662
+ // Fail fast while cooling down so retry/reload/render loops never reach the network
8663
+ if (this.#failure && Date.now() < this.#failure.retryAt) {
8664
+ return this.#resolveFallback(new ServiceDiscoveryUnavailableError({
8665
+ cause: this.#failure.error,
8666
+ retryAt: this.#failure.retryAt,
8667
+ attempt: this.#failure.attempt,
8668
+ }));
8669
+ }
8670
+ const startedAt = Date.now();
8671
+ try {
8672
+ // firstValueFrom returns the cached snapshot; lastValueFrom waits for
8673
+ // the freshest value from the query
8674
+ const fn = allow_cache ? firstValueFrom : lastValueFrom;
8675
+ const record = await fn(this.#query.query());
8676
+ // Only a fresh response proves discovery works; a cached (possibly expired) snapshot must
8677
+ // not reset the failure streak or renew the age of the fallback list
8678
+ if (record.status === 'complete') {
8679
+ this.#failure = undefined;
8680
+ this.#lastKnownGood = { services: record.value, receivedAt: Date.now() };
8681
+ }
8682
+ return record.value;
8683
+ }
8684
+ catch (error) {
8685
+ this.#registerFailure(error, startedAt);
8686
+ return this.#resolveFallback(error);
8687
+ }
8688
+ }
8689
+ /**
8690
+ * Records a failed request and schedules the next allowed request time.
8691
+ *
8692
+ * Concurrent callers share one in-flight request through {@link Query}, so they all
8693
+ * reject with the same failure; only the first one to settle may extend the streak,
8694
+ * otherwise a single failed request would be counted once per waiting caller.
8695
+ *
8696
+ * @param error - The error from the failed request.
8697
+ * @param startedAt - Epoch milliseconds when the caller started waiting for the request.
8698
+ */
8699
+ #registerFailure(error, startedAt) {
8700
+ // A concurrent caller already recorded this same failed request
8701
+ if (this.#failure && this.#failure.failedAt >= startedAt) {
8702
+ return;
8703
+ }
8704
+ const attempt = (this.#failure?.attempt ?? 0) + 1;
8705
+ const delay = Math.min(failureBackoffMaxMs, failureBackoffInitialMs * 2 ** (attempt - 1));
8706
+ // Up to 20% jitter keeps many clients that failed together from retrying in lockstep
8707
+ const jittered = Math.round(delay * (0.8 + Math.random() * 0.2));
8708
+ const failedAt = Date.now();
8709
+ this.#failure = { error, attempt, failedAt, retryAt: failedAt + jittered };
8710
+ // Warn once per streak rather than once per call to keep consoles readable
8711
+ if (attempt === 1) {
8712
+ console.warn(`[service-discovery] request failed; pausing requests with backoff (max ${failureBackoffMaxMs}ms)`, error);
8713
+ }
8714
+ }
8715
+ /**
8716
+ * Returns the last successful service list when it is still fresh enough,
8717
+ * otherwise rethrows the given error.
8718
+ *
8719
+ * @param error - Error to throw when no usable fallback exists.
8720
+ * @returns The last known good service list.
8721
+ * @throws The provided `error` when no service list younger than 24 hours exists.
8722
+ */
8723
+ #resolveFallback(error) {
8724
+ const lastKnownGood = this.#lastKnownGood;
8725
+ // Prefer a recent service list over an error so callers have nothing to retry
8726
+ if (lastKnownGood && Date.now() - lastKnownGood.receivedAt <= staleIfErrorMs) {
8727
+ return lastKnownGood.services;
8728
+ }
8729
+ throw error;
8515
8730
  }
8516
8731
  /** {@inheritDoc IServiceDiscoveryClient.resolveService} */
8517
8732
  async resolveService(key, allow_cache) {
@@ -8713,7 +8928,7 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
8713
8928
  }
8714
8929
 
8715
8930
  // Generated by genversion.
8716
- const version$1 = '10.1.1';
8931
+ const version$1 = '10.2.0';
8717
8932
 
8718
8933
  /**
8719
8934
  * Default implementation of {@link IServiceDiscoveryProvider}.
@@ -8876,95 +9091,6 @@ const enableServiceDiscovery = (configurator, callback) => {
8876
9091
  configurator.addConfig(configureServiceDiscovery(callback ?? (() => Promise.resolve())));
8877
9092
  };
8878
9093
 
8879
- /**
8880
- * Abstract base class for telemetry adapters.
8881
- *
8882
- * Provides a common implementation for filtering telemetry items before processing.
8883
- * Subclasses must implement the `_processItem` method to define how telemetry items are handled.
8884
- *
8885
- * @template TelemetryItem - The type representing a telemetry item.
8886
- * @implements {ITelemetryAdapter}
8887
- *
8888
- * @remarks
8889
- * - An optional filter function can be provided to determine which telemetry items should be processed.
8890
- *
8891
- * @example
8892
- * class MyTelemetryAdapter extends BaseTelemetryAdapter {
8893
- * protected _processItem(item: TelemetryItem): void {
8894
- * // Custom processing logic
8895
- * }
8896
- * }
8897
- */
8898
- class BaseTelemetryAdapter {
8899
- #filter;
8900
- #initialized = false;
8901
- /**
8902
- * Creates a new instance of the TelemetryAdapter.
8903
- *
8904
- * @param filter - An optional function to filter telemetry items. If provided, only items for which the function returns true will be processed.
8905
- */
8906
- constructor(filter) {
8907
- this.#filter = filter;
8908
- }
8909
- /**
8910
- * Processes a telemetry item by applying an optional filter before handling it.
8911
- *
8912
- * If a filter is defined and the item does not pass the filter, the method returns early.
8913
- * Otherwise, it delegates the processing of the item to the internal `_processItem` method.
8914
- *
8915
- * @param item - The telemetry item to be processed.
8916
- */
8917
- processItem(item) {
8918
- // If the adapter is not initialized, do not process the item
8919
- if (!this.#initialized) {
8920
- return;
8921
- }
8922
- // If a filter is defined and the item does not pass the filter, do not process the item
8923
- if (this.#filter && !this.#filter(item)) {
8924
- return;
8925
- }
8926
- // Delegate the processing of the item to the internal `_processItem` method
8927
- this._processItem(item);
8928
- }
8929
- /**
8930
- * Initializes the telemetry adapter asynchronously.
8931
- *
8932
- * This method can only be called once. Subsequent calls will return immediately
8933
- * without performing any initialization. It calls the protected `_initialize` method which
8934
- * subclasses can override to provide custom initialization logic.
8935
- *
8936
- * TODO(#5112): Consider changing return type from Promise<void> to Promise<TelemetryItem[]>
8937
- * to allow adapters to return telemetry items (errors/warnings) that occurred during
8938
- * initialization, eliminating the chicken-and-egg problem with reporting init errors.
8939
- *
8940
- * @returns A promise that resolves when initialization is complete.
8941
- * @sealed
8942
- */
8943
- async initialize() {
8944
- // If the adapter is already initialized, do not initialize it again
8945
- if (this.#initialized) {
8946
- return;
8947
- }
8948
- // Initialize the adapter
8949
- await this._initialize();
8950
- // Mark the adapter as initialized
8951
- this.#initialized = true;
8952
- }
8953
- /**
8954
- * Protected initialization method that subclasses can override.
8955
- *
8956
- * This method is called only once during the adapter's lifetime.
8957
- * Subclasses should override this method to perform any necessary async setup.
8958
- * The base implementation is a no-op for adapters that don't need initialization.
8959
- *
8960
- * @returns A promise that resolves when initialization is complete.
8961
- * @protected
8962
- */
8963
- async _initialize() {
8964
- // Default implementation - no-op for adapters that don't need initialization
8965
- }
8966
- }
8967
-
8968
9094
  /**
8969
9095
  * Telemetry adapter that outputs telemetry data to the browser console
8970
9096
  * with formatted titles and colour-coded log levels.
@@ -9402,7 +9528,7 @@ async function registerServiceWorker(framework) {
9402
9528
  }
9403
9529
 
9404
9530
  // Generated by genversion.
9405
- const version = '5.1.0';
9531
+ const version = '5.2.2';
9406
9532
 
9407
9533
  // Allow dynamic import without vite
9408
9534
  const importWithoutVite = (path) => import(/* @vite-ignore */ path);
@@ -9422,7 +9548,7 @@ enableServiceDiscovery(configurator, async (builder) => {
9422
9548
  });
9423
9549
  // Avoid interactive Entra ID authentication when the SPA runs in CI or Playwright.
9424
9550
  if (isEnabledEnvValue(import.meta.env.FUSION_SPA_MSAL_MOCK)) {
9425
- const { enableMsalMock } = await import('../index-Df9EZ6lh.js');
9551
+ const { enableMsalMock } = await import('../index-glg6-DFO.js');
9426
9552
  const mockServerUrl = import.meta.env.FUSION_SPA_MSAL_MOCK_SERVER_URL;
9427
9553
  enableMsalMock(configurator, (builder) => {
9428
9554
  // The SPA owns the HTTP adapter; MSAL owns applying the returned token and account.
@@ -9443,6 +9569,19 @@ else {
9443
9569
  builder.setRequiresAuth(isEnabledEnvValue(import.meta.env.FUSION_SPA_MSAL_REQUIRES_AUTH));
9444
9570
  });
9445
9571
  }
9572
+ // Initialize tracing before app startup so network requests and logs share active trace context.
9573
+ if (import.meta.env.FUSION_SPA_TELEMETRY_OTLP_TRACES_ENDPOINT) {
9574
+ const { enableDevServerTracing } = await import('../enable-dev-server-tracing-GfRoCLxu.js');
9575
+ enableDevServerTracing(new URL(import.meta.env.FUSION_SPA_TELEMETRY_OTLP_TRACES_ENDPOINT, window.location.origin).href);
9576
+ }
9577
+ // The dev-server environment bridge owns activation; the SPA only consumes its endpoint.
9578
+ const devServerOtlpAdapter = import.meta.env.FUSION_SPA_TELEMETRY_OTLP_ENDPOINT
9579
+ ? new (await import('../index-CiqJ1Og1.js')).OtlpAdapter({
9580
+ url: new URL(import.meta.env.FUSION_SPA_TELEMETRY_OTLP_ENDPOINT, window.location.origin).href,
9581
+ fallback: true,
9582
+ serviceName: 'fusion.dev-server',
9583
+ })
9584
+ : undefined;
9446
9585
  enableTelemetry(configurator, {
9447
9586
  attachConfiguratorEvents: true,
9448
9587
  configure: (builder) => {
@@ -9451,6 +9590,10 @@ enableTelemetry(configurator, {
9451
9590
  filter: Number.isNaN(consoleLevel) ? undefined : (item) => item.level >= consoleLevel,
9452
9591
  });
9453
9592
  builder.setAdapter('console', consoleAdapter);
9593
+ // Only the dev-server environment bridge opts the shell into OTLP export.
9594
+ if (devServerOtlpAdapter) {
9595
+ builder.setAdapter('dev-server-otlp', devServerOtlpAdapter);
9596
+ }
9454
9597
  builder.setMetadata(({ modules }) => {
9455
9598
  const metadata = {
9456
9599
  fusion: {