@itwin/core-backend 5.13.1 → 5.14.0-dev.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +1 -6
  2. package/lib/cjs/BriefcaseManager.d.ts +6 -0
  3. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  4. package/lib/cjs/BriefcaseManager.js +1 -1
  5. package/lib/cjs/BriefcaseManager.js.map +1 -1
  6. package/lib/cjs/ChangesetReader.d.ts.map +1 -1
  7. package/lib/cjs/ChangesetReader.js +1 -0
  8. package/lib/cjs/ChangesetReader.js.map +1 -1
  9. package/lib/cjs/ChangesetReaderTypes.d.ts +2 -1
  10. package/lib/cjs/ChangesetReaderTypes.d.ts.map +1 -1
  11. package/lib/cjs/ChangesetReaderTypes.js.map +1 -1
  12. package/lib/cjs/IModelDb.d.ts +41 -28
  13. package/lib/cjs/IModelDb.d.ts.map +1 -1
  14. package/lib/cjs/IModelDb.js +21 -15
  15. package/lib/cjs/IModelDb.js.map +1 -1
  16. package/lib/cjs/IpcHost.d.ts.map +1 -1
  17. package/lib/cjs/IpcHost.js +51 -17
  18. package/lib/cjs/IpcHost.js.map +1 -1
  19. package/lib/cjs/TxnManager.js +8 -8
  20. package/lib/cjs/TxnManager.js.map +1 -1
  21. package/lib/cjs/internal/IntegrityCheck.d.ts +57 -0
  22. package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -1
  23. package/lib/cjs/internal/IntegrityCheck.js.map +1 -1
  24. package/lib/esm/BriefcaseManager.d.ts +6 -0
  25. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  26. package/lib/esm/BriefcaseManager.js +1 -1
  27. package/lib/esm/BriefcaseManager.js.map +1 -1
  28. package/lib/esm/ChangesetReader.d.ts.map +1 -1
  29. package/lib/esm/ChangesetReader.js +1 -0
  30. package/lib/esm/ChangesetReader.js.map +1 -1
  31. package/lib/esm/ChangesetReaderTypes.d.ts +2 -1
  32. package/lib/esm/ChangesetReaderTypes.d.ts.map +1 -1
  33. package/lib/esm/ChangesetReaderTypes.js.map +1 -1
  34. package/lib/esm/IModelDb.d.ts +41 -28
  35. package/lib/esm/IModelDb.d.ts.map +1 -1
  36. package/lib/esm/IModelDb.js +21 -15
  37. package/lib/esm/IModelDb.js.map +1 -1
  38. package/lib/esm/IpcHost.d.ts.map +1 -1
  39. package/lib/esm/IpcHost.js +52 -18
  40. package/lib/esm/IpcHost.js.map +1 -1
  41. package/lib/esm/TxnManager.js +8 -8
  42. package/lib/esm/TxnManager.js.map +1 -1
  43. package/lib/esm/internal/IntegrityCheck.d.ts +57 -0
  44. package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -1
  45. package/lib/esm/internal/IntegrityCheck.js.map +1 -1
  46. package/lib/esm/test/annotations/FrameGeometry.test.js +1 -1
  47. package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
  48. package/lib/esm/test/hubaccess/BriefcaseManager.test.js +65 -1
  49. package/lib/esm/test/hubaccess/BriefcaseManager.test.js.map +1 -1
  50. package/lib/esm/test/hubaccess/SemanticRebase.test.js +189 -0
  51. package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
  52. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  53. package/package.json +14 -14
@@ -217,6 +217,58 @@ class TestIModel {
217
217
  <BaseClass>A</BaseClass>
218
218
  <ECProperty propertyName="PropD" typeName="string"/>
219
219
  </ECEntityClass>
220
+ </ECSchema>`,
221
+ /** v01x00x01 - Adds a link-table relationship class ARefersToA (ElementRefersToElements subclass) between A elements */
222
+ v01x00x01WithRelationship: `<?xml version="1.0" encoding="UTF-8"?>
223
+ <ECSchema schemaName="TestDomain" alias="td" version="01.00.01" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
224
+ <ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
225
+ <ECEntityClass typeName="A">
226
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
227
+ <ECProperty propertyName="PropA" typeName="string"/>
228
+ </ECEntityClass>
229
+ <ECEntityClass typeName="C">
230
+ <BaseClass>A</BaseClass>
231
+ <ECProperty propertyName="PropC" typeName="string"/>
232
+ </ECEntityClass>
233
+ <ECEntityClass typeName="D">
234
+ <BaseClass>A</BaseClass>
235
+ <ECProperty propertyName="PropD" typeName="string"/>
236
+ </ECEntityClass>
237
+ <ECRelationshipClass typeName="ARefersToA" strength="referencing" modifier="None">
238
+ <BaseClass>bis:ElementRefersToElements</BaseClass>
239
+ <Source multiplicity="(0..*)" roleLabel="refers to" polymorphic="true">
240
+ <Class class="A"/>
241
+ </Source>
242
+ <Target multiplicity="(0..*)" roleLabel="is referred to by" polymorphic="true">
243
+ <Class class="A"/>
244
+ </Target>
245
+ </ECRelationshipClass>
246
+ </ECSchema>`,
247
+ /** v01x00x02 - Moves PropC from C to A (transforming) while keeping the ARefersToA relationship class */
248
+ v01x00x02WithRelationshipMovePropCToA: `<?xml version="1.0" encoding="UTF-8"?>
249
+ <ECSchema schemaName="TestDomain" alias="td" version="01.00.02" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
250
+ <ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
251
+ <ECEntityClass typeName="A">
252
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
253
+ <ECProperty propertyName="PropA" typeName="string"/>
254
+ <ECProperty propertyName="PropC" typeName="string"/>
255
+ </ECEntityClass>
256
+ <ECEntityClass typeName="C">
257
+ <BaseClass>A</BaseClass>
258
+ </ECEntityClass>
259
+ <ECEntityClass typeName="D">
260
+ <BaseClass>A</BaseClass>
261
+ <ECProperty propertyName="PropD" typeName="string"/>
262
+ </ECEntityClass>
263
+ <ECRelationshipClass typeName="ARefersToA" strength="referencing" modifier="None">
264
+ <BaseClass>bis:ElementRefersToElements</BaseClass>
265
+ <Source multiplicity="(0..*)" roleLabel="refers to" polymorphic="true">
266
+ <Class class="A"/>
267
+ </Source>
268
+ <Target multiplicity="(0..*)" roleLabel="is referred to by" polymorphic="true">
269
+ <Class class="A"/>
270
+ </Target>
271
+ </ECRelationshipClass>
220
272
  </ECSchema>`,
221
273
  };
222
274
  /** Additional schemas for extended edge-case tests */
@@ -1287,6 +1339,143 @@ describe("Semantic Rebase", function () {
1287
1339
  chai.expect(schema.version).to.equal("01.00.00", "Schema should remain at v01.00.00");
1288
1340
  chai.expect(t.local.isOpen).to.be.true;
1289
1341
  });
1342
+ it("navigation property (parent) with explicit relationship class survives trivial schema rebase", async () => {
1343
+ t = await TestIModel.initialize("ClassIdNavTrivial");
1344
+ const localTxn = startTestTxn(t.local, "nav parent trivial local");
1345
+ const farTxn = startTestTxn(t.far, "nav parent trivial far");
1346
+ // Far imports a trivial additive schema change and pushes it (incoming change to rebase onto).
1347
+ await t.far.locks.acquireLocks({ shared: t.drawingModelId });
1348
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x01AddPropC2]);
1349
+ await pushChanges(farTxn, "add PropC2 to class C");
1350
+ // Local inserts (unpushed) a parent element and a child whose `parent` navigation property
1351
+ // carries an explicit relationship class (RelECClassId). These inserts are the changes that
1352
+ // get captured and reinstated during the rebase.
1353
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1354
+ const parentId = t.insertElement(localTxn, "TestDomain:A", { propA: "parent_a" });
1355
+ const childId = t.insertElement(localTxn, "TestDomain:C", {
1356
+ propA: "child_a",
1357
+ propC: "child_c",
1358
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1359
+ });
1360
+ localTxn.saveChanges("local insert parent + child");
1361
+ // Local pulls and rebases its local inserts onto the incoming schema change.
1362
+ await pullChanges(localTxn);
1363
+ t.local.clearCaches();
1364
+ // The navigation property (id + relClassName) captured from the insert must survive the rebase.
1365
+ const child = t.getElementProps(t.local, childId);
1366
+ chai.expect(child.parent).to.not.be.undefined;
1367
+ chai.expect(child.parent.id).to.equal(parentId, "parent navigation id must be preserved");
1368
+ chai.expect(child.parent.relClassName.replace(":", ".")).to.equal("BisCore.ElementOwnsChildElements", "parent navigation relationship class name must be preserved");
1369
+ chai.expect(child.classFullName).to.equal("TestDomain:C", "child classFullName must be preserved");
1370
+ chai.expect(child.propA).to.equal("child_a", "propA must be preserved");
1371
+ chai.expect(child.propC).to.equal("child_c", "propC must be preserved");
1372
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.01");
1373
+ });
1374
+ it("navigation property + multi-class ECClassId survive transforming schema rebase", async () => {
1375
+ t = await TestIModel.initialize("ClassIdNavTransforming");
1376
+ let localTxn = startTestTxn(t.local, "nav parent transforming local");
1377
+ let farTxn = startTestTxn(t.far, "nav parent transforming far");
1378
+ // Baseline: bump both briefcases to v01.00.01 so the incoming transforming change (v01.00.02
1379
+ // MovePropCToA) applies cleanly on top of it.
1380
+ await importSchemaStrings(localTxn, [TestIModel.schemas.v01x00x01AddPropC2]);
1381
+ await pushChanges(localTxn, "baseline v01.00.01");
1382
+ localTxn = startTestTxn(t.local, "nav parent transforming local");
1383
+ await pullChanges(farTxn);
1384
+ farTxn = startTestTxn(t.far, "nav parent transforming far");
1385
+ // Local inserts a parent (class A) and children of classes C and D, with explicit parent
1386
+ // relationship classes, then makes them local (unpushed) changes.
1387
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1388
+ const parentId = t.insertElement(localTxn, "TestDomain:A", { propA: "parent_a" });
1389
+ const cChildId = t.insertElement(localTxn, "TestDomain:C", {
1390
+ propA: "c_a",
1391
+ propC: "c_c",
1392
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1393
+ });
1394
+ const dChildId = t.insertElement(localTxn, "TestDomain:D", {
1395
+ propA: "d_a",
1396
+ propD: "d_d",
1397
+ parent: { id: parentId, relClassName: "BisCore:ElementOwnsChildElements" },
1398
+ });
1399
+ localTxn.saveChanges("local insert parent + C + D children");
1400
+ // Far pushes a transforming schema change (moves PropC from C to A).
1401
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x02MovePropCToA]);
1402
+ await pushChanges(farTxn, "far transforming schema v01.00.02");
1403
+ // Local pulls and rebases its local inserts onto the transforming schema change.
1404
+ await pullChanges(localTxn);
1405
+ t.local.clearCaches();
1406
+ // ECClassId of each element (a class-id-typed value) must resolve to the correct class name.
1407
+ const cChild = t.getElementProps(t.local, cChildId);
1408
+ chai.expect(cChild.classFullName).to.equal("TestDomain:C", "C child classFullName must be preserved");
1409
+ chai.expect(cChild.propC).to.equal("c_c", "propC value must survive column migration C→A");
1410
+ chai.expect(cChild.parent.id).to.equal(parentId, "C child parent id must be preserved");
1411
+ chai.expect(cChild.parent.relClassName.replace(":", ".")).to.equal("BisCore.ElementOwnsChildElements");
1412
+ const dChild = t.getElementProps(t.local, dChildId);
1413
+ chai.expect(dChild.classFullName).to.equal("TestDomain:D", "D child classFullName must be preserved");
1414
+ chai.expect(dChild.propD).to.equal("d_d");
1415
+ chai.expect(dChild.parent.id).to.equal(parentId, "D child parent id must be preserved");
1416
+ // ECSql resolves ECClassId to the correct class names after rebase.
1417
+ const rows = await TestIModel.queryToMap(t.local, `SELECT ECInstanceId, ec_className(ECClassId) AS className FROM TestDomain.A`);
1418
+ chai.expect(rows.get(cChildId)?.className).to.include("C");
1419
+ chai.expect(rows.get(dChildId)?.className).to.include("D");
1420
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.02");
1421
+ });
1422
+ it("link-table relationship (with constraint class ids) survives transforming schema rebase", async () => {
1423
+ t = await TestIModel.initialize("LinkTableRelTransforming");
1424
+ let localTxn = startTestTxn(t.local, "link table rel transforming local");
1425
+ let farTxn = startTestTxn(t.far, "link table rel transforming far");
1426
+ // Baseline: bump both briefcases to v01.00.01 so the ARefersToA link-table relationship class
1427
+ // exists on both sides and the incoming transforming change (v01.00.02 MovePropCToA) applies cleanly.
1428
+ await importSchemaStrings(localTxn, [TestIModel.schemas.v01x00x01WithRelationship]);
1429
+ await pushChanges(localTxn, "baseline v01.00.01 with relationship class");
1430
+ localTxn = startTestTxn(t.local, "link table rel transforming local");
1431
+ await pullChanges(farTxn);
1432
+ farTxn = startTestTxn(t.far, "link table rel transforming far");
1433
+ // Local inserts a source (class C) and a target (class D) element and a link-table relationship
1434
+ // (ARefersToA) between them - all unpushed local changes to be reinstated during rebase.
1435
+ await t.local.locks.acquireLocks({ shared: t.drawingModelId });
1436
+ const sourceId = t.insertElement(localTxn, "TestDomain:C", { propA: "src_a", propC: "src_c" });
1437
+ const targetId = t.insertElement(localTxn, "TestDomain:D", { propA: "tgt_a", propD: "tgt_d" });
1438
+ const relId = localTxn.insertRelationship({
1439
+ classFullName: "TestDomain:ARefersToA",
1440
+ sourceId,
1441
+ targetId,
1442
+ });
1443
+ localTxn.saveChanges("local insert source + target + relationship");
1444
+ // Far pushes a transforming schema change (moves PropC from C to A) which migrates the source
1445
+ // element's column, so the relationship's SourceECClassId must survive the migration.
1446
+ await importSchemaStrings(farTxn, [TestIModel.schemas.v01x00x02WithRelationshipMovePropCToA]);
1447
+ await pushChanges(farTxn, "far transforming schema v01.00.02");
1448
+ // Local pulls and rebases its local inserts onto the transforming schema change.
1449
+ await pullChanges(localTxn);
1450
+ t.local.clearCaches();
1451
+ // The relationship instance and its endpoints must survive the rebase.
1452
+ const rel = t.local.relationships.tryGetInstanceProps("TestDomain:ARefersToA", relId);
1453
+ chai.expect(rel, "relationship should exist after rebase").to.not.be.undefined;
1454
+ chai.expect(rel.sourceId).to.equal(sourceId, "relationship source id must be preserved");
1455
+ chai.expect(rel.targetId).to.equal(targetId, "relationship target id must be preserved");
1456
+ // ECSql resolves the relationship's ECClassId and its constraint class ids (Source/Target) to the
1457
+ // correct class names even after the transforming schema change migrated the endpoint columns.
1458
+ const rows = await TestIModel.queryToMap(t.local, `SELECT ECInstanceId, SourceECInstanceId AS sourceId, TargetECInstanceId AS targetId,
1459
+ ec_className(ECClassId, 's.c') AS className,
1460
+ ec_className(SourceECClassId, 's.c') AS sourceClassName,
1461
+ ec_className(TargetECClassId, 's.c') AS targetClassName
1462
+ FROM TestDomain.ARefersToA`);
1463
+ const relRow = rows.get(relId);
1464
+ chai.expect(relRow, "relationship row should be queryable after rebase").to.not.be.undefined;
1465
+ chai.expect(relRow.sourceId).to.equal(sourceId);
1466
+ chai.expect(relRow.targetId).to.equal(targetId);
1467
+ chai.expect(relRow.className).to.equal("TestDomain.ARefersToA", "relationship class id must resolve to ARefersToA");
1468
+ chai.expect(relRow.sourceClassName).to.equal("TestDomain.C", "source constraint class id must resolve to class C");
1469
+ chai.expect(relRow.targetClassName).to.equal("TestDomain.D", "target constraint class id must resolve to class D");
1470
+ // The endpoint elements themselves survive the transforming change with values intact.
1471
+ const source = t.getElementProps(t.local, sourceId);
1472
+ chai.expect(source.classFullName).to.equal("TestDomain:C", "source classFullName must be preserved");
1473
+ chai.expect(source.propC).to.equal("src_c", "propC value must survive column migration C→A");
1474
+ const target = t.getElementProps(t.local, targetId);
1475
+ chai.expect(target.classFullName).to.equal("TestDomain:D", "target classFullName must be preserved");
1476
+ chai.expect(target.propD).to.equal("tgt_d", "propD value must be preserved");
1477
+ chai.expect(t.local.getSchemaProps("TestDomain").version).to.equal("01.00.02");
1478
+ });
1290
1479
  });
1291
1480
  /**
1292
1481
  * Test suite for tests related to rebase logic with schema changes (for indirect changes) that require data transformations.