@itwin/rpcinterface-full-stack-tests 5.15.0-dev.3 → 5.15.0-dev.4

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.
@@ -112238,12 +112238,27 @@ class IModelApp {
112238
112238
  static get publicPath() { return this._publicPath; }
112239
112239
  /** The [[FormatsProvider]] for this session.
112240
112240
  * @param provider The provider to use for formatting quantities.
112241
+ * @note Prefer [[IModelApp.setFormatsProvider]] when replacing the provider; assigning this property starts an asynchronous reload without returning a promise.
112241
112242
  * @beta
112242
112243
  */
112243
112244
  static get formatsProvider() { return this._formatsProviderManager; }
112244
112245
  static set formatsProvider(provider) {
112245
112246
  this._formatsProviderManager.formatsProvider = provider;
112246
112247
  }
112248
+ /**
112249
+ * Replaces the formats provider and optionally changes the active unit system.
112250
+ * Resolves after the formatter has rebuilt its formatting and parsing caches.
112251
+ * Incompatible provider entries are logged and skipped, so they do not reject this Promise.
112252
+ * If the reload fails, this Promise rejects and the new provider stays installed. The formatter remains usable, but some cached formats may still come from the previous provider.
112253
+ * If a later setFormatsProvider call supersedes this request, this Promise rejects.
112254
+ * It also rejects if the application shuts down first.
112255
+ * @beta
112256
+ */
112257
+ static async setFormatsProvider(provider, options) {
112258
+ await this.quantityFormatter.runAndWaitForReload(() => {
112259
+ this._formatsProviderManager.setFormatsProvider(provider, options?.unitSystem);
112260
+ });
112261
+ }
112247
112262
  /** @alpha */
112248
112263
  static extensionAdmin = this._createExtensionAdmin();
112249
112264
  /** Map of classFullName to EntityState class */
@@ -181342,6 +181357,161 @@ class BaseUnitFormattingSettingsProvider {
181342
181357
  }
181343
181358
 
181344
181359
 
181360
+ /***/ },
181361
+
181362
+ /***/ "../../core/frontend/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.js"
181363
+ /*!*******************************************************************************************!*\
181364
+ !*** ../../core/frontend/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.js ***!
181365
+ \*******************************************************************************************/
181366
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
181367
+
181368
+ "use strict";
181369
+ __webpack_require__.r(__webpack_exports__);
181370
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
181371
+ /* harmony export */ FormatsProviderReloadCoordinator: () => (/* binding */ FormatsProviderReloadCoordinator),
181372
+ /* harmony export */ ReloadSupersededError: () => (/* binding */ ReloadSupersededError)
181373
+ /* harmony export */ });
181374
+ /*---------------------------------------------------------------------------------------------
181375
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
181376
+ * See LICENSE.md in the project root for license terms and full copyright notice.
181377
+ *--------------------------------------------------------------------------------------------*/
181378
+ /** @internal */
181379
+ class ReloadSupersededError extends Error {
181380
+ constructor() {
181381
+ super("QuantityFormatter reload was superseded by a newer request.");
181382
+ this.name = "ReloadSupersededError";
181383
+ }
181384
+ }
181385
+ /**
181386
+ * Serializes formatting reloads and resolves or rejects the caller waiting for formatting to become ready.
181387
+ * @internal
181388
+ */
181389
+ class FormatsProviderReloadCoordinator {
181390
+ _host;
181391
+ _disposedError;
181392
+ _reloadInFlight = false;
181393
+ _pendingReload;
181394
+ _pendingFormatsChange;
181395
+ _reloadCaller;
181396
+ _isDisposed = false;
181397
+ constructor(_host, _disposedError) {
181398
+ this._host = _host;
181399
+ this._disposedError = _disposedError;
181400
+ }
181401
+ dispose() {
181402
+ if (this._isDisposed)
181403
+ return;
181404
+ this._isDisposed = true;
181405
+ this._pendingReload = undefined;
181406
+ this._pendingFormatsChange = undefined;
181407
+ this._rejectReloadCaller(this._disposedError);
181408
+ }
181409
+ /**
181410
+ * Runs an action that schedules a reload and waits for the reload queue to drain.
181411
+ * A newer call rejects an older call that is still waiting.
181412
+ */
181413
+ async runAndWaitForReload(action) {
181414
+ if (this._isDisposed)
181415
+ throw this._disposedError;
181416
+ let caller;
181417
+ const reload = new Promise((resolve, reject) => {
181418
+ caller = { resolve, reject };
181419
+ });
181420
+ this._rejectReloadCaller(new ReloadSupersededError());
181421
+ this._reloadCaller = caller;
181422
+ try {
181423
+ action();
181424
+ }
181425
+ catch (error) {
181426
+ if (this._reloadCaller === caller)
181427
+ this._reloadCaller = undefined;
181428
+ throw error;
181429
+ }
181430
+ await reload;
181431
+ }
181432
+ /**
181433
+ * Runs a reload now, or queues it if one is already running.
181434
+ * Pending format changes are merged and kept apart from other pending reloads, so a later unit-system or units-provider reload cannot drop a provider change.
181435
+ * If a reload is already running, this method returns immediately; use [[runAndWaitForReload]] when the caller must wait for completion.
181436
+ * The waiting caller is rejected if any reload fails before the queue drains.
181437
+ */
181438
+ async scheduleReload(intent) {
181439
+ if (this._isDisposed)
181440
+ return;
181441
+ if (this._reloadInFlight) {
181442
+ if (intent.scope === "formatsChanged")
181443
+ this._pendingFormatsChange = mergeFormatsChanges(this._pendingFormatsChange, intent);
181444
+ else
181445
+ this._pendingReload = intent;
181446
+ return;
181447
+ }
181448
+ this._reloadInFlight = true;
181449
+ let failure;
181450
+ let current = intent;
181451
+ while (current) {
181452
+ try {
181453
+ this._host.startReload();
181454
+ await this._host.executeReload(current);
181455
+ if (this._stopAfterDisposal())
181456
+ return;
181457
+ current = this._takePendingReload();
181458
+ if (!current) {
181459
+ await this._host.finalizeReload();
181460
+ if (this._stopAfterDisposal())
181461
+ return;
181462
+ current = this._takePendingReload();
181463
+ }
181464
+ }
181465
+ catch (error) {
181466
+ if (this._stopAfterDisposal())
181467
+ return;
181468
+ // Keep draining so queued work still runs, but report the failure to the waiting caller.
181469
+ this._host.handleReloadFailure(error);
181470
+ failure = { error };
181471
+ current = this._takePendingReload();
181472
+ }
181473
+ }
181474
+ this._reloadInFlight = false;
181475
+ if (failure)
181476
+ this._rejectReloadCaller(failure.error);
181477
+ else
181478
+ this._resolveReloadCaller();
181479
+ }
181480
+ _stopAfterDisposal() {
181481
+ if (!this._isDisposed)
181482
+ return false;
181483
+ this._reloadInFlight = false;
181484
+ return true;
181485
+ }
181486
+ _takePendingReload() {
181487
+ const next = this._pendingFormatsChange ?? this._pendingReload;
181488
+ if (next === this._pendingFormatsChange)
181489
+ this._pendingFormatsChange = undefined;
181490
+ else
181491
+ this._pendingReload = undefined;
181492
+ return next;
181493
+ }
181494
+ _resolveReloadCaller() {
181495
+ const caller = this._reloadCaller;
181496
+ this._reloadCaller = undefined;
181497
+ caller?.resolve();
181498
+ }
181499
+ _rejectReloadCaller(error) {
181500
+ const caller = this._reloadCaller;
181501
+ this._reloadCaller = undefined;
181502
+ caller?.reject(error);
181503
+ }
181504
+ }
181505
+ function mergeFormatsChanges(pending, next) {
181506
+ if (!pending)
181507
+ return next;
181508
+ const pendingNames = pending.args.formatsChanged;
181509
+ const nextNames = next.args.formatsChanged;
181510
+ const formatsChanged = pendingNames === "all" || nextNames === "all" ? "all" : [...new Set([...pendingNames, ...nextNames])];
181511
+ return { scope: "formatsChanged", args: { formatsChanged } };
181512
+ }
181513
+
181514
+
181345
181515
  /***/ },
181346
181516
 
181347
181517
  /***/ "../../core/frontend/lib/esm/quantity-formatting/LocalUnitFormatProvider.js"
@@ -181450,6 +181620,7 @@ __webpack_require__.r(__webpack_exports__);
181450
181620
  /* harmony import */ var _common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../common/FrontendLoggerCategory */ "../../core/frontend/lib/esm/common/FrontendLoggerCategory.js");
181451
181621
  /* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
181452
181622
  /* harmony import */ var _AlternateUnitLabels__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlternateUnitLabels */ "../../core/frontend/lib/esm/quantity-formatting/AlternateUnitLabels.js");
181623
+ /* harmony import */ var _FormatsProviderReloadCoordinator__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FormatsProviderReloadCoordinator */ "../../core/frontend/lib/esm/quantity-formatting/FormatsProviderReloadCoordinator.js");
181453
181624
  /*---------------------------------------------------------------------------------------------
181454
181625
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
181455
181626
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -181462,6 +181633,7 @@ __webpack_require__.r(__webpack_exports__);
181462
181633
 
181463
181634
 
181464
181635
 
181636
+
181465
181637
  // cSpell:ignore FORMATPROPS FORMATKEY ussurvey uscustomary USCUSTOM
181466
181638
  /**
181467
181639
  * Defines standard format types for tools that need to display measurements to user.
@@ -181646,12 +181818,24 @@ class FormatsProviderManager {
181646
181818
  }
181647
181819
  get formatsProvider() { return this; }
181648
181820
  set formatsProvider(formatsProvider) {
181821
+ this.setFormatsProvider(formatsProvider);
181822
+ }
181823
+ /**
181824
+ * Replaces the underlying formats provider and raises an event indicating that all formats changed.
181825
+ * @param formatsProvider The formats provider to use for subsequent format lookups.
181826
+ * @param impliedUnitSystem The unit system implied by the replacement provider, if any. Not stored here; [[QuantityFormatter]] applies it as the active unit system when handling `onFormatsChanged`.
181827
+ * @internal
181828
+ */
181829
+ setFormatsProvider(formatsProvider, impliedUnitSystem) {
181649
181830
  this._removeProviderListener?.();
181650
181831
  this._formatsProvider = formatsProvider;
181651
181832
  this._removeProviderListener = this._formatsProvider.onFormatsChanged.addListener((args) => {
181652
181833
  this.onFormatsChanged.raiseEvent(args);
181653
181834
  });
181654
- this.onFormatsChanged.raiseEvent({ formatsChanged: "all" });
181835
+ const args = { formatsChanged: "all" };
181836
+ if (impliedUnitSystem !== undefined)
181837
+ args.impliedUnitSystem = impliedUnitSystem;
181838
+ this.onFormatsChanged.raiseEvent(args);
181655
181839
  }
181656
181840
  }
181657
181841
  /** The QuantityFormatter class provides methods for formatting and parsing quantities. There are a set of standard quantity types
@@ -181732,10 +181916,13 @@ class QuantityFormatter {
181732
181916
  _hasEverBeenReady = false;
181733
181917
  _initializedPromise;
181734
181918
  _resolveInitialized;
181735
- _reloadInFlight = false;
181736
- _pendingReload;
181737
- _deferredSystemChangedEmit;
181919
+ _emitSystemChangedOnReady = false;
181920
+ _isDisposed = false;
181921
+ _disposedError = new Error("QuantityFormatter was disposed before the reload completed.");
181922
+ _reloadCoordinator;
181738
181923
  _removeFormatsProviderListener;
181924
+ _activeFormatSpecsTarget;
181925
+ _activeParserSpecsTarget;
181739
181926
  /**
181740
181927
  * constructor
181741
181928
  * @param showMetricOrUnitSystem - Pass in `true` to show Metric formatted quantity values. Defaults to Imperial. To explicitly
@@ -181745,6 +181932,12 @@ class QuantityFormatter {
181745
181932
  this._initializedPromise = new Promise((resolve) => {
181746
181933
  this._resolveInitialized = resolve;
181747
181934
  });
181935
+ this._reloadCoordinator = new _FormatsProviderReloadCoordinator__WEBPACK_IMPORTED_MODULE_5__.FormatsProviderReloadCoordinator({
181936
+ startReload: () => { this._isReady = false; },
181937
+ executeReload: async (intent) => this._executeReload(intent),
181938
+ finalizeReload: async () => this.finalizeReload(),
181939
+ handleReloadFailure: (error) => this._handleReloadFailure(error),
181940
+ }, this._disposedError);
181748
181941
  if (undefined !== showMetricOrUnitSystem) {
181749
181942
  if (typeof showMetricOrUnitSystem === "boolean")
181750
181943
  this._activeUnitSystem = showMetricOrUnitSystem ? "metric" : "imperial";
@@ -181753,70 +181946,44 @@ class QuantityFormatter {
181753
181946
  }
181754
181947
  }
181755
181948
  [Symbol.dispose]() {
181949
+ if (this._isDisposed)
181950
+ return;
181951
+ this._isDisposed = true;
181952
+ this._isReady = false;
181953
+ this._emitSystemChangedOnReady = false;
181954
+ this._reloadCoordinator.dispose();
181756
181955
  if (this._removeFormatsProviderListener) {
181757
181956
  this._removeFormatsProviderListener();
181758
181957
  this._removeFormatsProviderListener = undefined;
181759
181958
  }
181760
181959
  }
181960
+ /** Runs an action that schedules a reload and waits for the reload queue to drain.
181961
+ * The most recent call wins. If another call is made before this reload queue drains, this call is rejected.
181962
+ * @internal
181963
+ */
181964
+ async runAndWaitForReload(action) {
181965
+ return this._reloadCoordinator.runAndWaitForReload(action);
181966
+ }
181761
181967
  /** Schedule an async reload. If no reload is in flight, runs immediately. If a reload is
181762
- * already in flight, stores the intent as pending (latest-wins: only the last scheduled reload
181763
- * is kept). `finalizeReload()` fires only when the queue is fully drained.
181968
+ * already in flight, stores the intent as pending. Pending format changes are merged and run before
181969
+ * the latest other pending intent. `finalizeReload()` fires only when the queue is fully drained.
181764
181970
  *
181765
181971
  * **Await semantics:** When a reload is already in flight, the returned promise resolves
181766
181972
  * immediately *without* the requested reload having run. Callers that need to know when
181767
- * the reload has actually completed should listen for `onFormattingReady` instead.
181973
+ * an explicitly triggered reload has actually completed should use [[runAndWaitForReload]].
181768
181974
  *
181769
- * Reload intents:
181770
- * - `"full"` — rebuild entire registry + re-register provider listener (onInitialized, setUnitsProvider)
181771
- * - `"formatsChanged"` — patch registry from provider + load maps (formatsChanged listener)
181772
- * - `"activeSystem"` — reload format/parsing maps for current unit system (setActiveUnitSystem, reinitializeFormatAndParsingsMaps)
181773
181975
  * @internal
181774
181976
  */
181775
181977
  async scheduleReload(intent) {
181776
- if (this._reloadInFlight) {
181777
- // A reload is already running — queue this one (latest-wins)
181778
- this._pendingReload = intent;
181779
- return;
181780
- }
181781
- this._reloadInFlight = true;
181782
- this._isReady = false;
181783
- this._deferredSystemChangedEmit = undefined; // Clear stale deferred from prior cycle
181784
- try {
181785
- await this._executeReload(intent);
181786
- }
181787
- catch (err) {
181788
- _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logError(`${_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__.FrontendLoggerCategory.Package}.QuantityFormatter`, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BentleyError.getErrorMessage(err));
181789
- this._reloadInFlight = false;
181790
- // If there's a pending reload, still try to run it
181791
- if (this._pendingReload) {
181792
- const next = this._pendingReload;
181793
- this._pendingReload = undefined;
181794
- return this.scheduleReload(next);
181795
- }
181796
- // Restore prior ready state so stale-but-usable specs remain accessible
181797
- if (this._hasEverBeenReady) {
181798
- _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(`${_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__.FrontendLoggerCategory.Package}.QuantityFormatter`, "Reload failed — restoring previous ready state. Cached specs may be stale.");
181799
- this._isReady = true;
181800
- }
181801
- return;
181802
- }
181803
- // Current reload succeeded — check if another was queued
181804
- if (this._pendingReload) {
181805
- const next = this._pendingReload;
181806
- this._pendingReload = undefined;
181807
- this._reloadInFlight = false;
181808
- return this.scheduleReload(next);
181809
- }
181810
- // Queue is drained — finalize
181811
- await this.finalizeReload();
181812
- // A new reload may have been queued during the async finalizeReload window
181813
- if (this._pendingReload) {
181814
- const next = this._pendingReload;
181815
- this._pendingReload = undefined;
181816
- this._reloadInFlight = false;
181817
- return this.scheduleReload(next);
181978
+ return this._reloadCoordinator.scheduleReload(intent);
181979
+ }
181980
+ _handleReloadFailure(error) {
181981
+ if (!this._isDisposed)
181982
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logError(`${_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__.FrontendLoggerCategory.Package}.QuantityFormatter`, _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BentleyError.getErrorMessage(error));
181983
+ if (this._hasEverBeenReady && !this._isDisposed) {
181984
+ _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(`${_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_2__.FrontendLoggerCategory.Package}.QuantityFormatter`, "Reload failed — restoring previous ready state. Cached specs may be stale.");
181985
+ this._isReady = true;
181818
181986
  }
181819
- this._reloadInFlight = false;
181820
181987
  }
181821
181988
  /** Execute the reload work for a given intent. All reload logic is centralized here.
181822
181989
  * @internal
@@ -181825,47 +181992,51 @@ class QuantityFormatter {
181825
181992
  switch (intent.scope) {
181826
181993
  case "full":
181827
181994
  await this._reloadCore();
181995
+ return;
181996
+ case "formatsChanged":
181997
+ await this._rebuildRegistryFromProvider(intent.args);
181828
181998
  break;
181829
- case "formatsChanged": {
181830
- const { args } = intent;
181831
- await this._rebuildRegistryFromProvider(args);
181832
- if (args.impliedUnitSystem && args.impliedUnitSystem !== this._activeUnitSystem) {
181833
- this._activeUnitSystem = args.impliedUnitSystem;
181834
- }
181835
- await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
181836
- if (args.impliedUnitSystem) {
181837
- this._deferredSystemChangedEmit = { system: this._activeUnitSystem };
181838
- }
181839
- break;
181840
- }
181841
- case "activeSystem":
181842
- await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
181843
- if (intent.emitSystemChanged) {
181844
- this._deferredSystemChangedEmit = { system: this._activeUnitSystem };
181845
- }
181846
- break;
181847
181999
  }
182000
+ // Build the active specs in temporary maps so readers keep using complete specs until the new ones are ready.
182001
+ const nextFormatSpecs = new Map();
182002
+ const nextParserSpecs = new Map();
182003
+ this._activeFormatSpecsTarget = nextFormatSpecs;
182004
+ this._activeParserSpecsTarget = nextParserSpecs;
182005
+ try {
182006
+ await this.loadFormatAndParsingMapsForSystem(this._activeUnitSystem);
182007
+ }
182008
+ finally {
182009
+ this._activeFormatSpecsTarget = undefined;
182010
+ this._activeParserSpecsTarget = undefined;
182011
+ }
182012
+ this._activeFormatSpecsByType = nextFormatSpecs;
182013
+ this._activeParserSpecsByType = nextParserSpecs;
181848
182014
  }
181849
182015
  /** Called when the reload queue is fully drained after a successful reload.
181850
182016
  * Sets `isReady` to true, resolves `whenInitialized` (one-shot), and emits ready events.
181851
182017
  * @internal
181852
182018
  */
181853
182019
  async finalizeReload() {
182020
+ if (this._isDisposed)
182021
+ return;
181854
182022
  // Phase 1: Let providers register async work
181855
182023
  const collector = new _itwin_core_quantity__WEBPACK_IMPORTED_MODULE_1__.FormattingReadyCollector();
181856
182024
  this.onBeforeFormattingReady.raiseEvent(collector);
181857
182025
  await collector.awaitAll();
182026
+ if (this._isDisposed)
182027
+ return;
181858
182028
  // Phase 2: Signal ready to consumers
181859
182029
  this._isReady = true;
181860
182030
  this._hasEverBeenReady = true;
181861
182031
  this._resolveInitialized();
181862
182032
  this.onFormattingReady.emit();
181863
- // Phase 3: Emit deferred unit-system-changed if the winning reload set one.
182033
+ if (this._isDisposed)
182034
+ return;
182035
+ // Phase 3: Emit unit-system-changed if the unit system was changed since the last ready state, reporting the system that is now active.
181864
182036
  // This fires after isReady === true so listeners can safely use the formatter.
181865
- if (this._deferredSystemChangedEmit) {
181866
- const args = this._deferredSystemChangedEmit;
181867
- this._deferredSystemChangedEmit = undefined;
181868
- this.onActiveFormattingUnitSystemChanged.emit(args);
182037
+ if (this._emitSystemChangedOnReady) {
182038
+ this._emitSystemChangedOnReady = false;
182039
+ this.onActiveFormattingUnitSystemChanged.emit({ system: this._activeUnitSystem });
181869
182040
  }
181870
182041
  }
181871
182042
  getOverrideFormatPropsByQuantityType(quantityTypeKey, unitSystem) {
@@ -181936,8 +182107,8 @@ class QuantityFormatter {
181936
182107
  async loadFormatAndParserSpec(quantityTypeDefinition, formatProps) {
181937
182108
  const formatterSpec = await quantityTypeDefinition.generateFormatterSpec(formatProps, this.unitsProvider);
181938
182109
  const parserSpec = await quantityTypeDefinition.generateParserSpec(formatProps, this.unitsProvider, this.alternateUnitLabelsProvider);
181939
- this._activeFormatSpecsByType.set(quantityTypeDefinition.key, formatterSpec);
181940
- this._activeParserSpecsByType.set(quantityTypeDefinition.key, parserSpec);
182110
+ (this._activeFormatSpecsTarget ?? this._activeFormatSpecsByType).set(quantityTypeDefinition.key, formatterSpec);
182111
+ (this._activeParserSpecsTarget ?? this._activeParserSpecsByType).set(quantityTypeDefinition.key, parserSpec);
181941
182112
  }
181942
182113
  // repopulate formatSpec and parserSpec entries using only default format
181943
182114
  async loadDefaultFormatAndParserSpecForQuantity(typeKey) {
@@ -181994,17 +182165,20 @@ class QuantityFormatter {
181994
182165
  * @internal
181995
182166
  */
181996
182167
  async onInitialized() {
182168
+ // Register once, before the first reload, so provider changes made while a units-provider reload is running are not missed.
182169
+ this._removeFormatsProviderListener ??= _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.formatsProvider.onFormatsChanged.addListener((args) => {
182170
+ if (args.impliedUnitSystem && args.impliedUnitSystem !== this._activeUnitSystem) {
182171
+ this._activeUnitSystem = args.impliedUnitSystem;
182172
+ this._emitSystemChangedOnReady = true;
182173
+ }
182174
+ void this.scheduleReload({ scope: "formatsChanged", args });
182175
+ });
181997
182176
  await this.scheduleReload({ scope: "full" });
181998
182177
  }
181999
182178
  /** Core reload logic — does all async I/O and cache rebuilding without events or state management.
182000
182179
  * @internal
182001
182180
  */
182002
182181
  async _reloadCore() {
182003
- // Remove any existing listener before re-registering to avoid duplicates when called via setUnitsProvider.
182004
- if (this._removeFormatsProviderListener) {
182005
- this._removeFormatsProviderListener();
182006
- this._removeFormatsProviderListener = undefined;
182007
- }
182008
182182
  await this.initializeQuantityTypesRegistry();
182009
182183
  const initialKoQs = [["DefaultToolsUnits.LENGTH", "Units.M"], ["DefaultToolsUnits.ANGLE", "Units.RAD"], ["DefaultToolsUnits.AREA", "Units.SQ_M"], ["DefaultToolsUnits.VOLUME", "Units.CUB_M"], ["DefaultToolsUnits.LENGTH_COORDINATE", "Units.M"], ["CivilUnits.STATION", "Units.M"], ["CivilUnits.LENGTH", "Units.M"], ["AecUnits.LENGTH", "Units.M"]];
182010
182184
  for (const entry of initialKoQs) {
@@ -182017,10 +182191,6 @@ class QuantityFormatter {
182017
182191
  }
182018
182192
  }
182019
182193
  }
182020
- // Register formatsProvider listener that triggers a queued reload when formats change
182021
- this._removeFormatsProviderListener = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.formatsProvider.onFormatsChanged.addListener((args) => {
182022
- void this.scheduleReload({ scope: "formatsChanged", args });
182023
- });
182024
182194
  // initialize default format and parsing specs
182025
182195
  await this.loadFormatAndParsingMapsForSystem();
182026
182196
  }
@@ -182114,6 +182284,9 @@ class QuantityFormatter {
182114
182284
  await _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.quantityFormatter.resetToUseInternalUnitsProvider();
182115
182285
  return;
182116
182286
  }
182287
+ // Disposal can occur while the reload is awaited, so do not notify afterward.
182288
+ if (this._isDisposed)
182289
+ return;
182117
182290
  this.onUnitsProviderChanged.emit();
182118
182291
  }
182119
182292
  /**
@@ -182153,7 +182326,11 @@ class QuantityFormatter {
182153
182326
  this._overrideFormatPropsByUnitSystem = overrideFormatPropsByUnitSystem;
182154
182327
  }
182155
182328
  unitSystemKey && (this._activeUnitSystem = unitSystemKey);
182156
- await this.scheduleReload({ scope: "activeSystem", emitSystemChanged: fireUnitSystemChanged });
182329
+ if (fireUnitSystemChanged)
182330
+ this._emitSystemChangedOnReady = true;
182331
+ await this.scheduleReload({ scope: "activeSystem" });
182332
+ if (this._isDisposed)
182333
+ return;
182157
182334
  _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.toolAdmin && startDefaultTool && await _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.toolAdmin.startDefaultTool();
182158
182335
  }
182159
182336
  /** Set the Active unit system to one of the supported types. This will asynchronously load the formatter and parser specs for the activated system. */
@@ -182166,7 +182343,10 @@ class QuantityFormatter {
182166
182343
  if (this._activeUnitSystem === systemType)
182167
182344
  return;
182168
182345
  this._activeUnitSystem = systemType;
182169
- await this.scheduleReload({ scope: "activeSystem", emitSystemChanged: true });
182346
+ this._emitSystemChangedOnReady = true;
182347
+ await this.scheduleReload({ scope: "activeSystem" });
182348
+ if (this._isDisposed)
182349
+ return;
182170
182350
  // allow settings provider to store the change
182171
182351
  await this._unitFormattingSettingsProvider?.storeUnitSystemSetting({ system: systemType });
182172
182352
  if (_IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.toolAdmin && restartActiveTool)
@@ -227153,6 +227333,7 @@ __webpack_require__.r(__webpack_exports__);
227153
227333
  /* harmony export */ EllipsoidPatch: () => (/* reexport safe */ _geometry3d_Ellipsoid__WEBPACK_IMPORTED_MODULE_5__.EllipsoidPatch),
227154
227334
  /* harmony export */ EllipticalArcApproximationOptions: () => (/* reexport safe */ _curve_Arc3d__WEBPACK_IMPORTED_MODULE_60__.EllipticalArcApproximationOptions),
227155
227335
  /* harmony export */ EllipticalArcSampleMethod: () => (/* reexport safe */ _curve_Arc3d__WEBPACK_IMPORTED_MODULE_60__.EllipticalArcSampleMethod),
227336
+ /* harmony export */ ExteriorFractionSelector: () => (/* reexport safe */ _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_1__.ExteriorFractionSelector),
227156
227337
  /* harmony export */ FacetFaceData: () => (/* reexport safe */ _polyface_FacetFaceData__WEBPACK_IMPORTED_MODULE_113__.FacetFaceData),
227157
227338
  /* harmony export */ FacetIntersectOptions: () => (/* reexport safe */ _polyface_FacetLocationDetail__WEBPACK_IMPORTED_MODULE_115__.FacetIntersectOptions),
227158
227339
  /* harmony export */ FacetLocationDetailPair: () => (/* reexport safe */ _polyface_FacetLocationDetail__WEBPACK_IMPORTED_MODULE_115__.FacetLocationDetailPair),
@@ -231434,6 +231615,7 @@ __webpack_require__.r(__webpack_exports__);
231434
231615
  /* harmony export */ CurveExtendOptions: () => (/* binding */ CurveExtendOptions)
231435
231616
  /* harmony export */ });
231436
231617
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
231618
+ /* harmony import */ var _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../geometry3d/AngleSweep */ "../../core/geometry/lib/esm/geometry3d/AngleSweep.js");
231437
231619
  /*---------------------------------------------------------------------------------------------
231438
231620
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
231439
231621
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -231442,6 +231624,7 @@ __webpack_require__.r(__webpack_exports__);
231442
231624
  * @module Curve
231443
231625
  */
231444
231626
 
231627
+
231445
231628
  /**
231446
231629
  * Enumeration of condition for extending a curve beyond start or end point.
231447
231630
  * * Not all CurvePrimitives support these modes.
@@ -231509,27 +231692,21 @@ class CurveExtendOptions {
231509
231692
  * the sweep extended per `extendParam`.
231510
231693
  */
231511
231694
  static resolveRadiansToValidSweepFraction(extendParam, radians, sweep) {
231512
- extendParam ??= false;
231513
- let fraction = sweep.radiansToSignedPeriodicFraction(radians);
231695
+ let fraction = sweep.radiansToSignedPeriodicFraction(radians, 0, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_1__.ExteriorFractionSelector.Closer);
231514
231696
  let isValid = true;
231515
- if (!sweep.isRadiansInSweep(radians)) {
231516
- const fractionPeriod = sweep.fractionPeriod();
231697
+ if (!_Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.isIn01(fraction)) {
231517
231698
  const mode0 = CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(extendParam, 0);
231518
231699
  const mode1 = CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(extendParam, 1);
231519
- if (mode0 !== CurveExtendMode.None) {
231520
- if (mode1 === CurveExtendMode.None) { // only extend to negative
231521
- if (fraction > 1.0)
231522
- fraction -= fractionPeriod;
231523
- }
231524
- }
231525
- else if (mode1 !== CurveExtendMode.None) { // only extend to positive
231526
- if (fraction < 0.0)
231527
- fraction += fractionPeriod;
231528
- }
231529
- else { // no extension allowed
231700
+ if (mode0 === CurveExtendMode.None && mode1 === CurveExtendMode.None) {
231530
231701
  fraction = _Geometry__WEBPACK_IMPORTED_MODULE_0__.Geometry.clamp(fraction, 0, 1);
231531
231702
  isValid = false;
231532
231703
  }
231704
+ else if (mode1 === CurveExtendMode.None && mode0 !== CurveExtendMode.None) {
231705
+ fraction = sweep.radiansToSignedPeriodicFraction(radians, 0, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_1__.ExteriorFractionSelector.Negative);
231706
+ }
231707
+ else if (mode0 === CurveExtendMode.None && mode1 !== CurveExtendMode.None) {
231708
+ fraction = sweep.radiansToSignedPeriodicFraction(radians, 0, _geometry3d_AngleSweep__WEBPACK_IMPORTED_MODULE_1__.ExteriorFractionSelector.Positive);
231709
+ }
231533
231710
  }
231534
231711
  return { fraction, isValid };
231535
231712
  }
@@ -232885,7 +233062,22 @@ class CurveLocationDetail {
232885
233062
  if (detailA) {
232886
233063
  if (!detailB)
232887
233064
  return detailA;
232888
- return detailA.a <= detailB.a ? detailA : detailB;
233065
+ // tiebreakers (exact comparison!)
233066
+ if (detailA.a === detailB.a) {
233067
+ // prefer interior to exterior
233068
+ const isInteriorA = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isIn01(detailA.fraction);
233069
+ const isInteriorB = _Geometry__WEBPACK_IMPORTED_MODULE_1__.Geometry.isIn01(detailB.fraction);
233070
+ if (isInteriorA && !isInteriorB)
233071
+ return detailA;
233072
+ if (!isInteriorA && isInteriorB)
233073
+ return detailB;
233074
+ if (!isInteriorA && !isInteriorB) { // prefer exterior closer to [0,1]
233075
+ const distFrom01A = detailA.fraction < 0 ? -detailA.fraction : detailA.fraction - 1;
233076
+ const distFrom01B = detailB.fraction < 0 ? -detailB.fraction : detailB.fraction - 1;
233077
+ return (distFrom01A <= distFrom01B) ? detailA : detailB;
233078
+ }
233079
+ }
233080
+ return detailA.a < detailB.a ? detailA : detailB;
232889
233081
  }
232890
233082
  return detailB;
232891
233083
  }
@@ -253976,7 +254168,8 @@ class Angle {
253976
254168
  "use strict";
253977
254169
  __webpack_require__.r(__webpack_exports__);
253978
254170
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
253979
- /* harmony export */ AngleSweep: () => (/* binding */ AngleSweep)
254171
+ /* harmony export */ AngleSweep: () => (/* binding */ AngleSweep),
254172
+ /* harmony export */ ExteriorFractionSelector: () => (/* binding */ ExteriorFractionSelector)
253980
254173
  /* harmony export */ });
253981
254174
  /* harmony import */ var _Geometry__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Geometry */ "../../core/geometry/lib/esm/Geometry.js");
253982
254175
  /* harmony import */ var _Angle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Angle */ "../../core/geometry/lib/esm/geometry3d/Angle.js");
@@ -253989,6 +254182,22 @@ __webpack_require__.r(__webpack_exports__);
253989
254182
  */
253990
254183
 
253991
254184
 
254185
+ /**
254186
+ * Selector for how to convert an angle outside of a sweep to an exterior fraction.
254187
+ * @see [[AngleSweep.radiansToSignedPeriodicFractionStartEnd]], [[AngleSweep.angleToSignedPeriodicFraction]], [[AngleSweep.radiansToSignedPeriodicFraction]]
254188
+ * @public
254189
+ */
254190
+ var ExteriorFractionSelector;
254191
+ (function (ExteriorFractionSelector) {
254192
+ /** Request [[Positive]] or [[Negative]] based on input sign. */
254193
+ ExteriorFractionSelector[ExteriorFractionSelector["SameSign"] = -1] = "SameSign";
254194
+ /** Request positive exterior fraction within one period of 1. */
254195
+ ExteriorFractionSelector[ExteriorFractionSelector["Positive"] = 0] = "Positive";
254196
+ /** Request negative exterior fraction within one period of 0. */
254197
+ ExteriorFractionSelector[ExteriorFractionSelector["Negative"] = 1] = "Negative";
254198
+ /** Request the period-shifted exterior fraction closest to [0,1]. */
254199
+ ExteriorFractionSelector[ExteriorFractionSelector["Closer"] = 2] = "Closer";
254200
+ })(ExteriorFractionSelector || (ExteriorFractionSelector = {}));
253992
254201
  /**
253993
254202
  * An `AngleSweep` is a pair of angles at start and end of an interval.
253994
254203
  *
@@ -254373,9 +254582,12 @@ class AngleSweep {
254373
254582
  * @param radians0 start angle of sweep (in radians)
254374
254583
  * @param radians1 end angle of sweep (in radians)
254375
254584
  * @param zeroSweepDefault return value when the sweep is empty (default 0)
254585
+ * @param selector how to handle an angle outside of the sweep. Default value is
254586
+ * [[ExteriorFractionSelector.SameSign]], to request a fraction with the same sign
254587
+ * as the unbounded fraction `(radians - radians0) / (radians1 - radians0)`.
254376
254588
  * @returns fraction, or `zeroSweepDefault` if the sweep is empty.
254377
254589
  */
254378
- static radiansToSignedPeriodicFractionStartEnd(radians, radians0, radians1, zeroSweepDefault = 0.0) {
254590
+ static radiansToSignedPeriodicFractionStartEnd(radians, radians0, radians1, zeroSweepDefault = 0.0, selector = ExteriorFractionSelector.SameSign) {
254379
254591
  const sweep = radians1 - radians0;
254380
254592
  if (_Angle__WEBPACK_IMPORTED_MODULE_1__.Angle.isAlmostEqualRadiansNoPeriodShift(0, sweep))
254381
254593
  return zeroSweepDefault;
@@ -254393,7 +254605,14 @@ class AngleSweep {
254393
254605
  return 1.0;
254394
254606
  }
254395
254607
  const fraction = (radians - radians0) / sweep;
254396
- return this.fractionToSignedPeriodicFractionStartEnd(fraction, radians0, radians1, fraction < 0);
254608
+ let toNegativeFraction;
254609
+ if (selector === ExteriorFractionSelector.Negative)
254610
+ toNegativeFraction = true;
254611
+ else if (selector === ExteriorFractionSelector.Positive)
254612
+ toNegativeFraction = false;
254613
+ else if (selector === ExteriorFractionSelector.SameSign)
254614
+ toNegativeFraction = fraction < 0;
254615
+ return this.fractionToSignedPeriodicFractionStartEnd(fraction, radians0, radians1, toNegativeFraction);
254397
254616
  }
254398
254617
  /**
254399
254618
  * Return the fractionalized position of the given angle (as radians) computed with consideration of
@@ -254406,10 +254625,13 @@ class AngleSweep {
254406
254625
  * * allows period shift
254407
254626
  * @param radians input angle (in radians)
254408
254627
  * @param zeroSweepDefault return value when this sweep is empty (default 0)
254628
+ * @param selector how to handle an angle outside of the sweep. Default value is
254629
+ * [[ExteriorFractionSelector.SameSign]], to request a fraction with the same sign
254630
+ * as the unbounded fraction `(radians - startRadians) / sweepRadians`.
254409
254631
  * @returns fraction, or `zeroSweepDefault` if this sweep is empty.
254410
254632
  */
254411
- radiansToSignedPeriodicFraction(radians, zeroSweepDefault = 0.0) {
254412
- return AngleSweep.radiansToSignedPeriodicFractionStartEnd(radians, this._radians0, this._radians1, zeroSweepDefault);
254633
+ radiansToSignedPeriodicFraction(radians, zeroSweepDefault = 0.0, selector = ExteriorFractionSelector.SameSign) {
254634
+ return AngleSweep.radiansToSignedPeriodicFractionStartEnd(radians, this._radians0, this._radians1, zeroSweepDefault, selector);
254413
254635
  }
254414
254636
  /**
254415
254637
  * Return the fractionalized position of the given angle (as Angle) computed with consideration of
@@ -254422,10 +254644,13 @@ class AngleSweep {
254422
254644
  * * allows period shift
254423
254645
  * @param theta input angle
254424
254646
  * @param zeroSweepDefault return value when this sweep is empty (default 0)
254647
+ * @param selector how to handle an angle outside of the sweep. Default value is
254648
+ * [[ExteriorFractionSelector.SameSign]], to request a fraction with the same sign
254649
+ * as the fraction returned by `angleToUnboundedFraction(theta)`.
254425
254650
  * @returns fraction, or `zeroSweepDefault` if this sweep is empty.
254426
254651
  */
254427
- angleToSignedPeriodicFraction(theta, zeroSweepDefault = 0.0) {
254428
- return this.radiansToSignedPeriodicFraction(theta.radians, zeroSweepDefault);
254652
+ angleToSignedPeriodicFraction(theta, zeroSweepDefault = 0.0, selector = ExteriorFractionSelector.SameSign) {
254653
+ return this.radiansToSignedPeriodicFraction(theta.radians, zeroSweepDefault, selector);
254429
254654
  }
254430
254655
  /**
254431
254656
  * Return the fractionalized position of the given radian angle with respect to the sweep.
@@ -343905,7 +344130,7 @@ class TestContext {
343905
344130
  this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
343906
344131
  const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
343907
344132
  await core_frontend_1.NoRenderApp.startup({
343908
- applicationVersion: "5.15.0-dev.3",
344133
+ applicationVersion: "5.15.0-dev.4",
343909
344134
  applicationId: this.settings.gprid,
343910
344135
  authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
343911
344136
  hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
@@ -370647,7 +370872,7 @@ class WMS {
370647
370872
  (module) {
370648
370873
 
370649
370874
  "use strict";
370650
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.15.0-dev.3","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s build:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run build:test-worker && vitest --run","cover":"npm run build:test-worker && vitest --run","build:test-worker":"vite build --config ./src/test/worker/vite.config.mts 1>&2","build:workers":"rimraf lib/workers/webpack && vite build --config ./src/workers/ImdlParser/vite.config.mts 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.11","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/node":"~20.17.0","@types/sinon":"^17.0.2","@vitest/browser-playwright":"^4.1.10","@vitest/coverage-v8":"^4.1.10","cpx2":"^8.0.0","eslint":"^9.31.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","typescript":"~5.6.2","vite":"^6.4.3","vitest":"^4.1.10"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^4.4.5","@loaders.gl/draco":"^4.4.5","fuse.js":"^3.3.0","wms-capabilities":"0.6.0"}}');
370875
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.15.0-dev.4","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s build:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run build:test-worker && vitest --run","cover":"npm run build:test-worker && vitest --run","build:test-worker":"vite build --config ./src/test/worker/vite.config.mts 1>&2","build:workers":"rimraf lib/workers/webpack && vite build --config ./src/workers/ImdlParser/vite.config.mts 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.11","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/node":"~20.17.0","@types/sinon":"^17.0.2","@vitest/browser-playwright":"^4.1.10","@vitest/coverage-v8":"^4.1.10","cpx2":"^8.0.0","eslint":"^9.31.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","typescript":"~5.6.2","vite":"^6.4.3","vitest":"^4.1.10"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"^4.4.5","@loaders.gl/draco":"^4.4.5","fuse.js":"^3.3.0","wms-capabilities":"0.6.0"}}');
370651
370876
 
370652
370877
  /***/ },
370653
370878