@itwin/core-quantity 5.14.0-dev.9 → 5.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +44 -1
  2. package/lib/cjs/BasicUnitsProvider.d.ts +10 -7
  3. package/lib/cjs/BasicUnitsProvider.d.ts.map +1 -1
  4. package/lib/cjs/BasicUnitsProvider.js +22 -33
  5. package/lib/cjs/BasicUnitsProvider.js.map +1 -1
  6. package/lib/cjs/Formatter/Format.d.ts +3 -1
  7. package/lib/cjs/Formatter/Format.d.ts.map +1 -1
  8. package/lib/cjs/Formatter/Format.js +77 -38
  9. package/lib/cjs/Formatter/Format.js.map +1 -1
  10. package/lib/cjs/Formatter/FormatterSpec.d.ts +6 -2
  11. package/lib/cjs/Formatter/FormatterSpec.d.ts.map +1 -1
  12. package/lib/cjs/Formatter/FormatterSpec.js +42 -20
  13. package/lib/cjs/Formatter/FormatterSpec.js.map +1 -1
  14. package/lib/cjs/Formatter/Interfaces.d.ts +27 -2
  15. package/lib/cjs/Formatter/Interfaces.d.ts.map +1 -1
  16. package/lib/cjs/Formatter/Interfaces.js.map +1 -1
  17. package/lib/cjs/Interfaces.d.ts +14 -0
  18. package/lib/cjs/Interfaces.d.ts.map +1 -1
  19. package/lib/cjs/Interfaces.js.map +1 -1
  20. package/lib/cjs/Parser.js +2 -2
  21. package/lib/cjs/Parser.js.map +1 -1
  22. package/lib/cjs/internal/BasicUnitsResolvedStateCache.d.ts +4 -0
  23. package/lib/cjs/internal/BasicUnitsResolvedStateCache.d.ts.map +1 -1
  24. package/lib/cjs/internal/BasicUnitsResolvedStateCache.js +7 -0
  25. package/lib/cjs/internal/BasicUnitsResolvedStateCache.js.map +1 -1
  26. package/lib/esm/BasicUnitsProvider.d.ts +10 -7
  27. package/lib/esm/BasicUnitsProvider.d.ts.map +1 -1
  28. package/lib/esm/BasicUnitsProvider.js +21 -12
  29. package/lib/esm/BasicUnitsProvider.js.map +1 -1
  30. package/lib/esm/Formatter/Format.d.ts +3 -1
  31. package/lib/esm/Formatter/Format.d.ts.map +1 -1
  32. package/lib/esm/Formatter/Format.js +77 -38
  33. package/lib/esm/Formatter/Format.js.map +1 -1
  34. package/lib/esm/Formatter/FormatterSpec.d.ts +6 -2
  35. package/lib/esm/Formatter/FormatterSpec.d.ts.map +1 -1
  36. package/lib/esm/Formatter/FormatterSpec.js +42 -20
  37. package/lib/esm/Formatter/FormatterSpec.js.map +1 -1
  38. package/lib/esm/Formatter/Interfaces.d.ts +27 -2
  39. package/lib/esm/Formatter/Interfaces.d.ts.map +1 -1
  40. package/lib/esm/Formatter/Interfaces.js.map +1 -1
  41. package/lib/esm/Interfaces.d.ts +14 -0
  42. package/lib/esm/Interfaces.d.ts.map +1 -1
  43. package/lib/esm/Interfaces.js.map +1 -1
  44. package/lib/esm/Parser.js +2 -2
  45. package/lib/esm/Parser.js.map +1 -1
  46. package/lib/esm/internal/BasicUnitsResolvedStateCache.d.ts +4 -0
  47. package/lib/esm/internal/BasicUnitsResolvedStateCache.d.ts.map +1 -1
  48. package/lib/esm/internal/BasicUnitsResolvedStateCache.js +6 -0
  49. package/lib/esm/internal/BasicUnitsResolvedStateCache.js.map +1 -1
  50. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,6 +1,49 @@
1
1
  # Change Log - @itwin/core-quantity
2
2
 
3
- This log was last generated on Thu, 03 Sep 2026 18:51:17 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 02 Oct 2026 14:55:04 GMT and should not be manually modified.
4
+
5
+ ## 5.14.0
6
+ Fri, 02 Oct 2026 14:55:04 GMT
7
+
8
+ ### Updates
9
+
10
+ - Allow ratio separators to be a string with one non-whitespace character
11
+ - Add synchronous unit and format APIs to @itwin/core-quantity.
12
+
13
+ ## 5.13.7
14
+ Thu, 01 Oct 2026 15:15:30 GMT
15
+
16
+ _Version update only_
17
+
18
+ ## 5.13.6
19
+ Fri, 25 Sep 2026 22:27:22 GMT
20
+
21
+ _Version update only_
22
+
23
+ ## 5.13.5
24
+ Tue, 22 Sep 2026 22:38:08 GMT
25
+
26
+ _Version update only_
27
+
28
+ ## 5.13.4
29
+ Fri, 18 Sep 2026 15:11:19 GMT
30
+
31
+ _Version update only_
32
+
33
+ ## 5.13.3
34
+ Tue, 15 Sep 2026 20:25:28 GMT
35
+
36
+ _Version update only_
37
+
38
+ ## 5.13.2
39
+ Mon, 14 Sep 2026 20:22:20 GMT
40
+
41
+ _Version update only_
42
+
43
+ ## 5.13.1
44
+ Tue, 08 Sep 2026 18:43:29 GMT
45
+
46
+ _Version update only_
4
47
 
5
48
  ## 5.13.0
6
49
  Thu, 03 Sep 2026 18:49:56 GMT
@@ -1,15 +1,14 @@
1
- import type { UnitProps, UnitsProvider } from "./Interfaces";
1
+ import type { SyncUnitsProvider, UnitProps, UnitsProvider } from "./Interfaces";
2
2
  /** @internal — test use only. Resets the shared module-level lazy cache. */
3
3
  export declare function _testResetUnitsCache(): void;
4
4
  /**
5
5
  * A `UnitsProvider` backed by the full BIS `Units.ecschema.json` bundled as a JSON asset.
6
6
  *
7
- * The bundled JSON is loaded lazily via dynamic `import()` on the first provider call and cached
8
- * at module scope — construction is essentially free, and multiple instances
9
- * share the same immutable lookup indexes.
7
+ * The bundled data is available locally. The provider builds its immutable lookup indexes on the
8
+ * first call and caches them at module scope, so multiple instances share the same indexes.
10
9
  *
11
- * If an initial schema load fails, later provider calls will retry the load instead of pinning the
12
- * provider into a permanently failed module-level state.
10
+ * If resolving the bundled data fails, the next provider call retries instead of retaining a failed
11
+ * module-level state.
13
12
  *
14
13
  * This is the zero-dependency default for backends, tools, and any frontend that doesn't need
15
14
  * iModel overrides. Equivalent to calling `createUnitsProvider()` with no arguments.
@@ -17,7 +16,11 @@ export declare function _testResetUnitsCache(): void;
17
16
  * @see createUnitsProvider for layering schema-defined units on top of basic BIS units.
18
17
  * @beta
19
18
  */
20
- export declare class BasicUnitsProvider implements UnitsProvider {
19
+ export declare class BasicUnitsProvider implements UnitsProvider, SyncUnitsProvider {
20
+ /** Find a built-in unit by fully qualified name using local data. */
21
+ findUnitByNameSync(unitName: string): UnitProps;
22
+ /** Compute a conversion between built-in units using the same bundled data as [[getConversion]]. */
23
+ getConversionSync(fromUnit: UnitProps, toUnit: UnitProps): import("./Interfaces").UnitConversionProps;
21
24
  /** Find a unit by its display label, optionally filtering by schema name, phenomenon, and unit system.
22
25
  * @param unitLabel - The display label to search for (case-insensitive).
23
26
  * @param schemaName - Optional schema name filter. Returns `BadUnit` if provided and not `"Units"`.
@@ -1 +1 @@
1
- {"version":3,"file":"BasicUnitsProvider.d.ts","sourceRoot":"","sources":["../../src/BasicUnitsProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAe7D,4EAA4E;AAC5E,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IAItD;;;;;;OAMG;IACU,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAuB3H;;;OAGG;IACU,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMvE;;;OAGG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAMjE;;;;;OAKG;IACU,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS;CAIlE"}
1
+ {"version":3,"file":"BasicUnitsProvider.d.ts","sourceRoot":"","sources":["../../src/BasicUnitsProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAiBhF,4EAA4E;AAC5E,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,kBAAmB,YAAW,aAAa,EAAE,iBAAiB;IAEzE,qEAAqE;IAC9D,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAMtD,oGAAoG;IAC7F,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS;IAM/D;;;;;;OAMG;IACU,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAuB3H;;;OAGG;IACU,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMvE;;;OAGG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAMjE;;;;;OAKG;IACU,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS;CAIlE"}
@@ -1,26 +1,6 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
4
  };
25
5
  Object.defineProperty(exports, "__esModule", { value: true });
26
6
  exports.BasicUnitsProvider = void 0;
@@ -28,13 +8,13 @@ exports._testResetUnitsCache = _testResetUnitsCache;
28
8
  const Unit_1 = require("./Unit");
29
9
  const BasicUnitConversionData_1 = require("./internal/BasicUnitConversionData");
30
10
  const BasicUnitsResolvedStateCache_1 = require("./internal/BasicUnitsResolvedStateCache");
11
+ const Units_json_1 = __importDefault(require("./assets/Units.json"));
12
+ const bundledSchema = Units_json_1.default;
31
13
  async function resolveState() {
32
- return (0, BasicUnitsResolvedStateCache_1.resolveBasicUnitsData)(async () => {
33
- // First caller pays the dynamic-import + schema-index build cost.
34
- // Concurrent callers await the same promise, and later callers reuse the resolved state.
35
- const { default: schema } = await Promise.resolve().then(() => __importStar(require("./assets/Units.json")));
36
- return schema;
37
- });
14
+ return (0, BasicUnitsResolvedStateCache_1.resolveBasicUnitsData)(async () => bundledSchema);
15
+ }
16
+ function resolveStateSync() {
17
+ return (0, BasicUnitsResolvedStateCache_1.resolveBasicUnitsDataSync)(bundledSchema);
38
18
  }
39
19
  /** @internal — test use only. Resets the shared module-level lazy cache. */
40
20
  function _testResetUnitsCache() {
@@ -43,12 +23,11 @@ function _testResetUnitsCache() {
43
23
  /**
44
24
  * A `UnitsProvider` backed by the full BIS `Units.ecschema.json` bundled as a JSON asset.
45
25
  *
46
- * The bundled JSON is loaded lazily via dynamic `import()` on the first provider call and cached
47
- * at module scope — construction is essentially free, and multiple instances
48
- * share the same immutable lookup indexes.
26
+ * The bundled data is available locally. The provider builds its immutable lookup indexes on the
27
+ * first call and caches them at module scope, so multiple instances share the same indexes.
49
28
  *
50
- * If an initial schema load fails, later provider calls will retry the load instead of pinning the
51
- * provider into a permanently failed module-level state.
29
+ * If resolving the bundled data fails, the next provider call retries instead of retaining a failed
30
+ * module-level state.
52
31
  *
53
32
  * This is the zero-dependency default for backends, tools, and any frontend that doesn't need
54
33
  * iModel overrides. Equivalent to calling `createUnitsProvider()` with no arguments.
@@ -57,6 +36,16 @@ function _testResetUnitsCache() {
57
36
  * @beta
58
37
  */
59
38
  class BasicUnitsProvider {
39
+ /** Find a built-in unit by fully qualified name using local data. */
40
+ findUnitByNameSync(unitName) {
41
+ const state = resolveStateSync();
42
+ const entry = state.nameMap.get(unitName);
43
+ return entry ? entry.props : new Unit_1.BadUnit();
44
+ }
45
+ /** Compute a conversion between built-in units using the same bundled data as [[getConversion]]. */
46
+ getConversionSync(fromUnit, toUnit) {
47
+ return (0, BasicUnitConversionData_1.getBasicUnitConversion)(resolveStateSync(), fromUnit, toUnit);
48
+ }
60
49
  // ── UnitsProvider implementation ─────────────────────────────────────
61
50
  /** Find a unit by its display label, optionally filtering by schema name, phenomenon, and unit system.
62
51
  * @param unitLabel - The display label to search for (case-insensitive).
@@ -1 +1 @@
1
- {"version":3,"file":"BasicUnitsProvider.js","sourceRoot":"","sources":["../../src/BasicUnitsProvider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,oDAEC;AAhBD,iCAAiC;AACjC,gFAA4E;AAC5E,0FAAuH;AAEvH,KAAK,UAAU,YAAY;IACzB,OAAO,IAAA,oDAAqB,EAAC,KAAK,IAAI,EAAE;QACtC,kEAAkE;QAClE,yFAAyF;QACzF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,wDAAa,qBAAqB,GAAC,CAAC;QAChE,OAAO,MAA8B,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,SAAgB,oBAAoB;IAClC,IAAA,oEAAqC,GAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAa,kBAAkB;IAE7B,wEAAwE;IAExE;;;;;;OAMG;IACI,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,UAAmB,EAAE,UAAmB,EAAE,UAAmB;QACpG,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;QACnC,IAAI,UAAU,IAAI,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;YAClD,OAAO,IAAI,cAAO,EAAE,CAAC;QACvB,CAAC;QACD,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,cAAO,EAAE,CAAC;QACvB,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,IAAI,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,OAAO,CAAC,CAAC,KAAK,CAAC;QACjB,CAAC;QAED,OAAO,IAAI,cAAO,EAAE,CAAC;IACvB,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,gBAAgB,CAAC,UAAkB;QAC9C,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,cAAc,CAAC,QAAgB;QAC1C,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,cAAO,EAAE,CAAC;IAC7C,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,aAAa,CAAC,QAAmB,EAAE,MAAiB;QAC/D,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;QACnC,OAAO,IAAA,gDAAsB,EAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;CACF;AAhED,gDAgEC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nimport type { UnitProps, UnitsProvider } from \"./Interfaces\";\r\nimport type { SerializedUnitSchema } from \"./SerializedUnitSchema\";\r\nimport { BadUnit } from \"./Unit\";\r\nimport { getBasicUnitConversion } from \"./internal/BasicUnitConversionData\";\r\nimport { _testResetResolvedBasicUnitsDataCache, resolveBasicUnitsData } from \"./internal/BasicUnitsResolvedStateCache\";\r\n\r\nasync function resolveState() {\r\n return resolveBasicUnitsData(async () => {\r\n // First caller pays the dynamic-import + schema-index build cost.\r\n // Concurrent callers await the same promise, and later callers reuse the resolved state.\r\n const { default: schema } = await import(\"./assets/Units.json\");\r\n return schema as SerializedUnitSchema;\r\n });\r\n}\r\n\r\n/** @internal — test use only. Resets the shared module-level lazy cache. */\r\nexport function _testResetUnitsCache(): void {\r\n _testResetResolvedBasicUnitsDataCache();\r\n}\r\n\r\n/**\r\n * A `UnitsProvider` backed by the full BIS `Units.ecschema.json` bundled as a JSON asset.\r\n *\r\n * The bundled JSON is loaded lazily via dynamic `import()` on the first provider call and cached\r\n * at module scope — construction is essentially free, and multiple instances\r\n * share the same immutable lookup indexes.\r\n *\r\n * If an initial schema load fails, later provider calls will retry the load instead of pinning the\r\n * provider into a permanently failed module-level state.\r\n *\r\n * This is the zero-dependency default for backends, tools, and any frontend that doesn't need\r\n * iModel overrides. Equivalent to calling `createUnitsProvider()` with no arguments.\r\n *\r\n * @see createUnitsProvider for layering schema-defined units on top of basic BIS units.\r\n * @beta\r\n */\r\nexport class BasicUnitsProvider implements UnitsProvider {\r\n\r\n // ── UnitsProvider implementation ─────────────────────────────────────\r\n\r\n /** Find a unit by its display label, optionally filtering by schema name, phenomenon, and unit system.\r\n * @param unitLabel - The display label to search for (case-insensitive).\r\n * @param schemaName - Optional schema name filter. Returns `BadUnit` if provided and not `\"Units\"`.\r\n * @param phenomenon - Optional phenomenon filter (e.g. `\"Units.LENGTH\"`).\r\n * @param unitSystem - Optional unit system filter (e.g. `\"Units.METRIC\"`).\r\n * @returns The matching `UnitProps`, or a `BadUnit` if no match is found.\r\n */\r\n public async findUnit(unitLabel: string, schemaName?: string, phenomenon?: string, unitSystem?: string): Promise<UnitProps> {\r\n const state = await resolveState();\r\n if (schemaName && schemaName !== state.schemaName) {\r\n return new BadUnit();\r\n }\r\n const candidates = state.labelMap.get(unitLabel.toLowerCase());\r\n if (!candidates || candidates.length === 0) {\r\n return new BadUnit();\r\n }\r\n\r\n for (const c of candidates) {\r\n if (phenomenon && c.props.phenomenon !== phenomenon) {\r\n continue;\r\n }\r\n if (unitSystem && c.props.system !== unitSystem) {\r\n continue;\r\n }\r\n return c.props;\r\n }\r\n\r\n return new BadUnit();\r\n }\r\n\r\n /** Return all units belonging to the given phenomenon (unit family).\r\n * @param phenomenon - The phenomenon full name (e.g. `\"Units.LENGTH\"`).\r\n * @returns An array of matching `UnitProps`, or an empty array if none.\r\n */\r\n public async getUnitsByFamily(phenomenon: string): Promise<UnitProps[]> {\r\n const state = await resolveState();\r\n const entries = state.phenomenonMap.get(phenomenon);\r\n return entries ? entries.map((e) => e.props) : [];\r\n }\r\n\r\n /** Find a unit by its fully-qualified name (e.g. `\"Units.M\"`).\r\n * @param unitName - The qualified unit name.\r\n * @returns The matching `UnitProps`, or a `BadUnit` if not found.\r\n */\r\n public async findUnitByName(unitName: string): Promise<UnitProps> {\r\n const state = await resolveState();\r\n const entry = state.nameMap.get(unitName);\r\n return entry ? entry.props : new BadUnit();\r\n }\r\n\r\n /** Compute the conversion factors from `fromUnit` to `toUnit`.\r\n * Handles normal units, inverted units, and mixed (inverted ↔ non-inverted) conversions.\r\n * @param fromUnit - The source unit.\r\n * @param toUnit - The target unit.\r\n * @returns A `UnitConversionProps` with `factor`, `offset`, and optionally `inversion` and `error`.\r\n */\r\n public async getConversion(fromUnit: UnitProps, toUnit: UnitProps) {\r\n const state = await resolveState();\r\n return getBasicUnitConversion(state, fromUnit, toUnit);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"BasicUnitsProvider.js","sourceRoot":"","sources":["../../src/BasicUnitsProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nimport type { SyncUnitsProvider, UnitProps, UnitsProvider } from \"./Interfaces\";\r\nimport type { SerializedUnitSchema } from \"./SerializedUnitSchema\";\r\nimport { BadUnit } from \"./Unit\";\r\nimport { getBasicUnitConversion } from \"./internal/BasicUnitConversionData\";\r\nimport { _testResetResolvedBasicUnitsDataCache, resolveBasicUnitsData, resolveBasicUnitsDataSync } from \"./internal/BasicUnitsResolvedStateCache\";\r\nimport bundledUnitsSchema from \"./assets/Units.json\";\r\n\r\nconst bundledSchema = bundledUnitsSchema as SerializedUnitSchema;\r\n\r\nasync function resolveState() {\r\n return resolveBasicUnitsData(async () => bundledSchema);\r\n}\r\n\r\nfunction resolveStateSync() {\r\n return resolveBasicUnitsDataSync(bundledSchema);\r\n}\r\n\r\n/** @internal — test use only. Resets the shared module-level lazy cache. */\r\nexport function _testResetUnitsCache(): void {\r\n _testResetResolvedBasicUnitsDataCache();\r\n}\r\n\r\n/**\r\n * A `UnitsProvider` backed by the full BIS `Units.ecschema.json` bundled as a JSON asset.\r\n *\r\n * The bundled data is available locally. The provider builds its immutable lookup indexes on the\r\n * first call and caches them at module scope, so multiple instances share the same indexes.\r\n *\r\n * If resolving the bundled data fails, the next provider call retries instead of retaining a failed\r\n * module-level state.\r\n *\r\n * This is the zero-dependency default for backends, tools, and any frontend that doesn't need\r\n * iModel overrides. Equivalent to calling `createUnitsProvider()` with no arguments.\r\n *\r\n * @see createUnitsProvider for layering schema-defined units on top of basic BIS units.\r\n * @beta\r\n */\r\nexport class BasicUnitsProvider implements UnitsProvider, SyncUnitsProvider {\r\n\r\n /** Find a built-in unit by fully qualified name using local data. */\r\n public findUnitByNameSync(unitName: string): UnitProps {\r\n const state = resolveStateSync();\r\n const entry = state.nameMap.get(unitName);\r\n return entry ? entry.props : new BadUnit();\r\n }\r\n\r\n /** Compute a conversion between built-in units using the same bundled data as [[getConversion]]. */\r\n public getConversionSync(fromUnit: UnitProps, toUnit: UnitProps) {\r\n return getBasicUnitConversion(resolveStateSync(), fromUnit, toUnit);\r\n }\r\n\r\n // ── UnitsProvider implementation ─────────────────────────────────────\r\n\r\n /** Find a unit by its display label, optionally filtering by schema name, phenomenon, and unit system.\r\n * @param unitLabel - The display label to search for (case-insensitive).\r\n * @param schemaName - Optional schema name filter. Returns `BadUnit` if provided and not `\"Units\"`.\r\n * @param phenomenon - Optional phenomenon filter (e.g. `\"Units.LENGTH\"`).\r\n * @param unitSystem - Optional unit system filter (e.g. `\"Units.METRIC\"`).\r\n * @returns The matching `UnitProps`, or a `BadUnit` if no match is found.\r\n */\r\n public async findUnit(unitLabel: string, schemaName?: string, phenomenon?: string, unitSystem?: string): Promise<UnitProps> {\r\n const state = await resolveState();\r\n if (schemaName && schemaName !== state.schemaName) {\r\n return new BadUnit();\r\n }\r\n const candidates = state.labelMap.get(unitLabel.toLowerCase());\r\n if (!candidates || candidates.length === 0) {\r\n return new BadUnit();\r\n }\r\n\r\n for (const c of candidates) {\r\n if (phenomenon && c.props.phenomenon !== phenomenon) {\r\n continue;\r\n }\r\n if (unitSystem && c.props.system !== unitSystem) {\r\n continue;\r\n }\r\n return c.props;\r\n }\r\n\r\n return new BadUnit();\r\n }\r\n\r\n /** Return all units belonging to the given phenomenon (unit family).\r\n * @param phenomenon - The phenomenon full name (e.g. `\"Units.LENGTH\"`).\r\n * @returns An array of matching `UnitProps`, or an empty array if none.\r\n */\r\n public async getUnitsByFamily(phenomenon: string): Promise<UnitProps[]> {\r\n const state = await resolveState();\r\n const entries = state.phenomenonMap.get(phenomenon);\r\n return entries ? entries.map((e) => e.props) : [];\r\n }\r\n\r\n /** Find a unit by its fully-qualified name (e.g. `\"Units.M\"`).\r\n * @param unitName - The qualified unit name.\r\n * @returns The matching `UnitProps`, or a `BadUnit` if not found.\r\n */\r\n public async findUnitByName(unitName: string): Promise<UnitProps> {\r\n const state = await resolveState();\r\n const entry = state.nameMap.get(unitName);\r\n return entry ? entry.props : new BadUnit();\r\n }\r\n\r\n /** Compute the conversion factors from `fromUnit` to `toUnit`.\r\n * Handles normal units, inverted units, and mixed (inverted ↔ non-inverted) conversions.\r\n * @param fromUnit - The source unit.\r\n * @param toUnit - The target unit.\r\n * @returns A `UnitConversionProps` with `factor`, `offset`, and optionally `inversion` and `error`.\r\n */\r\n public async getConversion(fromUnit: UnitProps, toUnit: UnitProps) {\r\n const state = await resolveState();\r\n return getBasicUnitConversion(state, fromUnit, toUnit);\r\n }\r\n}\r\n"]}
@@ -1,7 +1,7 @@
1
1
  /** @packageDocumentation
2
2
  * @module Quantity
3
3
  */
4
- import { UnitProps, UnitsProvider } from "../Interfaces";
4
+ import { SyncUnitsProvider, UnitProps, UnitsProvider } from "../Interfaces";
5
5
  import { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision, RatioFormatType, RatioType, ScientificType, ShowSignOption } from "./FormatEnums";
6
6
  import { CloneOptions, FormatProps, ResolvedFormatProps } from "./Interfaces";
7
7
  /** A base Format class with shared properties and functionality between quantity and ecschema-metadata Format classes
@@ -124,6 +124,8 @@ export declare class Format extends BaseFormat {
124
124
  fromFullyResolvedJSON(jsonObj: ResolvedFormatProps): void;
125
125
  /** Create a Format from FormatProps */
126
126
  static createFromJSON(name: string, unitsProvider: UnitsProvider, formatProps: FormatProps): Promise<Format>;
127
+ /** Create a `Format` from `FormatProps` using a synchronous unit provider. */
128
+ static createFromJSONSync(name: string, unitsProvider: SyncUnitsProvider, formatProps: FormatProps): Format;
127
129
  static createFromFullyResolvedJSON(name: string, formatProps: ResolvedFormatProps): Format;
128
130
  /**
129
131
  * Returns a JSON object that contain the specification for this Format.
@@ -1 +1 @@
1
- {"version":3,"file":"Format.d.ts","sourceRoot":"","sources":["../../../src/Formatter/Format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Format.d.ts","sourceRoot":"","sources":["../../../src/Formatter/Format.ts"],"names":[],"mappings":"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"}
@@ -35,7 +35,7 @@ class BaseFormat {
35
35
  _stationBaseFactor; // optional positive integer base factor for station formatting; default is 1
36
36
  _ratioType; // required if type is ratio; options: oneToN, NToOne, ValueBased, useGreatestCommonDivisor
37
37
  _ratioFormatType; // defaults to Decimal if not specified
38
- _ratioSeparator; // default is ":"; separator character used in ratio formatting
38
+ _ratioSeparator; // default is ":"; separator string used in ratio formatting
39
39
  _azimuthBase; // value always clockwise from north
40
40
  _azimuthBaseUnit; // unit for azimuthBase value
41
41
  _azimuthCounterClockwise; // if set to true, azimuth values are returned counter-clockwise from base
@@ -137,11 +137,12 @@ class BaseFormat {
137
137
  if (undefined === formatProps.ratioType)
138
138
  throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${this.name} is 'Ratio' type therefore the attribute 'ratioType' is required.`);
139
139
  this._ratioType = (0, FormatEnums_1.parseRatioType)(formatProps.ratioType, this.name);
140
- if (undefined !== formatProps.ratioSeparator) { // optional; default is 0.0
140
+ if (undefined !== formatProps.ratioSeparator) { // optional; default is ":"
141
141
  if (typeof (formatProps.ratioSeparator) !== "string")
142
142
  throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'ratioSeparator' attribute. It should be of type 'string'.`);
143
- if (formatProps.ratioSeparator.length !== 1)
144
- throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'ratioSeparator' attribute. It should be a one character string.`);
143
+ const nonSpaceCharacters = [...formatProps.ratioSeparator].filter((character) => character !== " ");
144
+ if (nonSpaceCharacters.length !== 1 || nonSpaceCharacters[0].trim().length === 0)
145
+ throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'ratioSeparator' attribute. It should contain exactly one non-space character, optionally surrounded by spaces.`);
145
146
  this._ratioSeparator = formatProps.ratioSeparator;
146
147
  }
147
148
  else {
@@ -376,6 +377,12 @@ class Format extends BaseFormat {
376
377
  await actualFormat.fromJSON(unitsProvider, formatProps);
377
378
  return actualFormat;
378
379
  }
380
+ /** Create a `Format` from `FormatProps` using a synchronous unit provider. */
381
+ static createFromJSONSync(name, unitsProvider, formatProps) {
382
+ const actualFormat = new Format(name);
383
+ actualFormat.fromFullyResolvedJSON(resolveFormatPropsSync(name, unitsProvider, formatProps));
384
+ return actualFormat;
385
+ }
379
386
  static createFromFullyResolvedJSON(name, formatProps) {
380
387
  const actualFormat = new Format(name);
381
388
  actualFormat.fromFullyResolvedJSON(formatProps);
@@ -443,52 +450,50 @@ class Format extends BaseFormat {
443
450
  }
444
451
  }
445
452
  exports.Format = Format;
446
- async function resolveCompositeUnit(provider, name, label) {
453
+ function validateCompositeUnitInput(name, label) {
447
454
  if (typeof name !== "string" || (undefined !== label && typeof label !== "string")) {
448
455
  throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `This Composite has a unit with an invalid 'name' or 'label' attribute.`);
449
456
  }
450
- const unit = await provider.findUnitByName(name);
457
+ }
458
+ function validateResolvedUnit(unit, errorMessage) {
451
459
  if (!unit || !unit.isValid) {
452
- throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `Invalid unit name '${name}'.`);
460
+ throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, errorMessage);
453
461
  }
454
462
  return unit;
455
463
  }
456
- async function resolveAzimuthBearingUnit(formatName, jsonObj, key, provider) {
464
+ function getAzimuthBearingUnitName(formatName, jsonObj, key) {
457
465
  const unitName = jsonObj[key];
458
- if (undefined !== unitName) {
459
- if (typeof unitName !== "string") {
460
- throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid '${key}' attribute. It should be of type 'string'.`);
461
- }
462
- const unit = await provider.findUnitByName(unitName);
463
- if (!unit || !unit.isValid) {
464
- throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `Invalid unit name '${unitName}' for ${key} in Format '${formatName}'.`);
465
- }
466
- return unit;
466
+ if (undefined !== unitName && typeof unitName !== "string") {
467
+ throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid '${key}' attribute. It should be of type 'string'.`);
467
468
  }
468
- return undefined;
469
+ return unitName;
469
470
  }
470
- async function resolveFormatProps(formatName, unitsProvider, jsonObj) {
471
- let units;
472
- if (undefined !== jsonObj.composite?.units) {
473
- units = await Promise.all(jsonObj.composite.units.map(async (entry) => {
474
- const unit = await resolveCompositeUnit(unitsProvider, entry.name);
475
- return { unit, label: entry.label };
476
- }));
477
- // For Ratio formats with 2 units: validate both units have the same phenomenon
478
- const formatType = (0, FormatEnums_1.parseFormatType)(jsonObj.type, formatName);
479
- if (formatType === FormatEnums_1.FormatType.Ratio && units.length === 2) {
480
- const phenomenon1 = units[0].unit.phenomenon;
481
- const phenomenon2 = units[1].unit.phenomenon;
482
- if (phenomenon1 !== phenomenon2) {
483
- throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} has 2-unit composite with different phenomena. Both units must have the same phenomenon. Found '${phenomenon1}' and '${phenomenon2}'.`);
484
- }
471
+ async function resolveCompositeUnit(provider, name, label) {
472
+ validateCompositeUnitInput(name, label);
473
+ return validateResolvedUnit(await provider.findUnitByName(name), `Invalid unit name '${name}'.`);
474
+ }
475
+ function resolveCompositeUnitSync(provider, name, label) {
476
+ validateCompositeUnitInput(name, label);
477
+ return validateResolvedUnit(provider.findUnitByNameSync(name), `Invalid unit name '${name}'.`);
478
+ }
479
+ async function resolveAzimuthBearingUnit(formatName, jsonObj, key, provider) {
480
+ const unitName = getAzimuthBearingUnitName(formatName, jsonObj, key);
481
+ return undefined === unitName ? undefined : validateResolvedUnit(await provider.findUnitByName(unitName), `Invalid unit name '${unitName}' for ${key} in Format '${formatName}'.`);
482
+ }
483
+ function resolveAzimuthBearingUnitSync(formatName, jsonObj, key, provider) {
484
+ const unitName = getAzimuthBearingUnitName(formatName, jsonObj, key);
485
+ return undefined === unitName ? undefined : validateResolvedUnit(provider.findUnitByNameSync(unitName), `Invalid unit name '${unitName}' for ${key} in Format '${formatName}'.`);
486
+ }
487
+ function validateResolvedFormatProps(formatName, jsonObj, units, azimuthBaseUnit, revolutionUnit) {
488
+ const formatType = (0, FormatEnums_1.parseFormatType)(jsonObj.type, formatName);
489
+ if (formatType === FormatEnums_1.FormatType.Ratio && units?.length === 2) {
490
+ const phenomenon1 = units[0].unit.phenomenon;
491
+ const phenomenon2 = units[1].unit.phenomenon;
492
+ if (phenomenon1 !== phenomenon2) {
493
+ throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} has 2-unit composite with different phenomena. Both units must have the same phenomenon. Found '${phenomenon1}' and '${phenomenon2}'.`);
485
494
  }
486
495
  }
487
- let azimuthBaseUnit, revolutionUnit;
488
- const type = (0, FormatEnums_1.parseFormatType)(jsonObj.type, formatName);
489
- if (type === FormatEnums_1.FormatType.Azimuth || type === FormatEnums_1.FormatType.Bearing) {
490
- azimuthBaseUnit = await resolveAzimuthBearingUnit(formatName, jsonObj, "azimuthBaseUnit", unitsProvider);
491
- revolutionUnit = await resolveAzimuthBearingUnit(formatName, jsonObj, "revolutionUnit", unitsProvider);
496
+ if (formatType === FormatEnums_1.FormatType.Azimuth || formatType === FormatEnums_1.FormatType.Bearing) {
492
497
  if (!revolutionUnit) {
493
498
  throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} is 'Azimuth' or 'Bearing' type therefore the attribute 'revolutionUnit' is required.`);
494
499
  }
@@ -496,6 +501,8 @@ async function resolveFormatProps(formatName, unitsProvider, jsonObj) {
496
501
  throw new Exception_1.QuantityError(Exception_1.QuantityStatus.InvalidJson, `The Format ${formatName} has an 'azimuthBase' attribute therefore the attribute 'azimuthBaseUnit' is required.`);
497
502
  }
498
503
  }
504
+ }
505
+ function createResolvedFormatProps(jsonObj, units, azimuthBaseUnit, revolutionUnit) {
499
506
  return {
500
507
  ...jsonObj,
501
508
  azimuthBaseUnit,
@@ -506,4 +513,36 @@ async function resolveFormatProps(formatName, unitsProvider, jsonObj) {
506
513
  } : undefined,
507
514
  };
508
515
  }
516
+ async function resolveFormatProps(formatName, unitsProvider, jsonObj) {
517
+ const units = undefined === jsonObj.composite?.units ? undefined : await Promise.all(jsonObj.composite.units.map(async (entry) => ({
518
+ // Label is intentionally not validated, matching master: existing JSON may carry a non-string label (e.g. null).
519
+ unit: await resolveCompositeUnit(unitsProvider, entry.name),
520
+ label: entry.label,
521
+ })));
522
+ let azimuthBaseUnit;
523
+ let revolutionUnit;
524
+ const formatType = (0, FormatEnums_1.parseFormatType)(jsonObj.type, formatName);
525
+ if (formatType === FormatEnums_1.FormatType.Azimuth || formatType === FormatEnums_1.FormatType.Bearing) {
526
+ azimuthBaseUnit = await resolveAzimuthBearingUnit(formatName, jsonObj, "azimuthBaseUnit", unitsProvider);
527
+ revolutionUnit = await resolveAzimuthBearingUnit(formatName, jsonObj, "revolutionUnit", unitsProvider);
528
+ }
529
+ validateResolvedFormatProps(formatName, jsonObj, units, azimuthBaseUnit, revolutionUnit);
530
+ return createResolvedFormatProps(jsonObj, units, azimuthBaseUnit, revolutionUnit);
531
+ }
532
+ function resolveFormatPropsSync(formatName, unitsProvider, jsonObj) {
533
+ const units = undefined === jsonObj.composite?.units ? undefined : jsonObj.composite.units.map((entry) => ({
534
+ // Keep in sync with resolveFormatProps: label is intentionally not validated.
535
+ unit: resolveCompositeUnitSync(unitsProvider, entry.name),
536
+ label: entry.label,
537
+ }));
538
+ let azimuthBaseUnit;
539
+ let revolutionUnit;
540
+ const formatType = (0, FormatEnums_1.parseFormatType)(jsonObj.type, formatName);
541
+ if (formatType === FormatEnums_1.FormatType.Azimuth || formatType === FormatEnums_1.FormatType.Bearing) {
542
+ azimuthBaseUnit = resolveAzimuthBearingUnitSync(formatName, jsonObj, "azimuthBaseUnit", unitsProvider);
543
+ revolutionUnit = resolveAzimuthBearingUnitSync(formatName, jsonObj, "revolutionUnit", unitsProvider);
544
+ }
545
+ validateResolvedFormatProps(formatName, jsonObj, units, azimuthBaseUnit, revolutionUnit);
546
+ return createResolvedFormatProps(jsonObj, units, azimuthBaseUnit, revolutionUnit);
547
+ }
509
548
  //# sourceMappingURL=Format.js.map