5.14.0 Change Notes
- 5.14.0 Change Notes
Frontend
Download progress for pushChanges
Pushing local changes first pulls, applies, and merges any changesets made by other users. That download could not previously be observed or cancelled. A new @beta overload of BriefcaseConnection.pushChanges accepts PushChangesOptions, mirroring the options already available on BriefcaseConnection.pullChanges:
Aborting rejects the returned promise and leaves the local changes pending, so the push can be retried later.
OPC point clouds without a vertical datum use the iModel's vertical datum
When an OPC point cloud's CRS does not say whether its heights are ellipsoidal or orthometric (relative to the geoid), the point cloud is now assumed to use the same height convention as the iModel it is displayed in. Previously a fixed assumption was made, displacing the point cloud by the local geoid-ellipsoid separation whenever it did not match the iModel. If you applied a manual vertical offset to compensate, remove it.
Backend
Schema sync rework
Schema sync lets the briefcases of one iModel import ECSchemas without taking the exclusive schema lock. This new version explicitly splits between updates, which update the sync db, and upgrades which rewrite the sync db and push it with the briefcase at the same time via the new BriefcaseDb.upgradeSchemas API.
Updates no longer automatically end up in other users' briefcases when they import schemas. Instead, they only pick the reference closure of what they import, so updates only hit when a briefcase pushes.
A change that would move or destroy existing data is now refused with BE_SQLITE_ERROR_DataTransformRequired or the new BE_SQLITE_ERROR_DataDeletionRequired; the new @alpha BriefcaseDb.upgradeSchemas runs those under the exclusive schema lock and lands the changeset and the sync db together. iModels without schema sync are unaffected.
SchemaSync databases now require version 5.0.0. Existing version 4 containers are outside this compatibility boundary and cannot be opened by this release.
Experimental Relations() table valued function
ECSQL gains a new experimental table valued function, ECVLib.Relations(), that returns every instance directly related to a seed instance without the caller having to know which relationships apply to it. Its native traversal generates SQL from property maps and reads relationship storage directly, avoiding ECSQL preparation for each candidate relationship class. The outer query still goes through ECSQL preparation.
The ECInstanceId and ECClassId arguments are mandatory; a query that omits either is rejected rather than silently returning no rows. The optional third argument is the traversal direction — 'forward', 'backward' or 'both' (the default, also used when the argument is NULL). The comparison is case insensitive; any other value is an error. The function may also be written unqualified as Relations(...).
Each row describes one traversed relationship:
| Column | Description |
|---|---|
RelatedECInstanceId |
ECInstanceId of the related instance. |
RelatedECClassId |
ECClassId of the related instance. |
Direction |
forward when the seed is the source of the relationship, backward when it is the target. |
RelationshipECClassId |
ECClassId of the relationship that was traversed. |
RelationshipECInstanceId |
ECInstanceId of the relationship instance, which distinguishes two link table rows connecting the same pair of instances. |
NavPropertyName |
Name of the navigation property holding the relationship for end table (foreign key) relationships; NULL for link tables. |
Because Relations() is experimental it is disabled by default. Enable it with PRAGMA experimental_features_enabled=true or per query with ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES.
Example — find the model that contains an element, without knowing that BisCore:ModelContainsElements is stored in the Model navigation property:
Only instances of the primary (main) table space are traversed, and the ECSQL version was bumped to 2.0.4.1.
See the Relations virtual table reference for more details.
Import CSV data into ECDb
CSV data can be imported into an ECClass from in-memory string rows or streamed from a file. Both beta APIs return the number of inserted rows:
ECDb.importCSVData uses V8 serialization to cross the JavaScript-to-native boundary once. ECDb.importCSVFile reads and parses the file in native code; its path must be accessible to the backend process. Both reuse one ECSQL statement, convert each CSV string according to its mapped EC property type, ignore unmapped columns, and roll back the complete import if parsing, conversion, or insertion fails.
ChangesetReader changes
ChangesetReader row options
The useJsName option has been deprecated in the @beta RowFormatOptions used by ChangesetReader. Use classIdsToClassNames to resolve class Id values to fully-qualified class names.
SQLite changeset schema sources
The @beta SqliteChangesetReader.openFile method now accepts a plain SQLiteDb as its source of table and column metadata. The database must be open and contain every table referenced by the changeset. Set disableSchemaCheck to tolerate changeset columns that are not present in the database. A missing table always produces an error for every database type; disableSchemaCheck does not relax this requirement. EC-specific consumers such as ChangesetECAdaptor continue to require an IModelDb or ECDb.
ChangesetReader identifiers filter
The @beta PropertyFilter enum has a new InstanceKeyAndIdentifiers member. It returns ECInstanceId, ECClassId, and a fixed set of identifiers read only from the changeset, so it still works when a changeset is read after its instances were deleted. See Identifiers returned by InstanceKeyAndIdentifiers for the list.
Text annotation fields can read values from JSON properties
A FieldRun can now display a value stored inside a string property that holds serialized JSON, such as JsonProperties. Set the new @beta FieldPropertyPath.jsonAccessors to the object keys and array indices to follow once FieldPropertyPath.propertyName and FieldPropertyPath.accessors have reached a string property of extended type Json:
The JSON property may be nested; accessors walks the EC properties to the JSON property and jsonAccessors walks the parsed JSON:
The path must end on a string, number, or boolean; a path that ends on an object, an array, or a JSON null resolves to no value and the field displays FieldRun.invalidContentIndicator. A numeric leaf is treated as a "quantity"; it has no KindOfQuantity of its own, so it renders as its raw number unless the field supplies both kindOfQuantity and persistenceUnit in its format options (see below).
Quantity formatting for text annotation fields
FieldRuns whose target property resolves to a "quantity" or "coordinate" value are now rendered through the standard iTwin.js quantity formatting pipeline instead of the previous placeholder toString() representation. By default each KindOfQuantity is presented using the format its schema declares, in the metric unit system. An application can adopt its own FormatSets for an iModel via the new ElementDrivesTextAnnotation.registerFieldFormatting, and individual fields can override the KindOfQuantity or FormatSet used to format them, and supply a persistence unit for values that have none.
Two changes need attention when upgrading:
- Any numeric property carrying a KindOfQuantity previously rendered as a bare number and now renders as a formatted quantity, with no opt-in required: a
doublepersisting 2.5 m renders as2.5 minstead of2.5, and anintpersisting 2500 mm under a KindOfQuantity presenting meters changes from2500to2.5 m. Persisted FieldRun.cachedContent is updated the next time the source element is edited. @itwin/core-quantityis now a peer dependency of@itwin/core-backend. Most applications already list it, since packages such as@itwin/core-frontendand@itwin/core-ecschema-metadatadepend on it too. If yours does not, add it at the same version as the rest of your iTwin.js core packages.
See Quantity formatting for text annotation fields for a walkthrough covering format resolution, registration lifetime, and evaluating fields.
Geometry
PlanarRegionProps refactor
The flag Loop.isInner did not always survive round-trip through JSON or FlatBuffers due to an oversight. To address this, the CurveCollection class and PlanarRegionProps schema have been slightly refactored.
CurveCollection.isInner is now moved to Loop.isInner since Loop is the only subclass of CurveCollection for which this flag is relevant. As this flag is a) only set by user code, b) does not effect region processing, and c) was previously accessible to Loop by virtue of inheritance, this should not break existing code.
The JSON schema IModelJson.PlanarRegionProps has been refactored to extend 3 new interfaces: LoopProps (which includes isInner), ParityRegionProps, and UnionProps. This has 3 effects:
PlanarRegionProps.isInneris a new optional property. In concert with the existingPlanarRegionProps.loopproperty, aParityRegionPropscan now specify aLoopthat has been marked "inner" by the user.PlanarRegionProps.parityRegionis now an array ofLoopProps, thus each of its entries now inherits theisInnerproperty, allowing the specification of the common solid-with-holes type of parity region.PlanarRegionProps.unionRegionis now an array ofLoopProps | ParityRegionProps, which explicitly disallows illegal nestedUnionRegions. Previously, this property could specify a nested union because it was an array ofPlanarRegionProps. Regions code consistently assumes thatUnionRegions are not nested for efficiency.
Quantity
Synchronous quantity formatting
@itwin/core-quantity now provides beta synchronous quantity-formatting capabilities through SyncUnitsProvider, SyncFormatsProvider, Format.createFromJSONSync, and FormatterSpec.createSync. Use these APIs only when the required format and unit data are already available locally; they do not load schemas or perform asynchronous I/O. Missing synchronous unit data is reported through BadUnit or an identity conversion with error: true, while missing synchronous formats are reported as undefined. Use the existing asynchronous construction path or a plain-value fallback when the required data is not local. Providers that delegate a format lookup can forward its optional context to preserve cycle detection; omit the context only for an independent lookup.
Synchronous format lookup
SchemaFormatsProvider and FormatSetFormatsProvider now implement SyncFormatsProvider. SchemaFormatsProvider.getFormatSync follows the same selection order as getFormat but reads only schema metadata already loaded in the SchemaContext, returning undefined instead of loading a schema. FormatSetFormatsProvider.getFormatSync resolves local entries and string references without awaiting, and uses the fallback provider only when it also implements SyncFormatsProvider. FormatSetFormatsProvider now forwards the lookup context to its fallback provider, so a fallback chain that leads back to the same provider returns undefined instead of recursing, provided each delegating provider in the chain forwards the context.
Electron
Process-specific Electron ESM/CommonJS entry points
Use the process-specific entry points when importing from @itwin/core-electron:
For CommonJS applications, use the same entry-point paths with require:
renderer resolves to the ESM build for import and to the CommonJS build for require. main resolves to the CommonJS build for both. The package now uses an exports map, so subpaths that are not listed are not supported; in particular, lib/esm/* paths and ElectronPreload are not public package entry points. The existing @itwin/core-electron/lib/cjs/* wildcard paths remain available in this release for compatibility with legacy consumers and will be removed in iTwin.js 6.0. New code should use the process-specific entry points. The Electron preload script remains an internal implementation detail configured by ElectronHost.
Platform support
Electron 44 support
In addition to already supported Electron versions, iTwin.js now supports Electron 44.
Last Updated: 02 October, 2026