@itwin/ecschema-metadata 5.14.0-dev.8 → 5.15.0-dev.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.
- package/CHANGELOG.md +31 -1
- package/lib/cjs/ECName.d.ts +4 -0
- package/lib/cjs/ECName.d.ts.map +1 -1
- package/lib/cjs/ECName.js +9 -1
- package/lib/cjs/ECName.js.map +1 -1
- package/lib/cjs/Formatting/FormatSetFormatsProvider.d.ts +13 -5
- package/lib/cjs/Formatting/FormatSetFormatsProvider.d.ts.map +1 -1
- package/lib/cjs/Formatting/FormatSetFormatsProvider.js +65 -22
- package/lib/cjs/Formatting/FormatSetFormatsProvider.js.map +1 -1
- package/lib/cjs/Formatting/SchemaFormatsProvider.d.ts +15 -6
- package/lib/cjs/Formatting/SchemaFormatsProvider.d.ts.map +1 -1
- package/lib/cjs/Formatting/SchemaFormatsProvider.js +163 -44
- package/lib/cjs/Formatting/SchemaFormatsProvider.js.map +1 -1
- package/lib/cjs/SchemaView/SchemaManifest.d.ts +11 -14
- package/lib/cjs/SchemaView/SchemaManifest.d.ts.map +1 -1
- package/lib/cjs/SchemaView/SchemaManifest.js +8 -11
- package/lib/cjs/SchemaView/SchemaManifest.js.map +1 -1
- package/lib/cjs/SchemaView/SchemaView.d.ts +14 -5
- package/lib/cjs/SchemaView/SchemaView.d.ts.map +1 -1
- package/lib/cjs/SchemaView/SchemaView.js +22 -12
- package/lib/cjs/SchemaView/SchemaView.js.map +1 -1
- package/lib/cjs/SchemaView/SchemaViewManager.d.ts +22 -17
- package/lib/cjs/SchemaView/SchemaViewManager.d.ts.map +1 -1
- package/lib/cjs/SchemaView/SchemaViewManager.js +11 -11
- package/lib/cjs/SchemaView/SchemaViewManager.js.map +1 -1
- package/lib/esm/ECName.d.ts +4 -0
- package/lib/esm/ECName.d.ts.map +1 -1
- package/lib/esm/ECName.js +9 -1
- package/lib/esm/ECName.js.map +1 -1
- package/lib/esm/Formatting/FormatSetFormatsProvider.d.ts +13 -5
- package/lib/esm/Formatting/FormatSetFormatsProvider.d.ts.map +1 -1
- package/lib/esm/Formatting/FormatSetFormatsProvider.js +65 -22
- package/lib/esm/Formatting/FormatSetFormatsProvider.js.map +1 -1
- package/lib/esm/Formatting/SchemaFormatsProvider.d.ts +15 -6
- package/lib/esm/Formatting/SchemaFormatsProvider.d.ts.map +1 -1
- package/lib/esm/Formatting/SchemaFormatsProvider.js +163 -44
- package/lib/esm/Formatting/SchemaFormatsProvider.js.map +1 -1
- package/lib/esm/SchemaView/SchemaManifest.d.ts +11 -14
- package/lib/esm/SchemaView/SchemaManifest.d.ts.map +1 -1
- package/lib/esm/SchemaView/SchemaManifest.js +8 -11
- package/lib/esm/SchemaView/SchemaManifest.js.map +1 -1
- package/lib/esm/SchemaView/SchemaView.d.ts +14 -5
- package/lib/esm/SchemaView/SchemaView.d.ts.map +1 -1
- package/lib/esm/SchemaView/SchemaView.js +22 -12
- package/lib/esm/SchemaView/SchemaView.js.map +1 -1
- package/lib/esm/SchemaView/SchemaViewManager.d.ts +22 -17
- package/lib/esm/SchemaView/SchemaViewManager.d.ts.map +1 -1
- package/lib/esm/SchemaView/SchemaViewManager.js +11 -11
- package/lib/esm/SchemaView/SchemaViewManager.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaViewManager.js","sourceRoot":"","sources":["../../../src/SchemaView/SchemaViewManager.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\n/** @packageDocumentation\r\n * @module Schema\r\n */\r\n\r\nimport { SchemaManifest } from \"./SchemaManifest\";\r\nimport { SchemaView } from \"./SchemaView\";\r\n\r\n/** One schema-view blob with its cache-invalidation token, as fetched by a\r\n * {@link SchemaViewDataProvider}. Full and fragment blobs share this shape.\r\n * @internal\r\n */\r\nexport interface SchemaViewBlob {\r\n /** The binary schema metadata (the `data` column of `PRAGMA schema_view` / `schema_view_fragment`). */\r\n readonly data: Uint8Array;\r\n /** Schema-identity hash of the iModel's whole schema set (the `schemaToken` column). Empty string when unavailable. */\r\n readonly schemaToken: string;\r\n}\r\n\r\n/** The data source a {@link SchemaViewManager} loads schema-view data from, implemented by the hosts\r\n * that own the query APIs: `IModelDb` on the backend and `IModelConnection` on the frontend. The\r\n * manager deals only in schema names, blobs and the manifest; everything transport-specific - pragma\r\n * strings, format-version pinning - belongs to the provider.\r\n * @internal\r\n */\r\nexport interface SchemaViewDataProvider {\r\n /** Fetch the blob containing every schema in the iModel (`PRAGMA schema_view`). */\r\n fetchFullBlob(): Promise<SchemaViewBlob>;\r\n\r\n /** Fetch one blob containing exactly the given schemas (`PRAGMA schema_view_fragment`). The\r\n * requested set is always dependency-closed - the manager computes the reference closure from the\r\n * manifest before calling. */\r\n fetchFragmentBlob(schemaNames: readonly string[]): Promise<SchemaViewBlob>;\r\n\r\n /** Fetch the reference graph of every schema in the iModel, built from ECDbMeta\r\n * (`meta.ECSchemaDef` + `meta.SchemaHasSchemaReferences`; see {@link SchemaManifest.fromRows}). */\r\n fetchManifest(): Promise<SchemaManifest>;\r\n\r\n /** Fetch the current schema-identity token (`PRAGMA checksum(schema_token)`). */\r\n fetchSchemaToken(): Promise<string>;\r\n}\r\n\r\n/** Options for `getSchemaView` (see `IModelDb.getSchemaView` / `IModelConnection.getSchemaView`,\r\n * which delegate to {@link SchemaViewManager.getSchemaView}).\r\n * @beta\r\n */\r\nexport interface GetSchemaViewArgs {\r\n /** When provided, return a view loaded with at least these schemas plus their references, instead\r\n * of every schema in the iModel.\r\n *\r\n * The view accumulates: one instance is reused across calls, so a later request - with different\r\n * schemas or with no filter at all - merges the still-missing schemas into the same view and\r\n * everything requested earlier stays available. It resets when the iModel's schemas change.\r\n *\r\n * Names the iModel does not contain are ignored. Omitting this option loads all schemas, identical\r\n * to calling `getSchemaView()` with no arguments.\r\n */\r\n readonly schemas?: readonly string[];\r\n\r\n /** When `true`, discard whatever is currently loaded and rebuild the view from scratch before\r\n * returning it. The previously returned view instance (if any) is marked outdated. Like every other\r\n * request this is serialized behind any in-flight load, so it never leaves the view in an invalid\r\n * intermediate state.\r\n * @internal\r\n */\r\n readonly forceReload?: boolean;\r\n}\r\n\r\n/** Owns the lifetime of one iModel's {@link (SchemaView:class)}: lazy loading, incremental (filtered)\r\n * hydration, serialization of concurrent requests, and invalidation. Hosts (`IModelDb`,\r\n * `IModelConnection`) hold one instance and delegate to it; all data access goes through the\r\n * host-implemented {@link SchemaViewDataProvider}.\r\n * @internal\r\n */\r\nexport class SchemaViewManager {\r\n private readonly _dataProvider: SchemaViewDataProvider;\r\n\r\n /** The single accumulating view, held as a promise so all requests chain onto it and never overlap.\r\n * Undefined (or resolving to undefined) means nothing is loaded. */\r\n private _viewPromise?: Promise<SchemaView | undefined>;\r\n\r\n /** Reference graph for incremental loading; undefined when the view is (or will be) fully loaded. */\r\n private _manifest?: SchemaManifest;\r\n\r\n /** Schema-identity token the manifest - and thus every fragment merged under it - belongs to. */\r\n private _manifestToken?: string;\r\n\r\n /** Lower-cased names already merged into the view (incremental mode only). */\r\n private readonly _loadedSchemaNames = new Set<string>();\r\n\r\n public constructor(dataProvider: SchemaViewDataProvider) {\r\n this._dataProvider = dataProvider;\r\n }\r\n\r\n /** Get the schema view, loading whatever the request needs that is not present yet. See\r\n * {@link GetSchemaViewArgs} for filtering and reload semantics; hosts document the full\r\n * user-facing contract on their `getSchemaView` methods.\r\n */\r\n public async getSchemaView(args?: GetSchemaViewArgs): Promise<SchemaView> {\r\n const previous = this._viewPromise;\r\n const next = this._loadSchemaView(previous, args?.schemas, args?.forceReload === true);\r\n this._viewPromise = next;\r\n return next;\r\n }\r\n\r\n /** Throw away the current schema view. Called by the host when schemas may have changed (e.g.\r\n * `IModelDb.clearCaches` after a schema import). Chains behind any in-flight load and marks the\r\n * discarded view outdated; the next getSchemaView starts over.\r\n */\r\n public reset(): void {\r\n if (this._viewPromise) {\r\n this._viewPromise = this._viewPromise.then(\r\n (view) => { view?.markOutdated(); this._resetIncrementalState(); return undefined; },\r\n () => { this._resetIncrementalState(); return undefined; },\r\n );\r\n }\r\n }\r\n\r\n /** Check whether the iModel's schemas have changed since the current view was built, and discard\r\n * the view only if they have. For hosts that *cannot* determine whether an operation actually\r\n * modified schemas - e.g. `BriefcaseConnection.pullChanges` on the frontend, whose IPC response\r\n * carries only the new changeset id, not the applied changesets' types. Discarding after every\r\n * such operation would reload unnecessarily in the common case where schemas are unchanged, so\r\n * this compares the cheap schema-identity token instead.\r\n * @note If the token cannot be fetched, the view is discarded rather than risking stale metadata.\r\n */\r\n public async invalidateIfChanged(): Promise<void> {\r\n const previous = this._viewPromise;\r\n if (previous === undefined)\r\n return;\r\n // Queue the check on the same chain as loading, so a getSchemaView arriving while the token is\r\n // in flight cannot swap in a new promise for the same stale view and hide the schema change.\r\n const next = this._invalidateIfChanged(previous);\r\n this._viewPromise = next;\r\n await next;\r\n }\r\n\r\n /** Serialized body of {@link SchemaViewManager.invalidateIfChanged}. Resolves to the view to keep,\r\n * or to `undefined` when it was discarded and the next getSchemaView has to start over.\r\n */\r\n private async _invalidateIfChanged(previous: Promise<SchemaView | undefined>): Promise<SchemaView | undefined> {\r\n let existing: SchemaView | undefined;\r\n try {\r\n existing = await previous;\r\n } catch {\r\n return undefined;\r\n }\r\n if (existing === undefined)\r\n return undefined;\r\n // A view without a token (e.g. built directly from a SchemaViewBuilder) cannot be verified by\r\n // token; views loaded through this manager always carry one.\r\n if (existing.schemaToken === \"\")\r\n return existing;\r\n\r\n try {\r\n if (await this._dataProvider.fetchSchemaToken() === existing.schemaToken)\r\n return existing;\r\n } catch {\r\n // Cannot verify the cached view: drop it rather than risk stale metadata.\r\n }\r\n existing.markOutdated();\r\n this._resetIncrementalState();\r\n return undefined;\r\n }\r\n\r\n /** Serialized body of {@link SchemaViewManager.getSchemaView}. On failure it resets and rejects,\r\n * so the next call starts over.\r\n */\r\n private async _loadSchemaView(previous: Promise<SchemaView | undefined> | undefined, schemas: readonly string[] | undefined, forceReload: boolean): Promise<SchemaView> {\r\n let currentView: SchemaView | undefined;\r\n if (previous !== undefined) {\r\n try {\r\n currentView = await previous;\r\n } catch {\r\n currentView = undefined; // the failed load already reset; start over\r\n }\r\n }\r\n\r\n if (forceReload) {\r\n currentView?.markOutdated();\r\n currentView = undefined;\r\n this._resetIncrementalState();\r\n }\r\n\r\n try {\r\n return await this._ensureSchemasLoaded(currentView, schemas);\r\n } catch (err) {\r\n // A failed merge may have left the view partially extended - discard everything.\r\n currentView?.markOutdated();\r\n this._resetIncrementalState();\r\n throw err;\r\n }\r\n }\r\n\r\n /** Clear the incremental schema-view bookkeeping. */\r\n private _resetIncrementalState(): void {\r\n this._manifest = undefined;\r\n this._manifestToken = undefined;\r\n this._loadedSchemaNames.clear();\r\n }\r\n\r\n /** Ensures the requested schemas (or all schemas, when no filter is given) are present in\r\n * `currentView` (or a freshly created view) and returns it. The first load fixes the strategy:\r\n * no filter fetches everything as one full blob; a filter fetches fragments and keeps the\r\n * manifest and loaded-name set so later calls extend the same view. Once every schema is loaded\r\n * the incremental state is dropped, collapsing back to full mode.\r\n */\r\n private async _ensureSchemasLoaded(currentView: SchemaView | undefined, schemas: readonly string[] | undefined, isRetry = false): Promise<SchemaView> {\r\n const isFirstLoad = currentView === undefined;\r\n // No manifest means everything is loaded; in incremental mode a filtered request is satisfied as\r\n // soon as every requested name is present.\r\n if (!isFirstLoad &&\r\n (this._manifest === undefined ||\r\n (schemas !== undefined && schemas.every((name) => this._loadedSchemaNames.has(name.toLowerCase())))))\r\n return currentView;\r\n\r\n if (isFirstLoad && schemas === undefined) {\r\n const blob = await this._dataProvider.fetchFullBlob();\r\n const schemaView = SchemaView.fromBinary(blob.data, blob.schemaToken);\r\n this._resetIncrementalState();\r\n return schemaView;\r\n }\r\n\r\n if (this._manifest === undefined) {\r\n // Token first: any schema change after this point shows up as a token mismatch below.\r\n this._manifestToken = await this._dataProvider.fetchSchemaToken();\r\n this._manifest = await this._dataProvider.fetchManifest();\r\n }\r\n const manifest = this._manifest;\r\n\r\n const requested = schemas ?? manifest.getAvailableSchemaNames();\r\n const namesToLoad = manifest.getSchemaClosure(requested).filter((name) => !this._loadedSchemaNames.has(name.toLowerCase()));\r\n const husk = currentView ?? SchemaView.createMergeable(this._manifestToken);\r\n if (namesToLoad.length > 0) {\r\n const blob = await this._dataProvider.fetchFragmentBlob(namesToLoad);\r\n if (blob.schemaToken !== this._manifestToken) {\r\n // Schemas changed between the manifest and fragment fetches. Everything loaded so far\r\n // belongs to the old revision - discard it and start over, once.\r\n currentView?.markOutdated();\r\n this._resetIncrementalState();\r\n if (isRetry)\r\n throw new Error(\"The iModel's schemas changed while the schema view was loading.\");\r\n return this._ensureSchemasLoaded(undefined, schemas, true);\r\n }\r\n husk.mergeFragment(blob.data);\r\n // Record the whole closure as loaded, including *excluded* schemas (e.g. CoreCustomAttributes)\r\n // the writer emits no rows for, so later requests prune them instead of re-fetching.\r\n for (const name of namesToLoad)\r\n this._loadedSchemaNames.add(name.toLowerCase());\r\n }\r\n // Once every schema is loaded, collapse back to full mode (the size check is just a fast path).\r\n if (schemas === undefined || (this._loadedSchemaNames.size >= manifest.schemaCount && manifest.entries.every((entry) => this._loadedSchemaNames.has(entry.name.toLowerCase()))))\r\n this._resetIncrementalState();\r\n return husk;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"SchemaViewManager.js","sourceRoot":"","sources":["../../../src/SchemaView/SchemaViewManager.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\n/** @packageDocumentation\r\n * @module Schema\r\n */\r\n\r\nimport { SchemaManifest } from \"./SchemaManifest\";\r\nimport { SchemaView } from \"./SchemaView\";\r\n\r\n/** One schema-view blob with its cache-invalidation token, as fetched by a\r\n * {@link SchemaViewDataProvider}. Full and fragment blobs share this shape.\r\n * @beta\r\n */\r\nexport interface SchemaViewBlob {\r\n /** The binary schema metadata (the `data` column of `PRAGMA schema_view` / `schema_view_fragment`). */\r\n readonly data: Uint8Array;\r\n /** Schema-identity hash of the iModel's whole schema set (the `schemaToken` column). */\r\n readonly schemaToken: string;\r\n}\r\n\r\n/** The data source a {@link SchemaViewManager} loads schema-view data from. Implement this interface\r\n * to load schema metadata through your own query API, without an `IModelDb` or `IModelConnection`.\r\n * The manager deals only in schema names, blobs and the manifest; everything transport-specific -\r\n * pragma strings, format-version pinning - belongs to the provider.\r\n * @beta\r\n */\r\nexport interface SchemaViewDataProvider {\r\n /** Fetch the blob containing every schema in the iModel (`PRAGMA schema_view`). */\r\n fetchFullBlob(): Promise<SchemaViewBlob>;\r\n\r\n /** Fetch one blob containing exactly the given schemas (`PRAGMA schema_view_fragment`), subject\r\n * to SchemaView's schema exclusions. The manager computes the reference closure and omits schemas\r\n * already loaded, so references may target schemas in this blob or in previously fetched blobs.\r\n * Use {@link schemaViewFormatVersion} to pin the format: `PRAGMA schema_view_fragment('v<N>;name,name,...')`. */\r\n fetchFragmentBlob(schemaNames: readonly string[]): Promise<SchemaViewBlob>;\r\n\r\n /** Fetch the reference graph of every schema in the iModel, built from ECDbMeta\r\n * (`meta.ECSchemaDef` + `meta.SchemaHasSchemaReferences`; see {@link SchemaManifest.fromRows}). */\r\n fetchManifest(): Promise<SchemaManifest>;\r\n\r\n /** Fetch the current schema-identity token (`PRAGMA checksum(schema_token)`). */\r\n fetchSchemaToken(): Promise<string>;\r\n}\r\n\r\n/** Options for `getSchemaView` (see `IModelDb.getSchemaView` / `IModelConnection.getSchemaView`,\r\n * which delegate to {@link SchemaViewManager.getSchemaView}).\r\n * @beta\r\n */\r\nexport interface GetSchemaViewArgs {\r\n /** When provided, return a view loaded with at least these schemas plus their references, instead\r\n * of every schema in the iModel.\r\n *\r\n * The view accumulates: one instance is reused across calls, so a later request - with different\r\n * schemas or with no filter at all - merges the still-missing schemas into the same view and\r\n * everything requested earlier stays available. It resets when the iModel's schemas change.\r\n *\r\n * Names the iModel does not contain are ignored. Omitting this option loads all schemas, identical\r\n * to calling `getSchemaView()` with no arguments.\r\n */\r\n readonly schemas?: readonly string[];\r\n\r\n /** When `true`, discard whatever is currently loaded and rebuild the view from scratch before\r\n * returning it. The previously returned view instance (if any) is marked outdated. Like every other\r\n * request this is serialized behind any in-flight load, so it never leaves the view in an invalid\r\n * intermediate state.\r\n * @internal\r\n */\r\n readonly forceReload?: boolean;\r\n}\r\n\r\n/** Owns the lifetime of one iModel's {@link (SchemaView:class)}: lazy loading, incremental (filtered)\r\n * loading, serialization of concurrent requests, and invalidation. All data access goes through the\r\n * supplied {@link SchemaViewDataProvider}.\r\n *\r\n * Keep one manager per iModel connection. Calls to {@link SchemaViewManager.getSchemaView} reuse\r\n * one accumulating view until it is invalidated. The manager does not monitor schema changes;\r\n * call {@link SchemaViewManager.reset} after a known change, or await\r\n * {@link SchemaViewManager.invalidateIfChanged} after an operation that may have changed schemas.\r\n * @beta\r\n */\r\nexport class SchemaViewManager {\r\n private readonly _dataProvider: SchemaViewDataProvider;\r\n\r\n /** The single accumulating view, held as a promise so all requests chain onto it and never overlap.\r\n * Undefined (or resolving to undefined) means nothing is loaded. */\r\n private _viewPromise?: Promise<SchemaView | undefined>;\r\n\r\n /** Reference graph for incremental loading; undefined when the view is (or will be) fully loaded. */\r\n private _manifest?: SchemaManifest;\r\n\r\n /** Schema-identity token the manifest - and thus every fragment merged under it - belongs to. */\r\n private _manifestToken?: string;\r\n\r\n /** Lower-cased names already merged into the view (incremental mode only). */\r\n private readonly _loadedSchemaNames = new Set<string>();\r\n\r\n public constructor(dataProvider: SchemaViewDataProvider) {\r\n this._dataProvider = dataProvider;\r\n }\r\n\r\n /** Get the schema view, loading the requested schemas and their references that are not present\r\n * yet. Omitting the schema filter loads every schema. Calls accumulate into the same view until\r\n * it is invalidated. See {@link GetSchemaViewArgs} for filtering semantics.\r\n */\r\n public async getSchemaView(args?: GetSchemaViewArgs): Promise<SchemaView> {\r\n const previous = this._viewPromise;\r\n const next = this._loadSchemaView(previous, args?.schemas, args?.forceReload === true);\r\n this._viewPromise = next;\r\n return next;\r\n }\r\n\r\n /** Throw away the current schema view. Called by the host when schemas may have changed (e.g.\r\n * `IModelDb.clearCaches` after a schema import). Chains behind any in-flight load and marks the\r\n * discarded view outdated; the next getSchemaView starts over.\r\n */\r\n public reset(): void {\r\n if (this._viewPromise) {\r\n this._viewPromise = this._viewPromise.then(\r\n (view) => { view?.markOutdated(); this._resetIncrementalState(); return undefined; },\r\n () => { this._resetIncrementalState(); return undefined; },\r\n );\r\n }\r\n }\r\n\r\n /** Check whether the iModel's schemas have changed since the current view was built, and discard\r\n * the view only if they have. For hosts that *cannot* determine whether an operation actually\r\n * modified schemas - e.g. `BriefcaseConnection.pullChanges` on the frontend, whose IPC response\r\n * carries only the new changeset id, not the applied changesets' types. Discarding after every\r\n * such operation would reload unnecessarily in the common case where schemas are unchanged, so\r\n * this compares the cheap schema-identity token instead.\r\n * @note If the token cannot be fetched, the view is discarded rather than risking stale metadata.\r\n */\r\n public async invalidateIfChanged(): Promise<void> {\r\n const previous = this._viewPromise;\r\n if (previous === undefined)\r\n return;\r\n // Queue the check on the same chain as loading, so a getSchemaView arriving while the token is\r\n // in flight cannot swap in a new promise for the same stale view and hide the schema change.\r\n const next = this._invalidateIfChanged(previous);\r\n this._viewPromise = next;\r\n await next;\r\n }\r\n\r\n /** Serialized body of {@link SchemaViewManager.invalidateIfChanged}. Resolves to the view to keep,\r\n * or to `undefined` when it was discarded and the next getSchemaView has to start over.\r\n */\r\n private async _invalidateIfChanged(previous: Promise<SchemaView | undefined>): Promise<SchemaView | undefined> {\r\n let existing: SchemaView | undefined;\r\n try {\r\n existing = await previous;\r\n } catch {\r\n return undefined;\r\n }\r\n if (existing === undefined)\r\n return undefined;\r\n\r\n try {\r\n if (await this._dataProvider.fetchSchemaToken() === existing.schemaToken)\r\n return existing;\r\n } catch {\r\n // Cannot verify the cached view: drop it rather than risk stale metadata.\r\n }\r\n existing.markOutdated();\r\n this._resetIncrementalState();\r\n return undefined;\r\n }\r\n\r\n /** Serialized body of {@link SchemaViewManager.getSchemaView}. On failure it resets and rejects,\r\n * so the next call starts over.\r\n */\r\n private async _loadSchemaView(previous: Promise<SchemaView | undefined> | undefined, schemas: readonly string[] | undefined, forceReload: boolean): Promise<SchemaView> {\r\n let currentView: SchemaView | undefined;\r\n if (previous !== undefined) {\r\n try {\r\n currentView = await previous;\r\n } catch {\r\n currentView = undefined; // the failed load already reset; start over\r\n }\r\n }\r\n\r\n if (forceReload) {\r\n currentView?.markOutdated();\r\n currentView = undefined;\r\n this._resetIncrementalState();\r\n }\r\n\r\n try {\r\n return await this._ensureSchemasLoaded(currentView, schemas);\r\n } catch (err) {\r\n // A failed merge may have left the view partially extended - discard everything.\r\n currentView?.markOutdated();\r\n this._resetIncrementalState();\r\n throw err;\r\n }\r\n }\r\n\r\n /** Clear the incremental schema-view bookkeeping. */\r\n private _resetIncrementalState(): void {\r\n this._manifest = undefined;\r\n this._manifestToken = undefined;\r\n this._loadedSchemaNames.clear();\r\n }\r\n\r\n /** Ensures the requested schemas (or all schemas, when no filter is given) are present in\r\n * `currentView` (or a freshly created view) and returns it. The first load fixes the strategy:\r\n * no filter fetches everything as one full blob; a filter fetches fragments and keeps the\r\n * manifest and loaded-name set so later calls extend the same view. Once every schema is loaded\r\n * the incremental state is dropped, collapsing back to full mode.\r\n */\r\n private async _ensureSchemasLoaded(currentView: SchemaView | undefined, schemas: readonly string[] | undefined, isRetry = false): Promise<SchemaView> {\r\n const isFirstLoad = currentView === undefined;\r\n // No manifest means everything is loaded; in incremental mode a filtered request is satisfied as\r\n // soon as every requested name is present.\r\n if (!isFirstLoad &&\r\n (this._manifest === undefined ||\r\n (schemas !== undefined && schemas.every((name) => this._loadedSchemaNames.has(name.toLowerCase())))))\r\n return currentView;\r\n\r\n if (isFirstLoad && schemas === undefined) {\r\n const blob = await this._dataProvider.fetchFullBlob();\r\n const schemaView = SchemaView.fromBinary(blob.data, blob.schemaToken);\r\n this._resetIncrementalState();\r\n return schemaView;\r\n }\r\n\r\n if (this._manifest === undefined) {\r\n // Token first: any schema change after this point shows up as a token mismatch below.\r\n this._manifestToken = await this._dataProvider.fetchSchemaToken();\r\n this._manifest = await this._dataProvider.fetchManifest();\r\n }\r\n const manifest = this._manifest;\r\n\r\n const requested = schemas ?? manifest.getAvailableSchemaNames();\r\n const namesToLoad = manifest.getSchemaClosure(requested).filter((name) => !this._loadedSchemaNames.has(name.toLowerCase()));\r\n const husk = currentView ?? SchemaView.createMergeable(this._manifestToken);\r\n if (namesToLoad.length > 0) {\r\n const blob = await this._dataProvider.fetchFragmentBlob(namesToLoad);\r\n if (blob.schemaToken !== this._manifestToken) {\r\n // Schemas changed between the manifest and fragment fetches. Everything loaded so far\r\n // belongs to the old revision - discard it and start over, once.\r\n currentView?.markOutdated();\r\n this._resetIncrementalState();\r\n if (isRetry)\r\n throw new Error(\"The iModel's schemas changed while the schema view was loading.\");\r\n return this._ensureSchemasLoaded(undefined, schemas, true);\r\n }\r\n husk.mergeFragment(blob.data);\r\n // Record the whole closure as loaded, including *excluded* schemas (e.g. CoreCustomAttributes)\r\n // the writer emits no rows for, so later requests prune them instead of re-fetching.\r\n for (const name of namesToLoad)\r\n this._loadedSchemaNames.add(name.toLowerCase());\r\n }\r\n // Once every schema is loaded, collapse back to full mode (the size check is just a fast path).\r\n if (schemas === undefined || (this._loadedSchemaNames.size >= manifest.schemaCount && manifest.entries.every((entry) => this._loadedSchemaNames.has(entry.name.toLowerCase()))))\r\n this._resetIncrementalState();\r\n return husk;\r\n }\r\n}\r\n"]}
|
package/lib/esm/ECName.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ export declare class ECName {
|
|
|
25
25
|
* @throws ECSchemaError if `input` is an empty string.
|
|
26
26
|
*/
|
|
27
27
|
static encode(input: string): ECName;
|
|
28
|
+
/** Decode EC name escape sequences without requiring a valid EC identifier.
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
static decode(name: string): string;
|
|
28
32
|
/** Decode this ECName, replacing encoded special characters with the characters they encode. */
|
|
29
33
|
decode(): string;
|
|
30
34
|
}
|
package/lib/esm/ECName.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ECName.d.ts","sourceRoot":"","sources":["../../src/ECName.ts"],"names":[],"mappings":"AAIA;;GAEG;AAmBH;;;;;;;;;GASG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAS;IAEtB;;OAEG;gBACS,IAAI,EAAE,MAAM;IAOxB,sEAAsE;WACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7C,uCAAuC;IACvC,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;WACW,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiC3C,gGAAgG;IACzF,MAAM,IAAI,MAAM;CAGxB"}
|
|
1
|
+
{"version":3,"file":"ECName.d.ts","sourceRoot":"","sources":["../../src/ECName.ts"],"names":[],"mappings":"AAIA;;GAEG;AAmBH;;;;;;;;;GASG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAS;IAEtB;;OAEG;gBACS,IAAI,EAAE,MAAM;IAOxB,sEAAsE;WACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7C,uCAAuC;IACvC,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;WACW,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAiC3C;;OAEG;WACW,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAO1C,gGAAgG;IACzF,MAAM,IAAI,MAAM;CAGxB"}
|
package/lib/esm/ECName.js
CHANGED
|
@@ -75,9 +75,17 @@ export class ECName {
|
|
|
75
75
|
}
|
|
76
76
|
return new ECName(output);
|
|
77
77
|
}
|
|
78
|
+
/** Decode EC name escape sequences without requiring a valid EC identifier.
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
static decode(name) {
|
|
82
|
+
if (!name.includes("__x"))
|
|
83
|
+
return name;
|
|
84
|
+
return name.replace(ecNameReplacerRegex, (_match, hex) => String.fromCharCode(Number.parseInt(hex, 16)));
|
|
85
|
+
}
|
|
78
86
|
/** Decode this ECName, replacing encoded special characters with the characters they encode. */
|
|
79
87
|
decode() {
|
|
80
|
-
return this.name
|
|
88
|
+
return ECName.decode(this.name);
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
//# sourceMappingURL=ECName.js.map
|
package/lib/esm/ECName.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ECName.js","sourceRoot":"","sources":["../../src/ECName.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ECName.js","sourceRoot":"","sources":["../../src/ECName.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\n/** @packageDocumentation\r\n * @module Metadata\r\n */\r\n\r\nimport { assert } from \"@itwin/core-bentley\";\r\nimport { ECSchemaError, ECSchemaStatus } from \"./Exception\";\r\n\r\nconst validECNameRegex = /^[a-zA-Z_]\\w*$/i;\r\nconst ecNameReplacerRegex = /__x([0-9a-fA-F]{4})__/g;\r\nconst leadingDigits = [\"0000\", \"000\", \"00\", \"0\", \"\"];\r\n\r\nfunction isDigit(character: string): boolean {\r\n assert(1 === character.length);\r\n return character >= \"0\" && character <= \"9\";\r\n}\r\n\r\nfunction isValidAlphaNumericCharacter(c: string): boolean {\r\n assert(1 === c.length);\r\n return (((c >= \"0\" && c <= \"9\") || (c >= \"A\" && c <= \"Z\") || (c >= \"a\" && c <= \"z\") || c === \"_\"));\r\n}\r\n\r\n/** The name of an item in a [[Schema]], encoded to meet restrictions on the characters usable in such names.\r\n * An ECName meets the following criteria:\r\n * - Contains at least one character.\r\n * - Does not begin with a digit.\r\n * - Consists entirely of characters in the ASCII ranges A-Z, a-z, and 0-9; and the underscore (\"_\") character.\r\n *\r\n * All characters not meeting the above criteria are encoded as \"__x####__\" where \"####\" is the UTF-16 character code.\r\n * Such names are often automatically generated from the item's display label, which is unrestricted in the characters it may contain.\r\n * @public\r\n */\r\nexport class ECName {\r\n private _name: string;\r\n\r\n /** Construct a new ECName from a valid EC name.\r\n * throws ECSchemaError if `name` does not meet the criteria for a valid EC name.\r\n */\r\n constructor(name: string) {\r\n if (!ECName.validate(name))\r\n throw new ECSchemaError(ECSchemaStatus.InvalidECName);\r\n\r\n this._name = name;\r\n }\r\n\r\n /** Returns true if a string meets the criteria of a valid EC name. */\r\n public static validate(name: string): boolean {\r\n return validECNameRegex.test(name);\r\n }\r\n\r\n /** The underlying name as a string. */\r\n public get name(): string {\r\n return this._name;\r\n }\r\n\r\n /** Create an ECName from an arbitrary string, encoding any special characters as \"__x####__\" where \"####\" is the UTF-16 character code.\r\n * @throws ECSchemaError if `input` is an empty string.\r\n */\r\n public static encode(input: string): ECName {\r\n if (0 === input.length)\r\n throw new ECSchemaError(ECSchemaStatus.InvalidECName);\r\n\r\n if (ECName.validate(input)) {\r\n // It's already a valid EC name.\r\n return new ECName(input);\r\n }\r\n\r\n let output = \"\";\r\n\r\n function appendEncodedCharacter(index: number): void {\r\n const hex = input.charCodeAt(index).toString(16).toUpperCase();\r\n assert(hex.length > 0 && hex.length < 5);\r\n output += `__x${leadingDigits[hex.length]}${hex}__`;\r\n }\r\n\r\n // First character cannot be a digit.\r\n const firstCharIsDigit = isDigit(input[0]);\r\n if (firstCharIsDigit)\r\n appendEncodedCharacter(0);\r\n\r\n for (let i = firstCharIsDigit ? 1 : 0; i < input.length; i++) {\r\n const char = input[i];\r\n if (!isValidAlphaNumericCharacter(char))\r\n appendEncodedCharacter(i);\r\n else\r\n output += char;\r\n }\r\n\r\n return new ECName(output);\r\n }\r\n\r\n /** Decode EC name escape sequences without requiring a valid EC identifier.\r\n * @internal\r\n */\r\n public static decode(name: string): string {\r\n if (!name.includes(\"__x\"))\r\n return name;\r\n\r\n return name.replace(ecNameReplacerRegex, (_match, hex: string) => String.fromCharCode(Number.parseInt(hex, 16)));\r\n }\r\n\r\n /** Decode this ECName, replacing encoded special characters with the characters they encode. */\r\n public decode(): string {\r\n return ECName.decode(this.name);\r\n }\r\n}\r\n"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BeEvent } from "@itwin/core-bentley";
|
|
2
|
-
import { FormatDefinition, FormatsChangedArgs, FormatsProvider, MutableFormatsProvider, UnitSystemKey } from "@itwin/core-quantity";
|
|
2
|
+
import { FormatDefinition, FormatsChangedArgs, FormatsProvider, FormatsProviderContext, MutableFormatsProvider, SyncFormatsProvider, UnitSystemKey } from "@itwin/core-quantity";
|
|
3
3
|
import { FormatSet } from "../Deserialization/JsonProps";
|
|
4
4
|
/**
|
|
5
5
|
* A mutable format provider that manages format definitions within a format set.
|
|
6
6
|
* When formats are added or removed, the underlying format set is automatically updated.
|
|
7
7
|
* @beta
|
|
8
8
|
*/
|
|
9
|
-
export declare class FormatSetFormatsProvider implements MutableFormatsProvider {
|
|
9
|
+
export declare class FormatSetFormatsProvider implements MutableFormatsProvider, SyncFormatsProvider {
|
|
10
10
|
onFormatsChanged: BeEvent<(args: FormatsChangedArgs) => void>;
|
|
11
11
|
private _formatSet;
|
|
12
12
|
private _fallbackProvider?;
|
|
@@ -26,17 +26,25 @@ export declare class FormatSetFormatsProvider implements MutableFormatsProvider
|
|
|
26
26
|
*/
|
|
27
27
|
clearFallbackProvider(): void;
|
|
28
28
|
/**
|
|
29
|
-
* Retrieves a format definition
|
|
30
|
-
* If the format is a string reference to another format, it resolves the reference and returns the FormatDefinition.
|
|
29
|
+
* Retrieves a format definition from the format set, resolving string references and consulting the fallback provider when needed.
|
|
31
30
|
*/
|
|
32
|
-
getFormat(input: string, system?: UnitSystemKey): Promise<FormatDefinition | undefined>;
|
|
31
|
+
getFormat(input: string, system?: UnitSystemKey, context?: FormatsProviderContext): Promise<FormatDefinition | undefined>;
|
|
32
|
+
private getFormatFromFallback;
|
|
33
|
+
/**
|
|
34
|
+
* Retrieves a format definition from the format set without awaiting a provider. String references are resolved
|
|
35
|
+
* locally; a fallback is used only when it implements `SyncFormatsProvider`.
|
|
36
|
+
*/
|
|
37
|
+
getFormatSync(input: string, system?: UnitSystemKey, context?: FormatsProviderContext): FormatDefinition | undefined;
|
|
38
|
+
private getFormatSyncFromFallback;
|
|
33
39
|
/**
|
|
34
40
|
* Resolves a string reference to its FormatDefinition, following chains of references.
|
|
35
41
|
* @param reference The string reference to resolve
|
|
36
42
|
* @param visited Set of visited references to detect circular references
|
|
37
43
|
* @param system Optional unit system override
|
|
44
|
+
* @param context Lookup context to forward to the fallback provider
|
|
38
45
|
*/
|
|
39
46
|
private resolveReference;
|
|
47
|
+
private resolveReferenceSync;
|
|
40
48
|
/**
|
|
41
49
|
* Removes a format definition or string reference from the format set.
|
|
42
50
|
* @param name The name of the format to remove
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormatSetFormatsProvider.d.ts","sourceRoot":"","sources":["../../../src/Formatting/FormatSetFormatsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"FormatSetFormatsProvider.d.ts","sourceRoot":"","sources":["../../../src/Formatting/FormatSetFormatsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACjL,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD;;;;GAIG;AACH,qBAAa,wBAAyB,YAAW,sBAAsB,EAAE,mBAAmB;IACnF,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC,CAAqD;IAEzH,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAkB;IAC5C,OAAO,CAAC,WAAW,CAAsB;gBAEtB,KAAK,EAAE;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,gBAAgB,CAAC,EAAE,eAAe,CAAA;KAAC;IAapF;;;;OAIG;IACU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBtF;;OAEG;IACI,qBAAqB,IAAI,IAAI;IAIpC;;OAEG;IACU,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAiBxH,qBAAqB;IAOnC;;;OAGG;IACI,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,gBAAgB,GAAG,SAAS;IAiB3H,OAAO,CAAC,yBAAyB;IAKjC;;;;;;OAMG;YACW,gBAAgB;IAkB9B,OAAO,CAAC,oBAAoB;IAiB5B;;;OAGG;IACU,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWtD;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;CAiBpC"}
|
|
@@ -47,48 +47,79 @@ export class FormatSetFormatsProvider {
|
|
|
47
47
|
this._fallbackProvider = undefined;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Retrieves a format definition
|
|
51
|
-
* If the format is a string reference to another format, it resolves the reference and returns the FormatDefinition.
|
|
50
|
+
* Retrieves a format definition from the format set, resolving string references and consulting the fallback provider when needed.
|
|
52
51
|
*/
|
|
53
|
-
async getFormat(input, system) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
async getFormat(input, system, context) {
|
|
53
|
+
const lookupContext = extendProviderContext(context, this);
|
|
54
|
+
if (!lookupContext)
|
|
55
|
+
return undefined;
|
|
56
|
+
const name = normalizeFormatName(input);
|
|
57
57
|
const format = this._formatSet.formats[name];
|
|
58
58
|
if (format !== undefined) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return this.resolveReference(format, undefined, system);
|
|
62
|
-
}
|
|
59
|
+
if (typeof format === "string")
|
|
60
|
+
return this.resolveReference(format, new Set(), system, lookupContext);
|
|
63
61
|
return format;
|
|
64
62
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
return this.getFormatFromFallback(name, system, lookupContext);
|
|
64
|
+
}
|
|
65
|
+
async getFormatFromFallback(name, system, context) {
|
|
66
|
+
const fallbackProvider = this._fallbackProvider;
|
|
67
|
+
if (!fallbackProvider)
|
|
68
|
+
return undefined;
|
|
69
|
+
return fallbackProvider.getFormat(name, system, context);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Retrieves a format definition from the format set without awaiting a provider. String references are resolved
|
|
73
|
+
* locally; a fallback is used only when it implements `SyncFormatsProvider`.
|
|
74
|
+
*/
|
|
75
|
+
getFormatSync(input, system, context) {
|
|
76
|
+
const lookupContext = extendProviderContext(context, this);
|
|
77
|
+
if (!lookupContext)
|
|
78
|
+
return undefined;
|
|
79
|
+
const name = normalizeFormatName(input);
|
|
80
|
+
const format = this._formatSet.formats[name];
|
|
81
|
+
if (format !== undefined) {
|
|
82
|
+
if (typeof format === "string")
|
|
83
|
+
return this.resolveReferenceSync(format, new Set(), system, lookupContext);
|
|
84
|
+
return format;
|
|
85
|
+
}
|
|
86
|
+
return this.getFormatSyncFromFallback(name, system, lookupContext);
|
|
87
|
+
}
|
|
88
|
+
getFormatSyncFromFallback(name, system, context) {
|
|
89
|
+
const fallbackProvider = this._fallbackProvider;
|
|
90
|
+
return typeof fallbackProvider?.getFormatSync === "function" ? fallbackProvider.getFormatSync(name, system, context) : undefined;
|
|
68
91
|
}
|
|
69
92
|
/**
|
|
70
93
|
* Resolves a string reference to its FormatDefinition, following chains of references.
|
|
71
94
|
* @param reference The string reference to resolve
|
|
72
95
|
* @param visited Set of visited references to detect circular references
|
|
73
96
|
* @param system Optional unit system override
|
|
97
|
+
* @param context Lookup context to forward to the fallback provider
|
|
74
98
|
*/
|
|
75
|
-
async resolveReference(reference, visited
|
|
99
|
+
async resolveReference(reference, visited, system, context) {
|
|
76
100
|
// Prevent infinite loops from circular references
|
|
77
101
|
if (visited.has(reference)) {
|
|
78
102
|
return undefined;
|
|
79
103
|
}
|
|
80
104
|
visited.add(reference);
|
|
81
105
|
const format = this._formatSet.formats[reference];
|
|
82
|
-
if (format === undefined)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
if (format === undefined)
|
|
107
|
+
return this.getFormatFromFallback(reference, system, context);
|
|
108
|
+
if (typeof format === "string")
|
|
109
|
+
return this.resolveReference(format, visited, system, context);
|
|
110
|
+
return format;
|
|
111
|
+
}
|
|
112
|
+
resolveReferenceSync(reference, visited, system, context) {
|
|
113
|
+
// Prevent infinite loops from circular references
|
|
114
|
+
if (visited.has(reference)) {
|
|
86
115
|
return undefined;
|
|
87
116
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
117
|
+
visited.add(reference);
|
|
118
|
+
const format = this._formatSet.formats[reference];
|
|
119
|
+
if (format === undefined)
|
|
120
|
+
return this.getFormatSyncFromFallback(reference, system, context);
|
|
121
|
+
if (typeof format === "string")
|
|
122
|
+
return this.resolveReferenceSync(format, visited, system, context);
|
|
92
123
|
return format;
|
|
93
124
|
}
|
|
94
125
|
/**
|
|
@@ -124,4 +155,16 @@ export class FormatSetFormatsProvider {
|
|
|
124
155
|
return referencingFormats;
|
|
125
156
|
}
|
|
126
157
|
}
|
|
158
|
+
function extendProviderContext(context, provider) {
|
|
159
|
+
const providerChain = new Set(context?.providerChain);
|
|
160
|
+
if (providerChain.has(provider))
|
|
161
|
+
return undefined;
|
|
162
|
+
providerChain.add(provider);
|
|
163
|
+
return { providerChain };
|
|
164
|
+
}
|
|
165
|
+
function normalizeFormatName(input) {
|
|
166
|
+
// Convert node-addon names from `schemaName:schemaItemName` to the dot-separated key used by FormatSet.
|
|
167
|
+
const [schemaName, itemName] = SchemaItem.parseFullName(input);
|
|
168
|
+
return schemaName === "" ? itemName : `${schemaName}.${itemName}`;
|
|
169
|
+
}
|
|
127
170
|
//# sourceMappingURL=FormatSetFormatsProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormatSetFormatsProvider.js","sourceRoot":"","sources":["../../../src/Formatting/FormatSetFormatsProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { BeEvent } from \"@itwin/core-bentley\";\r\nimport { FormatDefinition, FormatsChangedArgs, FormatsProvider, MutableFormatsProvider, UnitSystemKey } from \"@itwin/core-quantity\";\r\nimport { FormatSet } from \"../Deserialization/JsonProps\";\r\nimport { SchemaItem } from \"../Metadata/SchemaItem\";\r\n\r\n/**\r\n * A mutable format provider that manages format definitions within a format set.\r\n * When formats are added or removed, the underlying format set is automatically updated.\r\n * @beta\r\n */\r\nexport class FormatSetFormatsProvider implements MutableFormatsProvider {\r\n public onFormatsChanged: BeEvent<(args: FormatsChangedArgs) => void> = new BeEvent<(args: FormatsChangedArgs) => void>();\r\n\r\n private _formatSet: FormatSet;\r\n private _fallbackProvider?: FormatsProvider;\r\n private _references: Map<string, string>; // Maps format name to the reference it points to\r\n\r\n public constructor(props: {formatSet: FormatSet, fallbackProvider?: FormatsProvider}) {\r\n this._formatSet = props.formatSet;\r\n this._fallbackProvider = props.fallbackProvider;\r\n this._references = new Map<string, string>();\r\n\r\n // Build up the map of string references\r\n for (const [name, format] of Object.entries(this._formatSet.formats)) {\r\n if (typeof format === \"string\") {\r\n this._references.set(name, format);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adds or updates the format definition returned for a kind of quantity. Takes either a format definition or a kind of quantity full name that will be used to lookup the format that will be used.\r\n * @param name A kind of quantity full name used as a key to lookup this format\r\n * @param format The format definition or the name of a kind of quantity\r\n */\r\n public async addFormat(name: string, format: FormatDefinition | string): Promise<void> {\r\n this._formatSet.formats[name] = format;\r\n\r\n // Update the references map\r\n if (typeof format === \"string\") {\r\n this._references.set(name, format);\r\n } else {\r\n this._references.delete(name);\r\n }\r\n\r\n // Collect all formats that reference this format (directly or indirectly)\r\n const affectedFormats = this.getFormatsReferencingTarget(name);\r\n affectedFormats.add(name); // Include the format itself\r\n\r\n this.onFormatsChanged.raiseEvent({ formatsChanged: Array.from(affectedFormats) });\r\n }\r\n\r\n /**\r\n * Clears the fallback provider, if one is set.\r\n */\r\n public clearFallbackProvider(): void {\r\n this._fallbackProvider = undefined;\r\n }\r\n\r\n /**\r\n * Retrieves a format definition by its name from the format set. If not found, it checks the fallback provider to find the format, else returns undefined.\r\n * If the format is a string reference to another format, it resolves the reference and returns the FormatDefinition.\r\n */\r\n public async getFormat(input: string, system?: UnitSystemKey): Promise<FormatDefinition | undefined> {\r\n // Normalizes any schemaItem names coming from node addon 'schemaName:schemaItemName' -> 'schemaName.schemaItemName'\r\n const [schemaName, itemName] = SchemaItem.parseFullName(input);\r\n\r\n const name = (schemaName === \"\") ? itemName : `${schemaName}.${itemName}`;\r\n const format = this._formatSet.formats[name];\r\n\r\n if (format !== undefined) {\r\n // If format is a string reference, resolve it\r\n if (typeof format === \"string\") {\r\n return this.resolveReference(format, undefined, system);\r\n }\r\n return format;\r\n }\r\n\r\n if (this._fallbackProvider) return this._fallbackProvider.getFormat(name, system);\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Resolves a string reference to its FormatDefinition, following chains of references.\r\n * @param reference The string reference to resolve\r\n * @param visited Set of visited references to detect circular references\r\n * @param system Optional unit system override\r\n */\r\n private async resolveReference(reference: string, visited: Set<string> = new Set(), system?: UnitSystemKey): Promise<FormatDefinition | undefined> {\r\n // Prevent infinite loops from circular references\r\n if (visited.has(reference)) {\r\n return undefined;\r\n }\r\n visited.add(reference);\r\n\r\n const format = this._formatSet.formats[reference];\r\n\r\n if (format === undefined) {\r\n if (this._fallbackProvider) {\r\n return this._fallbackProvider.getFormat(reference, system);\r\n }\r\n return undefined;\r\n }\r\n\r\n // If we found another string reference, resolve it recursively\r\n if (typeof format === \"string\") {\r\n return this.resolveReference(format, visited, system);\r\n }\r\n\r\n return format;\r\n }\r\n\r\n /**\r\n * Removes a format definition or string reference from the format set.\r\n * @param name The name of the format to remove\r\n */\r\n public async removeFormat(name: string): Promise<void> {\r\n // Collect all formats that reference this format (directly or indirectly)\r\n const affectedFormats = this.getFormatsReferencingTarget(name);\r\n affectedFormats.add(name); // Include the format itself\r\n\r\n delete this._formatSet.formats[name];\r\n this._references.delete(name);\r\n\r\n this.onFormatsChanged.raiseEvent({ formatsChanged: Array.from(affectedFormats) });\r\n }\r\n\r\n /**\r\n * Gets all format names that reference the target format (directly or indirectly).\r\n * @param target The format name to find references to\r\n * @returns Set of format names that reference the target\r\n */\r\n private getFormatsReferencingTarget(target: string): Set<string> {\r\n const referencingFormats = new Set<string>();\r\n\r\n // Find all formats that directly reference the target\r\n for (const [formatName, reference] of this._references.entries()) {\r\n if (reference === target) {\r\n referencingFormats.add(formatName);\r\n // Recursively find formats that reference this format\r\n const indirectReferences = this.getFormatsReferencingTarget(formatName);\r\n for (const indirectRef of indirectReferences) {\r\n referencingFormats.add(indirectRef);\r\n }\r\n }\r\n }\r\n\r\n return referencingFormats;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"FormatSetFormatsProvider.js","sourceRoot":"","sources":["../../../src/Formatting/FormatSetFormatsProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { BeEvent } from \"@itwin/core-bentley\";\r\nimport { FormatDefinition, FormatsChangedArgs, FormatsProvider, FormatsProviderContext, MutableFormatsProvider, SyncFormatsProvider, UnitSystemKey } from \"@itwin/core-quantity\";\r\nimport { FormatSet } from \"../Deserialization/JsonProps\";\r\nimport { SchemaItem } from \"../Metadata/SchemaItem\";\r\n\r\n/**\r\n * A mutable format provider that manages format definitions within a format set.\r\n * When formats are added or removed, the underlying format set is automatically updated.\r\n * @beta\r\n */\r\nexport class FormatSetFormatsProvider implements MutableFormatsProvider, SyncFormatsProvider {\r\n public onFormatsChanged: BeEvent<(args: FormatsChangedArgs) => void> = new BeEvent<(args: FormatsChangedArgs) => void>();\r\n\r\n private _formatSet: FormatSet;\r\n private _fallbackProvider?: FormatsProvider;\r\n private _references: Map<string, string>; // Maps format name to the reference it points to\r\n\r\n public constructor(props: {formatSet: FormatSet, fallbackProvider?: FormatsProvider}) {\r\n this._formatSet = props.formatSet;\r\n this._fallbackProvider = props.fallbackProvider;\r\n this._references = new Map<string, string>();\r\n\r\n // Build up the map of string references\r\n for (const [name, format] of Object.entries(this._formatSet.formats)) {\r\n if (typeof format === \"string\") {\r\n this._references.set(name, format);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adds or updates the format definition returned for a kind of quantity. Takes either a format definition or a kind of quantity full name that will be used to lookup the format that will be used.\r\n * @param name A kind of quantity full name used as a key to lookup this format\r\n * @param format The format definition or the name of a kind of quantity\r\n */\r\n public async addFormat(name: string, format: FormatDefinition | string): Promise<void> {\r\n this._formatSet.formats[name] = format;\r\n\r\n // Update the references map\r\n if (typeof format === \"string\") {\r\n this._references.set(name, format);\r\n } else {\r\n this._references.delete(name);\r\n }\r\n\r\n // Collect all formats that reference this format (directly or indirectly)\r\n const affectedFormats = this.getFormatsReferencingTarget(name);\r\n affectedFormats.add(name); // Include the format itself\r\n\r\n this.onFormatsChanged.raiseEvent({ formatsChanged: Array.from(affectedFormats) });\r\n }\r\n\r\n /**\r\n * Clears the fallback provider, if one is set.\r\n */\r\n public clearFallbackProvider(): void {\r\n this._fallbackProvider = undefined;\r\n }\r\n\r\n /**\r\n * Retrieves a format definition from the format set, resolving string references and consulting the fallback provider when needed.\r\n */\r\n public async getFormat(input: string, system?: UnitSystemKey, context?: FormatsProviderContext): Promise<FormatDefinition | undefined> {\r\n const lookupContext = extendProviderContext(context, this);\r\n if (!lookupContext)\r\n return undefined;\r\n\r\n const name = normalizeFormatName(input);\r\n const format = this._formatSet.formats[name];\r\n\r\n if (format !== undefined) {\r\n if (typeof format === \"string\")\r\n return this.resolveReference(format, new Set(), system, lookupContext);\r\n return format;\r\n }\r\n\r\n return this.getFormatFromFallback(name, system, lookupContext);\r\n }\r\n\r\n private async getFormatFromFallback(name: string, system: UnitSystemKey | undefined, context: FormatsProviderContext): Promise<FormatDefinition | undefined> {\r\n const fallbackProvider = this._fallbackProvider;\r\n if (!fallbackProvider)\r\n return undefined;\r\n return fallbackProvider.getFormat(name, system, context);\r\n }\r\n\r\n /**\r\n * Retrieves a format definition from the format set without awaiting a provider. String references are resolved\r\n * locally; a fallback is used only when it implements `SyncFormatsProvider`.\r\n */\r\n public getFormatSync(input: string, system?: UnitSystemKey, context?: FormatsProviderContext): FormatDefinition | undefined {\r\n const lookupContext = extendProviderContext(context, this);\r\n if (!lookupContext)\r\n return undefined;\r\n\r\n const name = normalizeFormatName(input);\r\n const format = this._formatSet.formats[name];\r\n\r\n if (format !== undefined) {\r\n if (typeof format === \"string\")\r\n return this.resolveReferenceSync(format, new Set(), system, lookupContext);\r\n return format;\r\n }\r\n\r\n return this.getFormatSyncFromFallback(name, system, lookupContext);\r\n }\r\n\r\n private getFormatSyncFromFallback(name: string, system: UnitSystemKey | undefined, context: FormatsProviderContext): FormatDefinition | undefined {\r\n const fallbackProvider: (FormatsProvider & Partial<SyncFormatsProvider>) | undefined = this._fallbackProvider;\r\n return typeof fallbackProvider?.getFormatSync === \"function\" ? fallbackProvider.getFormatSync(name, system, context) : undefined;\r\n }\r\n\r\n /**\r\n * Resolves a string reference to its FormatDefinition, following chains of references.\r\n * @param reference The string reference to resolve\r\n * @param visited Set of visited references to detect circular references\r\n * @param system Optional unit system override\r\n * @param context Lookup context to forward to the fallback provider\r\n */\r\n private async resolveReference(reference: string, visited: Set<string>, system: UnitSystemKey | undefined, context: FormatsProviderContext): Promise<FormatDefinition | undefined> {\r\n // Prevent infinite loops from circular references\r\n if (visited.has(reference)) {\r\n return undefined;\r\n }\r\n visited.add(reference);\r\n\r\n const format = this._formatSet.formats[reference];\r\n\r\n if (format === undefined)\r\n return this.getFormatFromFallback(reference, system, context);\r\n\r\n if (typeof format === \"string\")\r\n return this.resolveReference(format, visited, system, context);\r\n\r\n return format;\r\n }\r\n\r\n private resolveReferenceSync(reference: string, visited: Set<string>, system: UnitSystemKey | undefined, context: FormatsProviderContext): FormatDefinition | undefined {\r\n // Prevent infinite loops from circular references\r\n if (visited.has(reference)) {\r\n return undefined;\r\n }\r\n visited.add(reference);\r\n\r\n const format = this._formatSet.formats[reference];\r\n if (format === undefined)\r\n return this.getFormatSyncFromFallback(reference, system, context);\r\n\r\n if (typeof format === \"string\")\r\n return this.resolveReferenceSync(format, visited, system, context);\r\n\r\n return format;\r\n }\r\n\r\n /**\r\n * Removes a format definition or string reference from the format set.\r\n * @param name The name of the format to remove\r\n */\r\n public async removeFormat(name: string): Promise<void> {\r\n // Collect all formats that reference this format (directly or indirectly)\r\n const affectedFormats = this.getFormatsReferencingTarget(name);\r\n affectedFormats.add(name); // Include the format itself\r\n\r\n delete this._formatSet.formats[name];\r\n this._references.delete(name);\r\n\r\n this.onFormatsChanged.raiseEvent({ formatsChanged: Array.from(affectedFormats) });\r\n }\r\n\r\n /**\r\n * Gets all format names that reference the target format (directly or indirectly).\r\n * @param target The format name to find references to\r\n * @returns Set of format names that reference the target\r\n */\r\n private getFormatsReferencingTarget(target: string): Set<string> {\r\n const referencingFormats = new Set<string>();\r\n\r\n // Find all formats that directly reference the target\r\n for (const [formatName, reference] of this._references.entries()) {\r\n if (reference === target) {\r\n referencingFormats.add(formatName);\r\n // Recursively find formats that reference this format\r\n const indirectReferences = this.getFormatsReferencingTarget(formatName);\r\n for (const indirectRef of indirectReferences) {\r\n referencingFormats.add(indirectRef);\r\n }\r\n }\r\n }\r\n\r\n return referencingFormats;\r\n }\r\n}\r\n\r\nfunction extendProviderContext(context: FormatsProviderContext | undefined, provider: FormatsProvider): FormatsProviderContext | undefined {\r\n const providerChain = new Set(context?.providerChain);\r\n if (providerChain.has(provider))\r\n return undefined;\r\n\r\n providerChain.add(provider);\r\n return { providerChain };\r\n}\r\n\r\nfunction normalizeFormatName(input: string): string {\r\n // Convert node-addon names from `schemaName:schemaItemName` to the dot-separated key used by FormatSet.\r\n const [schemaName, itemName] = SchemaItem.parseFullName(input);\r\n return schemaName === \"\" ? itemName : `${schemaName}.${itemName}`;\r\n}\r\n"]}
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { ISchemaLocater, SchemaContext } from "../Context";
|
|
5
5
|
import { BeEvent } from "@itwin/core-bentley";
|
|
6
|
-
import { FormatDefinition, FormatsChangedArgs, FormatsProvider, UnitSystemKey } from "@itwin/core-quantity";
|
|
6
|
+
import { FormatDefinition, FormatsChangedArgs, FormatsProvider, SyncFormatsProvider, UnitSystemKey } from "@itwin/core-quantity";
|
|
7
7
|
/**
|
|
8
8
|
* Provides default formats and kind of quantities from a given SchemaContext or SchemaLocater.
|
|
9
9
|
* @beta
|
|
10
10
|
*/
|
|
11
|
-
export declare class SchemaFormatsProvider implements FormatsProvider {
|
|
11
|
+
export declare class SchemaFormatsProvider implements FormatsProvider, SyncFormatsProvider {
|
|
12
12
|
private _context;
|
|
13
13
|
private _unitSystem?;
|
|
14
14
|
private _formatsRetrieved;
|
|
@@ -29,13 +29,22 @@ export declare class SchemaFormatsProvider implements FormatsProvider {
|
|
|
29
29
|
/** When using a presentation unit from a KindOfQuantity, the label and description should come from the KindOfQuantity */
|
|
30
30
|
private convertToFormatDefinition;
|
|
31
31
|
private getKindOfQuantityFormatFromSchema;
|
|
32
|
+
private getKindOfQuantityFormatProps;
|
|
32
33
|
/**
|
|
33
|
-
* Retrieves a
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* Retrieves a format definition from the schema context.
|
|
35
|
+
*
|
|
36
|
+
* For a KindOfQuantity with a unit system, matching presentation formats are checked first, followed by the persistence unit and then the default presentation format. Without a unit system, the default presentation format is used.
|
|
36
37
|
* @param name The full name of the Format or KindOfQuantity.
|
|
37
|
-
* @
|
|
38
|
+
* @param system Optional unit system used to select a KindOfQuantity format.
|
|
38
39
|
*/
|
|
39
40
|
getFormat(name: string, system?: UnitSystemKey): Promise<FormatDefinition | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves a format definition using only schema metadata already loaded in the context.
|
|
43
|
+
* It follows the same selection order as `getFormat` but never asks a locater to load a schema. Returns `undefined` when required metadata is not cached.
|
|
44
|
+
* Unlike `getFormat`, which logs lookup errors and returns `undefined`, this method treats only a schema that is still loading as a cache miss and rethrows other errors.
|
|
45
|
+
*/
|
|
46
|
+
getFormatSync(name: string, system?: UnitSystemKey): FormatDefinition | undefined;
|
|
47
|
+
private getKindOfQuantityFormatFromSchemaSync;
|
|
48
|
+
private getKindOfQuantityFormatPropsSync;
|
|
40
49
|
}
|
|
41
50
|
//# sourceMappingURL=SchemaFormatsProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaFormatsProvider.d.ts","sourceRoot":"","sources":["../../../src/Formatting/SchemaFormatsProvider.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"SchemaFormatsProvider.d.ts","sourceRoot":"","sources":["../../../src/Formatting/SchemaFormatsProvider.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ3D,OAAO,EAAE,OAAO,EAAU,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAe,kBAAkB,EAAE,eAAe,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO9I;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,eAAe,EAAE,mBAAmB;IAChF,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,WAAW,CAAC,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAA0B;IAC5C,gBAAgB,iBAAsB,kBAAkB,KAAK,IAAI,EAAI;IAC5E;;;;;;;OAOG;gBACS,gBAAgB,EAAE,cAAc,EAAE,UAAU,CAAC,EAAE,aAAa;IAUxE,IAAW,OAAO,kBAA4B;IAC9C,IAAW,UAAU,IAEa,aAAa,GAAG,SAAS,CAFP;IAEpD,IAAW,UAAU,CAAC,UAAU,EAAE,aAAa,GAAG,SAAS,EAG1D;IAED,OAAO,CAAC,KAAK;IAMb,0HAA0H;IAC1H,OAAO,CAAC,yBAAyB;YAenB,iCAAiC;YAoBjC,4BAA4B;IA0B1C;;;;;;OAMG;IACU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IA+BnG;;;;OAIG;IACI,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS;IAgBxF,OAAO,CAAC,qCAAqC;IAc7C,OAAO,CAAC,gCAAgC;CAkCzC"}
|