@itwin/core-backend 5.10.0-dev.19 → 5.10.0-dev.21
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/lib/cjs/BriefcaseManager.d.ts +8 -1
- package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/ClassRegistry.d.ts +3 -3
- package/lib/cjs/ClassRegistry.js +3 -3
- package/lib/cjs/ClassRegistry.js.map +1 -1
- package/lib/cjs/Element.d.ts +6 -3
- package/lib/cjs/Element.d.ts.map +1 -1
- package/lib/cjs/Element.js +6 -3
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/Entity.d.ts +13 -5
- package/lib/cjs/Entity.d.ts.map +1 -1
- package/lib/cjs/Entity.js +13 -5
- package/lib/cjs/Entity.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +79 -17
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +181 -22
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +3 -1
- package/lib/cjs/Relationship.d.ts.map +1 -1
- package/lib/cjs/Relationship.js +3 -1
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/cjs/internal/workspace/WorkspaceImpl.js +7 -11
- package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/cjs/workspace/Workspace.d.ts +3 -1
- package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
- package/lib/cjs/workspace/Workspace.js.map +1 -1
- package/lib/esm/BriefcaseManager.d.ts +8 -1
- package/lib/esm/BriefcaseManager.d.ts.map +1 -1
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/ClassRegistry.d.ts +3 -3
- package/lib/esm/ClassRegistry.js +3 -3
- package/lib/esm/ClassRegistry.js.map +1 -1
- package/lib/esm/Element.d.ts +6 -3
- package/lib/esm/Element.d.ts.map +1 -1
- package/lib/esm/Element.js +6 -3
- package/lib/esm/Element.js.map +1 -1
- package/lib/esm/Entity.d.ts +13 -5
- package/lib/esm/Entity.d.ts.map +1 -1
- package/lib/esm/Entity.js +13 -5
- package/lib/esm/Entity.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +79 -17
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +182 -23
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/Relationship.d.ts +3 -1
- package/lib/esm/Relationship.d.ts.map +1 -1
- package/lib/esm/Relationship.js +3 -1
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
- package/lib/esm/internal/workspace/WorkspaceImpl.js +7 -11
- package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
- package/lib/esm/test/imodel/IModel.test.js +2 -0
- package/lib/esm/test/imodel/IModel.test.js.map +1 -1
- package/lib/esm/test/schema/ClassRegistry.test.js +3 -0
- package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
- package/lib/esm/test/schema/IModelSchemaContext.test.js +2 -0
- package/lib/esm/test/schema/IModelSchemaContext.test.js.map +1 -1
- package/lib/esm/test/schema/SchemaViewHidden.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewHidden.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewHidden.test.js +275 -0
- package/lib/esm/test/schema/SchemaViewHidden.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewKoQ.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewKoQ.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewKoQ.test.js +175 -0
- package/lib/esm/test/schema/SchemaViewKoQ.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewLifecycle.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewLifecycle.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewLifecycle.test.js +141 -0
- package/lib/esm/test/schema/SchemaViewLifecycle.test.js.map +1 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.d.ts +2 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.d.ts.map +1 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.js +475 -0
- package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -0
- package/lib/esm/test/standalone/Workspace.test.js +23 -0
- package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
- package/lib/esm/workspace/Workspace.d.ts +3 -1
- package/lib/esm/workspace/Workspace.d.ts.map +1 -1
- package/lib/esm/workspace/Workspace.js.map +1 -1
- package/package.json +14 -14
package/lib/cjs/IModelDb.js
CHANGED
|
@@ -165,6 +165,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
165
165
|
_jsClassMap;
|
|
166
166
|
_schemaMap;
|
|
167
167
|
_schemaContext;
|
|
168
|
+
_schemasPromise;
|
|
168
169
|
/** @deprecated in 5.0.0 - will not be removed until after 2026-06-13. Use [[fonts]]. */
|
|
169
170
|
_fontMap; // eslint-disable-line @typescript-eslint/no-deprecated
|
|
170
171
|
_fonts = (0, IModelDbFontsImpl_1.createIModelDbFonts)(this);
|
|
@@ -797,6 +798,11 @@ class IModelDb extends core_common_1.IModel {
|
|
|
797
798
|
this._jsClassMap = undefined;
|
|
798
799
|
this._schemaMap = undefined;
|
|
799
800
|
this._schemaContext = undefined;
|
|
801
|
+
if (this._schemasPromise) {
|
|
802
|
+
const old = this._schemasPromise;
|
|
803
|
+
this._schemasPromise = undefined;
|
|
804
|
+
old.then((view) => view.markOutdated()).catch(() => { });
|
|
805
|
+
}
|
|
800
806
|
this[Symbols_1._nativeDb].clearECDbCache();
|
|
801
807
|
}
|
|
802
808
|
this.elements[Symbols_1._cache].clear();
|
|
@@ -1237,7 +1243,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1237
1243
|
}
|
|
1238
1244
|
/** The registry of entity metadata for this iModel.
|
|
1239
1245
|
* @internal
|
|
1240
|
-
* @deprecated in 5.0 - will not be removed until after 2026-06-13.
|
|
1246
|
+
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `getSchemaView()` from the `iModel` instead.
|
|
1241
1247
|
*
|
|
1242
1248
|
* @example
|
|
1243
1249
|
* ```typescript
|
|
@@ -1245,7 +1251,8 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1245
1251
|
* const classMetaData: EntityMetaData | undefined = iModel.classMetaDataRegistry.find("SchemaName:ClassName");
|
|
1246
1252
|
*
|
|
1247
1253
|
* // Replacement:
|
|
1248
|
-
* const
|
|
1254
|
+
* const view = await imodel.getSchemaView();
|
|
1255
|
+
* const cls = view.findClass("SchemaName:ClassName");
|
|
1249
1256
|
* ```
|
|
1250
1257
|
*/
|
|
1251
1258
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -1272,7 +1279,11 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1272
1279
|
return this._schemaMap;
|
|
1273
1280
|
}
|
|
1274
1281
|
/**
|
|
1275
|
-
* Gets the context that allows accessing the metadata (ecschema-metadata package) of this iModel
|
|
1282
|
+
* Gets the context that allows accessing the metadata (`@itwin/ecschema-metadata` package) of this iModel.
|
|
1283
|
+
*
|
|
1284
|
+
* For runtime read-only access - class/property iteration, IS-A checks, navigating relationships, KOQ lookups -
|
|
1285
|
+
* prefer [[getSchemaView]]. `schemaContext` remains the right choice when you need schema authoring
|
|
1286
|
+
* (via `@itwin/ecschema-editing`), custom-attribute deserialization, or the full ecschema-metadata object graph.
|
|
1276
1287
|
* @public @preview
|
|
1277
1288
|
*/
|
|
1278
1289
|
get schemaContext() {
|
|
@@ -1286,6 +1297,55 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1286
1297
|
}
|
|
1287
1298
|
return this._schemaContext;
|
|
1288
1299
|
}
|
|
1300
|
+
/** Get the schema view for this iModel. The view is built lazily on
|
|
1301
|
+
* first call by fetching compact binary schema data via `PRAGMA schema_view` through
|
|
1302
|
+
* the ConcurrentQuery thread pool. Subsequent calls return the cached view. Multiple
|
|
1303
|
+
* concurrent callers share a single in-flight build.
|
|
1304
|
+
*
|
|
1305
|
+
* The returned `SchemaView` is a lightweight, read-only, synchronous API for
|
|
1306
|
+
* navigating schema metadata - classes, properties, relationships, enumerations, etc.
|
|
1307
|
+
* It is the recommended default for runtime read-only metadata access and is significantly
|
|
1308
|
+
* faster and lower-memory than [[schemaContext]]. Use [[schemaContext]] for schema authoring,
|
|
1309
|
+
* custom-attribute deserialization, or anywhere you need the full ecschema-metadata object graph.
|
|
1310
|
+
* @beta
|
|
1311
|
+
*/
|
|
1312
|
+
async getSchemaView() {
|
|
1313
|
+
if (this._schemasPromise) {
|
|
1314
|
+
const ctx = await this._schemasPromise;
|
|
1315
|
+
if (!ctx.isOutdated)
|
|
1316
|
+
return ctx;
|
|
1317
|
+
}
|
|
1318
|
+
// Capture the in-flight promise locally so the rejection handler only clears
|
|
1319
|
+
// `_schemasPromise` if it still points at this build. A concurrent invalidation +
|
|
1320
|
+
// re-fetch could otherwise replace the field before our hydrate fails, and a naive
|
|
1321
|
+
// `_schemasPromise = undefined` would clobber that newer reference.
|
|
1322
|
+
const inflight = this._hydrateSchemas();
|
|
1323
|
+
this._schemasPromise = inflight;
|
|
1324
|
+
inflight.catch(() => {
|
|
1325
|
+
if (this._schemasPromise === inflight)
|
|
1326
|
+
this._schemasPromise = undefined;
|
|
1327
|
+
});
|
|
1328
|
+
return inflight;
|
|
1329
|
+
}
|
|
1330
|
+
async _hydrateSchemas() {
|
|
1331
|
+
// PRAGMA returns exactly one row with format, formatVersion, data (binary), schemaToken.
|
|
1332
|
+
// Important: only call reader.next() once - do NOT use `for await` on PRAGMA results.
|
|
1333
|
+
// ConcurrentQuery wraps regular ECSQL in LIMIT/OFFSET for pagination but skips this for
|
|
1334
|
+
// PRAGMAs. If the serialized result exceeds the memory threshold, the response is marked
|
|
1335
|
+
// "Partial", and a `for await` loop would re-issue the same PRAGMA forever since PRAGMAs
|
|
1336
|
+
// don't support OFFSET-based pagination.
|
|
1337
|
+
// This implementation uses the non-pinned version of the pragma other than frontend - because backend
|
|
1338
|
+
// is always strictly coupled with the native code.
|
|
1339
|
+
const reader = this.createQueryReader("PRAGMA schema_view");
|
|
1340
|
+
const result = await reader.next();
|
|
1341
|
+
if (result.done)
|
|
1342
|
+
throw new core_common_1.IModelError(core_bentley_1.DbResult.BE_SQLITE_ERROR, "PRAGMA schema_view returned no rows");
|
|
1343
|
+
const data = result.value.data;
|
|
1344
|
+
const token = result.value.schemaToken;
|
|
1345
|
+
if (data === undefined || data === null)
|
|
1346
|
+
throw new core_common_1.IModelError(core_bentley_1.DbResult.BE_SQLITE_ERROR, "PRAGMA schema_view returned null data column");
|
|
1347
|
+
return ecschema_metadata_1.SchemaView.fromBinary(data, token ?? "");
|
|
1348
|
+
}
|
|
1289
1349
|
/** Get the linkTableRelationships for this IModel */
|
|
1290
1350
|
get relationships() {
|
|
1291
1351
|
return this._relationships || (this._relationships = new Relationship_1.Relationships(this));
|
|
@@ -1360,7 +1420,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1360
1420
|
}
|
|
1361
1421
|
/** Get metadata for a class. This method will load the metadata from the iModel into the cache as a side-effect, if necessary.
|
|
1362
1422
|
* @throws [[IModelError]] if the metadata cannot be found nor loaded.
|
|
1363
|
-
* @deprecated in 5.0 - will not be removed until after 2026-06-13.
|
|
1423
|
+
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `getSchemaView()` on the iModel and call `view.findClass(...)` instead.
|
|
1364
1424
|
*
|
|
1365
1425
|
* @example
|
|
1366
1426
|
* * ```typescript
|
|
@@ -1368,7 +1428,8 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1368
1428
|
* const metaData: EntityMetaData = imodel.getMetaData("SchemaName:ClassName");
|
|
1369
1429
|
*
|
|
1370
1430
|
* // Replacement:
|
|
1371
|
-
* const
|
|
1431
|
+
* const view = await imodel.getSchemaView();
|
|
1432
|
+
* const cls = view.findClass("SchemaName:ClassName");
|
|
1372
1433
|
* ```
|
|
1373
1434
|
*/
|
|
1374
1435
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -1386,7 +1447,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1386
1447
|
return metadata;
|
|
1387
1448
|
}
|
|
1388
1449
|
/** Identical to [[getMetaData]], except it returns `undefined` instead of throwing an error if the metadata cannot be found nor loaded.
|
|
1389
|
-
* @deprecated in 5.0 - will not be removed until after 2026-06-13.
|
|
1450
|
+
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `getSchemaView()` on the iModel and call `view.findClass(...)` instead.
|
|
1390
1451
|
*
|
|
1391
1452
|
* @example
|
|
1392
1453
|
* * ```typescript
|
|
@@ -1394,7 +1455,8 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1394
1455
|
* const metaData: EntityMetaData | undefined = imodel.tryGetMetaData("SchemaName:ClassName");
|
|
1395
1456
|
*
|
|
1396
1457
|
* // Replacement:
|
|
1397
|
-
* const
|
|
1458
|
+
* const view = await imodel.getSchemaView();
|
|
1459
|
+
* const cls = view.findClass("SchemaName:ClassName");
|
|
1398
1460
|
* ```
|
|
1399
1461
|
*/
|
|
1400
1462
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -1414,7 +1476,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1414
1476
|
* @param func The callback to be invoked on each property
|
|
1415
1477
|
* @param includeCustom If true (default), include custom-handled properties in the iteration. Otherwise, skip custom-handled properties.
|
|
1416
1478
|
* @note Custom-handled properties are core properties that have behavior enforced by C++ handlers.
|
|
1417
|
-
* @deprecated in 5.0 - will not be removed until after 2026-06-13.
|
|
1479
|
+
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `getSchemaView()` on the iModel and iterate `view.findClass(classFullName)?.getProperties()` instead.
|
|
1418
1480
|
*
|
|
1419
1481
|
* @example
|
|
1420
1482
|
* ```typescript
|
|
@@ -1424,9 +1486,10 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1424
1486
|
* }, false);
|
|
1425
1487
|
*
|
|
1426
1488
|
* // Replacement:
|
|
1427
|
-
* await
|
|
1428
|
-
*
|
|
1429
|
-
* },
|
|
1489
|
+
* const view = await imodel.getSchemaView();
|
|
1490
|
+
* for (const property of view.findClass("BisCore:Element")?.getProperties() ?? []) {
|
|
1491
|
+
* console.log(`Property name: ${property.name}, Kind: ${property.kind}`);
|
|
1492
|
+
* }
|
|
1430
1493
|
* ```
|
|
1431
1494
|
*/
|
|
1432
1495
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -1440,7 +1503,7 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1440
1503
|
* @param func The callback to be invoked on each property
|
|
1441
1504
|
* @param includeCustom If true (default), include custom-handled properties in the iteration. Otherwise, skip custom-handled properties.
|
|
1442
1505
|
* @note Custom-handled properties are core properties that have behavior enforced by C++ handlers.
|
|
1443
|
-
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `
|
|
1506
|
+
* @deprecated in 5.0 - will not be removed until after 2026-06-13. Use `getSchemaView()` on the iModel and iterate `view.findClass(classFullName)?.getProperties()` instead.
|
|
1444
1507
|
*
|
|
1445
1508
|
* @example
|
|
1446
1509
|
* ```typescript
|
|
@@ -1450,9 +1513,10 @@ class IModelDb extends core_common_1.IModel {
|
|
|
1450
1513
|
* });
|
|
1451
1514
|
*
|
|
1452
1515
|
* // Replacement:
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
* });
|
|
1516
|
+
* const view = await imodel.getSchemaView();
|
|
1517
|
+
* for (const property of view.findClass("BisCore:Element")?.getProperties() ?? []) {
|
|
1518
|
+
* console.log(`Property name: ${property.name}, Kind: ${property.kind}`);
|
|
1519
|
+
* }
|
|
1456
1520
|
* ```
|
|
1457
1521
|
*/
|
|
1458
1522
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -3339,7 +3403,63 @@ class BriefcaseDb extends IModelDb {
|
|
|
3339
3403
|
async getAllChangesetHealthData() {
|
|
3340
3404
|
return this[Symbols_1._nativeDb].getAllChangesetHealthData();
|
|
3341
3405
|
}
|
|
3342
|
-
/**
|
|
3406
|
+
/**
|
|
3407
|
+
* Whether file-based transactions are enabled for this briefcase.
|
|
3408
|
+
*
|
|
3409
|
+
* When enabled, transaction data is stored in separate temporary `.txn` files rather than in the
|
|
3410
|
+
* briefcase's internal transaction table. This avoids SQLite blob size limits and reduces memory
|
|
3411
|
+
* pressure for very large changesets, at the cost of additional disk I/O.
|
|
3412
|
+
* @see [[enableFileBasedTxns]] to enable, [[disableFileBasedTxns]] to disable.
|
|
3413
|
+
* @internal
|
|
3414
|
+
*/
|
|
3415
|
+
get isFileBasedTxnsEnabled() {
|
|
3416
|
+
return this[Symbols_1._nativeDb].queryLocalValue("fileBasedTxns") === "1";
|
|
3417
|
+
}
|
|
3418
|
+
/**
|
|
3419
|
+
* Enable file-based transactions for this briefcase.
|
|
3420
|
+
* @throws IModelError with [[ChangeSetStatus.HasUncommittedChanges]] if there are unsaved changes.
|
|
3421
|
+
* @throws IModelError with [[ChangeSetStatus.HasLocalChanges]] if there are pending transactions.
|
|
3422
|
+
* @internal
|
|
3423
|
+
*/
|
|
3424
|
+
enableFileBasedTxns() {
|
|
3425
|
+
this._setFileBasedTxnsSetting(true);
|
|
3426
|
+
}
|
|
3427
|
+
/**
|
|
3428
|
+
* Disable file-based transactions for this briefcase, reverting to the default storage mode
|
|
3429
|
+
* (transactions stored within the briefcase's internal transaction table).
|
|
3430
|
+
* @throws IModelError with [[ChangeSetStatus.HasUncommittedChanges]] if there are unsaved changes.
|
|
3431
|
+
* @throws IModelError with [[ChangeSetStatus.HasLocalChanges]] if there are pending transactions.
|
|
3432
|
+
* @internal
|
|
3433
|
+
*/
|
|
3434
|
+
disableFileBasedTxns() {
|
|
3435
|
+
this._setFileBasedTxnsSetting(false);
|
|
3436
|
+
}
|
|
3437
|
+
_setFileBasedTxnsSetting(enabled) {
|
|
3438
|
+
if (this.isFileBasedTxnsEnabled === enabled)
|
|
3439
|
+
return;
|
|
3440
|
+
const nativeDb = this[Symbols_1._nativeDb];
|
|
3441
|
+
if (nativeDb.hasUnsavedChanges())
|
|
3442
|
+
throw new core_common_1.IModelError(core_bentley_1.ChangeSetStatus.HasUncommittedChanges, "Cannot change file-based transactions setting while there are unsaved changes");
|
|
3443
|
+
if (nativeDb.hasPendingTxns())
|
|
3444
|
+
throw new core_common_1.IModelError(core_bentley_1.ChangeSetStatus.HasLocalChanges, "Cannot change file-based transactions setting while there are pending transactions");
|
|
3445
|
+
if (enabled)
|
|
3446
|
+
nativeDb.saveLocalValue("fileBasedTxns", "1");
|
|
3447
|
+
else
|
|
3448
|
+
nativeDb.deleteLocalValue("fileBasedTxns");
|
|
3449
|
+
}
|
|
3450
|
+
/**
|
|
3451
|
+
* Revert timeline changes and push the resulting changeset.
|
|
3452
|
+
*
|
|
3453
|
+
* Pulls the latest changes, acquires the schema lock, reverts the inclusive range of
|
|
3454
|
+
* changesets `[toIndex..current]`, and pushes the revert as a new changeset. On failure,
|
|
3455
|
+
* follow the behavior specified by `arg.inCaseOfFailure`, which may discard local changes,
|
|
3456
|
+
* retain local changes, or delete the briefcase.
|
|
3457
|
+
*
|
|
3458
|
+
* @param arg - Arguments specifying the target changeset index, push options, access token, and failure handling behavior.
|
|
3459
|
+
* @throws IModelError with [[ChangeSetStatus.ApplyError]] if `toIndex` is not specified.
|
|
3460
|
+
* @throws IModelError with [[ChangeSetStatus.HasUncommittedChanges]] if there are unsaved changes.
|
|
3461
|
+
* @throws IModelError with [[ChangeSetStatus.HasLocalChanges]] if there are pending transactions.
|
|
3462
|
+
*/
|
|
3343
3463
|
async revertAndPushChanges(arg) {
|
|
3344
3464
|
const nativeDb = this[Symbols_1._nativeDb];
|
|
3345
3465
|
if (arg.toIndex === undefined) {
|
|
@@ -3371,11 +3491,14 @@ class BriefcaseDb extends IModelDb {
|
|
|
3371
3491
|
if (nativeDb.schemaSyncEnabled()) {
|
|
3372
3492
|
arg.skipSchemaChanges = true;
|
|
3373
3493
|
}
|
|
3494
|
+
// The native side enables file-based txns during revert. Restore the original setting afterward.
|
|
3495
|
+
const wasFileBasedTxnsEnabled = this.isFileBasedTxnsEnabled;
|
|
3496
|
+
const preRevertIndex = this.changeset.index;
|
|
3374
3497
|
try {
|
|
3375
3498
|
await BriefcaseManager_1.BriefcaseManager.revertTimelineChanges(this, arg);
|
|
3376
|
-
|
|
3499
|
+
nativeDb.saveChanges("Revert changes");
|
|
3377
3500
|
if (!arg.description) {
|
|
3378
|
-
arg.description = `Reverted changes from ${
|
|
3501
|
+
arg.description = `Reverted changes from ${preRevertIndex} to ${arg.toIndex}${arg.skipSchemaChanges ? " (schema changes skipped)" : ""}`;
|
|
3379
3502
|
}
|
|
3380
3503
|
const pushArgs = {
|
|
3381
3504
|
description: arg.description,
|
|
@@ -3390,13 +3513,49 @@ class BriefcaseDb extends IModelDb {
|
|
|
3390
3513
|
this.clearCaches();
|
|
3391
3514
|
}
|
|
3392
3515
|
catch (err) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3516
|
+
const failureAction = arg.inCaseOfFailure ?? "revert";
|
|
3517
|
+
try {
|
|
3518
|
+
switch (failureAction) {
|
|
3519
|
+
case "revert":
|
|
3520
|
+
// Restore the briefcase to its pre-revert state: save any unsaved changes into txns,
|
|
3521
|
+
// reverse all txns, then delete them.
|
|
3522
|
+
nativeDb.saveChanges();
|
|
3523
|
+
if (nativeDb.hasPendingTxns())
|
|
3524
|
+
nativeDb.reverseAll();
|
|
3525
|
+
nativeDb.deleteAllTxns();
|
|
3526
|
+
break;
|
|
3527
|
+
case "delete":
|
|
3528
|
+
// Clear local changes first so lock release can succeed.
|
|
3529
|
+
nativeDb.abandonChanges();
|
|
3530
|
+
nativeDb.deleteAllTxns();
|
|
3531
|
+
if (!arg.retainLocks)
|
|
3532
|
+
await this.locks.releaseAllLocks();
|
|
3533
|
+
const filePath = this.pathName;
|
|
3534
|
+
this.close();
|
|
3535
|
+
await BriefcaseManager_1.BriefcaseManager.deleteBriefcaseFiles(filePath, arg.accessToken);
|
|
3536
|
+
break;
|
|
3537
|
+
case "retain":
|
|
3538
|
+
// Keep local changes as-is for caller inspection/recovery.
|
|
3539
|
+
nativeDb.saveChanges();
|
|
3540
|
+
break;
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
catch (cleanupErr) {
|
|
3544
|
+
core_bentley_1.Logger.logError(loggerCategory, `Failed to clean up after revert error (action=${failureAction}): ${String(cleanupErr)}`);
|
|
3545
|
+
}
|
|
3546
|
+
if (!arg.retainLocks && this.isOpen) {
|
|
3547
|
+
try {
|
|
3548
|
+
await this.locks.releaseAllLocks();
|
|
3549
|
+
}
|
|
3550
|
+
catch (lockErr) {
|
|
3551
|
+
core_bentley_1.Logger.logError(loggerCategory, `Failed to release locks after revert failure (action=${failureAction}): ${String(lockErr)}`);
|
|
3552
|
+
}
|
|
3396
3553
|
}
|
|
3554
|
+
throw err;
|
|
3397
3555
|
}
|
|
3398
3556
|
finally {
|
|
3399
|
-
this
|
|
3557
|
+
if (this.isOpen && !wasFileBasedTxnsEnabled && !nativeDb.hasPendingTxns() && !nativeDb.hasUnsavedChanges())
|
|
3558
|
+
this.disableFileBasedTxns();
|
|
3400
3559
|
}
|
|
3401
3560
|
}
|
|
3402
3561
|
/**
|