@equinor/fusion-framework-vite-plugin-spa 4.0.16 → 4.0.17-next.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.
@@ -6314,7 +6314,7 @@ async function runDisposePhase(ctx, instance, ref) {
6314
6314
  }
6315
6315
 
6316
6316
  // Generated by genversion.
6317
- const version$8 = '6.1.2';
6317
+ const version$8 = '6.1.3-next.0';
6318
6318
 
6319
6319
  // 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
6320
6320
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -6449,7 +6449,34 @@ class ModulesConfigurator {
6449
6449
  * @param modules - Optional array of module descriptors to pre-register.
6450
6450
  */
6451
6451
  constructor(modules) {
6452
- this._modules = new Set(modules);
6452
+ this._modules = new Set(modules ? this._dedupeModulesByName(modules) : []);
6453
+ }
6454
+ /**
6455
+ * Keeps the last registration for each module name.
6456
+ *
6457
+ * @param modules - Module descriptors to deduplicate.
6458
+ * @returns The deduplicated module descriptors.
6459
+ */
6460
+ _dedupeModulesByName(modules) {
6461
+ const lastByName = new Map();
6462
+ // Iterate in registration order so later descriptors intentionally override earlier ones.
6463
+ for (const module of modules) {
6464
+ lastByName.set(module.name, module);
6465
+ }
6466
+ return Array.from(lastByName.values());
6467
+ }
6468
+ /**
6469
+ * Removes lifecycle callbacks belonging to a replaced module.
6470
+ *
6471
+ * @param moduleName - Name of the module whose callbacks are removed.
6472
+ */
6473
+ _removeModuleCallbacks(moduleName) {
6474
+ // Remove callbacks from each lifecycle phase so replaced modules cannot run stale behavior.
6475
+ this._configs = this._configs.filter((callback) => callback.moduleName !== moduleName);
6476
+ // Keep cleanup callbacks aligned with the module replacement.
6477
+ this._afterConfiguration = this._afterConfiguration.filter((callback) => callback.moduleName !== moduleName);
6478
+ // Remove initialization callbacks as well, preventing the old module from being initialized.
6479
+ this._afterInit = this._afterInit.filter((callback) => callback.moduleName !== moduleName);
6453
6480
  }
6454
6481
  /**
6455
6482
  * Returns all registered module descriptors as an ordered array.
@@ -6476,6 +6503,9 @@ class ModulesConfigurator {
6476
6503
  /**
6477
6504
  * Registers a single module configurator.
6478
6505
  *
6506
+ * If a module with the same `name` was already registered, the previous
6507
+ * registration is replaced so the last added module wins.
6508
+ *
6479
6509
  * Adds the module to the known module set and registers the optional
6480
6510
  * `configure`, `afterConfig`, and `afterInit` callbacks into their
6481
6511
  * respective lifecycle phase arrays.
@@ -6486,7 +6516,26 @@ class ModulesConfigurator {
6486
6516
  */
6487
6517
  addConfig(config) {
6488
6518
  const { module, afterConfig, afterInit, configure } = config;
6489
- this._modules.add(module);
6519
+ // Find an existing descriptor so re-registering a name can replace all of its lifecycle hooks.
6520
+ const existingModule = Array.from(this._modules).find((m) => m.name === module.name);
6521
+ // Only handle replacement/dedupe when a descriptor is already registered under this name.
6522
+ if (existingModule) {
6523
+ // Only a genuinely different descriptor for this name is a replacement that must
6524
+ // discard the old callbacks. Re-registering the SAME descriptor object (as helpers
6525
+ // like `configureHttpClient`/`useFrameworkServiceClient` do on every call, since they
6526
+ // all share one module singleton) must stay additive so multiple calls can register
6527
+ // multiple named clients without clobbering each other.
6528
+ if (existingModule !== module) {
6529
+ this._removeModuleCallbacks(module.name);
6530
+ const modules = Array.from(this._modules)
6531
+ // Preserve every descriptor while substituting the newly registered module.
6532
+ .map((m) => (m.name === module.name ? module : m));
6533
+ this._modules = new Set(modules);
6534
+ }
6535
+ }
6536
+ else {
6537
+ this._modules.add(module);
6538
+ }
6490
6539
  this._registerEvent({
6491
6540
  level: ModuleEventLevel.Debug,
6492
6541
  name: ModuleConfiguratorEventName.ModuleConfigAdded,
@@ -6499,15 +6548,26 @@ class ModulesConfigurator {
6499
6548
  afterInit: !!afterInit,
6500
6549
  },
6501
6550
  });
6502
- // Register each optional callback into its corresponding lifecycle phase array
6503
- if (configure)
6504
- this._configs.push((cfg, ref) => configure(cfg[module.name], ref));
6505
- // Register the afterConfig callback, if provided
6506
- if (afterConfig)
6507
- this._afterConfiguration.push((cfg) => afterConfig(cfg[module.name]));
6508
- // Register the afterInit callback, if provided
6509
- if (afterInit)
6510
- this._afterInit.push((instances) => afterInit(instances[module.name]));
6551
+ // Register each optional callback into its corresponding lifecycle phase array.
6552
+ // When the same module name is re-registered, previous callbacks are removed
6553
+ // so the latest configuration wins.
6554
+ if (configure) {
6555
+ const callback = ((cfg, ref) => configure(cfg[module.name], ref));
6556
+ callback.moduleName = module.name;
6557
+ this._configs.push(callback);
6558
+ }
6559
+ // Register the afterConfig callback, if provided.
6560
+ if (afterConfig) {
6561
+ const callback = ((cfg) => afterConfig(cfg[module.name]));
6562
+ callback.moduleName = module.name;
6563
+ this._afterConfiguration.push(callback);
6564
+ }
6565
+ // Register the afterInit callback, if provided.
6566
+ if (afterInit) {
6567
+ const callback = ((instances) => afterInit(instances[module.name]));
6568
+ callback.moduleName = module.name;
6569
+ this._afterInit.push(callback);
6570
+ }
6511
6571
  }
6512
6572
  /**
6513
6573
  * Registers a callback for the post-configure phase.
@@ -6929,6 +6989,49 @@ class HttpRequestHandler extends ProcessOperators {
6929
6989
  class HttpResponseHandler extends ProcessOperators {
6930
6990
  }
6931
6991
 
6992
+ /**
6993
+ * Normalizes a step's result to a `Promise`, so a middleware calling `next(...)` never has to
6994
+ * branch on whether the next step short-circuited with a plain `Response` or reached all the
6995
+ * way to an Observable-returning network call.
6996
+ */
6997
+ function toPromise(result) {
6998
+ return result instanceof Response ? Promise.resolve(result) : firstValueFrom(from(result));
6999
+ }
7000
+ /**
7001
+ * Composes registered {@link HttpMiddleware} into a single execution pipeline wrapping the
7002
+ * network call, so retries, caching, telemetry, or circuit-breaking can wrap `_performFetch`
7003
+ * without touching request or response payload transforms.
7004
+ *
7005
+ * @see {@link HttpClient}
7006
+ */
7007
+ class HttpMiddlewareHandler {
7008
+ #middleware;
7009
+ /**
7010
+ * Constructs a handler, optionally cloning another handler's registered middleware.
7011
+ * @param source - An existing handler to clone the registered middleware from.
7012
+ */
7013
+ constructor(source) {
7014
+ this.#middleware = source ? [...source.middleware] : [];
7015
+ }
7016
+ /** @inheritdoc */
7017
+ get middleware() {
7018
+ return this.#middleware;
7019
+ }
7020
+ /** @inheritdoc */
7021
+ use(middleware) {
7022
+ this.#middleware.push(middleware);
7023
+ return this;
7024
+ }
7025
+ /** @inheritdoc */
7026
+ process(uri, init, terminal) {
7027
+ // wrap outward-in so the first-registered middleware is outermost, matching a conventional middleware chain
7028
+ const chain = this.#middleware.reduceRight((next, middleware) => (nextUri, nextInit) => middleware(nextUri, nextInit, (u, i) => toPromise(next(u, i))), terminal);
7029
+ const result = chain(uri, init);
7030
+ // a middleware may short-circuit with a plain Response (no ObservableInput wrapping needed)
7031
+ return result instanceof Response ? of(result) : from(result);
7032
+ }
7033
+ }
7034
+
6932
7035
  var _a$1;
6933
7036
  /** A special constant with type `never` */
6934
7037
  const NEVER = /*@__PURE__*/ Object.freeze({
@@ -22530,6 +22633,8 @@ class HttpClientConfigurator {
22530
22633
  // validate the request object
22531
22634
  'request-validation': requestValidationOperator(),
22532
22635
  });
22636
+ /** Default middleware chain cloned into each created client instance. */
22637
+ defaultHttpMiddlewareHandler = new HttpMiddlewareHandler();
22533
22638
  /**
22534
22639
  * Creates a configurator with the default client constructor.
22535
22640
  * @param client - The default client constructor used when `ctor` is not configured per client.
@@ -22542,6 +22647,11 @@ class HttpClientConfigurator {
22542
22647
  return Object.keys(this._clients).includes(name);
22543
22648
  }
22544
22649
  /** @inheritdoc */
22650
+ addMiddleware(middleware) {
22651
+ this.defaultHttpMiddlewareHandler.use(middleware);
22652
+ return this;
22653
+ }
22654
+ /** @inheritdoc */
22545
22655
  configureClient(name, args) {
22546
22656
  const argFn = typeof args === 'string' ? { baseUri: args } : args;
22547
22657
  const options = typeof argFn === 'function' ? { onCreate: argFn } : argFn;
@@ -22556,7 +22666,7 @@ class HttpClientConfigurator {
22556
22666
  }
22557
22667
 
22558
22668
  // Generated by genversion.
22559
- const version$6 = '8.0.5';
22669
+ const version$6 = '8.1.0-next.0';
22560
22670
 
22561
22671
  /** URL protocols accepted as valid ad-hoc base URIs. */
22562
22672
  const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ws:', 'wss:'];
@@ -22595,6 +22705,13 @@ class HttpClientProvider extends BaseModuleProvider {
22595
22705
  get defaultHttpRequestHandler() {
22596
22706
  return this.config.defaultHttpRequestHandler;
22597
22707
  }
22708
+ /**
22709
+ * Gets the default middleware chain for the HTTP client provider.
22710
+ * @returns The default middleware chain.
22711
+ */
22712
+ get defaultHttpMiddlewareHandler() {
22713
+ return this.config.defaultHttpMiddlewareHandler;
22714
+ }
22598
22715
  /**
22599
22716
  * Creates a new `HttpClientProvider`.
22600
22717
  * @param config - The configurator providing client definitions and defaults.
@@ -22632,8 +22749,8 @@ class HttpClientProvider extends BaseModuleProvider {
22632
22749
  */
22633
22750
  createClient(keyOrConfig) {
22634
22751
  const config = this._resolveConfig(keyOrConfig);
22635
- const { baseUri, defaultScopes = [], onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.defaultHttpRequestHandler, responseHandler, } = config;
22636
- const options = { requestHandler, responseHandler };
22752
+ const { baseUri, defaultScopes = [], onCreate, ctor = this.config.defaultHttpClientCtor, requestHandler = this.defaultHttpRequestHandler, responseHandler, middlewareHandler = this.defaultHttpMiddlewareHandler, } = config;
22753
+ const options = { requestHandler, responseHandler, middlewareHandler };
22637
22754
  const instance = new ctor(baseUri || '', options);
22638
22755
  // attach the resolved default scopes onto the instance without overwriting other own properties
22639
22756
  Object.assign(instance, { defaultScopes });
@@ -22832,6 +22949,12 @@ class HttpClient {
22832
22949
  * This property is part of the `HttpClientCreateOptions` configuration object used to create an `HttpClient` instance.
22833
22950
  */
22834
22951
  responseHandler;
22952
+ /**
22953
+ * Middleware wrapping the network call, for cross-cutting concerns such as retries,
22954
+ * caching, or telemetry. This property is part of the `HttpClientCreateOptions`
22955
+ * configuration object used to create an `HttpClient` instance.
22956
+ */
22957
+ middlewareHandler;
22835
22958
  /**
22836
22959
  * A stream of requests that are about to be executed.
22837
22960
  * This property is used internally by the `HttpClient` class to manage the lifecycle of requests.
@@ -22870,6 +22993,7 @@ class HttpClient {
22870
22993
  this.uri = uri;
22871
22994
  this.requestHandler = new HttpRequestHandler(options?.requestHandler);
22872
22995
  this.responseHandler = new HttpResponseHandler(options?.responseHandler);
22996
+ this.middlewareHandler = new HttpMiddlewareHandler(options?.middlewareHandler);
22873
22997
  this._init();
22874
22998
  }
22875
22999
  /**
@@ -23041,7 +23165,9 @@ class HttpClient {
23041
23165
  /**
23042
23166
  * Aborts any ongoing HTTP requests made by this `IHttpClient` instance.
23043
23167
  * This will trigger the `takeUntil` operator in the `_fetch$` method,
23044
- * causing any in-flight requests to be cancelled.
23168
+ * causing any in-flight requests to be cancelled, and abort the
23169
+ * per-request `AbortSignal` passed through to `_performFetch`, so the
23170
+ * underlying network call is cancelled even behind registered middleware.
23045
23171
  */
23046
23172
  abort() {
23047
23173
  this._abort$.next();
@@ -23066,11 +23192,26 @@ class HttpClient {
23066
23192
  */
23067
23193
  _fetch$(path, args) {
23068
23194
  const { selector, ...options } = args || {};
23195
+ // A registered middleware's `next(...)` resolves through a `Promise` (see
23196
+ // `HttpMiddlewareHandler`), which `firstValueFrom` fulfils via its own independent
23197
+ // subscription to `_performFetch` — one the `takeUntil(this._abort$)` below never reaches,
23198
+ // since it sits outside the subscription tree that `takeUntil` tears down. Combining this
23199
+ // controller's signal into the request `init` lets `_performFetch` (`fromFetch` by default)
23200
+ // abort the underlying network call directly, regardless of whether middleware severed the
23201
+ // RxJS teardown chain.
23202
+ const abortController = new AbortController();
23203
+ // abort only fires once per request; the subscription is torn down in `finalize` below
23204
+ const abort = this._abort$.pipe(take(1)).subscribe(() => abortController.abort());
23205
+ const callerSignal = options.signal;
23206
+ const signal = callerSignal
23207
+ ? AbortSignal.any([callerSignal, abortController.signal])
23208
+ : abortController.signal;
23069
23209
  // `fromFetch` yields the raw fetch `Response`, but `responseHandler.process()` (called via
23070
23210
  // `_prepareResponse`) expects the pipeline's generic `TResponse` shape — cast through
23071
23211
  // `unknown` since the two are only compatible after that processing step.
23072
23212
  const response$ = of({
23073
23213
  ...options,
23214
+ signal,
23074
23215
  path,
23075
23216
  uri: this._resolveUrl(path),
23076
23217
  }).pipe(
@@ -23078,8 +23219,8 @@ class HttpClient {
23078
23219
  switchMap((x) => this._prepareRequest(x)),
23079
23220
  /** push request to event buss */
23080
23221
  tap((x) => this._request$.next(x)),
23081
- /** execute request */
23082
- switchMap(({ uri, path: _path, ...init }) => fromFetch(uri, init)),
23222
+ /** execute request through registered middleware, terminating at _performFetch */
23223
+ switchMap(({ uri, path: _path, ...init }) => this.middlewareHandler.process(uri, init, (u, i) => this._performFetch(u, i))),
23083
23224
  /** prepare response, allow extensions to modify response */
23084
23225
  switchMap((x) => this._prepareResponse(x)),
23085
23226
  /** push response to event buss */
@@ -23100,11 +23241,30 @@ class HttpClient {
23100
23241
  return of(response);
23101
23242
  }),
23102
23243
  /** cancel request on abort signal */
23103
- takeUntil(this._abort$));
23244
+ takeUntil(this._abort$),
23245
+ /** the abort signal subscription only ever fires once; tear it down once this request settles either way */
23246
+ finalize$2(() => abort.unsubscribe()));
23104
23247
  // The pipe above resolves to the per-call generic `T` (via the optional `selector`), but
23105
23248
  // the observable's static type tracks the class-level `TResponse` — cast to the caller's `T`.
23106
23249
  return response$;
23107
23250
  }
23251
+ /**
23252
+ * Performs the actual network call for a prepared request.
23253
+ *
23254
+ * @remarks
23255
+ * Isolated from {@link _fetch$} so a test double can replace only this step —
23256
+ * matching a request against registered route handlers instead of reaching
23257
+ * the network — while everything around it (request preparation, the
23258
+ * response pipeline, abort handling) runs unchanged. See
23259
+ * `@equinor/fusion-framework-module-http/mock`.
23260
+ *
23261
+ * @param uri - The fully resolved URL for the request.
23262
+ * @param init - The prepared `fetch` request options.
23263
+ * @returns An observable of the raw `Response`, ahead of {@link _prepareResponse}.
23264
+ */
23265
+ _performFetch(uri, init) {
23266
+ return fromFetch(uri, init);
23267
+ }
23108
23268
  /**
23109
23269
  * Prepares the request by passing it through the `requestHandler.process()` method.
23110
23270
  * This method is an implementation detail of the `_fetch$()` method, and is not part of the public API.
@@ -25008,7 +25168,7 @@ class TelemetryConfigurator extends BaseConfigBuilder {
25008
25168
  }
25009
25169
 
25010
25170
  // Generated by genversion.
25011
- const version$5 = '7.0.2';
25171
+ const version$5 = '8.0.0-next.1';
25012
25172
 
25013
25173
  /**
25014
25174
  * Enum representing the severity levels of telemetry items.
@@ -43861,7 +44021,7 @@ const createClientLogCallback = (provider, metadata, scope) => {
43861
44021
  };
43862
44022
 
43863
44023
  // Generated by genversion.
43864
- const version$2 = '10.0.2';
44024
+ const version$2 = '11.0.0-next.0';
43865
44025
 
43866
44026
  /**
43867
44027
  * Zod schema for telemetry configuration validation.
@@ -43876,10 +44036,15 @@ const TelemetryConfigSchema = z.object({
43876
44036
  }),
43877
44037
  scope: z.array(z.string()).optional().default(['framework', 'authentication']),
43878
44038
  });
44039
+
43879
44040
  /**
43880
44041
  * Zod schema for MSAL module configuration validation.
43881
44042
  *
43882
- * @internal
44043
+ * @remarks
44044
+ * Kept in its own module so the configuration can be extended at its source.
44045
+ * The schema itself describes what reaches `MsalProvider` and strips anything
44046
+ * else; keys a variant of this module needs only while the configuration is
44047
+ * being built are declared on {@link MsalConfigExtension} instead.
43883
44048
  */
43884
44049
  const MsalConfigSchema = z.object({
43885
44050
  client: z.custom().optional(),
@@ -43892,9 +44057,19 @@ const MsalConfigSchema = z.object({
43892
44057
  .custom((val) => typeof val === 'number' &&
43893
44058
  Object.values(CacheLookupPolicy).includes(val))
43894
44059
  .optional(),
43895
- version: z.string().transform((x) => String(semver.coerce(x))),
44060
+ version: z.string().transform((value, ctx) => {
44061
+ const coerced = semver.coerce(value);
44062
+ // `semver.coerce` returns `null` for an unparseable version; without this guard it
44063
+ // would silently become the literal string "null" instead of failing validation.
44064
+ if (!coerced) {
44065
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid MSAL module version' });
44066
+ return z.NEVER;
44067
+ }
44068
+ return coerced.version;
44069
+ }),
43896
44070
  telemetry: TelemetryConfigSchema,
43897
44071
  });
44072
+
43898
44073
  /**
43899
44074
  * Configuration builder for MSAL v4 authentication module.
43900
44075
  *
@@ -43910,6 +44085,7 @@ const MsalConfigSchema = z.object({
43910
44085
  */
43911
44086
  class MsalConfigurator extends BaseConfigBuilder {
43912
44087
  #msalConfig;
44088
+ #client;
43913
44089
  /**
43914
44090
  * The MSAL module version being configured.
43915
44091
  *
@@ -43936,6 +44112,9 @@ class MsalConfigurator extends BaseConfigBuilder {
43936
44112
  return telemetry;
43937
44113
  }
43938
44114
  });
44115
+ // Always resolve the configured client instance through the builder.
44116
+ // This keeps the client getter live and avoids re-registering the same config key.
44117
+ this._set('client', async () => this.#client);
43939
44118
  // Default cache lookup policy to AccessTokenAndRefreshToken to avoid iframe fallback delays
43940
44119
  this._set('cacheLookupPolicy', async () => CacheLookupPolicy.AccessTokenAndRefreshToken);
43941
44120
  }
@@ -43963,6 +44142,22 @@ class MsalConfigurator extends BaseConfigBuilder {
43963
44142
  this.#msalConfig = config;
43964
44143
  return this;
43965
44144
  }
44145
+ /**
44146
+ * Returns the client configuration declared through
44147
+ * {@link MsalConfigurator.setClientConfig | setClientConfig}, if any.
44148
+ *
44149
+ * @remarks
44150
+ * This is the configuration as declared, not the resolved one a client is
44151
+ * built from — see
44152
+ * {@link MsalConfigurator._createClientConfig | _createClientConfig} for that.
44153
+ * Reading it is how a subclass can tell "nothing was declared" apart from
44154
+ * "declared, and here it is", without re-deriving that from a resolved value.
44155
+ *
44156
+ * @returns The declared client configuration, or `undefined` when none was declared.
44157
+ */
44158
+ getClientConfig() {
44159
+ return this.#msalConfig;
44160
+ }
43966
44161
  /**
43967
44162
  * Sets the cache lookup policy used for every silent token acquisition.
43968
44163
  *
@@ -44096,9 +44291,21 @@ class MsalConfigurator extends BaseConfigBuilder {
44096
44291
  * ```
44097
44292
  */
44098
44293
  setClient(client) {
44099
- this._set('client', async () => client);
44294
+ this.#client = client;
44100
44295
  return this;
44101
44296
  }
44297
+ /**
44298
+ * Returns the currently configured MSAL client, if one has been set.
44299
+ *
44300
+ * @remarks
44301
+ * This is useful in tests when a mock client has been provided and the test
44302
+ * wants to adjust its state after it has been assigned to the configurator.
44303
+ *
44304
+ * @returns The configured client, or `undefined` when none has been set.
44305
+ */
44306
+ getClient() {
44307
+ return this.#client;
44308
+ }
44102
44309
  /**
44103
44310
  * Sets telemetry provider for MSAL authentication events.
44104
44311
  *
@@ -44146,64 +44353,151 @@ class MsalConfigurator extends BaseConfigBuilder {
44146
44353
  /**
44147
44354
  * Processes and validates the configuration.
44148
44355
  *
44149
- * @param config - Raw configuration object
44356
+ * @param rawConfig - Raw configuration object
44357
+ * @param init - The builder arguments, carrying the host reference when hoisted
44150
44358
  * @returns Processed and validated configuration
44151
44359
  */
44152
- async _processConfig(rawConfig) {
44360
+ async _processConfig(rawConfig, init) {
44153
44361
  // Validate and coerce configuration using Zod schema
44154
44362
  const config = await MsalConfigSchema.parseAsync(rawConfig);
44155
- // Auto-create client if config provided but no client instance
44363
+ // Auto-create client if no client instance was supplied
44156
44364
  // This allows users to provide configuration without manually instantiating the client
44157
- if (!config.client && this.#msalConfig) {
44158
- const clientConfig = this.#msalConfig;
44159
- config.telemetry.provider?.trackEvent({
44160
- name: 'module-msal.configurator._processConfig.creating-client',
44365
+ // A hoisted module authenticates through the host's provider, so any client built here
44366
+ // would be discarded — gate it here rather than in `_createClient`, so a substituted
44367
+ // client (see `MsalMockConfigurator`) cannot shadow the host's signed-in user
44368
+ if (!config.client && !this._isHoisted(init)) {
44369
+ config.client = await this._createClient(config, init);
44370
+ }
44371
+ return config;
44372
+ }
44373
+ /**
44374
+ * Creates the client to authenticate through, when none was supplied.
44375
+ *
44376
+ * @remarks
44377
+ * Called by {@link MsalConfigurator._processConfig | _processConfig} only when
44378
+ * no client was set, so a client supplied through
44379
+ * {@link MsalConfigurator.setClient | setClient} always wins. It is likewise
44380
+ * not called when the module is hoisted onto a host application's provider —
44381
+ * see {@link MsalConfigurator._isHoisted | _isHoisted}.
44382
+ *
44383
+ * This is the seam for authenticating through something other than Entra ID.
44384
+ * Overriding it replaces only the client, leaving the builder, the schema
44385
+ * validation and `MsalProvider` untouched — which is how
44386
+ * `MsalMockConfigurator` substitutes an in-process client for tests.
44387
+ *
44388
+ * An override normally builds from
44389
+ * {@link MsalConfigurator._createClientConfig | _createClientConfig}, so it
44390
+ * receives the same fully-resolved {@link MsalClientConfig} the real client is
44391
+ * built from rather than re-deriving it.
44392
+ *
44393
+ * Returning `undefined` is legitimate and means "there is nothing to build a
44394
+ * client from", which leaves the module without one.
44395
+ *
44396
+ * @param config - The validated configuration the client is built from.
44397
+ * @param init - The builder arguments, carrying the host reference when hoisted.
44398
+ * @returns The client, or `undefined` when there is nothing to build one from.
44399
+ */
44400
+ async _createClient(config, _init) {
44401
+ const clientConfig = this._createClientConfig(config);
44402
+ // A client can be omitted for a hoisted module or an intentionally incomplete setup.
44403
+ if (!clientConfig) {
44404
+ return undefined;
44405
+ }
44406
+ // Instantiate MSAL client with fully configured options
44407
+ return new MsalClient(clientConfig);
44408
+ }
44409
+ /**
44410
+ * Whether this module is hoisted onto a host application's authentication.
44411
+ *
44412
+ * @remarks
44413
+ * When an application runs inside a host — a portal loading an app, or an app
44414
+ * loading a widget — the module initializer returns a proxy of the host's
44415
+ * provider instead of building its own (see the host-provider branch of the
44416
+ * module initializer). A client built during configuration would therefore be
44417
+ * constructed and immediately discarded.
44418
+ *
44419
+ * Detecting this during configuration lets the configurator skip building a
44420
+ * client entirely, which matters most for substituted clients: a mock client
44421
+ * built here would otherwise silently shadow the host's real signed-in user.
44422
+ *
44423
+ * @param init - The builder arguments, carrying the host reference when hoisted.
44424
+ * @returns `true` when a host provider will be used instead of a locally built client.
44425
+ */
44426
+ _isHoisted(init) {
44427
+ return !!init?.ref?.auth;
44428
+ }
44429
+ /**
44430
+ * Resolves the full MSAL client configuration to build a client from.
44431
+ *
44432
+ * @remarks
44433
+ * Applies the defaults a client is expected to be built with — authority
44434
+ * derived from the tenant, cache location, telemetry-backed logging and the
44435
+ * configured cache lookup policy.
44436
+ *
44437
+ * Kept separate from {@link MsalConfigurator._createClient | _createClient} so
44438
+ * that substituting the client does not also mean re-implementing this
44439
+ * resolution. `MsalMockConfigurator` relies on it to hand its mock client the
44440
+ * very same configuration the real client would have received.
44441
+ *
44442
+ * @param config - The validated configuration.
44443
+ * @returns The client configuration, or `undefined` when none was declared.
44444
+ */
44445
+ _createClientConfig(config) {
44446
+ const declared = this.#msalConfig;
44447
+ // Do not construct a client when configuration has not supplied client settings.
44448
+ if (!declared) {
44449
+ return undefined;
44450
+ }
44451
+ config.telemetry.provider?.trackEvent({
44452
+ name: 'module-msal.configurator._processConfig.creating-client',
44453
+ level: TelemetryLevel.Debug,
44454
+ scope: config.telemetry.scope,
44455
+ metadata: { ...config.telemetry.metadata, clientConfig: declared },
44456
+ });
44457
+ // Copied rather than enriched in place, so the object a caller passed to
44458
+ // `setClientConfig` is never rewritten behind its back — a caller may well
44459
+ // be reusing or asserting on it
44460
+ const clientConfig = {
44461
+ ...declared,
44462
+ auth: { ...declared.auth },
44463
+ // Default to localStorage: MSAL supports sessionStorage too, but
44464
+ // localStorage is the standard for persistent auth in browsers
44465
+ cache: declared.cache ?? { cacheLocation: 'localStorage' },
44466
+ };
44467
+ // Auto-generate authority URL from tenant ID if not explicitly provided
44468
+ // This simplifies configuration for most common cases
44469
+ if (!clientConfig.auth.authority && clientConfig.auth.tenantId) {
44470
+ clientConfig.auth.authority = `https://login.microsoftonline.com/${clientConfig.auth.tenantId}`;
44471
+ }
44472
+ // Integrate framework telemetry with MSAL logging system
44473
+ // This allows MSAL events to flow through the framework's telemetry pipeline
44474
+ if (!clientConfig.system?.loggerOptions && config.telemetry?.provider) {
44475
+ const { provider, metadata, scope } = config.telemetry;
44476
+ provider.trackEvent({
44477
+ name: 'module-msal.configurator._processConfig.client-telemetry-connected',
44161
44478
  level: TelemetryLevel.Debug,
44162
- scope: config.telemetry.scope,
44163
- metadata: { ...config.telemetry.metadata, clientConfig },
44479
+ scope,
44480
+ metadata,
44164
44481
  });
44165
- // Auto-generate authority URL from tenant ID if not explicitly provided
44166
- // This simplifies configuration for most common cases
44167
- if (!clientConfig.auth.authority && clientConfig.auth.tenantId) {
44168
- clientConfig.auth.authority = `https://login.microsoftonline.com/${clientConfig.auth.tenantId}`;
44169
- }
44170
- // Set default cache location to localStorage for browser environments
44171
- // MSAL supports sessionStorage as well, but localStorage is the standard for persistent auth
44172
- if (!clientConfig.cache) {
44173
- clientConfig.cache = { cacheLocation: 'localStorage' };
44174
- }
44175
- // Integrate framework telemetry with MSAL logging system
44176
- // This allows MSAL events to flow through the framework's telemetry pipeline
44177
- if (!clientConfig.system?.loggerOptions && config.telemetry?.provider) {
44178
- const { provider, metadata, scope } = config.telemetry;
44179
- provider.trackEvent({
44180
- name: 'module-msal.configurator._processConfig.client-telemetry-connected',
44181
- level: TelemetryLevel.Debug,
44182
- scope,
44183
- metadata,
44184
- });
44185
- clientConfig.system = {
44186
- ...clientConfig.system,
44187
- loggerOptions: {
44188
- // Only log PII in development to protect user privacy in production
44189
- piiLoggingEnabled: process.env.NODE_ENV === 'development',
44190
- // Bridge MSAL log events to framework telemetry system
44191
- loggerCallback: createClientLogCallback(provider, metadata, [...scope, '3rd-party']),
44192
- // Use Warning level by default - captures errors and warnings without being verbose
44193
- logLevel: LogLevel.Warning,
44194
- // Preserve any user-provided logger options (allows customization)
44195
- ...clientConfig.system?.loggerOptions,
44196
- },
44197
- };
44198
- }
44199
- // Apply silent cache lookup policy if configured
44200
- if (config.cacheLookupPolicy !== undefined) {
44201
- clientConfig.cacheLookupPolicy = config.cacheLookupPolicy;
44202
- }
44203
- // Instantiate MSAL client with fully configured options
44204
- config.client = new MsalClient(clientConfig);
44482
+ clientConfig.system = {
44483
+ ...clientConfig.system,
44484
+ loggerOptions: {
44485
+ // Only log PII in development to protect user privacy in production
44486
+ piiLoggingEnabled: process.env.NODE_ENV === 'development',
44487
+ // Bridge MSAL log events to framework telemetry system
44488
+ loggerCallback: createClientLogCallback(provider, metadata, [...scope, '3rd-party']),
44489
+ // Use Warning level by default - captures errors and warnings without being verbose
44490
+ logLevel: LogLevel.Warning,
44491
+ // Preserve any user-provided logger options (allows customization)
44492
+ ...clientConfig.system?.loggerOptions,
44493
+ },
44494
+ };
44205
44495
  }
44206
- return config;
44496
+ // Apply silent cache lookup policy if configured
44497
+ if (config.cacheLookupPolicy !== undefined) {
44498
+ clientConfig.cacheLookupPolicy = config.cacheLookupPolicy;
44499
+ }
44500
+ return clientConfig;
44207
44501
  }
44208
44502
  }
44209
44503
 
@@ -44321,7 +44615,6 @@ class VersionError extends Error {
44321
44615
  * ```
44322
44616
  */
44323
44617
  function mapVersionToEnumVersion(version) {
44324
- console.log('Resolving version:', version);
44325
44618
  const coercedVersion = semver.coerce(version);
44326
44619
  // An uncoercible version string cannot be mapped to a module version
44327
44620
  if (!coercedVersion) {
@@ -48208,7 +48501,7 @@ class ServiceDiscoveryConfigurator extends BaseConfigBuilder {
48208
48501
  }
48209
48502
 
48210
48503
  // Generated by genversion.
48211
- const version$1 = '10.0.2';
48504
+ const version$1 = '10.1.0-next.0';
48212
48505
 
48213
48506
  /**
48214
48507
  * Default implementation of {@link IServiceDiscoveryProvider}.
@@ -48232,6 +48525,10 @@ class ServiceDiscoveryProvider extends BaseModuleProvider {
48232
48525
  this.config = config;
48233
48526
  this._http = _http;
48234
48527
  }
48528
+ /** {@inheritDoc IServiceDiscoveryProvider.client} */
48529
+ get client() {
48530
+ return this.config.discoveryClient;
48531
+ }
48235
48532
  /** {@inheritDoc IServiceDiscoveryProvider.resolveServices} */
48236
48533
  resolveServices() {
48237
48534
  return this.config.discoveryClient.resolveServices();
@@ -48346,8 +48643,9 @@ const configureServiceDiscovery = (callback) => ({
48346
48643
  *
48347
48644
  * @param configurator - The modules configurator to register the module on.
48348
48645
  * Must already include {@link HttpModule}.
48349
- * @param callback - Optional async callback receiving a
48350
- * {@link ServiceDiscoveryConfigurator} for advanced setup.
48646
+ * @param callback - Optional callback receiving a
48647
+ * {@link ServiceDiscoveryConfigurator} for advanced setup. May be synchronous
48648
+ * or asynchronous.
48351
48649
  *
48352
48650
  * @example
48353
48651
  * ```typescript
@@ -48842,7 +49140,7 @@ async function registerServiceWorker(framework) {
48842
49140
  }
48843
49141
 
48844
49142
  // Generated by genversion.
48845
- const version = '4.0.16';
49143
+ const version = '4.0.17-next.1';
48846
49144
 
48847
49145
  // Allow dynamic import without vite
48848
49146
  const importWithoutVite = (path) => import(/* @vite-ignore */ path);