@itwin/imodel-transformer 1.0.0-dev.13 → 1.0.0-dev.14

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.
@@ -172,7 +172,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
172
172
  if (this._isProvenanceInitTransform) {
173
173
  return "forward";
174
174
  }
175
- if (!this._isSynchronization) {
175
+ if (!this._options.argsForProcessChanges) {
176
176
  return "not-sync";
177
177
  }
178
178
  try {
@@ -224,7 +224,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
224
224
  this._elementsWithExplicitlyTrackedProvenance = new Set();
225
225
  /** map of partially committed entities to their partial commit progress */
226
226
  this._partiallyCommittedEntities = new EntityMap_1.EntityMap();
227
- this._isSynchronization = false;
228
227
  /**
229
228
  * A private variable meant to be set by tests which have an outdated way of setting up transforms. In all synchronizations today we expect to find an ESA in the branch db which describes the master -> branch relationship.
230
229
  * The exception to this is the first transform aka the provenance initializing transform which requires that the master imodel and the branch imodel are identical at the time of provenance initialization.
@@ -278,6 +277,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
278
277
  branchRelationshipDataBehavior: options?.branchRelationshipDataBehavior ?? "reject",
279
278
  skipPropagateChangesToRootElements: options?.skipPropagateChangesToRootElements ?? true,
280
279
  };
280
+ // check if authorization client is defined
281
+ if (core_backend_1.IModelHost.authorizationClient === undefined) {
282
+ core_bentley_1.Logger.logWarning(loggerCategory, "Authorization client is not set in IModelHost. If the transformer needs an accessToken, then it will fail.");
283
+ }
281
284
  this._isProvenanceInitTransform = this._options
282
285
  .wasSourceIModelCopiedToTarget
283
286
  ? true
@@ -361,9 +364,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
361
364
  core_bentley_1.Logger.logInfo(loggerCategory, `this._includeSourceProvenance=${this._options.includeSourceProvenance}`);
362
365
  core_bentley_1.Logger.logInfo(loggerCategory, `this._cloneUsingBinaryGeometry=${this._options.cloneUsingBinaryGeometry}`);
363
366
  core_bentley_1.Logger.logInfo(loggerCategory, `this._wasSourceIModelCopiedToTarget=${this._options.wasSourceIModelCopiedToTarget}`);
364
- core_bentley_1.Logger.logInfo(loggerCategory,
365
- // eslint-disable-next-line deprecation/deprecation
366
- `this._isReverseSynchronization=${this._options.isReverseSynchronization}`);
367
367
  core_bentley_1.Logger.logInfo(TransformerLoggerCategory_1.TransformerLoggerCategory.IModelImporter, `this.importer.autoExtendProjectExtents=${JSON.stringify(this.importer.options.autoExtendProjectExtents)}`);
368
368
  core_bentley_1.Logger.logInfo(TransformerLoggerCategory_1.TransformerLoggerCategory.IModelImporter, `this.importer.simplifyElementGeometry=${this.importer.options.simplifyElementGeometry}`);
369
369
  }
@@ -606,8 +606,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
606
606
  let madeChange = false;
607
607
  if (this._options.branchRelationshipDataBehavior !== "unsafe-migrate")
608
608
  return madeChange;
609
- const fallbackSyncVersionToUse = this._options.unsafeFallbackSyncVersion ?? "";
610
- const fallbackReverseSyncVersionToUse = this._options.unsafeFallbackReverseSyncVersion ?? "";
609
+ const fallbackSyncVersionToUse = this._options.argsForProcessChanges?.unsafeFallbackSyncVersion ?? "";
610
+ const fallbackReverseSyncVersionToUse = this._options.argsForProcessChanges?.unsafeFallbackReverseSyncVersion ??
611
+ "";
611
612
  if (aspectProps.version === undefined ||
612
613
  (aspectProps.version === "" &&
613
614
  aspectProps.version !== fallbackSyncVersionToUse)) {
@@ -867,7 +868,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
867
868
  }
868
869
  /** Returns `true` if *brute force* delete detections should be run.
869
870
  * @note This is only called if [[IModelTransformOptions.forceExternalSourceAspectProvenance]] option is true
870
- * @note Not relevant for processChanges when change history is known.
871
+ * @note Not relevant for [[process]] when [[IModelTransformOptions.argsForProcessChanges]] are provided and change history is known.
871
872
  */
872
873
  shouldDetectDeletes() {
873
874
  nodeAssert(this._syncType !== undefined);
@@ -877,9 +878,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
877
878
  * Detect Element deletes using ExternalSourceAspects in the target iModel and a *brute force* comparison against Elements
878
879
  * in the source iModel.
879
880
  * @deprecated in 1.x. Do not use this. // FIXME<MIKE>: how to better explain this?
880
- * This method is only called during [[processAll]] when the option
881
+ * This method is only called during [[process]] when [[IModelTransformOptions.argsForProcessChanges]] is undefined and the option
881
882
  * [[IModelTransformOptions.forceExternalSourceAspectProvenance]] is enabled. It is not
882
- * necessary when using [[processChanges]] since changeset information is sufficient.
883
+ * necessary when calling [[process]] with [[IModelTransformOptions.argsForProcessChanges]] defined, since changeset information is sufficient.
883
884
  * @note you do not need to call this directly unless processing a subset of an iModel.
884
885
  * @throws [[IModelError]] If the required provenance information is not available to detect deletes.
885
886
  */
@@ -1037,7 +1038,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1037
1038
  }
1038
1039
  /** Cause the specified Element and its child Elements (if applicable) to be exported from the source iModel and imported into the target iModel.
1039
1040
  * @param sourceElementId Identifies the Element from the source iModel to import.
1040
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1041
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1041
1042
  */
1042
1043
  async processElement(sourceElementId) {
1043
1044
  await this.initialize();
@@ -1048,7 +1049,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1048
1049
  }
1049
1050
  /** Import child elements into the target IModelDb
1050
1051
  * @param sourceElementId Import the child elements of this element in the source IModelDb.
1051
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1052
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1052
1053
  */
1053
1054
  async processChildElements(sourceElementId) {
1054
1055
  await this.initialize();
@@ -1333,7 +1334,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1333
1334
  }
1334
1335
  /** Cause the model container, contents, and sub-models to be exported from the source iModel and imported into the target iModel.
1335
1336
  * @param sourceModeledElementId Import this [Model]($backend) from the source IModelDb.
1336
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1337
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1337
1338
  */
1338
1339
  async processModel(sourceModeledElementId) {
1339
1340
  await this.initialize();
@@ -1343,7 +1344,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1343
1344
  * @param sourceModelId Import the contents of this model from the source IModelDb.
1344
1345
  * @param targetModelId Import into this model in the target IModelDb. The target model must exist prior to this call.
1345
1346
  * @param elementClassFullName Optional classFullName of an element subclass to limit import query against the source model.
1346
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1347
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1347
1348
  */
1348
1349
  async processModelContents(sourceModelId, targetModelId, elementClassFullName = core_backend_1.Element.classFullName) {
1349
1350
  await this.initialize();
@@ -1409,9 +1410,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1409
1410
  * source's changeset has been performed. Also stores all changesets that occurred
1410
1411
  * during the transformation as "pending synchronization changeset indices" @see TargetScopeProvenanceJsonProps
1411
1412
  *
1412
- * You generally should not call this function yourself and use [[processChanges]] instead.
1413
+ * You generally should not call this function yourself and use [[process]] with [[IModelTransformOptions.argsForProcessChanges]] provided instead.
1413
1414
  * It is public for unsupported use cases of custom synchronization transforms.
1414
- * @note if you are not running processChanges in this transformation, this will fail
1415
+ * @note if [[IModelTransformOptions.argsForProcessChanges]] are not defined in this transformation, this will fail
1415
1416
  * without setting the `force` option to `true`
1416
1417
  */
1417
1418
  updateSynchronizationVersion({ force = false } = {}) {
@@ -1438,7 +1439,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1438
1439
  core_bentley_1.Logger.logInfo(loggerCategory, `updating sync version from ${this._targetScopeProvenanceProps.version} to ${sourceVersion}`);
1439
1440
  this._targetScopeProvenanceProps.version = sourceVersion;
1440
1441
  }
1441
- if (this._isSynchronization ||
1442
+ if (this._options.argsForProcessChanges ||
1442
1443
  (this._startingChangesetIndices && this._isProvenanceInitTransform)) {
1443
1444
  nodeAssert(this.targetDb.changeset.index !== undefined &&
1444
1445
  this._startingChangesetIndices !== undefined, "updateSynchronizationVersion was called without change history");
@@ -1515,7 +1516,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1515
1516
  }
1516
1517
  /** Imports all relationships that subclass from the specified base class.
1517
1518
  * @param baseRelClassFullName The specified base relationship class.
1518
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1519
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1519
1520
  */
1520
1521
  async processRelationships(baseRelClassFullName) {
1521
1522
  await this.initialize();
@@ -1588,8 +1589,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1588
1589
  }
1589
1590
  /** Detect Relationship deletes using ExternalSourceAspects in the target iModel and a *brute force* comparison against relationships in the source iModel.
1590
1591
  * @deprecated in 1.x. Don't use this anymore
1591
- * @see processChanges
1592
- * @note This method is called from [[processAll]] and is not needed by [[processChanges]], so it only needs to be called directly when processing a subset of an iModel.
1592
+ * @see [[process]] with [[IModelTransformOptions.argsForProcessChanges]] provided.
1593
+ * @note This method is called from [[process]] when [[IModelTransformOptions.argsForProcessChanges]] are undefined, so it only needs to be called directly when processing a subset of an iModel.
1593
1594
  * @throws [[IModelError]] If the required provenance information is not available to detect deletes.
1594
1595
  */
1595
1596
  async detectRelationshipDeletes() {
@@ -1771,7 +1772,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1771
1772
  }
1772
1773
  }
1773
1774
  /** Cause all fonts to be exported from the source iModel and imported into the target iModel.
1774
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1775
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1775
1776
  */
1776
1777
  async processFonts() {
1777
1778
  // we do not need to initialize for this since no entities are exported
@@ -1783,14 +1784,14 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1783
1784
  this.context.importFont(font.id);
1784
1785
  }
1785
1786
  /** Cause all CodeSpecs to be exported from the source iModel and imported into the target iModel.
1786
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1787
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1787
1788
  */
1788
1789
  async processCodeSpecs() {
1789
1790
  await this.initialize();
1790
1791
  return this.exporter.exportCodeSpecs();
1791
1792
  }
1792
1793
  /** Cause a single CodeSpec to be exported from the source iModel and imported into the target iModel.
1793
- * @note This method is called from [[processChanges]] and [[processAll]], so it only needs to be called directly when processing a subset of an iModel.
1794
+ * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
1794
1795
  */
1795
1796
  async processCodeSpec(codeSpecName) {
1796
1797
  await this.initialize();
@@ -1818,17 +1819,18 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1818
1819
  }
1819
1820
  /**
1820
1821
  * Initialize prerequisites of processing, you must initialize with an [[InitOptions]] if you
1821
- * are intending to process changes, but prefer using [[processChanges]] explicitly since it calls this.
1822
+ * are intending to process changes. Callers may wish to explicitly call initialize if they need to execute code after initialize but before [[process]] is called.
1822
1823
  * @note Called by all `process*` functions implicitly.
1823
1824
  * Overriders must call `super.initialize()` first
1824
1825
  */
1825
- async initialize(args) {
1826
+ async initialize() {
1826
1827
  if (this._initialized)
1827
1828
  return;
1828
- await this._tryInitChangesetData(args);
1829
+ this.initScopeProvenance();
1830
+ await this._tryInitChangesetData(this._options.argsForProcessChanges);
1829
1831
  await this.context.initialize();
1830
1832
  // need exporter initialized to do remapdeletedsourceentities.
1831
- await this.exporter.initialize(this.getExportInitOpts(args ?? {}));
1833
+ await this.exporter.initialize(this.getExportInitOpts(this._options.argsForProcessChanges ?? {}));
1832
1834
  // Exporter must be initialized prior to processing changesets in order to properly handle entity recreations (an entity delete followed by an insert of that same entity).
1833
1835
  await this.processChangesets();
1834
1836
  this._initialized = true;
@@ -2037,10 +2039,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
2037
2039
  this._csFileProps = [];
2038
2040
  return;
2039
2041
  }
2042
+ const startChangeset = "startChangeset" in args ? args.startChangeset : undefined;
2040
2043
  // NOTE: that we do NOT download the changesummary for the last transformed version, we want
2041
2044
  // to ignore those already processed changes
2042
- const startChangesetIndexOrId = args.startChangeset?.index ??
2043
- args.startChangeset?.id ??
2045
+ const startChangesetIndexOrId = startChangeset?.index ??
2046
+ startChangeset?.id ??
2044
2047
  this.synchronizationVersion.index + 1;
2045
2048
  const endChangesetId = this.sourceDb.changeset.id;
2046
2049
  const [startChangesetIndex, endChangesetIndex] = await Promise.all([startChangesetIndexOrId, endChangesetId].map(async (indexOrId) => typeof indexOrId === "number"
@@ -2050,11 +2053,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
2050
2053
  iModelId: this.sourceDb.iModelId,
2051
2054
  // eslint-disable-next-line deprecation/deprecation
2052
2055
  changeset: { id: indexOrId },
2053
- accessToken: args.accessToken,
2054
2056
  })
2055
2057
  .then((changeset) => changeset.index)));
2056
2058
  const missingChangesets = startChangesetIndex > this.synchronizationVersion.index + 1;
2057
- if (!this._options.ignoreMissingChangesetsInSynchronizations &&
2059
+ if (!this._options.argsForProcessChanges
2060
+ ?.ignoreMissingChangesetsInSynchronizations &&
2058
2061
  startChangesetIndex !== this.synchronizationVersion.index + 1 &&
2059
2062
  this.synchronizationVersion.index !== -1) {
2060
2063
  throw Error(`synchronization is ${missingChangesets ? "missing changesets" : ""},` +
@@ -2089,13 +2092,40 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
2089
2092
  this._sourceChangeDataState =
2090
2093
  this._csFileProps.length === 0 ? "no-changes" : "has-changes";
2091
2094
  }
2095
+ /**
2096
+ * The behavior of process is influenced by [[IModelTransformOptions.argsForProcessChanges]] being defined or not defined during construction passed of the IModelTransformer.
2097
+ * @section When argsForProcessChanges are defined:
2098
+ *
2099
+ * Export changes from the source iModel and import the transformed entities into the target iModel.
2100
+ * Inserts, updates, and deletes are determined by inspecting the changeset(s).
2101
+ *
2102
+ * Notes:
2103
+ * - the transformer assumes that you saveChanges after processing changes. You should not modify the iModel after processChanges until saveChanges,
2104
+ * failure to do so may result in corrupted
2105
+ * data loss in future branch operations
2106
+ * - if no startChangesetId or startChangeset option is provided as part of the ProcessChangesOptions, the next unsynchronized changeset
2107
+ * will automatically be determined and used
2108
+ * - To form a range of versions to process, set `startChangesetId` for the start (inclusive) of the desired range and open the source iModel as of the end (inclusive) of the desired range.
2109
+ *
2110
+ * @section When argsForProcessChanges are undefined:
2111
+ *
2112
+ * Export everything from the source iModel and import the transformed entities into the target iModel.
2113
+ *
2114
+ * Notes:
2115
+ * - [[processSchemas]] is not called automatically since the target iModel may want a different collection of schemas.
2116
+ *
2117
+ */
2118
+ async process() {
2119
+ await this.initialize();
2120
+ this.logSettings();
2121
+ return this._options.argsForProcessChanges !== undefined
2122
+ ? this.processChanges(this._options.argsForProcessChanges)
2123
+ : this.processAll();
2124
+ }
2092
2125
  /** Export everything from the source iModel and import the transformed entities into the target iModel.
2093
2126
  * @note [[processSchemas]] is not called automatically since the target iModel may want a different collection of schemas.
2094
2127
  */
2095
2128
  async processAll() {
2096
- this.logSettings();
2097
- this.initScopeProvenance();
2098
- await this.initialize();
2099
2129
  await this.exporter.exportCodeSpecs();
2100
2130
  await this.exporter.exportFonts();
2101
2131
  if (this._options.skipPropagateChangesToRootElements) {
@@ -2145,10 +2175,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
2145
2175
  * @note To form a range of versions to process, set `startChangesetId` for the start (inclusive) of the desired range and open the source iModel as of the end (inclusive) of the desired range.
2146
2176
  */
2147
2177
  async processChanges(options) {
2148
- this._isSynchronization = true;
2149
- this.initScopeProvenance();
2150
- this.logSettings();
2151
- await this.initialize(options);
2152
2178
  // must wait for initialization of synchronization provenance data
2153
2179
  await this.exporter.exportChanges(this.getExportInitOpts(options));
2154
2180
  await this.processDeferredElements(); // eslint-disable-line deprecation/deprecation
@@ -2165,17 +2191,17 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
2165
2191
  * Call [[IModelTransformer.initialize]] for initialization of synchronization provenance data
2166
2192
  */
2167
2193
  getExportInitOpts(opts) {
2168
- if (!this._isSynchronization)
2194
+ if (!this._options.argsForProcessChanges)
2169
2195
  return {};
2196
+ const startChangeset = "startChangeset" in opts ? opts.startChangeset : undefined;
2170
2197
  return {
2171
2198
  skipPropagateChangesToRootElements: this._options.skipPropagateChangesToRootElements,
2172
- accessToken: opts.accessToken,
2173
2199
  ...(this._csFileProps
2174
2200
  ? { csFileProps: this._csFileProps }
2175
2201
  : this._changesetRanges
2176
2202
  ? { changesetRanges: this._changesetRanges }
2177
- : opts.startChangeset
2178
- ? { startChangeset: opts.startChangeset }
2203
+ : startChangeset
2204
+ ? { startChangeset }
2179
2205
  : {
2180
2206
  startChangeset: {
2181
2207
  index: this.synchronizationVersion.index + 1,