@itwin/imodel-transformer 1.0.1-dev.0 → 1.1.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +49 -1
  2. package/README.md +17 -0
  3. package/lib/cjs/Algo.d.ts +7 -0
  4. package/lib/cjs/Algo.d.ts.map +1 -1
  5. package/lib/cjs/Algo.js +7 -0
  6. package/lib/cjs/Algo.js.map +1 -1
  7. package/lib/cjs/BigMap.d.ts +6 -1
  8. package/lib/cjs/BigMap.d.ts.map +1 -1
  9. package/lib/cjs/BigMap.js +28 -2
  10. package/lib/cjs/BigMap.js.map +1 -1
  11. package/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
  12. package/lib/cjs/BranchProvenanceInitializer.js +2 -0
  13. package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
  14. package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +1 -1
  15. package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
  16. package/lib/cjs/ECReferenceTypesCache.js +8 -0
  17. package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
  18. package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js.map +1 -1
  19. package/lib/cjs/ElementCascadingDeleter.js.map +1 -1
  20. package/lib/cjs/EntityUnifier.d.ts.map +1 -1
  21. package/lib/cjs/EntityUnifier.js.map +1 -1
  22. package/lib/cjs/ExportElementAspectsStrategy.js.map +1 -1
  23. package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +1 -1
  24. package/lib/cjs/IModelCloneContext.d.ts +1 -4
  25. package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
  26. package/lib/cjs/IModelCloneContext.js +16 -31
  27. package/lib/cjs/IModelCloneContext.js.map +1 -1
  28. package/lib/cjs/IModelExporter.d.ts +67 -62
  29. package/lib/cjs/IModelExporter.d.ts.map +1 -1
  30. package/lib/cjs/IModelExporter.js +173 -83
  31. package/lib/cjs/IModelExporter.js.map +1 -1
  32. package/lib/cjs/IModelImporter.d.ts +31 -47
  33. package/lib/cjs/IModelImporter.d.ts.map +1 -1
  34. package/lib/cjs/IModelImporter.js +62 -72
  35. package/lib/cjs/IModelImporter.js.map +1 -1
  36. package/lib/cjs/IModelTransformer.d.ts +146 -210
  37. package/lib/cjs/IModelTransformer.d.ts.map +1 -1
  38. package/lib/cjs/IModelTransformer.js +515 -657
  39. package/lib/cjs/IModelTransformer.js.map +1 -1
  40. package/lib/cjs/{transformer.d.ts → imodel-transformer.d.ts} +1 -1
  41. package/lib/cjs/imodel-transformer.d.ts.map +1 -0
  42. package/lib/cjs/{transformer.js → imodel-transformer.js} +13 -3
  43. package/lib/cjs/imodel-transformer.js.map +1 -0
  44. package/package.json +22 -20
  45. package/lib/cjs/PendingReferenceMap.d.ts +0 -37
  46. package/lib/cjs/PendingReferenceMap.d.ts.map +0 -1
  47. package/lib/cjs/PendingReferenceMap.js +0 -92
  48. package/lib/cjs/PendingReferenceMap.js.map +0 -1
  49. package/lib/cjs/transformer.d.ts.map +0 -1
  50. package/lib/cjs/transformer.js.map +0 -1
@@ -55,7 +55,9 @@ class IModelExportHandler {
55
55
  shouldExportElement(_element) {
56
56
  return true;
57
57
  }
58
- /** Called when element is skipped instead of exported. */
58
+ /** Called when element is skipped instead of exported.
59
+ * @note When an element is skipped, exporter will not export any of its child elements. Because of this, [[onSkipElement]] will not be invoked for any children of a "skipped" element.
60
+ */
59
61
  onSkipElement(_elementId) { }
60
62
  /** Called when an element should be exported.
61
63
  * @param element The element to export
@@ -130,7 +132,7 @@ exports.IModelExportHandler = IModelExportHandler;
130
132
  class IModelExporter {
131
133
  /**
132
134
  * Retrieve the cached entity change information.
133
- * @note This will only be initialized after [IModelExporter.exportChanges] is invoked.
135
+ * @note This will only be initialized after [IModelExporter.exportChanges] is invoked or [IModelExporter.initialize] is called.
134
136
  */
135
137
  get sourceDbChanges() {
136
138
  return this._sourceDbChanges;
@@ -252,19 +254,24 @@ class IModelExporter {
252
254
  await this.exportModel(core_common_1.IModel.repositoryModelId);
253
255
  await this.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
254
256
  }
255
- async exportChanges(accessTokenOrOpts, startChangesetId) {
257
+ /** Export changes from the source iModel.
258
+ * Inserts, updates, and deletes are determined by inspecting the changeset(s).
259
+ * @note To form a range of versions to process, set `startChangesetId` for the start (inclusive) of the desired
260
+ * range and open the source iModel as of the end (inclusive) of the desired range.
261
+ * @note the changedInstanceIds are just for this call to exportChanges, so you must continue to pass it in
262
+ * for consecutive calls
263
+ */
264
+ async exportChanges(args) {
256
265
  if (!this.sourceDb.isBriefcaseDb())
257
266
  throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "Must be a briefcase to export changes");
258
267
  if ("" === this.sourceDb.changeset.id) {
259
268
  await this.exportAll(); // no changesets, so revert to exportAll
260
269
  return;
261
270
  }
262
- const initOpts = typeof accessTokenOrOpts === "object"
263
- ? accessTokenOrOpts
264
- : {
265
- accessToken: accessTokenOrOpts,
266
- startChangeset: { id: startChangesetId },
267
- };
271
+ const startChangeset = args && "startChangeset" in args ? args.startChangeset : undefined;
272
+ const initOpts = {
273
+ startChangeset: { id: startChangeset?.id },
274
+ };
268
275
  await this.initialize(initOpts);
269
276
  // _sourceDbChanges are initialized in this.initialize
270
277
  nodeAssert(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
@@ -592,6 +599,12 @@ class IModelExporter {
592
599
  core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportElement(${elementId})`);
593
600
  return;
594
601
  }
602
+ // Return early if the elementId is already in the excludedElementIds, that way we don't need to load the element from the db.
603
+ if (this._excludedElementIds.has(elementId)) {
604
+ core_bentley_1.Logger.logInfo(loggerCategory, `Excluded element ${elementId} by Id`);
605
+ this.handler.onSkipElement(elementId);
606
+ return;
607
+ }
595
608
  // are we processing changes?
596
609
  const isUpdate = this._sourceDbChanges?.element.insertIds.has(elementId)
597
610
  ? false
@@ -702,70 +715,10 @@ class IModelExporter {
702
715
  return this.handler.onProgress();
703
716
  }
704
717
  }
705
- /**
706
- * You may override this to store arbitrary json state in a exporter state dump, useful for some resumptions
707
- * @see [[IModelTransformer.saveStateToFile]]
708
- */
709
- getAdditionalStateJson() {
710
- return {};
711
- }
712
- /**
713
- * You may override this to load arbitrary json state in a transformer state dump, useful for some resumptions
714
- * @see [[IModelTransformer.loadStateFromFile]]
715
- */
716
- loadAdditionalStateJson(_additionalState) { }
717
- /**
718
- * Reload our state from a JSON object
719
- * Intended for [[IModelTransformer.resumeTransformation]]
720
- * @internal
721
- * You can load custom json from the exporter save state for custom exporters by overriding [[IModelExporter.loadAdditionalStateJson]]
722
- */
723
- loadStateFromJson(state) {
724
- if (state.exporterClass !== this.constructor.name)
725
- throw Error("resuming from a differently named exporter class, it is not necessarily valid to resume with a different exporter class");
726
- this.wantGeometry = state.wantGeometry;
727
- this.wantTemplateModels = state.wantTemplateModels;
728
- this.wantSystemSchemas = state.wantSystemSchemas;
729
- this.visitElements = state.visitElements;
730
- this.visitRelationships = state.visitRelationships;
731
- this._excludedCodeSpecNames = new Set(state.excludedCodeSpecNames);
732
- (this._excludedElementIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementIds)),
733
- (this._excludedElementCategoryIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementCategoryIds)),
734
- (this._excludedElementClasses = new Set(state.excludedElementClassNames.map((c) => this.sourceDb.getJsClass(c))));
735
- this._exportElementAspectsStrategy.loadExcludedElementAspectClasses(state.excludedElementAspectClassFullNames);
736
- this._excludedRelationshipClasses = new Set(state.excludedRelationshipClassNames.map((c) => this.sourceDb.getJsClass(c)));
737
- this.loadAdditionalStateJson(state.additionalState);
738
- }
739
- /**
740
- * Serialize state to a JSON object
741
- * Intended for [[IModelTransformer.resumeTransformation]]
742
- * @internal
743
- * You can add custom json to the exporter save state for custom exporters by overriding [[IModelExporter.getAdditionalStateJson]]
744
- */
745
- saveStateToJson() {
746
- return {
747
- exporterClass: this.constructor.name,
748
- wantGeometry: this.wantGeometry,
749
- wantTemplateModels: this.wantTemplateModels,
750
- wantSystemSchemas: this.wantSystemSchemas,
751
- visitElements: this.visitElements,
752
- visitRelationships: this.visitRelationships,
753
- excludedCodeSpecNames: [...this._excludedCodeSpecNames],
754
- excludedElementIds: core_bentley_1.CompressedId64Set.compressSet(this._excludedElementIds),
755
- excludedElementCategoryIds: core_bentley_1.CompressedId64Set.compressSet(this._excludedElementCategoryIds),
756
- excludedElementClassNames: Array.from(this._excludedElementClasses, (cls) => cls.classFullName),
757
- excludedElementAspectClassFullNames: [
758
- ...this._exportElementAspectsStrategy
759
- .excludedElementAspectClassFullNames,
760
- ],
761
- excludedRelationshipClassNames: Array.from(this._excludedRelationshipClasses, (cls) => cls.classFullName),
762
- additionalState: this.getAdditionalStateJson(),
763
- };
764
- }
765
718
  }
766
719
  exports.IModelExporter = IModelExporter;
767
720
  /** Class for holding change information.
768
- * @beta
721
+ * @public
769
722
  */
770
723
  class ChangedInstanceOps {
771
724
  constructor() {
@@ -784,11 +737,20 @@ class ChangedInstanceOps {
784
737
  val.delete.forEach((id) => this.deleteIds.add(id));
785
738
  }
786
739
  }
740
+ /**
741
+ * Checks if empty.
742
+ * @returns true if there no ids in the ChangedInstanceOps object.
743
+ */
744
+ get isEmpty() {
745
+ return (0 === this.insertIds.size &&
746
+ 0 === this.updateIds.size &&
747
+ 0 === this.deleteIds.size);
748
+ }
787
749
  }
788
750
  exports.ChangedInstanceOps = ChangedInstanceOps;
789
751
  /**
790
752
  * Class for discovering modified elements between 2 versions of an iModel.
791
- * @beta
753
+ * @public
792
754
  */
793
755
  class ChangedInstanceIds {
794
756
  constructor(db) {
@@ -806,6 +768,7 @@ class ChangedInstanceIds {
806
768
  this._elementSubclassIds = new Set();
807
769
  this._aspectSubclassIds = new Set();
808
770
  this._relationshipSubclassIds = new Set();
771
+ this._relationshipSubclassIdsToSkip = new Set();
809
772
  const addECClassIdsToSet = async (setToModify, baseClass) => {
810
773
  for await (const row of this._db.createQueryReader(`SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (${baseClass})`)) {
811
774
  setToModify.add(row.ECInstanceId);
@@ -818,6 +781,7 @@ class ChangedInstanceIds {
818
781
  addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementUniqueAspect"),
819
782
  addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementMultiAspect"),
820
783
  addECClassIdsToSet(this._relationshipSubclassIds, "BisCore.ElementRefersToElements"),
784
+ addECClassIdsToSet(this._relationshipSubclassIdsToSkip, "BisCore.ElementDrivesElement"),
821
785
  ];
822
786
  await Promise.all(promises);
823
787
  }
@@ -826,7 +790,8 @@ class ChangedInstanceIds {
826
790
  this._modelSubclassIds &&
827
791
  this._elementSubclassIds &&
828
792
  this._aspectSubclassIds &&
829
- this._relationshipSubclassIds);
793
+ this._relationshipSubclassIds &&
794
+ this._relationshipSubclassIdsToSkip);
830
795
  }
831
796
  isRelationship(ecClassId) {
832
797
  return this._relationshipSubclassIds?.has(ecClassId);
@@ -843,6 +808,17 @@ class ChangedInstanceIds {
843
808
  isElement(ecClassId) {
844
809
  return this._elementSubclassIds?.has(ecClassId);
845
810
  }
811
+ /** Checks if there are any changes.
812
+ * @returns true if there are any changes in the ChangedInstanceIds object.
813
+ */
814
+ get hasChanges() {
815
+ return (!this.codeSpec.isEmpty ||
816
+ !this.model.isEmpty ||
817
+ !this.element.isEmpty ||
818
+ !this.aspect.isEmpty ||
819
+ !this.relationship.isEmpty ||
820
+ !this.font.isEmpty);
821
+ }
846
822
  /**
847
823
  * Adds the provided [[ChangedECInstance]] to the appropriate set of changes by class type (codeSpec, model, element, aspect, or relationship) maintained by this instance of ChangedInstanceIds.
848
824
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
@@ -858,6 +834,8 @@ class ChangedInstanceIds {
858
834
  const changeType = change.$meta?.op;
859
835
  if (changeType === undefined)
860
836
  throw new Error(`ChangeType was undefined for id: ${change.ECInstanceId}.`);
837
+ if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
838
+ return;
861
839
  if (this.isRelationship(ecClassId))
862
840
  this.handleChange(this.relationship, changeType, change.ECInstanceId);
863
841
  else if (this.isCodeSpec(ecClassId))
@@ -869,6 +847,128 @@ class ChangedInstanceIds {
869
847
  else if (this.isElement(ecClassId))
870
848
  this.handleChange(this.element, changeType, change.ECInstanceId);
871
849
  }
850
+ /**
851
+ * This method should only be called inside [[IModelTransformer.addCustomChanges]].
852
+ * It adds the provided change to the element changes maintained by this instance of ChangedInstanceIds.
853
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
854
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
855
+ * @note Custom element 'Insert' and 'Update' will mark element's parent model hierarchy and their modeled elements as 'Updated' in [[ChangedInstanceIds.model]] and [[ChangedInstanceIds.element]]. Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models. Modeled elements hierarchy is marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted.
856
+ * @note Custom element 'Insert' will also mark element aspects and all element relationships as inserted.
857
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
858
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
859
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
860
+ * @beta
861
+ */
862
+ async addCustomElementChange(changeType, ids) {
863
+ if (core_bentley_1.Id64.sizeOf(ids) === 0) {
864
+ return;
865
+ }
866
+ for (const id of core_bentley_1.Id64.iterable(ids)) {
867
+ this.handleChange(this.element, changeType, id);
868
+ }
869
+ if (changeType === "Deleted") {
870
+ return;
871
+ }
872
+ const idsSet = core_bentley_1.Id64.toIdSet(ids);
873
+ // Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models.
874
+ // Transformer handles update as insert if element is not found in target, for this reason modeled elements will be also marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted. Otherwise error would be thrown about missing modeled element while inserting new model.
875
+ const parentModelIds = await this.markParentModelsAsUpdated(idsSet);
876
+ // Aspects and relationships of inserted data needs to be marked as inserted otherwise those would not be exported
877
+ if (changeType === "Inserted") {
878
+ // Adding parents as well as we are not sure if those were inserted or updated
879
+ parentModelIds.forEach((parentId) => {
880
+ idsSet.add(parentId);
881
+ });
882
+ await this.markElementAspectsAsInserted(idsSet);
883
+ // Marking only ElementRefersToElements.classFullName as only those are exported in exportRelationships()
884
+ await this.markElementRelationshipsAsInserted(core_backend_1.ElementRefersToElements.classFullName, idsSet);
885
+ }
886
+ }
887
+ /**
888
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
889
+ * Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds.
890
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
891
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
892
+ * Will add same change to the model's modeledElement by calling [[ChangedInstanceIds.addCustomElementChange]] which will register more needed changes. This is to ensure the changes from the model and its modeledElement get exported together.
893
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
894
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
895
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
896
+ * @beta
897
+ */
898
+ async addCustomModelChange(changeType, ids) {
899
+ // Also add the model's modeledElement to the element changes. The modeledElement and model go hand in hand and have the same id.
900
+ await this.addCustomElementChange(changeType, ids);
901
+ for (const id of core_bentley_1.Id64.iterable(ids)) {
902
+ this.handleChange(this.model, changeType, id);
903
+ }
904
+ }
905
+ /**
906
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
907
+ * Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
908
+ * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
909
+ * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
910
+ * @note It is the responsibility of the caller to ensure that the provided id is, in fact an aspect.
911
+ * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
912
+ * @beta
913
+ */
914
+ addCustomAspectChange(changeType, ids) {
915
+ for (const id of core_bentley_1.Id64.iterable(ids)) {
916
+ this.handleChange(this.aspect, changeType, id);
917
+ }
918
+ }
919
+ /**
920
+ * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is marked as `Updated` or 'Inserted' in sourceDbChanges. This method is used in [[addCustomElementChange]] and [[addCustomModelChange]] to add the parent model hierarchy to the 'updatedIds' so that the custom element changes are exported.
921
+ * Transformer will insert 'Updated' model to target if it does not exist there already. To handle such case, modeled elements of parent models are also marked as updated. This is done, because model can not be inserted without it's modeled element.
922
+ */
923
+ async markParentModelsAsUpdated(elementIds) {
924
+ const params = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
925
+ const ecQuery = `
926
+ WITH RECURSIVE hierarchy (parentId) AS (
927
+ SELECT Model.Id FROM bis.Element WHERE InVirtualSet(:elementIds, ECInstanceId)
928
+ UNION
929
+ SELECT ParentModel.id
930
+ FROM bis.Model e
931
+ INNER JOIN hierarchy h ON h.parentId = e.ECInstanceId
932
+ )
933
+ SELECT parentId FROM hierarchy where parentId is not null
934
+ `;
935
+ const parentModelIds = new Set();
936
+ for await (const row of this._db.createQueryReader(ecQuery, params)) {
937
+ // Transformer handles update as insert when element does not exist in target.
938
+ // Which means that in scenario where child and parent model are filtered out from target,
939
+ // and child element is inserted trough custom change, its parent model will be marked as updated.
940
+ // Transformer then will:
941
+ // 1. Handle parent update as insert (since it does not exist in target).
942
+ // 2. Will insert child element (otherwise this insert would be ignored due to missing parent).
943
+ this.handleChange(this.model, "Updated", row.parentId);
944
+ this.handleChange(this.element, "Updated", row.parentId);
945
+ parentModelIds.add(row.parentId);
946
+ }
947
+ return parentModelIds;
948
+ }
949
+ async markElementRelationshipsAsInserted(relationshipClassName, elementIds) {
950
+ const ecQuery = `SELECT ECInstanceId FROM ${relationshipClassName}
951
+ WHERE InVirtualSet(:elementIds, TargetECInstanceId)
952
+ OR InVirtualSet(:elementIds, SourceECInstanceId)`;
953
+ const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
954
+ const queryReader = this._db.createQueryReader(ecQuery, queryBinder);
955
+ for await (const row of queryReader) {
956
+ this.handleChange(this.relationship, "Inserted", row.ECInstanceId);
957
+ }
958
+ }
959
+ async markElementAspectsAsInserted(elementIds) {
960
+ for (const aspectClassName of [
961
+ core_backend_1.ElementUniqueAspect.classFullName,
962
+ core_backend_1.ElementMultiAspect.classFullName,
963
+ ]) {
964
+ const ecQuery = `Select ECInstanceId from ${aspectClassName} where InVirtualSet(:elementIds, Element.Id)`;
965
+ const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
966
+ const queryReader = this._db.createQueryReader(ecQuery, queryBinder);
967
+ for await (const row of queryReader) {
968
+ this.addCustomAspectChange("Inserted", row.toArray()[0]);
969
+ }
970
+ }
971
+ }
872
972
  handleChange(changedInstanceOps, changeType, id) {
873
973
  // if changeType is a delete and we already have the id in the inserts then we can remove the id from the inserts.
874
974
  // if changeType is a delete and we already have the id in the updates then we can remove the id from the updates AND add it to the deletes.
@@ -893,12 +993,12 @@ class ChangedInstanceIds {
893
993
  }
894
994
  /**
895
995
  * Initializes a new ChangedInstanceIds object with information taken from a range of changesets.
996
+ * @public
896
997
  */
897
998
  static async initialize(opts) {
898
999
  if ("changedInstanceIds" in opts)
899
1000
  return opts.changedInstanceIds;
900
1001
  const iModelId = opts.iModel.iModelId;
901
- const accessToken = opts.accessToken;
902
1002
  const startChangeset = "startChangeset" in opts ? opts.startChangeset : undefined;
903
1003
  const changesetRanges = startChangeset !== undefined
904
1004
  ? [
@@ -909,13 +1009,11 @@ class ChangedInstanceIds {
909
1009
  changeset: {
910
1010
  id: startChangeset.id ?? opts.iModel.changeset.id,
911
1011
  },
912
- accessToken,
913
1012
  })).index,
914
1013
  opts.iModel.changeset.index ??
915
1014
  (await core_backend_1.IModelHost.hubAccess.queryChangeset({
916
1015
  iModelId,
917
1016
  changeset: { id: opts.iModel.changeset.id },
918
- accessToken,
919
1017
  })).index,
920
1018
  ],
921
1019
  ]
@@ -924,7 +1022,6 @@ class ChangedInstanceIds {
924
1022
  : undefined;
925
1023
  const csFileProps = changesetRanges !== undefined
926
1024
  ? (await Promise.all(changesetRanges.map(async ([first, end]) => core_backend_1.IModelHost.hubAccess.downloadChangesets({
927
- accessToken,
928
1025
  iModelId,
929
1026
  range: { first, end },
930
1027
  targetDir: core_backend_1.BriefcaseManager.getChangeSetsPath(iModelId),
@@ -935,10 +1032,6 @@ class ChangedInstanceIds {
935
1032
  if (csFileProps === undefined)
936
1033
  return undefined;
937
1034
  const changedInstanceIds = new ChangedInstanceIds(opts.iModel);
938
- const relationshipECClassIdsToSkip = new Set();
939
- for await (const row of opts.iModel.createQueryReader("SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (BisCore.ElementDrivesElement)")) {
940
- relationshipECClassIdsToSkip.add(row.ECInstanceId);
941
- }
942
1035
  for (const csFile of csFileProps) {
943
1036
  const csReader = core_backend_1.SqliteChangesetReader.openFile({
944
1037
  fileName: csFile.pathname,
@@ -952,9 +1045,6 @@ class ChangedInstanceIds {
952
1045
  }
953
1046
  const changes = [...ecChangeUnifier.instances];
954
1047
  for (const change of changes) {
955
- if (change.ECClassId !== undefined &&
956
- relationshipECClassIdsToSkip.has(change.ECClassId))
957
- continue;
958
1048
  await changedInstanceIds.addChange(change);
959
1049
  }
960
1050
  csReader.close();