@equinor/fusion-framework-vite-plugin-spa 3.1.12-next.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -153,8 +153,8 @@ function requireRe () {
153
153
 
154
154
  // ## Pre-release Version Identifier
155
155
  // A numeric identifier, or a non-numeric identifier.
156
- // Non-numberic identifiers include numberic identifiers but can be longer.
157
- // Therefore non-numberic identifiers must go first.
156
+ // Non-numeric identifiers include numeric identifiers but can be longer.
157
+ // Therefore non-numeric identifiers must go first.
158
158
 
159
159
  createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
160
160
  }|${src[t.NUMERICIDENTIFIER]})`);
@@ -850,7 +850,7 @@ function requireDiff () {
850
850
  return prefix + 'patch'
851
851
  }
852
852
 
853
- // high and low are preleases
853
+ // high and low are prereleases
854
854
  return 'prerelease'
855
855
  };
856
856
 
@@ -2409,7 +2409,7 @@ function requireSubset () {
2409
2409
  // - If LT
2410
2410
  // - If LT.semver is greater than any < or <= comp in C, return false
2411
2411
  // - If LT is <=, and LT.semver does not satisfy every C, return false
2412
- // - If GT.semver has a prerelease, and not in prerelease mode
2412
+ // - If LT.semver has a prerelease, and not in prerelease mode
2413
2413
  // - If no C has a prerelease and the LT.semver tuple, return false
2414
2414
  // - Else return true
2415
2415
 
@@ -5239,9 +5239,31 @@ var ModuleEventLevel;
5239
5239
  })(ModuleEventLevel || (ModuleEventLevel = {}));
5240
5240
 
5241
5241
  /**
5242
- * Base class for creating module provider
5242
+ * Abstract base class for Fusion Framework module providers.
5243
+ *
5244
+ * Extend `BaseModuleProvider` to create the runtime instance that a module’s
5245
+ * {@link Module.initialize | initialize} method returns. The base class
5246
+ * handles version parsing, subscription lifecycle management, and duck-typed
5247
+ * `instanceof` checks.
5248
+ *
5249
+ * Subclasses should register teardown callbacks via {@link _addTeardown} so
5250
+ * that resources (subscriptions, timers, event listeners) are automatically
5251
+ * cleaned up when the framework calls {@link dispose}.
5243
5252
  *
5244
- * this is the interface which is returned after enabling a module
5253
+ * @template TConfig - The resolved configuration type for the module.
5254
+ *
5255
+ * @example
5256
+ * ```typescript
5257
+ * class MyProvider extends BaseModuleProvider<MyConfig> {
5258
+ * constructor(args: BaseModuleProviderCtorArgs<MyConfig>) {
5259
+ * super(args);
5260
+ * const sub = someObservable$.subscribe();
5261
+ * this._addTeardown(sub);
5262
+ * }
5263
+ * }
5264
+ * ```
5265
+ *
5266
+ * @see IModuleProvider
5245
5267
  */
5246
5268
  class BaseModuleProvider {
5247
5269
  /**
@@ -5273,6 +5295,11 @@ class BaseModuleProvider {
5273
5295
  get version() {
5274
5296
  return this.#version;
5275
5297
  }
5298
+ /**
5299
+ * Creates a new module provider.
5300
+ *
5301
+ * @param args - Version and resolved configuration for the module.
5302
+ */
5276
5303
  constructor(args) {
5277
5304
  const { version } = args;
5278
5305
  this.#version = new SemanticVersion(version);
@@ -5288,13 +5315,18 @@ class BaseModuleProvider {
5288
5315
  this.#subscriptions.add(teardown);
5289
5316
  return () => this.#subscriptions.remove(teardown);
5290
5317
  }
5318
+ /**
5319
+ * Unsubscribes all registered teardowns and releases held resources.
5320
+ *
5321
+ * Called automatically by the framework during module disposal.
5322
+ */
5291
5323
  dispose() {
5292
5324
  this.#subscriptions.unsubscribe();
5293
5325
  }
5294
5326
  }
5295
5327
 
5296
5328
  // Generated by genversion.
5297
- const version$8 = '5.0.7-next.0';
5329
+ const version$8 = '6.0.0';
5298
5330
 
5299
5331
  /* eslint-disable @typescript-eslint/no-explicit-any */
5300
5332
  /**
@@ -5310,9 +5342,37 @@ class RequiredModuleTimeoutError extends Error {
5310
5342
  }
5311
5343
  }
5312
5344
  /**
5313
- * Configurator class for modules.
5314
- * @template TModules - Array of modules.
5315
- * @template TRef - Reference type.
5345
+ * Core orchestrator that drives the module lifecycle in Fusion Framework.
5346
+ *
5347
+ * `ModulesConfigurator` manages the full configure → initialize → dispose pipeline
5348
+ * for a set of modules. Consumers register modules via {@link addConfig} or
5349
+ * {@link configure}, then call {@link initialize} to produce a sealed
5350
+ * {@link ModulesInstance} whose properties are the initialized module providers.
5351
+ *
5352
+ * The lifecycle phases executed during {@link initialize} are:
5353
+ *
5354
+ * 1. **Configure** – each module’s `configure()` factory creates a config builder;
5355
+ * registered callbacks mutate it; `postConfigure()` hooks run.
5356
+ * 2. **Initialize** – modules are initialized concurrently via `initialize()`;
5357
+ * cross-module dependencies are resolved through `requireInstance()`.
5358
+ * 3. **Post-initialize** – `postInitialize()` hooks and `onInitialized` callbacks run.
5359
+ *
5360
+ * All lifecycle transitions emit {@link ModuleEvent} entries on the {@link event$}
5361
+ * observable for telemetry and debugging.
5362
+ *
5363
+ * @template TModules - Tuple of module types managed by this configurator.
5364
+ * @template TRef - Reference type passed through configuration (usually a parent instance).
5365
+ *
5366
+ * @example
5367
+ * ```typescript
5368
+ * const configurator = new ModulesConfigurator([httpModule, authModule]);
5369
+ * configurator.addConfig({
5370
+ * module: httpModule,
5371
+ * configure: (cfg) => cfg.setBaseUrl('https://api.example.com'),
5372
+ * });
5373
+ * const modules = await configurator.initialize();
5374
+ * // modules.http, modules.auth are now available
5375
+ * ```
5316
5376
  */
5317
5377
  class ModulesConfigurator {
5318
5378
  /**
@@ -5984,6 +6044,8 @@ class ModulesConfigurator {
5984
6044
  },
5985
6045
  });
5986
6046
  }
6047
+ /**
6048
+ * Disposes all modules managed by this configurator.\n *\n * Calls each module\u2019s `dispose` hook (if defined) and completes the\n * internal event stream. After disposal the configurator should not be reused.\n *\n * @param instance - The initialized modules instance to tear down.\n * @param ref - Optional reference object forwarded to module dispose hooks.\n */
5987
6049
  async dispose(instance, ref) {
5988
6050
  this._registerEvent({
5989
6051
  level: ModuleEventLevel.Debug,
@@ -20674,16 +20736,234 @@ const requestValidationOperator = (options) => (request) => {
20674
20736
  }
20675
20737
  };
20676
20738
 
20739
+ /**
20740
+ * Represents an error that occurs when handling an HTTP response.
20741
+ * @template TResponse The type of the HTTP response.
20742
+ */
20743
+ class HttpResponseError extends Error {
20744
+ response;
20745
+ static Name = 'HttpResponseError';
20746
+ constructor(message, response, options) {
20747
+ super(message, options);
20748
+ this.response = response;
20749
+ }
20750
+ }
20751
+ /**
20752
+ * Represents an error that occurs when handling a JSON response in an HTTP request.
20753
+ * Extends the base `HttpResponseError` class.
20754
+ *
20755
+ * @template TType - The type of the data associated with the error.
20756
+ * @template TResponse - The type of the HTTP response.
20757
+ */
20758
+ class HttpJsonResponseError extends HttpResponseError {
20759
+ static Name = 'HttpJsonResponseError';
20760
+ data;
20761
+ /**
20762
+ * Creates a new instance of `HttpJsonResponseError`.
20763
+ *
20764
+ * @param message - The error message.
20765
+ * @param response - The HTTP response associated with the error.
20766
+ * @param options - Additional options for the error, including the associated data.
20767
+ */
20768
+ constructor(message, response, options) {
20769
+ super(message, response, options);
20770
+ this.name = HttpJsonResponseError.Name;
20771
+ this.data = options?.data;
20772
+ }
20773
+ }
20774
+ /**
20775
+ * Represents an error that occurs when handling a server-sent event (SSE) HTTP response.
20776
+ *
20777
+ * @template TType - The type of additional data associated with the error.
20778
+ * @template TResponse - The type of the HTTP response object.
20779
+ *
20780
+ * @extends HttpResponseError<TResponse>
20781
+ */
20782
+ class ServerSentEventResponseError extends HttpResponseError {
20783
+ static Name = 'ServerSentEventResponseError';
20784
+ /**
20785
+ * Creates a new instance of the error.
20786
+ *
20787
+ * @param message - The error message describing the cause of the error.
20788
+ * @param response - The HTTP response associated with the error.
20789
+ * @param options - Optional error options, which may include additional data of type `TType`.
20790
+ */
20791
+ constructor(message, response, options) {
20792
+ super(message, response, options);
20793
+ this.name = ServerSentEventResponseError.Name;
20794
+ }
20795
+ }
20796
+
20797
+ const defaultDataParser = (data) => {
20798
+ try {
20799
+ return JSON.parse(data);
20800
+ }
20801
+ catch {
20802
+ return data;
20803
+ }
20804
+ };
20805
+ /**
20806
+ * Parses a string containing Server-Sent Events (SSE) data into individual event objects.
20807
+ *
20808
+ * @template TData - The type of the parsed `data` field in the event.
20809
+ * @param text - The raw SSE data as a string, where events are separated by double newlines.
20810
+ * @param options - Optional configuration for parsing the events.
20811
+ * @param options.dataParser - A custom parser function for the `data` field. Defaults to JSON parsing,
20812
+ * falling back to returning the raw string if parsing fails.
20813
+ *
20814
+ * @returns A generator that yields `ServerSentEvent` objects parsed from the input string.
20815
+ *
20816
+ * @remarks
20817
+ * - Empty lines and events with no fields are ignored.
20818
+ * - If the `data` field cannot be parsed as JSON, it is returned as a plain string.
20819
+ * - Fields other than `data` are stored as strings in the resulting `ServerSentEvent` object.
20820
+ *
20821
+ * @example
20822
+ * ```typescript
20823
+ * const sseData = `
20824
+ * id: 1
20825
+ * event: message
20826
+ * data: {"key":"value"}
20827
+ *
20828
+ * id: 2
20829
+ * event: update
20830
+ * data: plain text
20831
+ * `;
20832
+ *
20833
+ * for (const event of parseEvents(sseData)) {
20834
+ * console.log(event);
20835
+ * }
20836
+ * // Output:
20837
+ * // { id: "1", event: "message", data: { key: "value" } }
20838
+ * // { id: "2", event: "update", data: "plain text" }
20839
+ * ```
20840
+ */
20841
+ function* parseEvents(text, options) {
20842
+ // Split the input string into individual event strings using double newline as separator
20843
+ const eventStrings = text.split('\n\n');
20844
+ const dataParser = options?.dataParser || defaultDataParser;
20845
+ // Iterate through each event string
20846
+ for (const eventStr of eventStrings) {
20847
+ // Skip empty event strings (after trimming whitespace)
20848
+ if (!eventStr.trim())
20849
+ continue;
20850
+ // Split the event string into lines (fields) using single newline
20851
+ const lines = eventStr.split('\n');
20852
+ // Use reduce to process each line in the event string
20853
+ const event = lines.reduce((event, line) => {
20854
+ // Skip empty lines
20855
+ if (!line)
20856
+ return event;
20857
+ // Find the index of the first colon, which separates field name and value
20858
+ const colonIndex = line.indexOf(':');
20859
+ // Skip lines without a colon (invalid format)
20860
+ if (colonIndex === -1)
20861
+ return event;
20862
+ // Extract the field name (before colon) and trim whitespace
20863
+ const field = line.slice(0, colonIndex).trim();
20864
+ // Extract the field value (after colon) and trim whitespace
20865
+ const value = line.slice(colonIndex + 1).trim();
20866
+ // Handle the 'data' field specially, attempting JSON parsing
20867
+ if (field === 'data') {
20868
+ event.data = dataParser(value);
20869
+ }
20870
+ else {
20871
+ // For non-data fields, assign the value as a string to the event object
20872
+ event[field] = value;
20873
+ }
20874
+ return event;
20875
+ }, {});
20876
+ // Only emit the event to the results if it has at least one field
20877
+ if (Object.keys(event).length) {
20878
+ yield event;
20879
+ }
20880
+ }
20881
+ }
20882
+ async function* readStream(reader, options) {
20883
+ const skipHeartbeats = !!options?.skipHeartbeats;
20884
+ const eventFilter = options?.eventFilter
20885
+ ? Array.isArray(options.eventFilter)
20886
+ ? options.eventFilter
20887
+ : [options.eventFilter]
20888
+ : null;
20889
+ const decoder = new TextDecoder();
20890
+ while (true) {
20891
+ const { done, value } = await reader.read();
20892
+ if (done) {
20893
+ break;
20894
+ }
20895
+ const text = decoder.decode(value, { stream: true });
20896
+ const events = parseEvents(text, { dataParser: options?.dataParser });
20897
+ for (const event of events) {
20898
+ if (event.retry) {
20899
+ await new Promise((resolve) => setTimeout(resolve, Number.parseInt(event.retry ?? '300', 10)));
20900
+ continue;
20901
+ }
20902
+ if (skipHeartbeats) {
20903
+ // Skip comment-based heartbeats (no event, data, or id)
20904
+ if (!event.event && !event.data && !event.id) {
20905
+ continue;
20906
+ }
20907
+ // Skip named heartbeat events (e.g., event: heartbeat or event: ping)
20908
+ if (event.event && ['heartbeat', 'ping'].includes(event.event)) {
20909
+ continue;
20910
+ }
20911
+ }
20912
+ if (!eventFilter || (event.event && eventFilter.includes(event.event))) {
20913
+ yield event;
20914
+ }
20915
+ }
20916
+ }
20917
+ }
20918
+ /**
20919
+ * Transforms an SSE response into an Observable stream of parsed events.
20920
+ * @param response - The HTTP response with Content-Type: text/event-stream.
20921
+ * @param options - Optional configuration for event filtering and heartbeat handling.
20922
+ * @param options.eventFilter - Filter events by type (single string or array).
20923
+ * @param options.skipHeartbeats - Skip empty/heartbeat events if true.
20924
+ * @param options.dataParser - Custom parser for the data field.
20925
+ * @param options.abortSignal - Abort signal to cancel the stream.
20926
+ * @returns An Observable emitting parsed ServerSentEvent objects.
20927
+ * @throws ServerSentEventResponseError if response is invalid or stream fails.
20928
+ */
20929
+ const createSseSelector = (options) => {
20930
+ return (response) => {
20931
+ if (!response.ok) {
20932
+ throw new ServerSentEventResponseError(`HTTP error! Status: ${response.status}`, response);
20933
+ }
20934
+ if (!response.body) {
20935
+ throw new ServerSentEventResponseError('Response body is not readable', response);
20936
+ }
20937
+ if (!response.headers.get('Content-Type')?.includes('text/event-stream')) {
20938
+ throw new ServerSentEventResponseError('Response is not a text/event-stream', response);
20939
+ }
20940
+ const reader = response.body.getReader();
20941
+ return from(readStream(reader, {
20942
+ dataParser: options?.dataParser,
20943
+ skipHeartbeats: options?.skipHeartbeats,
20944
+ eventFilter: options?.eventFilter,
20945
+ })).pipe(
20946
+ // Stop reading if the abort signal is triggered
20947
+ takeUntil(options?.abortSignal ? fromEvent(options.abortSignal, 'abort') : EMPTY), finalize$2(async () => {
20948
+ // cancel just in case of a pre-mature exit
20949
+ await reader.cancel().catch(() => {
20950
+ /** ignore cancellation errors */
20951
+ });
20952
+ reader.releaseLock();
20953
+ }));
20954
+ };
20955
+ };
20956
+
20677
20957
  /** @inheritdoc */
20678
20958
  class HttpClientConfigurator {
20679
20959
  _clients = {};
20680
- /** Get a clone of all configured clients */
20960
+ /** Gets a shallow clone of all named client configurations. */
20681
20961
  get clients() {
20682
20962
  return { ...this._clients };
20683
20963
  }
20684
- /** default class for creation of http clients */
20964
+ /** Default constructor used when a client configuration does not provide `ctor`. */
20685
20965
  defaultHttpClientCtor;
20686
- /** default request handler for http clients, applied on creation */
20966
+ /** Default request handler pipeline cloned into each created client instance. */
20687
20967
  defaultHttpRequestHandler = new HttpRequestHandler({
20688
20968
  // convert all request methods to uppercase
20689
20969
  'capitalize-method': capitalizeRequestMethodOperator(),
@@ -20691,8 +20971,8 @@ class HttpClientConfigurator {
20691
20971
  'request-validation': requestValidationOperator(),
20692
20972
  });
20693
20973
  /**
20694
- * Create a instance of http configuration
20695
- * @param client defaultHttpRequestHandler
20974
+ * Creates a configurator with the default client constructor.
20975
+ * @param client - The default client constructor used when `ctor` is not configured per client.
20696
20976
  */
20697
20977
  constructor(client) {
20698
20978
  this.defaultHttpClientCtor = client;
@@ -20714,32 +20994,40 @@ class HttpClientConfigurator {
20714
20994
  }
20715
20995
 
20716
20996
  // Generated by genversion.
20717
- const version$6 = '7.0.9-next.0';
20997
+ const version$6 = '8.0.0';
20718
20998
 
20719
20999
  /**
20720
- * Exception thrown when a client cannot be found.
21000
+ * Thrown when `createClient(name)` is called with an unknown client key.
20721
21001
  *
20722
- * This error is typically used to indicate that a requested client instance
20723
- * does not exist or cannot be located within the current context.
20724
- *
20725
- * @extends {Error}
21002
+ * This is only used when the provided string is neither a registered client name
21003
+ * nor an absolute `http:` or `https:` URL.
20726
21004
  */
20727
21005
  class ClientNotFoundException extends Error {
20728
21006
  }
21007
+ /** URL protocols accepted as valid ad-hoc base URIs. */
21008
+ const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ws:', 'wss:'];
20729
21009
  /**
20730
- * Checks if a given string is a valid URL.
20731
- * @param url - The string to check for a valid URL.
20732
- * @returns `true` if the input string is a valid URL, `false` otherwise.
21010
+ * Checks if a given string is a valid absolute URL with a supported protocol.
21011
+ * @param url - The string to check.
21012
+ * @returns `true` when the string uses one of {@link SUPPORTED_PROTOCOLS}.
20733
21013
  */
20734
21014
  const isURL = (url) => {
20735
- const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
20736
- '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name
20737
- '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
20738
- '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
20739
- '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
20740
- '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
20741
- return pattern.test(url);
21015
+ try {
21016
+ const parsed = new URL(url);
21017
+ return SUPPORTED_PROTOCOLS.includes(parsed.protocol);
21018
+ }
21019
+ catch {
21020
+ return false;
21021
+ }
20742
21022
  };
21023
+ /**
21024
+ * Heuristic check for strings that look like a bare hostname or URL without a
21025
+ * protocol prefix (e.g. `api.example.com` or `api.example.com/v1`).
21026
+ *
21027
+ * Used to emit a deprecation warning when callers rely on the old (pre-patch)
21028
+ * behaviour that accepted protocol-less URLs.
21029
+ */
21030
+ const looksLikeURL = (value) => !value.includes(' ') && /^[a-z\d]([a-z\d-]*\.)+[a-z]{2,}/i.test(value);
20743
21031
  /**
20744
21032
  * The `HttpClientProvider` class is responsible for managing HTTP client instances and their configuration.
20745
21033
  * It provides methods to check if a client is configured, create new client instances, and create custom client instances.
@@ -20769,7 +21057,7 @@ class HttpClientProvider extends BaseModuleProvider {
20769
21057
  return Object.keys(this.config.clients).includes(key);
20770
21058
  }
20771
21059
  /**
20772
- * Creates a new HTTP client instance with the specified configuration.
21060
+ * Creates a fresh HTTP client instance from a named or ad-hoc configuration.
20773
21061
  *
20774
21062
  * @param keyOrConfig - The key or configuration object for the HTTP client.
20775
21063
  * @returns The created HTTP client instance.
@@ -20779,26 +21067,22 @@ class HttpClientProvider extends BaseModuleProvider {
20779
21067
  * If a string is provided, it is treated as the key for a pre-configured client in the `HttpClientProvider`.
20780
21068
  * If an `HttpClientOptions` object is provided, it is used as the configuration for the new client instance.
20781
21069
  *
20782
- * The method sets up the HTTP client with the following options:
20783
- * - `baseUri`: The base URI for the HTTP client.
20784
- * - `defaultScopes`: The default scopes to be used for authentication.
20785
- * - `onCreate`: An optional callback function that is called when the client instance is created.
20786
- * - `ctor`: The constructor function for the HTTP client, defaulting to the configured `defaultHttpClientCtor`.
20787
- * - `requestHandler`: The HTTP request handler to be used by the client, defaulting to the `defaultHttpRequestHandler`.
21070
+ * The method applies `baseUri`, `defaultScopes`, `requestHandler`, `responseHandler`,
21071
+ * a custom `ctor` when configured, and finally runs `onCreate` for the newly created instance.
20788
21072
  *
20789
21073
  * The created HTTP client instance is returned.
20790
21074
  */
20791
21075
  createClient(keyOrConfig) {
20792
21076
  const config = this._resolveConfig(keyOrConfig);
20793
- const { baseUri, defaultScopes = [], onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.defaultHttpRequestHandler, } = config;
20794
- const options = { requestHandler };
21077
+ const { baseUri, defaultScopes = [], onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.defaultHttpRequestHandler, responseHandler, } = config;
21078
+ const options = { requestHandler, responseHandler };
20795
21079
  const instance = new ctor(baseUri || '', options);
20796
21080
  Object.assign(instance, { defaultScopes });
20797
21081
  onCreate?.(instance);
20798
21082
  return instance;
20799
21083
  }
20800
21084
  /**
20801
- * Creates a new HTTP client instance with the specified configuration.
21085
+ * Creates a client instance and returns it as the requested custom client type.
20802
21086
  *
20803
21087
  * @param key - The key of the pre-configured HTTP client to create.
20804
21088
  * @returns The created HTTP client instance, cast to the specified type `T`.
@@ -20815,8 +21099,9 @@ class HttpClientProvider extends BaseModuleProvider {
20815
21099
  /**
20816
21100
  * Resolves the configuration for an HTTP client based on the provided `keyOrConfig` parameter.
20817
21101
  *
20818
- * If a string is provided, it is treated as the key for a pre-configured client in the `HttpClientProvider`.
20819
- * If an `HttpClientOptions` object is provided, it is used as the configuration for the new client instance.
21102
+ * If a string is provided, it is treated as either a pre-configured client key or,
21103
+ * when it is an absolute `http:` or `https:` URL, as an ad-hoc `baseUri`.
21104
+ * If an `HttpClientOptions` object is provided, it is used directly as the configuration for the new client instance.
20820
21105
  *
20821
21106
  * @param keyOrConfig - The key or configuration object for the HTTP client.
20822
21107
  * @returns The resolved HTTP client configuration.
@@ -20827,6 +21112,12 @@ class HttpClientProvider extends BaseModuleProvider {
20827
21112
  if (!config && isURL(keyOrConfig)) {
20828
21113
  return { baseUri: keyOrConfig };
20829
21114
  }
21115
+ else if (!config && looksLikeURL(keyOrConfig)) {
21116
+ console.warn(`[HttpClientProvider] "${keyOrConfig}" looks like a URL but is missing the http:// or https:// protocol. ` +
21117
+ `Treating it as "https://${keyOrConfig}". ` +
21118
+ `Pass a fully-qualified URL to silence this warning.`);
21119
+ return { baseUri: `https://${keyOrConfig}` };
21120
+ }
20830
21121
  else if (!config) {
20831
21122
  throw new ClientNotFoundException(`No registered http client for key [${keyOrConfig}]`);
20832
21123
  }
@@ -20886,64 +21177,6 @@ function fromFetch(input, initWithSelector) {
20886
21177
  });
20887
21178
  }
20888
21179
 
20889
- /**
20890
- * Represents an error that occurs when handling an HTTP response.
20891
- * @template TResponse The type of the HTTP response.
20892
- */
20893
- class HttpResponseError extends Error {
20894
- response;
20895
- static Name = 'HttpResponseError';
20896
- constructor(message, response, options) {
20897
- super(message, options);
20898
- this.response = response;
20899
- }
20900
- }
20901
- /**
20902
- * Represents an error that occurs when handling a JSON response in an HTTP request.
20903
- * Extends the base `HttpResponseError` class.
20904
- *
20905
- * @template TType - The type of the data associated with the error.
20906
- * @template TResponse - The type of the HTTP response.
20907
- */
20908
- class HttpJsonResponseError extends HttpResponseError {
20909
- static Name = 'HttpJsonResponseError';
20910
- data;
20911
- /**
20912
- * Creates a new instance of `HttpJsonResponseError`.
20913
- *
20914
- * @param message - The error message.
20915
- * @param response - The HTTP response associated with the error.
20916
- * @param options - Additional options for the error, including the associated data.
20917
- */
20918
- constructor(message, response, options) {
20919
- super(message, response, options);
20920
- this.name = HttpJsonResponseError.Name;
20921
- this.data = options?.data;
20922
- }
20923
- }
20924
- /**
20925
- * Represents an error that occurs when handling a server-sent event (SSE) HTTP response.
20926
- *
20927
- * @template TType - The type of additional data associated with the error.
20928
- * @template TResponse - The type of the HTTP response object.
20929
- *
20930
- * @extends HttpResponseError<TResponse>
20931
- */
20932
- class ServerSentEventResponseError extends HttpResponseError {
20933
- static Name = 'ServerSentEventResponseError';
20934
- /**
20935
- * Creates a new instance of the error.
20936
- *
20937
- * @param message - The error message describing the cause of the error.
20938
- * @param response - The HTTP response associated with the error.
20939
- * @param options - Optional error options, which may include additional data of type `TType`.
20940
- */
20941
- constructor(message, response, options) {
20942
- super(message, response, options);
20943
- this.name = ServerSentEventResponseError.Name;
20944
- }
20945
- }
20946
-
20947
21180
  /**
20948
21181
  * Asynchronously parses the JSON data from a given HTTP response.
20949
21182
  *
@@ -21018,166 +21251,6 @@ const blobSelector = async (response) => {
21018
21251
  }
21019
21252
  };
21020
21253
 
21021
- const defaultDataParser = (data) => {
21022
- try {
21023
- return JSON.parse(data);
21024
- }
21025
- catch {
21026
- return data;
21027
- }
21028
- };
21029
- /**
21030
- * Parses a string containing Server-Sent Events (SSE) data into individual event objects.
21031
- *
21032
- * @template TData - The type of the parsed `data` field in the event.
21033
- * @param text - The raw SSE data as a string, where events are separated by double newlines.
21034
- * @param options - Optional configuration for parsing the events.
21035
- * @param options.dataParser - A custom parser function for the `data` field. Defaults to JSON parsing,
21036
- * falling back to returning the raw string if parsing fails.
21037
- *
21038
- * @returns A generator that yields `ServerSentEvent` objects parsed from the input string.
21039
- *
21040
- * @remarks
21041
- * - Empty lines and events with no fields are ignored.
21042
- * - If the `data` field cannot be parsed as JSON, it is returned as a plain string.
21043
- * - Fields other than `data` are stored as strings in the resulting `ServerSentEvent` object.
21044
- *
21045
- * @example
21046
- * ```typescript
21047
- * const sseData = `
21048
- * id: 1
21049
- * event: message
21050
- * data: {"key":"value"}
21051
- *
21052
- * id: 2
21053
- * event: update
21054
- * data: plain text
21055
- * `;
21056
- *
21057
- * for (const event of parseEvents(sseData)) {
21058
- * console.log(event);
21059
- * }
21060
- * // Output:
21061
- * // { id: "1", event: "message", data: { key: "value" } }
21062
- * // { id: "2", event: "update", data: "plain text" }
21063
- * ```
21064
- */
21065
- function* parseEvents(text, options) {
21066
- // Split the input string into individual event strings using double newline as separator
21067
- const eventStrings = text.split('\n\n');
21068
- const dataParser = options?.dataParser || defaultDataParser;
21069
- // Iterate through each event string
21070
- for (const eventStr of eventStrings) {
21071
- // Skip empty event strings (after trimming whitespace)
21072
- if (!eventStr.trim())
21073
- continue;
21074
- // Split the event string into lines (fields) using single newline
21075
- const lines = eventStr.split('\n');
21076
- // Use reduce to process each line in the event string
21077
- const event = lines.reduce((event, line) => {
21078
- // Skip empty lines
21079
- if (!line)
21080
- return event;
21081
- // Find the index of the first colon, which separates field name and value
21082
- const colonIndex = line.indexOf(':');
21083
- // Skip lines without a colon (invalid format)
21084
- if (colonIndex === -1)
21085
- return event;
21086
- // Extract the field name (before colon) and trim whitespace
21087
- const field = line.slice(0, colonIndex).trim();
21088
- // Extract the field value (after colon) and trim whitespace
21089
- const value = line.slice(colonIndex + 1).trim();
21090
- // Handle the 'data' field specially, attempting JSON parsing
21091
- if (field === 'data') {
21092
- event.data = dataParser(value);
21093
- }
21094
- else {
21095
- // For non-data fields, assign the value as a string to the event object
21096
- event[field] = value;
21097
- }
21098
- return event;
21099
- }, {});
21100
- // Only emit the event to the results if it has at least one field
21101
- if (Object.keys(event).length) {
21102
- yield event;
21103
- }
21104
- }
21105
- }
21106
- async function* readStream(reader, options) {
21107
- const skipHeartbeats = !!options?.skipHeartbeats;
21108
- const eventFilter = options?.eventFilter
21109
- ? Array.isArray(options.eventFilter)
21110
- ? options.eventFilter
21111
- : [options.eventFilter]
21112
- : null;
21113
- const decoder = new TextDecoder();
21114
- while (true) {
21115
- const { done, value } = await reader.read();
21116
- if (done) {
21117
- break;
21118
- }
21119
- const text = decoder.decode(value, { stream: true });
21120
- const events = parseEvents(text, { dataParser: options?.dataParser });
21121
- for (const event of events) {
21122
- if (event.retry) {
21123
- await new Promise((resolve) => setTimeout(resolve, Number.parseInt(event.retry ?? '300', 10)));
21124
- continue;
21125
- }
21126
- if (skipHeartbeats) {
21127
- // Skip comment-based heartbeats (no event, data, or id)
21128
- if (!event.event && !event.data && !event.id) {
21129
- continue;
21130
- }
21131
- // Skip named heartbeat events (e.g., event: heartbeat or event: ping)
21132
- if (event.event && ['heartbeat', 'ping'].includes(event.event)) {
21133
- continue;
21134
- }
21135
- }
21136
- if (!eventFilter || (event.event && eventFilter.includes(event.event))) {
21137
- yield event;
21138
- }
21139
- }
21140
- }
21141
- }
21142
- /**
21143
- * Transforms an SSE response into an Observable stream of parsed events.
21144
- * @param response - The HTTP response with Content-Type: text/event-stream.
21145
- * @param options - Optional configuration for event filtering and heartbeat handling.
21146
- * @param options.eventFilter - Filter events by type (single string or array).
21147
- * @param options.skipHeartbeats - Skip empty/heartbeat events if true.
21148
- * @param options.dataParser - Custom parser for the data field.
21149
- * @param options.abortSignal - Abort signal to cancel the stream.
21150
- * @returns An Observable emitting parsed ServerSentEvent objects.
21151
- * @throws ServerSentEventResponseError if response is invalid or stream fails.
21152
- */
21153
- const createSseSelector = (options) => {
21154
- return (response) => {
21155
- if (!response.ok) {
21156
- throw new ServerSentEventResponseError(`HTTP error! Status: ${response.status}`, response);
21157
- }
21158
- if (!response.body) {
21159
- throw new ServerSentEventResponseError('Response body is not readable', response);
21160
- }
21161
- if (!response.headers.get('Content-Type')?.includes('text/event-stream')) {
21162
- throw new ServerSentEventResponseError('Response is not a text/event-stream', response);
21163
- }
21164
- const reader = response.body.getReader();
21165
- return from(readStream(reader, {
21166
- dataParser: options?.dataParser,
21167
- skipHeartbeats: options?.skipHeartbeats,
21168
- eventFilter: options?.eventFilter,
21169
- })).pipe(
21170
- // Stop reading if the abort signal is triggered
21171
- takeUntil(options?.abortSignal ? fromEvent(options.abortSignal, 'abort') : EMPTY), finalize$2(async () => {
21172
- // cancel just in case of a pre-mature exit
21173
- await reader.cancel().catch(() => {
21174
- /** ignore cancellation errors */
21175
- });
21176
- reader.releaseLock();
21177
- }));
21178
- };
21179
- };
21180
-
21181
21254
  /** Base http client for executing requests */
21182
21255
  class HttpClient {
21183
21256
  uri;
@@ -21332,15 +21405,15 @@ class HttpClient {
21332
21405
  * @returns A `StreamResponse` that emits `ServerSentEvent<T>` objects as they are received from the server.
21333
21406
  *
21334
21407
  * @example
21335
- * const sse$ = httpClient.sse(
21336
- * '/events',
21337
- * { method: 'POST', body: JSON.stringify({ prompt: 'tell me a joke' }) },
21338
- * { eventFilter: ['message'] }
21408
+ * const sse$ = httpClient.sse$(
21409
+ * '/events',
21410
+ * { method: 'POST', body: JSON.stringify({ prompt: 'tell me a joke' }) },
21411
+ * { eventFilter: ['message'] },
21339
21412
  * );
21340
21413
  * sse$.subscribe({
21341
- * next: (event) => console.log(event),
21342
- * error: (err) => console.error(err),
21343
- * complete: () => console.log('Completed'),
21414
+ * next: (event) => console.log(event),
21415
+ * error: (err) => console.error(err),
21416
+ * complete: () => console.log('Completed'),
21344
21417
  * });
21345
21418
  */
21346
21419
  sse$(path, args, options) {
@@ -21397,6 +21470,7 @@ class HttpClient {
21397
21470
  const { selector, ...options } = args || {};
21398
21471
  const response$ = of({
21399
21472
  ...options,
21473
+ path,
21400
21474
  uri: this._resolveUrl(path),
21401
21475
  }).pipe(
21402
21476
  /** prepare request, allow extensions to modify request */
@@ -21503,16 +21577,21 @@ class HttpClientMsal extends HttpClient {
21503
21577
  * Merges the default scopes defined in the `HttpClientMsal` class with the scopes provided in the `init` parameter, if any.
21504
21578
  * This ensures that the request includes the necessary scopes for MSAL authentication.
21505
21579
  */
21506
- const args = Object.assign(init || {}, {
21580
+ const args = {
21581
+ ...init,
21507
21582
  scopes: this.defaultScopes.concat(init?.scopes || []),
21508
- });
21583
+ };
21509
21584
  return super._fetch$(path, args);
21510
21585
  }
21511
21586
  }
21512
21587
 
21513
21588
  /* eslint-disable @typescript-eslint/no-explicit-any */
21514
21589
  /**
21515
- * HTTP module with MSAL authentication.
21590
+ * Default HTTP module definition for Fusion Framework applications.
21591
+ *
21592
+ * The module uses `HttpClientMsal` as the default client implementation and,
21593
+ * when the auth module is available, installs a request handler that can acquire
21594
+ * bearer tokens for scoped requests.
21516
21595
  */
21517
21596
  const module$4 = {
21518
21597
  name: 'http',
@@ -21561,15 +21640,14 @@ const module$4 = {
21561
21640
  },
21562
21641
  };
21563
21642
  /**
21564
- * Configures the HTTP client with MSAL authentication.
21643
+ * Creates a module configurator that registers one named HTTP client.
21565
21644
  *
21566
- * This function creates a module configurator that can be used to configure the HTTP module
21567
- * with MSAL authentication. The configurator takes a name and a set of HTTP client options,
21568
- * and returns a module configurator that can be used to configure the HTTP module.
21645
+ * This is the convenience API for the common case where a setup step only needs to
21646
+ * register one client with `baseUri`, `defaultScopes`, handlers, or a custom constructor.
21569
21647
  *
21570
- * @param name - The name of the HTTP client configuration.
21571
- * @param args - The HTTP client options, including the MSAL configuration.
21572
- * @returns A module configurator that can be used to configure the HTTP module.
21648
+ * @param name - The client key used later with `createClient(name)`.
21649
+ * @param args - The named client configuration.
21650
+ * @returns A module configurator that registers the named client.
21573
21651
  */
21574
21652
  const configureHttpClient = (name, args) => ({
21575
21653
  module: module$4,
@@ -22437,12 +22515,58 @@ var immer = new Immer2();
22437
22515
  var produce = immer.produce;
22438
22516
  var castDraft = (value) => value;
22439
22517
 
22518
+ /**
22519
+ * RxJS operator that filters an action stream to only emit actions matching
22520
+ * one or more specified action types.
22521
+ *
22522
+ * @template TAction - The union of possible action types in the stream.
22523
+ * @template TType - The specific action type constant(s) to filter for.
22524
+ * @param types - One or more action type strings to filter by.
22525
+ * @returns An `OperatorFunction` that narrows the stream to matching actions.
22526
+ *
22527
+ * @example
22528
+ * ```ts
22529
+ * import { filterAction } from '@equinor/fusion-observable/operators';
22530
+ *
22531
+ * action$.pipe(
22532
+ * filterAction('increment', 'decrement'),
22533
+ * ).subscribe((action) => {
22534
+ * // action is narrowed to increment | decrement
22535
+ * });
22536
+ * ```
22537
+ */
22440
22538
  const filterAction = (...types) => filter((x) => types.includes(x.type));
22441
22539
 
22442
22540
  /**
22443
- * A specialized Observable that maintains internal state, which can be mutated by dispatching actions.
22541
+ * A specialized Observable that maintains internal state mutated by dispatching actions.
22542
+ *
22444
22543
  * Actions are processed sequentially by a reducer function to produce new state values.
22445
- * This class extends from Observable to allow subscribers to react to state changes over time.
22544
+ * Extends `Observable` so subscribers react to state changes over time.
22545
+ *
22546
+ * Inspired by Redux-style state management but built on top of RxJS, `FlowSubject`
22547
+ * combines a `BehaviorSubject` for state with a `Subject` for actions, providing
22548
+ * a reactive, observable state container.
22549
+ *
22550
+ * @template S - The state type managed by this subject.
22551
+ * @template A - The action type dispatched to this subject.
22552
+ *
22553
+ * @example
22554
+ * ```ts
22555
+ * import { FlowSubject, createReducer } from '@equinor/fusion-observable';
22556
+ *
22557
+ * type State = { count: number };
22558
+ * type Action = { type: 'increment' } | { type: 'decrement' };
22559
+ *
22560
+ * const reducer = createReducer<State, Action>({ count: 0 }, (builder) =>
22561
+ * builder
22562
+ * .addCase('increment', (state) => { state.count += 1; })
22563
+ * .addCase('decrement', (state) => { state.count -= 1; }),
22564
+ * );
22565
+ *
22566
+ * const subject = new FlowSubject(reducer);
22567
+ * subject.subscribe((state) => console.log(state.count));
22568
+ * subject.next({ type: 'increment' }); // logs: 1
22569
+ * ```
22446
22570
  */
22447
22571
  class FlowSubject extends Observable {
22448
22572
  /**
@@ -22539,21 +22663,38 @@ class FlowSubject extends Observable {
22539
22663
  .subscribe(this.#action);
22540
22664
  }
22541
22665
  /**
22542
- * Deprecated. Use `addFlow` instead.
22666
+ * @deprecated Use {@link FlowSubject.addFlow} instead.
22543
22667
  *
22544
- * @deprecated use `addFlow`
22545
- *
22546
- * @param fn The flow function to execute.
22668
+ * @param fn - The flow function to execute.
22547
22669
  * @returns A subscription to the flow.
22548
22670
  */
22549
22671
  addEpic(fn) {
22550
22672
  return this.addFlow(fn);
22551
22673
  }
22552
22674
  /**
22553
- * Adds a flow that listens for actions and performs side effects.
22675
+ * Adds a flow (epic-style) that transforms the action stream and optionally
22676
+ * reads state, then emits new actions back into the subject.
22554
22677
  *
22555
- * @param fn The flow function to execute.
22556
- * @returns A subscription to the flow.
22678
+ * Flows receive the full `action$` stream and the state observable, and must
22679
+ * return an `Observable<A>`. This is useful for complex async orchestration.
22680
+ *
22681
+ * @param fn - The flow function that receives `(action$, state$)` and returns an action observable.
22682
+ * @returns A subscription to the flow. Unsubscribe to remove the flow.
22683
+ * @throws {TypeError} If the flow function does not return an observable.
22684
+ *
22685
+ * @example
22686
+ * ```ts
22687
+ * subject.addFlow((action$) =>
22688
+ * action$.pipe(
22689
+ * filterAction('fetchData'),
22690
+ * switchMap((action) =>
22691
+ * fetchApi(action.payload).pipe(
22692
+ * map((data) => ({ type: 'fetchSuccess', payload: data })),
22693
+ * ),
22694
+ * ),
22695
+ * ),
22696
+ * );
22697
+ * ```
22557
22698
  */
22558
22699
  addFlow(fn) {
22559
22700
  const epic$ = fn(this.action$, this);
@@ -22568,23 +22709,27 @@ class FlowSubject extends Observable {
22568
22709
  .subscribe(this.#action);
22569
22710
  }
22570
22711
  /**
22571
- * Unsubscribes from actions and removes subscribers.
22712
+ * Tears down the subject by unsubscribing both the action and state subjects.
22713
+ *
22714
+ * After calling this method, the subject is no longer usable.
22572
22715
  */
22573
22716
  unsubscribe() {
22574
22717
  this.#action.unsubscribe();
22575
22718
  this.#state.unsubscribe();
22576
22719
  }
22577
22720
  /**
22578
- * Finalizes the subject and completes observers.
22721
+ * Completes both the action and state subjects, signalling to all
22722
+ * subscribers that no further values will be emitted.
22579
22723
  */
22580
22724
  complete() {
22581
22725
  this.#action.complete();
22582
22726
  this.#state.complete();
22583
22727
  }
22584
22728
  /**
22585
- * Clones the subject to a simple observable.
22729
+ * Returns a plain `Observable` of the state, hiding the subject's
22730
+ * `next`, `complete`, and other mutation methods.
22586
22731
  *
22587
- * @returns An observable of the state.
22732
+ * @returns A read-only observable of the state.
22588
22733
  */
22589
22734
  asObservable() {
22590
22735
  return this.#state.asObservable();
@@ -23158,7 +23303,7 @@ class TelemetryConfigurator extends BaseConfigBuilder {
23158
23303
  }
23159
23304
 
23160
23305
  // Generated by genversion.
23161
- const version$5 = '4.6.5-next.0';
23306
+ const version$5 = '5.0.0';
23162
23307
 
23163
23308
  /**
23164
23309
  * Enum representing the severity levels of telemetry items.
@@ -23310,6 +23455,12 @@ class FrameworkEvent {
23310
23455
  #cancelable;
23311
23456
  #canBubble;
23312
23457
  #created = Date.now();
23458
+ /**
23459
+ * Creates a new framework event.
23460
+ *
23461
+ * @param __type - The event name used for listener matching.
23462
+ * @param args - Initialization options including detail payload, source, and flags.
23463
+ */
23313
23464
  constructor(__type, args) {
23314
23465
  this.__type = __type;
23315
23466
  this.#detail = args.detail;
@@ -23568,6 +23719,16 @@ class Measurement {
23568
23719
  }
23569
23720
  }
23570
23721
 
23722
+ /**
23723
+ * Resolves metadata from a {@link MetadataExtractor} into an observable stream.
23724
+ *
23725
+ * Converts the extractor (which may be a static value, promise, function, or observable)
23726
+ * into a normalised `Observable` that emits the resolved metadata record.
23727
+ *
23728
+ * @param metadata - The metadata extractor to resolve.
23729
+ * @param args - Context passed to the extractor, including the telemetry item and optional module instances.
23730
+ * @returns An `Observable` emitting the resolved metadata record.
23731
+ */
23571
23732
  const resolveMetadata = (metadata, args) => {
23572
23733
  return toObservable(metadata, args);
23573
23734
  };
@@ -24043,6 +24204,21 @@ configurator) => {
24043
24204
  * `attachConfiguratorEvents` allows for the automatic attachment of configurator events to the telemetry builder,
24044
24205
  * ensuring that relevant events are captured and processed. __NOTE__ if the configurator crashes before the telemetry
24045
24206
  * builder is fully initialized, some events may be missed.
24207
+ *
24208
+ * @example
24209
+ * ```typescript
24210
+ * import { enableTelemetry } from '@equinor/fusion-framework-module-telemetry';
24211
+ *
24212
+ * const configure = (configurator) => {
24213
+ * enableTelemetry(configurator, {
24214
+ * attachConfiguratorEvents: true,
24215
+ * configure: (builder) => {
24216
+ * builder.setAdapter('console', new ConsoleAdapter());
24217
+ * builder.setMetadata(() => ({ appVersion: '1.0.0' }));
24218
+ * },
24219
+ * });
24220
+ * };
24221
+ * ```
24046
24222
  */
24047
24223
  const enableTelemetry = (
24048
24224
  // biome-ignore lint/suspicious/noExplicitAny: must be any to support all module types
@@ -40555,7 +40731,7 @@ const createClientLogCallback = (provider, metadata, scope) => {
40555
40731
  };
40556
40732
 
40557
40733
  // Generated by genversion.
40558
- const version$2 = '7.3.2-next.0';
40734
+ const version$2 = '8.0.1';
40559
40735
 
40560
40736
  /**
40561
40737
  * Zod schema for telemetry configuration validation.
@@ -40727,7 +40903,12 @@ class MsalConfigurator extends BaseConfigBuilder {
40727
40903
  return this;
40728
40904
  }
40729
40905
  /**
40730
- * @deprecated - since version 5.1.0, use setClient instead
40906
+ * Sets a pre-configured MSAL provider instance directly.
40907
+ *
40908
+ * @deprecated Since version 5.1.0. Use {@link MsalConfigurator.setClient | setClient} instead.
40909
+ *
40910
+ * @param provider - Pre-configured provider instance, or undefined to clear
40911
+ * @returns The configurator instance for method chaining
40731
40912
  */
40732
40913
  setProvider(provider) {
40733
40914
  this._set('provider', async () => provider);
@@ -40769,7 +40950,11 @@ class MsalConfigurator extends BaseConfigBuilder {
40769
40950
  }
40770
40951
  /**
40771
40952
  * Sets optional metadata to be included on all MSAL telemetry events.
40772
- * @deprecated Use setTelemetry({ metadata }) instead
40953
+ *
40954
+ * @deprecated Use {@link MsalConfigurator.setTelemetry | setTelemetry} instead.
40955
+ *
40956
+ * @param metadata - Key-value metadata to attach to telemetry events, or undefined to clear
40957
+ * @returns The configurator instance for method chaining
40773
40958
  */
40774
40959
  setTelemetryMetadata(metadata) {
40775
40960
  this._set('telemetry.metadata', async () => metadata);
@@ -41062,10 +41247,13 @@ function resolveVersion(version) {
41062
41247
  }
41063
41248
 
41064
41249
  /**
41065
- * Maps current AccountInfo to v2 AccountInfo format.
41250
+ * Maps a current (v4/v5) `AccountInfo` object to the v2-compatible `AccountInfo` format.
41066
41251
  *
41067
- * @param account - The current AccountInfo to convert
41068
- * @returns The v2 AccountInfo format
41252
+ * Strips properties that don't exist in v2, ensuring backward-compatible serialization
41253
+ * and type safety when passing account data through the v2 proxy layer.
41254
+ *
41255
+ * @param account - The current MSAL v4/v5 `AccountInfo` to convert
41256
+ * @returns A v2-compatible `AccountInfo` containing only fields recognised by MSAL v2 consumers
41069
41257
  */
41070
41258
  function mapAccountInfo(account) {
41071
41259
  return {
@@ -41080,10 +41268,14 @@ function mapAccountInfo(account) {
41080
41268
  }
41081
41269
 
41082
41270
  /**
41083
- * Maps current AuthenticationResult to v2 AuthenticationResult format.
41271
+ * Maps a current (v4/v5) `AuthenticationResult` to the v2-compatible format.
41272
+ *
41273
+ * Converts the full authentication result — including the nested account object —
41274
+ * to the subset of fields that MSAL v2 consumers expect. This enables the v2 proxy
41275
+ * layer to return type-safe results without exposing v4/v5-only properties.
41084
41276
  *
41085
- * @param result - The current AuthenticationResult to convert
41086
- * @returns The v2 AuthenticationResult format
41277
+ * @param result - The current MSAL v4/v5 `AuthenticationResult` to convert
41278
+ * @returns A v2-compatible `AuthenticationResult` with mapped account and token fields
41087
41279
  */
41088
41280
  function mapAuthenticationResult(result) {
41089
41281
  return {
@@ -41101,22 +41293,24 @@ function mapAuthenticationResult(result) {
41101
41293
  }
41102
41294
 
41103
41295
  /**
41104
- * Creates a v2-compatible proxy for MSAL PublicClientApplication.
41296
+ * Creates a v2-compatible proxy wrapper around an MSAL v4 client.
41105
41297
  *
41106
- * This function creates a proxy that wraps the MSAL v4 PublicClientApplication
41107
- * and provides v2-compatible method signatures and return types.
41298
+ * The proxy intercepts property access on the v4 `IMsalClient` and adapts method
41299
+ * signatures, return types, and account data to match the v2 `IAuthClient` interface.
41300
+ * This allows consumer code written against MSAL v2 to continue working unchanged
41301
+ * while the underlying implementation uses MSAL v4/v5.
41108
41302
  *
41109
- * @param client - The MSAL v4 PublicClientApplication instance
41110
- * @returns A proxy client with v2-compatible interface
41303
+ * @param client - The MSAL v4 `IMsalClient` instance to wrap
41304
+ * @returns A proxy implementing the v2-compatible `IAuthClient` interface
41111
41305
  *
41112
41306
  * @example
41113
41307
  * ```typescript
41114
- * const v4Client = new PublicClientApplication(config);
41115
- * const v2Client = createProxyClient_v2(v4Client);
41308
+ * const v4Client = new MsalClient(config);
41309
+ * const v2Client = createProxyClient(v4Client);
41116
41310
  *
41117
41311
  * // Use v2-compatible methods
41118
41312
  * const accounts = v2Client.getAllAccounts();
41119
- * const token = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
41313
+ * const result = await v2Client.acquireTokenSilent({ scopes: ['User.Read'], account });
41120
41314
  * ```
41121
41315
  */
41122
41316
  function createProxyClient(client) {
@@ -41691,6 +41885,19 @@ class MsalProvider extends BaseModuleProvider {
41691
41885
  * Apps should call acquireToken with actual scopes after initialization completes.
41692
41886
  */
41693
41887
  async initialize() {
41888
+ // Guard: skip authentication when running inside MSAL's hidden iframe.
41889
+ // MSAL uses a hidden iframe for silent token renewal (acquireTokenSilent).
41890
+ // The iframe loads the app URL, which would re-initialize MSAL and attempt
41891
+ // loginRedirect(), causing the "block_iframe_reload" error. Detect this
41892
+ // by checking if we're in an iframe and the URL contains MSAL's hash params.
41893
+ if (typeof window !== 'undefined' && window !== window.parent) {
41894
+ // Running inside an iframe — let the parent handle authentication.
41895
+ // Still initialize the client so handleRedirectPromise can process
41896
+ // the auth response and post it back to the parent frame.
41897
+ await this.#client.initialize();
41898
+ await this.#client.handleRedirectPromise();
41899
+ return;
41900
+ }
41694
41901
  const measurement = this._trackMeasurement('initialize', TelemetryLevel.Debug);
41695
41902
  // Initialize the underlying MSAL client first
41696
41903
  await this.#client.initialize();
@@ -41826,10 +42033,14 @@ class MsalProvider extends BaseModuleProvider {
41826
42033
  * ```
41827
42034
  */
41828
42035
  async acquireToken(options) {
42036
+ // Guard: when running inside MSAL's hidden iframe, only attempt silent
42037
+ // acquisition. Interactive flows (redirect/popup) must never be triggered
42038
+ // from an iframe — MSAL will throw "block_iframe_reload".
42039
+ const inIframe = typeof window !== 'undefined' && window !== window.parent;
41829
42040
  // Determine behavior and silent options, with defaults (redirect and true respectively)
41830
- const behavior = options?.behavior ?? 'redirect';
41831
- // Silent mode defaults to true, meaning the provider will attempt silent token acquisition first
41832
- const silent = options?.silent ?? true;
42041
+ const behavior = inIframe ? 'redirect' : (options?.behavior ?? 'redirect');
42042
+ // When in an iframe, force silent-only to prevent interactive fallback
42043
+ const silent = inIframe ? true : (options?.silent ?? true);
41833
42044
  const defaultScopes = this.defaultScopes;
41834
42045
  const inputRequest = options?.request;
41835
42046
  // Determine the account to use for token acquisition, prioritizing request-specific account, then active account
@@ -41877,6 +42088,15 @@ class MsalProvider extends BaseModuleProvider {
41877
42088
  return result;
41878
42089
  }
41879
42090
  catch (error) {
42091
+ // Inside MSAL's hidden iframe, silent acquisition may fail and the client
42092
+ // would fall back to acquireTokenRedirect which throws "block_iframe_reload".
42093
+ // Suppress this — the parent frame handles interactive auth.
42094
+ if (inIframe) {
42095
+ this._trackEvent('acquireToken.suppressed-in-iframe', TelemetryLevel.Debug, {
42096
+ properties: telemetryProperties,
42097
+ });
42098
+ return undefined;
42099
+ }
41880
42100
  this._trackException('acquireToken-failed', TelemetryLevel.Error, {
41881
42101
  exception: error,
41882
42102
  properties: telemetryProperties,
@@ -41932,6 +42152,10 @@ class MsalProvider extends BaseModuleProvider {
41932
42152
  * ```
41933
42153
  */
41934
42154
  async login(options) {
42155
+ // Guard: never attempt interactive login inside MSAL's hidden iframe.
42156
+ if (typeof window !== 'undefined' && window !== window.parent) {
42157
+ return undefined;
42158
+ }
41935
42159
  const { behavior = 'redirect', silent = true, request } = options;
41936
42160
  request.loginHint ??=
41937
42161
  this.#loginHint ?? this.account?.username ?? this.account?.loginHint ?? undefined;
@@ -42309,11 +42533,26 @@ const mergeQueue = (...args) => (source$) => source$.pipe(mergeMap(...args));
42309
42533
  */
42310
42534
  const switchQueue = (...args) => (source$) => source$.pipe(switchMap(...args));
42311
42535
  /**
42312
- * Transforms an Observable stream of `QueryTaskValue<TType>` into an Observable stream of `TType`.
42313
- * It extracts the `value` property from each `QueryTaskValue<TType>` in the stream.
42536
+ * Transforms a query result Observable into a plain value Observable by extracting the `value` property.
42537
+ *
42538
+ * Use this operator to strip query metadata (status, transaction, timestamps) from
42539
+ * the result stream when only the raw data is needed.
42540
+ *
42541
+ * @template TType - The type of the data value extracted from the query result.
42542
+ * @template TArgs - The type of the query arguments.
42543
+ *
42544
+ * @param source$ - An Observable stream of query task results (cached or completed).
42545
+ * @returns An Observable stream of `TType` where each emission is the extracted value.
42546
+ *
42547
+ * @example
42548
+ * ```typescript
42549
+ * import { Query, operators } from '@equinor/fusion-query';
42314
42550
  *
42315
- * @param source$ - An Observable stream of `QueryTaskValue<TType>`.
42316
- * @returns An Observable stream of `TType` where each emitted item is the `value` property from the input stream.
42551
+ * const query = new Query({ client: { fn: fetchUser }, key: (args) => args.id });
42552
+ * query.query({ id: '123' }).pipe(operators.queryValue).subscribe(user => {
42553
+ * console.log(user.name);
42554
+ * });
42555
+ * ```
42317
42556
  */
42318
42557
  const queryValue = (source$) => source$.pipe(map$1((entry) => entry.value));
42319
42558
 
@@ -43175,6 +43414,12 @@ class QueryClient extends Observable {
43175
43414
  getRequest(transaction) {
43176
43415
  return this.#state.value[transaction];
43177
43416
  }
43417
+ /**
43418
+ * Retrieves the request associated with the specified reference string.
43419
+ *
43420
+ * @param ref - The reference identifier to search for.
43421
+ * @returns The request matching the reference, or `undefined` if not found.
43422
+ */
43178
43423
  getRequestByRef(ref) {
43179
43424
  return Object.values(this.#state.value).find((x) => x.ref === ref);
43180
43425
  }
@@ -43715,7 +43960,13 @@ class QueryTask extends Subject {
43715
43960
  }
43716
43961
 
43717
43962
  /**
43718
- * Base class for Query events
43963
+ * Concrete event class emitted by the {@link Query} instance itself.
43964
+ *
43965
+ * Represents lifecycle events for query creation, completion, caching, and job management.
43966
+ * Subscribers can use `instanceof QueryEvent` to filter for query-level events
43967
+ * when the aggregated `event$` stream also contains client and cache events.
43968
+ *
43969
+ * @template TData - The type of data payload carried by this event.
43719
43970
  */
43720
43971
  class QueryEvent {
43721
43972
  type;
@@ -43835,8 +44086,12 @@ const getQueueOperator = (type = 'switch') => {
43835
44086
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43836
44087
  class Query {
43837
44088
  /**
43838
- * A static method that extracts the value from a query task.
43839
- * It is a utility function that can be used externally to access the result of a task.
44089
+ * Static utility that extracts the raw value from a query result Observable.
44090
+ *
44091
+ * Transforms a stream of `QueryTaskValue<TType>` into a plain `Observable<TType>`,
44092
+ * stripping away query metadata such as status, transaction, and timestamps.
44093
+ *
44094
+ * @see {@link queryValue} for the standalone operator function.
43840
44095
  */
43841
44096
  static extractQueryValue = queryValue;
43842
44097
  /**
@@ -44109,6 +44364,21 @@ class Query {
44109
44364
  fn(this._query(payload, args).pipe(throwIfEmpty())).then(resolve, reject);
44110
44365
  });
44111
44366
  }
44367
+ /**
44368
+ * Executes a query that remains subscribed to cache mutations after the initial fetch completes.
44369
+ *
44370
+ * Unlike {@link Query.query}, which completes after emitting the result, `persistentQuery`
44371
+ * continues to emit whenever the underlying cache entry is updated or mutated.
44372
+ * This is useful for scenarios where the UI must reflect optimistic updates,
44373
+ * background refetches, or external cache mutations in real time.
44374
+ *
44375
+ * The returned Observable deduplicates emissions based on the transaction identifier
44376
+ * and mutation timestamp, so subscribers only receive meaningful state changes.
44377
+ *
44378
+ * @param args - The arguments to pass to the query function.
44379
+ * @param options - Optional query options including signal, retry, and cache validation overrides.
44380
+ * @returns An Observable that emits cached and completed results, and continues emitting on cache mutations.
44381
+ */
44112
44382
  persistentQuery(args, options) {
44113
44383
  const key = this.#generateCacheKey(args);
44114
44384
  const original = this._query(args, options);
@@ -44340,7 +44610,12 @@ class Query {
44340
44610
  }
44341
44611
 
44342
44612
  /**
44343
- * Represents a service from the service discovery API.
44613
+ * Zod schema for a single service object returned by the service
44614
+ * discovery API.
44615
+ *
44616
+ * Validates required fields (`key`, `uri`) and optional metadata, then
44617
+ * transforms the result to include a backward-compatible `defaultScopes`
44618
+ * accessor.
44344
44619
  */
44345
44620
  const ApiService = z
44346
44621
  .object({
@@ -44361,26 +44636,29 @@ const ApiService = z
44361
44636
  },
44362
44637
  }));
44363
44638
  /**
44364
- * Represents a list of services from the service discovery API.
44639
+ * Zod schema for the service list returned by the service discovery API.
44365
44640
  *
44366
- * This constant is an array of `ApiService` objects, which are defined
44367
- * elsewhere in the codebase. It uses the `z.array` method from the Zod
44368
- * library to enforce that the array contains only `ApiService` objects.
44369
- *
44370
- * @constant
44371
- * @description A list of services from the service discovery API.
44641
+ * Parses and validates an array of service objects, each conforming to the
44642
+ * `ApiService` schema above. Used internally by
44643
+ * {@link ServiceDiscoveryClient} to validate API responses.
44372
44644
  */
44373
44645
  const ApiServices = z
44374
44646
  .array(ApiService)
44375
44647
  .describe('A list of services from the service discovery API');
44376
44648
 
44649
+ /** Cache key used by the internal {@link Query} instance. */
44377
44650
  const queryKey = 'services';
44378
44651
  /**
44379
- * Transforms a Response object into an ObservableInput of Service arrays.
44652
+ * Transforms a fetch {@link Response} into an observable that emits a
44653
+ * validated array of {@link Service} objects.
44654
+ *
44655
+ * The response body is parsed as JSON, validated against the
44656
+ * {@link ApiServices} Zod schema, and optionally piped through a
44657
+ * `postProcess` operator (used for session overrides).
44380
44658
  *
44381
- * @param response - The Response object to be transformed.
44382
- * @param postProcess - Optional callback to process the value.
44383
- * @returns An ObservableInput that emits an array of Service objects.
44659
+ * @param response - Raw fetch response from the service discovery API.
44660
+ * @param postProcess - Optional RxJS operator to transform the parsed list.
44661
+ * @returns An `ObservableInput` emitting the final `Service[]`.
44384
44662
  */
44385
44663
  const serviceResponseSelector = (response, postProcess) => {
44386
44664
  // parse response by using the jsonSelector
@@ -44392,12 +44670,26 @@ const serviceResponseSelector = (response, postProcess) => {
44392
44670
  }
44393
44671
  return result$;
44394
44672
  };
44673
+ /**
44674
+ * Default service discovery client that fetches endpoints from a remote API,
44675
+ * validates the response with Zod, caches results via {@link Query}, and
44676
+ * supports `sessionStorage`-based overrides.
44677
+ *
44678
+ * @remarks
44679
+ * Results are cached for 5 minutes. When `allow_cache` is `true`,
44680
+ * {@link resolveServices} returns the first cached value immediately;
44681
+ * otherwise it waits for the latest API response.
44682
+ */
44395
44683
  class ServiceDiscoveryClient {
44396
44684
  #query;
44397
- /** Endpoint for fetching services from API */
44685
+ /** Sub-path appended to the HTTP client's base URI when fetching services. */
44398
44686
  endpoint;
44399
- /** HTTP client for fetching services */
44687
+ /** HTTP client used to call the service discovery API. */
44400
44688
  http;
44689
+ /**
44690
+ * @param options - Construction options including the HTTP client,
44691
+ * optional endpoint path, and optional post-processing operator.
44692
+ */
44401
44693
  constructor(options) {
44402
44694
  this.http = options.http;
44403
44695
  this.endpoint = options.endpoint;
@@ -44414,10 +44706,14 @@ class ServiceDiscoveryClient {
44414
44706
  expire: 5 * 60 * 1000,
44415
44707
  });
44416
44708
  }
44709
+ /** {@inheritDoc IServiceDiscoveryClient.resolveServices} */
44417
44710
  resolveServices(allow_cache) {
44711
+ // firstValueFrom returns the cached snapshot; lastValueFrom waits for
44712
+ // the freshest value from the query
44418
44713
  const fn = allow_cache ? firstValueFrom : lastValueFrom;
44419
44714
  return fn(Query.extractQueryValue(this.#query.query()));
44420
44715
  }
44716
+ /** {@inheritDoc IServiceDiscoveryClient.resolveService} */
44421
44717
  async resolveService(key, allow_cache) {
44422
44718
  const services = await this.resolveServices(allow_cache);
44423
44719
  const service = services.find((s) => s.key === key);
@@ -44428,7 +44724,38 @@ class ServiceDiscoveryClient {
44428
44724
  }
44429
44725
  }
44430
44726
 
44727
+ /**
44728
+ * Configuration builder for the Service Discovery module.
44729
+ *
44730
+ * Provides a fluent API to set up how service endpoints are resolved.
44731
+ * The simplest path is to call
44732
+ * {@link ServiceDiscoveryConfigurator.configureServiceDiscoveryClientByClientKey | configureServiceDiscoveryClientByClientKey}
44733
+ * with the HTTP client key that points to the service discovery backend.
44734
+ *
44735
+ * For full control, use
44736
+ * {@link ServiceDiscoveryConfigurator.setServiceDiscoveryClient | setServiceDiscoveryClient}
44737
+ * to supply a custom {@link IServiceDiscoveryClient} implementation.
44738
+ *
44739
+ * @example
44740
+ * ```typescript
44741
+ * enableServiceDiscovery(configurator, async (builder) => {
44742
+ * builder.configureServiceDiscoveryClientByClientKey('sd_custom', '/services/v2');
44743
+ * });
44744
+ * ```
44745
+ */
44431
44746
  class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44747
+ /**
44748
+ * Creates the final {@link ServiceDiscoveryConfig}.
44749
+ *
44750
+ * When no explicit discovery client has been registered, this method
44751
+ * auto-detects an HTTP client with key `"service_discovery"` and uses it
44752
+ * as the default transport.
44753
+ *
44754
+ * @param init - Builder callback arguments providing module accessors.
44755
+ * @param initial - Optional partial config inherited from a parent module.
44756
+ * @returns The fully resolved configuration.
44757
+ * @throws {Error} When the HTTP module is not registered.
44758
+ */
44432
44759
  async _createConfig(init, initial) {
44433
44760
  if (!init.hasModule('http')) {
44434
44761
  throw new Error('http module is required');
@@ -44445,12 +44772,12 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44445
44772
  return lastValueFrom(from(super._createConfig(init, initial)));
44446
44773
  }
44447
44774
  /**
44448
- * Processes the service discovery configuration.
44775
+ * Validates and finalizes the service discovery configuration.
44449
44776
  *
44450
- * @param config - A partial configuration object for service discovery.
44451
- * @param init - Initialization arguments for the configuration builder callback.
44452
- * @returns An observable input of the complete service discovery configuration.
44453
- * @throws Will throw an error if `discoveryClient` is not configured.
44777
+ * @param config - Partial configuration assembled by the builder.
44778
+ * @param init - Builder callback arguments.
44779
+ * @returns An observable that emits the complete {@link ServiceDiscoveryConfig}.
44780
+ * @throws {Error} When `discoveryClient` has not been configured.
44454
44781
  */
44455
44782
  _processConfig(config, init) {
44456
44783
  if (!config.discoveryClient) {
@@ -44459,22 +44786,50 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44459
44786
  return super._processConfig(config, init);
44460
44787
  }
44461
44788
  /**
44462
- * Sets the service discovery client.
44789
+ * Sets the service discovery client directly.
44790
+ *
44791
+ * Accepts either a ready-made {@link IServiceDiscoveryClient} instance or a
44792
+ * {@link ConfigBuilderCallback} that will be invoked during module
44793
+ * initialization to produce one.
44794
+ *
44795
+ * Use this method when you need full control over service resolution
44796
+ * (e.g. a mock client for testing or a static service list).
44463
44797
  *
44464
- * @param discoveryClient - An instance of `IServiceDiscoveryClient` or a callback function that returns an instance of `IServiceDiscoveryClient`.
44798
+ * @param discoveryClient - A client instance or an async factory function.
44465
44799
  *
44466
- * This method configures the service discovery client by either directly setting the provided instance or by invoking the provided callback function to obtain the instance.
44800
+ * @example
44801
+ * ```typescript
44802
+ * // Static / mock client
44803
+ * builder.setServiceDiscoveryClient({
44804
+ * resolveServices: async () => [{ key: 'api', uri: 'https://localhost:5000', defaultScopes: [] }],
44805
+ * resolveService: async (key) => ({ key, uri: 'https://localhost:5000', defaultScopes: [] }),
44806
+ * });
44807
+ * ```
44467
44808
  */
44468
44809
  setServiceDiscoveryClient(discoveryClient) {
44469
44810
  this._set('discoveryClient', typeof discoveryClient === 'function' ? discoveryClient : async () => discoveryClient);
44470
44811
  }
44471
44812
  /**
44472
- * Configures the Service Discovery Client with the provided configuration callback.
44813
+ * Configures a {@link ServiceDiscoveryClient} with a custom HTTP client and
44814
+ * optional endpoint path.
44815
+ *
44816
+ * This is the mid-level configuration path: you supply the transport
44817
+ * details and the module constructs a standard
44818
+ * {@link ServiceDiscoveryClient} with built-in caching, response parsing,
44819
+ * and `sessionStorage` override support.
44473
44820
  *
44474
- * @param configCallback - A callback function that takes an argument of type `{ httpClient: IHttpClient; endpoint?: string }`
44475
- * and returns a configuration object. The `httpClient` is required, while the `endpoint` is optional.
44821
+ * @param configCallback - Async factory that must return
44822
+ * `{ httpClient, endpoint? }`. The `httpClient` is used to call the
44823
+ * service discovery API at the given `endpoint` (defaults to `""`).
44824
+ * @throws {Error} When the factory does not return an `httpClient`.
44476
44825
  *
44477
- * @throws {Error} Throws an error if `httpClient` is not provided in the configuration.
44826
+ * @example
44827
+ * ```typescript
44828
+ * builder.configureServiceDiscoveryClient(async ({ requireInstance }) => {
44829
+ * const http = await requireInstance('http');
44830
+ * return { httpClient: http.createClient('sd'), endpoint: '/services/v2' };
44831
+ * });
44832
+ * ```
44478
44833
  */
44479
44834
  configureServiceDiscoveryClient(configCallback) {
44480
44835
  this.setServiceDiscoveryClient(async (args) => {
@@ -44484,9 +44839,16 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44484
44839
  http: httpClient,
44485
44840
  endpoint,
44486
44841
  postProcess: map$1((input) => {
44842
+ // Get a reference to sessionStorage from globalThis
44843
+ const storage = typeof globalThis !== 'undefined' ? globalThis.sessionStorage : undefined;
44844
+ // Check if sessionStorage is available before attempting to access it.
44845
+ // If sessionStorage is not available, return the input as is without attempting to apply any overrides.
44846
+ if (!storage) {
44847
+ return input;
44848
+ }
44487
44849
  // Check if there are any session overrides in session storage.
44488
44850
  try {
44489
- const sessionOverrides = JSON.parse(sessionStorage.getItem('overriddenServiceDiscoveryUrls') || '{}');
44851
+ const sessionOverrides = JSON.parse(storage.getItem('overriddenServiceDiscoveryUrls') || '{}');
44490
44852
  for (const [key, { url, scopes }] of Object.entries(sessionOverrides)) {
44491
44853
  const service = input.find((service) => service.key === key);
44492
44854
  // If the service can be found, override the values with the values
@@ -44509,17 +44871,24 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44509
44871
  });
44510
44872
  }
44511
44873
  /**
44512
- * Configures a service discovery client using the provided client key and optional endpoint.
44874
+ * Configures service discovery using a named HTTP client key.
44513
44875
  *
44514
- * @param clientKey - The key used to identify the client.
44515
- * @param endpoint - An optional endpoint to be used by the service discovery client.
44876
+ * This is the simplest configuration path. The HTTP module must already
44877
+ * have a client registered under `clientKey`. If `endpoint` is omitted
44878
+ * the client calls the root path of the HTTP client's base URI.
44516
44879
  *
44517
- * @remarks
44518
- * The http module must have a configured client which match provided `clientKey`.
44880
+ * @param clientKey - Key of the HTTP client to use for service discovery
44881
+ * requests (must match an entry in the HTTP module configuration).
44882
+ * @param endpoint - Optional sub-path appended to the client's base URI
44883
+ * when fetching the service list.
44519
44884
  *
44520
- * This method sets up the service discovery client by requiring an HTTP provider instance,
44521
- * creating an HTTP client with the given client key, and returning an object containing
44522
- * the HTTP client and the optional endpoint.
44885
+ * @example
44886
+ * ```typescript
44887
+ * builder.configureServiceDiscoveryClientByClientKey(
44888
+ * 'service_discovery',
44889
+ * '/custom/services',
44890
+ * );
44891
+ * ```
44523
44892
  */
44524
44893
  configureServiceDiscoveryClientByClientKey(clientKey, endpoint) {
44525
44894
  this.configureServiceDiscoveryClient(async ({ requireInstance }) => {
@@ -44534,11 +44903,22 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
44534
44903
  }
44535
44904
 
44536
44905
  // Generated by genversion.
44537
- const version$1 = '9.1.2-next.0';
44906
+ const version$1 = '10.0.0';
44538
44907
 
44908
+ /**
44909
+ * Default implementation of {@link IServiceDiscoveryProvider}.
44910
+ *
44911
+ * Created during module initialization and delegates service resolution to
44912
+ * the underlying {@link IServiceDiscoveryClient} while using the
44913
+ * {@link HttpModule} to construct pre-configured HTTP clients.
44914
+ */
44539
44915
  class ServiceDiscoveryProvider extends BaseModuleProvider {
44540
44916
  config;
44541
44917
  _http;
44918
+ /**
44919
+ * @param config - Resolved service discovery configuration.
44920
+ * @param _http - HTTP module instance used to create clients.
44921
+ */
44542
44922
  constructor(config, _http) {
44543
44923
  super({
44544
44924
  version: version$1,
@@ -44547,12 +44927,15 @@ class ServiceDiscoveryProvider extends BaseModuleProvider {
44547
44927
  this.config = config;
44548
44928
  this._http = _http;
44549
44929
  }
44930
+ /** {@inheritDoc IServiceDiscoveryProvider.resolveServices} */
44550
44931
  resolveServices() {
44551
44932
  return this.config.discoveryClient.resolveServices();
44552
44933
  }
44934
+ /** {@inheritDoc IServiceDiscoveryProvider.resolveService} */
44553
44935
  async resolveService(key) {
44554
44936
  return this.config.discoveryClient.resolveService(key);
44555
44937
  }
44938
+ /** {@inheritDoc IServiceDiscoveryProvider.createClient} */
44556
44939
  async createClient(name, opt) {
44557
44940
  const service = await this.resolveService(name);
44558
44941
  if (!service) {
@@ -44564,6 +44947,7 @@ class ServiceDiscoveryProvider extends BaseModuleProvider {
44564
44947
  defaultScopes: service.scopes,
44565
44948
  });
44566
44949
  }
44950
+ /** {@inheritDoc IServiceDiscoveryProvider.configureClient} */
44567
44951
  async configureClient(serviceName, config) {
44568
44952
  const { key, alias } = typeof serviceName === 'string' ? { key: serviceName, alias: serviceName } : serviceName;
44569
44953
  const { uri: baseUri, scopes: defaultScopes } = await this.resolveService(key);
@@ -44571,25 +44955,27 @@ class ServiceDiscoveryProvider extends BaseModuleProvider {
44571
44955
  }
44572
44956
  }
44573
44957
 
44958
+ /**
44959
+ * Module identifier used to register and look up the Service Discovery module
44960
+ * within the Fusion Framework module system.
44961
+ */
44574
44962
  const moduleName = 'serviceDiscovery';
44575
44963
  /**
44576
- * Represents the Service Discovery module configuration.
44964
+ * Service Discovery module definition.
44577
44965
  *
44578
- * @remarks
44579
- * This module is responsible for configuring and initializing the service discovery mechanism.
44580
- * It ensures that the service discovery configuration is created and the necessary dependencies
44581
- * are initialized before providing the service discovery provider.
44966
+ * Configures and initializes the service discovery mechanism within the
44967
+ * Fusion Framework module system. During initialization the module:
44582
44968
  *
44583
- * @returns {Promise<ServiceDiscoveryProvider>} - Returns a promise that resolves to the service discovery provider.
44969
+ * 1. Creates the {@link ServiceDiscoveryConfig} (optionally inheriting the
44970
+ * parent module's discovery client so sub-modules share cache).
44971
+ * 2. Resolves the required {@link HttpModule} instance.
44972
+ * 3. Returns a {@link ServiceDiscoveryProvider} ready to resolve endpoints.
44584
44973
  *
44585
44974
  * @remarks
44586
- * The initialization process involves creating the service discovery configuration, which may include
44587
- * inheriting configurations from a parent module. This pattern, while allowing reuse of cache and ensuring
44588
- * up-to-date configurations, can be risky as it exposes the child module to potential breaking changes
44589
- * from the parent module's client.
44590
- *
44591
- * Additionally, the service discovery module requires the HTTP module to be initialized before it can
44592
- * function properly.
44975
+ * When a parent module exposes its own `serviceDiscovery` config, the child
44976
+ * module reuses that configuration by default. This enables shared caching
44977
+ * and consistent service resolution but means breaking changes in the
44978
+ * parent's client can affect child modules.
44593
44979
  */
44594
44980
  const module$1 = {
44595
44981
  name: moduleName,
@@ -44613,20 +44999,31 @@ const module$1 = {
44613
44999
  },
44614
45000
  };
44615
45001
  /**
44616
- * Configures the Service Discovery module.
45002
+ * Creates a module configurator object for the Service Discovery module.
45003
+ *
45004
+ * Use this when you need to add service discovery to a
45005
+ * {@link ModulesConfigurator} via `addConfig` and want full control over
45006
+ * the configuration callback.
45007
+ *
45008
+ * For the simpler "just enable it" path, prefer {@link enableServiceDiscovery}.
44617
45009
  *
44618
- * @template TRef - The type reference for the module configurator.
44619
- * @param callback - A function that takes a `ServiceDiscoveryConfigurator` and returns a promise that resolves when the configuration is complete.
44620
- * @returns An object implementing `IModuleConfigurator` for the `ServiceDiscoveryModule` with the provided configuration.
45010
+ * @template TRef - Module reference type forwarded to the configurator.
45011
+ * @param callback - Receives a {@link ServiceDiscoveryConfigurator} and must
45012
+ * return a `Promise` that resolves when configuration is complete.
45013
+ * @returns An `IModuleConfigurator` that can be passed to
45014
+ * `ModulesConfigurator.addConfig`.
44621
45015
  *
44622
45016
  * @example
44623
45017
  * ```typescript
44624
45018
  * import { configureServiceDiscovery } from '@equinor/fusion-framework-module-service-discovery';
44625
45019
  *
44626
- * const config = (configurator: ModuleConfigurator) => {
44627
- * configurator.addConfig(configureServiceDiscovery(async (config) => {
44628
- * // custom configuration
44629
- * });
45020
+ * const configure = (configurator: ModulesConfigurator) => {
45021
+ * configurator.addConfig(
45022
+ * configureServiceDiscovery(async (builder) => {
45023
+ * builder.configureServiceDiscoveryClientByClientKey('my_sd_key');
45024
+ * }),
45025
+ * );
45026
+ * };
44630
45027
  * ```
44631
45028
  */
44632
45029
  const configureServiceDiscovery = (callback) => ({
@@ -44634,24 +45031,29 @@ const configureServiceDiscovery = (callback) => ({
44634
45031
  configure: (config) => callback(config),
44635
45032
  });
44636
45033
  /**
44637
- * Enables the service discovery module by adding its configuration to the provided configurator.
45034
+ * Enables the Service Discovery module on a {@link ModulesConfigurator}.
45035
+ *
45036
+ * This is the recommended entry point for most consumers. When called
45037
+ * without a callback the module auto-detects an HTTP client registered
45038
+ * under the key `"service_discovery"`. Pass a callback to override the
45039
+ * client key, endpoint, or provide a fully custom discovery client.
44638
45040
  *
44639
- * @param configurator - The configurator to which the service discovery configuration will be added.
44640
- * @param callback - An optional callback function that can be used to customize the service discovery configuration.
45041
+ * @param configurator - The modules configurator to register the module on.
45042
+ * Must already include {@link HttpModule}.
45043
+ * @param callback - Optional async callback receiving a
45044
+ * {@link ServiceDiscoveryConfigurator} for advanced setup.
44641
45045
  *
44642
45046
  * @example
44643
45047
  * ```typescript
44644
45048
  * import { enableServiceDiscovery } from '@equinor/fusion-framework-module-service-discovery';
44645
45049
  *
44646
- * const config = (configurator: ModuleConfigurator) => {
44647
- * // simple
44648
- * enableServiceDiscovery(configurator);
45050
+ * // Simplest usage auto-detects the 'service_discovery' HTTP client
45051
+ * enableServiceDiscovery(configurator);
44649
45052
  *
44650
- * // with custom configuration
44651
- * enableServiceDiscovery(configurator, async (config) => {
44652
- * config.configureServiceDiscoveryClientByClientKey('service-discovery-custom');
44653
- * });
44654
- * };
45053
+ * // Custom HTTP client key
45054
+ * enableServiceDiscovery(configurator, async (builder) => {
45055
+ * builder.configureServiceDiscoveryClientByClientKey('sd_custom');
45056
+ * });
44655
45057
  * ```
44656
45058
  */
44657
45059
  const enableServiceDiscovery = (configurator, callback) => {
@@ -44749,7 +45151,20 @@ class BaseTelemetryAdapter {
44749
45151
 
44750
45152
  /**
44751
45153
  * Telemetry adapter that outputs telemetry data to the browser console
44752
- * with formatted titles and color-coded log levels
45154
+ * with formatted titles and colour-coded log levels.
45155
+ *
45156
+ * Each telemetry item is logged using the console method that matches its
45157
+ * {@link TelemetryLevel} (e.g. `console.error` for `Error` / `Critical`,
45158
+ * `console.warn` for `Warning`). Event names are prefixed with a styled
45159
+ * application title badge.
45160
+ *
45161
+ * @example
45162
+ * ```typescript
45163
+ * import { ConsoleAdapter } from '@equinor/fusion-framework-module-telemetry/console-adapter';
45164
+ *
45165
+ * const adapter = new ConsoleAdapter({ title: 'MyApp' });
45166
+ * configurator.setAdapter(ConsoleAdapter.Identifier, adapter);
45167
+ * ```
44753
45168
  */
44754
45169
  class ConsoleAdapter extends BaseTelemetryAdapter {
44755
45170
  /** Default identifier for console adapter instances */
@@ -44893,6 +45308,36 @@ class ConsoleAdapter extends BaseTelemetryAdapter {
44893
45308
  }
44894
45309
  }
44895
45310
 
45311
+ /**
45312
+ * Registers the Fusion SPA service worker and wires token acquisition.
45313
+ *
45314
+ * @remarks
45315
+ * The service worker intercepts outgoing fetch requests that match
45316
+ * the configured {@link ResourceConfiguration | resource patterns},
45317
+ * rewrites URLs, and injects Bearer tokens obtained from the MSAL
45318
+ * module. This function:
45319
+ *
45320
+ * 1. Registers `/@fusion-spa-sw.js` as a module service worker.
45321
+ * 2. Listens for `GET_TOKEN` messages from the worker and responds
45322
+ * with MSAL access tokens.
45323
+ * 3. Sends the `INIT_CONFIG` message containing resource configurations
45324
+ * to the active worker once it is ready and controlling the page.
45325
+ *
45326
+ * @param framework - An initialized Fusion Framework instance that
45327
+ * includes the {@link MsalModule} (for token acquisition) and
45328
+ * {@link TelemetryModule} (for structured logging).
45329
+ * @throws {Error} When service workers are not supported by the browser.
45330
+ * @throws {Error} When the `FUSION_SPA_SERVICE_WORKER_RESOURCES`
45331
+ * environment variable is not defined.
45332
+ *
45333
+ * @example
45334
+ * ```ts
45335
+ * import { registerServiceWorker } from '@equinor/fusion-framework-vite-plugin-spa/html';
45336
+ *
45337
+ * const framework = await configurator.initialize();
45338
+ * await registerServiceWorker(framework);
45339
+ * ```
45340
+ */
44896
45341
  async function registerServiceWorker(framework) {
44897
45342
  const telemetry = framework.telemetry;
44898
45343
  if ('serviceWorker' in navigator === false) {
@@ -45053,7 +45498,7 @@ async function registerServiceWorker(framework) {
45053
45498
  }
45054
45499
 
45055
45500
  // Generated by genversion.
45056
- const version = '3.1.12-next.0';
45501
+ const version = '4.0.1';
45057
45502
 
45058
45503
  // Allow dynamic import without vite
45059
45504
  const importWithoutVite = (path) => import(/* @vite-ignore */ path);