@itwin/core-backend 5.7.0-dev.9 → 5.8.0-dev.2

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 (104) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/lib/cjs/BriefcaseManager.d.ts +138 -1
  3. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  4. package/lib/cjs/BriefcaseManager.js +336 -1
  5. package/lib/cjs/BriefcaseManager.js.map +1 -1
  6. package/lib/cjs/CloudSqlite.js +1 -1
  7. package/lib/cjs/CloudSqlite.js.map +1 -1
  8. package/lib/cjs/IModelDb.d.ts +71 -0
  9. package/lib/cjs/IModelDb.d.ts.map +1 -1
  10. package/lib/cjs/IModelDb.js +122 -6
  11. package/lib/cjs/IModelDb.js.map +1 -1
  12. package/lib/cjs/IModelHost.d.ts +15 -0
  13. package/lib/cjs/IModelHost.d.ts.map +1 -1
  14. package/lib/cjs/IModelHost.js +12 -0
  15. package/lib/cjs/IModelHost.js.map +1 -1
  16. package/lib/cjs/IModelJsFs.d.ts +2 -0
  17. package/lib/cjs/IModelJsFs.d.ts.map +1 -1
  18. package/lib/cjs/IModelJsFs.js +2 -0
  19. package/lib/cjs/IModelJsFs.js.map +1 -1
  20. package/lib/cjs/TileStorage.js +1 -1
  21. package/lib/cjs/TileStorage.js.map +1 -1
  22. package/lib/cjs/TxnManager.d.ts +39 -0
  23. package/lib/cjs/TxnManager.d.ts.map +1 -1
  24. package/lib/cjs/TxnManager.js +149 -0
  25. package/lib/cjs/TxnManager.js.map +1 -1
  26. package/lib/cjs/ViewDefinition.d.ts.map +1 -1
  27. package/lib/cjs/ViewDefinition.js +2 -0
  28. package/lib/cjs/ViewDefinition.js.map +1 -1
  29. package/lib/cjs/internal/IModelDbFontsImpl.js +1 -1
  30. package/lib/cjs/internal/IModelDbFontsImpl.js.map +1 -1
  31. package/lib/cjs/internal/IntegrityCheck.d.ts +240 -0
  32. package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -0
  33. package/lib/cjs/internal/IntegrityCheck.js +193 -0
  34. package/lib/cjs/internal/IntegrityCheck.js.map +1 -0
  35. package/lib/cjs/internal/annotations/fields.js +2 -2
  36. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  37. package/lib/cjs/rpc/tracing.js +2 -2
  38. package/lib/cjs/rpc/tracing.js.map +1 -1
  39. package/lib/cjs/workspace/Workspace.js +1 -1
  40. package/lib/cjs/workspace/Workspace.js.map +1 -1
  41. package/lib/esm/BriefcaseManager.d.ts +138 -1
  42. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  43. package/lib/esm/BriefcaseManager.js +336 -1
  44. package/lib/esm/BriefcaseManager.js.map +1 -1
  45. package/lib/esm/CloudSqlite.js +1 -1
  46. package/lib/esm/CloudSqlite.js.map +1 -1
  47. package/lib/esm/IModelDb.d.ts +71 -0
  48. package/lib/esm/IModelDb.d.ts.map +1 -1
  49. package/lib/esm/IModelDb.js +122 -6
  50. package/lib/esm/IModelDb.js.map +1 -1
  51. package/lib/esm/IModelHost.d.ts +15 -0
  52. package/lib/esm/IModelHost.d.ts.map +1 -1
  53. package/lib/esm/IModelHost.js +12 -0
  54. package/lib/esm/IModelHost.js.map +1 -1
  55. package/lib/esm/IModelJsFs.d.ts +2 -0
  56. package/lib/esm/IModelJsFs.d.ts.map +1 -1
  57. package/lib/esm/IModelJsFs.js +2 -0
  58. package/lib/esm/IModelJsFs.js.map +1 -1
  59. package/lib/esm/TileStorage.js +1 -1
  60. package/lib/esm/TileStorage.js.map +1 -1
  61. package/lib/esm/TxnManager.d.ts +39 -0
  62. package/lib/esm/TxnManager.d.ts.map +1 -1
  63. package/lib/esm/TxnManager.js +150 -1
  64. package/lib/esm/TxnManager.js.map +1 -1
  65. package/lib/esm/ViewDefinition.d.ts.map +1 -1
  66. package/lib/esm/ViewDefinition.js +2 -0
  67. package/lib/esm/ViewDefinition.js.map +1 -1
  68. package/lib/esm/internal/IModelDbFontsImpl.js +1 -1
  69. package/lib/esm/internal/IModelDbFontsImpl.js.map +1 -1
  70. package/lib/esm/internal/IntegrityCheck.d.ts +240 -0
  71. package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -0
  72. package/lib/esm/internal/IntegrityCheck.js +187 -0
  73. package/lib/esm/internal/IntegrityCheck.js.map +1 -0
  74. package/lib/esm/internal/annotations/fields.js +2 -2
  75. package/lib/esm/internal/annotations/fields.js.map +1 -1
  76. package/lib/esm/rpc/tracing.js +2 -2
  77. package/lib/esm/rpc/tracing.js.map +1 -1
  78. package/lib/esm/test/SquashSchemaAndDataChanges.test.d.ts +2 -0
  79. package/lib/esm/test/SquashSchemaAndDataChanges.test.d.ts.map +1 -0
  80. package/lib/esm/test/SquashSchemaAndDataChanges.test.js +241 -0
  81. package/lib/esm/test/SquashSchemaAndDataChanges.test.js.map +1 -0
  82. package/lib/esm/test/ecdb/ECSqlQuery.test.js +13 -2
  83. package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
  84. package/lib/esm/test/hubaccess/Rebase.test.js +1575 -1568
  85. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
  86. package/lib/esm/test/hubaccess/SemanticRebase.test.d.ts +2 -0
  87. package/lib/esm/test/hubaccess/SemanticRebase.test.d.ts.map +1 -0
  88. package/lib/esm/test/hubaccess/SemanticRebase.test.js +1206 -0
  89. package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -0
  90. package/lib/esm/test/imodel/IModel.test.js +1 -1
  91. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  92. package/lib/esm/test/standalone/ChangesetReader.test.js +173 -2
  93. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  94. package/lib/esm/test/standalone/IntegrityCheck.test.d.ts +2 -0
  95. package/lib/esm/test/standalone/IntegrityCheck.test.d.ts.map +1 -0
  96. package/lib/esm/test/standalone/IntegrityCheck.test.js +385 -0
  97. package/lib/esm/test/standalone/IntegrityCheck.test.js.map +1 -0
  98. package/lib/esm/test/standalone/ViewDefinition.test.js +14 -2
  99. package/lib/esm/test/standalone/ViewDefinition.test.js.map +1 -1
  100. package/lib/esm/test/standalone/Workspace.test.js +5 -0
  101. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  102. package/lib/esm/workspace/Workspace.js +1 -1
  103. package/lib/esm/workspace/Workspace.js.map +1 -1
  104. package/package.json +14 -14
@@ -5,6 +5,58 @@
5
5
  /** @packageDocumentation
6
6
  * @module iModels
7
7
  */
8
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
9
+ if (value !== null && value !== void 0) {
10
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
11
+ var dispose, inner;
12
+ if (async) {
13
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
14
+ dispose = value[Symbol.asyncDispose];
15
+ }
16
+ if (dispose === void 0) {
17
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
18
+ dispose = value[Symbol.dispose];
19
+ if (async) inner = dispose;
20
+ }
21
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
22
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
23
+ env.stack.push({ value: value, dispose: dispose, async: async });
24
+ }
25
+ else if (async) {
26
+ env.stack.push({ async: true });
27
+ }
28
+ return value;
29
+ };
30
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
31
+ return function (env) {
32
+ function fail(e) {
33
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
34
+ env.hasError = true;
35
+ }
36
+ var r, s = 0;
37
+ function next() {
38
+ while (r = env.stack.pop()) {
39
+ try {
40
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
41
+ if (r.dispose) {
42
+ var result = r.dispose.call(r.value);
43
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
44
+ }
45
+ else s |= 1;
46
+ }
47
+ catch (e) {
48
+ fail(e);
49
+ }
50
+ }
51
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
52
+ if (env.hasError) throw env.error;
53
+ }
54
+ return next();
55
+ };
56
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
57
+ var e = new Error(message);
58
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
59
+ });
8
60
  // cspell:ignore cset csets ecchanges
9
61
  import * as path from "node:path";
10
62
  import * as os from "node:os";
@@ -19,6 +71,8 @@ import { SchemaSync } from "./SchemaSync";
19
71
  import { _hubAccess, _nativeDb, _releaseAllLocks } from "./internal/Symbols";
20
72
  import { IModelNative } from "./internal/NativePlatform";
21
73
  import { StashManager } from "./StashManager";
74
+ import { ChangesetECAdaptor, ECChangeUnifierCache, PartialECChangeUnifier } from "./ChangesetECAdaptor";
75
+ import { SqliteChangesetReader } from "./SqliteChangesetReader";
22
76
  const loggerCategory = BackendLoggerCategory.IModelDb;
23
77
  /** Manages downloading Briefcases and downloading and uploading changesets.
24
78
  * @public
@@ -229,6 +283,8 @@ export class BriefcaseManager {
229
283
  briefcaseId: db.getBriefcaseId(),
230
284
  };
231
285
  db.closeFile();
286
+ if (this.isValidBriefcaseId(briefcase.briefcaseId))
287
+ this.cleanupRebaseFolders(filePath, briefcase.briefcaseId); // cleanup rebase folders
232
288
  if (accessToken) {
233
289
  if (this.isValidBriefcaseId(briefcase.briefcaseId)) {
234
290
  await BriefcaseManager.releaseBriefcase(accessToken, briefcase);
@@ -462,10 +518,24 @@ export class BriefcaseManager {
462
518
  Logger.logInfo(loggerCategory, `Creating restore point ${this.PULL_MERGE_RESTORE_POINT_NAME}`);
463
519
  await this.createRestorePoint(briefcaseDb, this.PULL_MERGE_RESTORE_POINT_NAME);
464
520
  }
521
+ const hasIncomingSchemaChange = changesets.some((changeset) => changeset.changesType === ChangesetType.Schema);
522
+ const hasLocalSchemaTxn = briefcaseDb?.checkIfSchemaTxnExists() ?? false;
523
+ const useSemanticRebase = briefcaseDb !== undefined &&
524
+ IModelHost.useSemanticRebase &&
525
+ (hasIncomingSchemaChange || hasLocalSchemaTxn);
526
+ if (useSemanticRebase) {
527
+ Logger.logInfo(loggerCategory, `Using semantic rebase (incoming schema change: ${hasIncomingSchemaChange}, local schema txn: ${hasLocalSchemaTxn})`);
528
+ }
465
529
  if (!reverse) {
466
530
  if (briefcaseDb) {
531
+ if (useSemanticRebase) {
532
+ this.capturePatchInstances(briefcaseDb);
533
+ }
467
534
  briefcaseDb.txns.rebaser.notifyReverseLocalChangesBegin();
468
535
  const reversedTxns = nativeDb.pullMergeReverseLocalChanges();
536
+ if (useSemanticRebase) {
537
+ nativeDb.clearECDbCache(); // Clear the ECDb cache after reversing local changes to ensure consistency during semantic rebase with schema changes.
538
+ }
469
539
  const reversedTxnProps = reversedTxns.map((txn) => briefcaseDb.txns.getTxnProps(txn)).filter((props) => props !== undefined);
470
540
  briefcaseDb.txns.rebaser.notifyReverseLocalChangesEnd(reversedTxnProps);
471
541
  Logger.logInfo(loggerCategory, `Reversed ${reversedTxns.length} local changes`);
@@ -498,7 +568,10 @@ export class BriefcaseManager {
498
568
  }
499
569
  if (!reverse) {
500
570
  if (briefcaseDb) {
501
- await briefcaseDb.txns.rebaser.resume();
571
+ if (useSemanticRebase)
572
+ await briefcaseDb.txns.rebaser.resumeSemantic();
573
+ else
574
+ await briefcaseDb.txns.rebaser.resume();
502
575
  }
503
576
  else {
504
577
  // Only Briefcase has change management. Following is
@@ -678,5 +751,267 @@ export class BriefcaseManager {
678
751
  }
679
752
  }
680
753
  }
754
+ // #region Semantic Rebase Interop Helper
755
+ static REBASING_FOLDER = ".rebasing";
756
+ static EC_FOLDER = "ec";
757
+ static SCHEMAS_FOLDER = "schemas";
758
+ static DATA_FOLDER = "data";
759
+ static DATA_FILE_NAME = "data.json";
760
+ /**
761
+ * Captures the changed instances as patch instances from each data txn in the briefcase db for semantic rebase
762
+ * @param db The {@link BriefcaseDb} instance for which to capture the changed instances as patch instances for all data txns
763
+ * @internal
764
+ */
765
+ static capturePatchInstances(db) {
766
+ const txns = Array.from(db.txns.queryTxns());
767
+ txns.forEach((txn) => {
768
+ if (txn.type !== "Data")
769
+ return;
770
+ // already captured(This actually shows that first rebase operation is already done but during that while reinstating this txns,
771
+ // some error happened so the folder still exists so we don't want to capture again)
772
+ if (this.semanticRebaseDataFolderExists(db, txn.id))
773
+ return;
774
+ const changedInstances = this.captureChangedInstancesAsJSON(db, txn.id);
775
+ const instancePatches = this.constructPatchInstances(db, changedInstances);
776
+ this.storeChangedInstancesForSemanticRebase(db, txn.id, instancePatches);
777
+ });
778
+ }
779
+ /**
780
+ * Captures changed instances from a txn as JSON
781
+ * @param txnId The txn id for which to capture changed instances
782
+ * @param db The {@link BriefcaseDb} instance from which to capture changed instances as json
783
+ * @returns changed instances for semantic rebase
784
+ * @internal
785
+ */
786
+ static captureChangedInstancesAsJSON(db, txnId) {
787
+ const env_1 = { stack: [], error: void 0, hasError: false };
788
+ try {
789
+ const reader = SqliteChangesetReader.openTxn({
790
+ txnId, db, disableSchemaCheck: true
791
+ });
792
+ const adaptor = new ChangesetECAdaptor(reader);
793
+ const indirectUnifier = __addDisposableResource(env_1, new PartialECChangeUnifier(reader.db, ECChangeUnifierCache.createInMemoryCache()), false);
794
+ const directUnifier = __addDisposableResource(env_1, new PartialECChangeUnifier(reader.db, ECChangeUnifierCache.createInMemoryCache()), false);
795
+ while (adaptor.step()) {
796
+ if (adaptor.reader.isIndirect)
797
+ indirectUnifier.appendFrom(adaptor);
798
+ else
799
+ directUnifier.appendFrom(adaptor);
800
+ }
801
+ return [...Array.from(directUnifier.instances).map((instance) => ({ isIndirect: false, instance })), ...Array.from(indirectUnifier.instances).map((instance) => ({ isIndirect: true, instance }))];
802
+ }
803
+ catch (e_1) {
804
+ env_1.error = e_1;
805
+ env_1.hasError = true;
806
+ }
807
+ finally {
808
+ __disposeResources(env_1);
809
+ }
810
+ }
811
+ /**
812
+ * Constructs patch instances from changed instances
813
+ * @param changedInstances The changed instances from which to construct the patch instances
814
+ * @param db The {@link BriefcaseDb} instance for which to construct the patch instances
815
+ * @returns The {@link InstancePatch} instance patches for semantic rebase
816
+ * @internal
817
+ */
818
+ static constructPatchInstances(db, changedInstances) {
819
+ return changedInstances
820
+ .filter((changedInstance) => !(changedInstance.instance.$meta?.op === "Updated" && changedInstance.instance.$meta.stage === "Old")) // we will not take the old stage of updated instances
821
+ .map((changedInstance) => this.constructPatchInstance(db, changedInstance));
822
+ }
823
+ /**
824
+ * Constructs a single patch instance from changed instance
825
+ * @param changedInstance The changed instance from which to construct the patch instance
826
+ * @param db The {@link BriefcaseDb} instance for which to construct the single patch instance
827
+ * @returns a single instance patch {@link InstancePatch}
828
+ * @throws IModelError If cannot determine classId or unknown operation encountered
829
+ */
830
+ static constructPatchInstance(db, changedInstance) {
831
+ const className = (changedInstance.instance.ECClassId && db.getClassNameFromId(changedInstance.instance.ECClassId))
832
+ ?? changedInstance.instance.$meta?.classFullName
833
+ ?? (changedInstance.instance.$meta?.fallbackClassId && db.getClassNameFromId(changedInstance.instance.$meta.fallbackClassId));
834
+ if (!className)
835
+ throw new IModelError(IModelStatus.BadArg, "Cannot determine classId of changed instance");
836
+ const instanceKey = { id: changedInstance.instance.ECInstanceId, classFullName: className };
837
+ const op = changedInstance.instance.$meta?.op;
838
+ if (op !== "Inserted" && op !== "Updated" && op !== "Deleted")
839
+ throw new IModelError(IModelStatus.BadArg, `Unknown operation: ${op}`);
840
+ return {
841
+ key: instanceKey,
842
+ op,
843
+ isIndirect: changedInstance.isIndirect,
844
+ props: op !== "Deleted" ? db[_nativeDb].readInstance(instanceKey, { useJsNames: true }) : undefined,
845
+ };
846
+ }
847
+ /**
848
+ * Stores changed instances for semantic rebase locally in appropriate json file in a folder structure
849
+ * @param db The {@link BriefcaseDb} instance for storing the changed instances against a txn
850
+ * @param txnId The txn id for which we are storing the changed instances
851
+ * @param instancePatches The {@link InstancePatch} instance patches to be stored
852
+ * @internal
853
+ */
854
+ static storeChangedInstancesForSemanticRebase(db, txnId, instancePatches) {
855
+ const basePath = this.getBasePathForSemanticRebaseLocalFiles(db);
856
+ const targetDir = path.join(basePath, txnId, this.DATA_FOLDER);
857
+ const filePath = path.join(targetDir, this.DATA_FILE_NAME);
858
+ if (IModelJsFs.existsSync(targetDir))
859
+ IModelJsFs.removeSync(targetDir);
860
+ IModelJsFs.recursiveMkDirSync(targetDir);
861
+ IModelJsFs.writeFileSync(filePath, JSON.stringify(instancePatches, undefined, 2));
862
+ }
863
+ /**
864
+ * Gets the base path for semantic rebase local files
865
+ * @param db The {@link BriefcaseDb} instance for which to get the base path
866
+ * @returns base path for semantic rebase local files
867
+ * @internal
868
+ */
869
+ static getBasePathForSemanticRebaseLocalFiles(db) {
870
+ return path.join(path.dirname(db.pathName), this.REBASING_FOLDER, db.briefcaseId.toString(), this.EC_FOLDER);
871
+ }
872
+ /**
873
+ * Stores schemas for semantic rebase locally in appropriate folder structure
874
+ * @param db The {@link BriefcaseDb} instance for storing the schemas against a txn
875
+ * @param txnId The txn id for which we are storing the schemas
876
+ * @param schemaFileNames The schema file paths or schema xml strings to be stored
877
+ * @internal
878
+ */
879
+ static storeSchemasForSemanticRebase(db, txnId, schemaFileNames) {
880
+ const basePath = this.getBasePathForSemanticRebaseLocalFiles(db);
881
+ const targetDir = path.join(basePath, txnId, this.SCHEMAS_FOLDER);
882
+ if (IModelJsFs.existsSync(targetDir))
883
+ IModelJsFs.removeSync(targetDir);
884
+ IModelJsFs.recursiveMkDirSync(targetDir);
885
+ schemaFileNames.forEach((schemaFileOrXml, index) => {
886
+ if (IModelJsFs.existsSync(schemaFileOrXml)) { // This means it is a file
887
+ const fileName = path.basename(schemaFileOrXml);
888
+ const filePath = path.join(targetDir, fileName);
889
+ IModelJsFs.copySync(schemaFileOrXml, filePath);
890
+ }
891
+ else {
892
+ const fileName = `${"Schema"}_${index}.ecschema.xml`;
893
+ const filePath = path.join(targetDir, fileName);
894
+ IModelJsFs.writeFileSync(filePath, schemaFileOrXml);
895
+ }
896
+ });
897
+ }
898
+ /**
899
+ * Gets schemas for semantic rebase for a txn
900
+ * @param db The {@link BriefcaseDb} instance for getting the locally stored schemas against a txn
901
+ * @param txnId The txn id for which we are getting the schemas
902
+ * @returns the schema file paths
903
+ * @internal
904
+ */
905
+ static getSchemasForTxn(db, txnId) {
906
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
907
+ const folderPath = path.join(basePath, txnId, BriefcaseManager.SCHEMAS_FOLDER);
908
+ return IModelJsFs.readdirSync(folderPath).map((file) => path.join(folderPath, file));
909
+ }
910
+ /**
911
+ * Get the changed instances data for semantic rebase for a txn
912
+ * @param db - The {@link BriefcaseDb} instance for getting the locally stored changed instances against a txn
913
+ * @param txnId - The txn id for which we are getting the changed instances
914
+ * @returns Instance patches
915
+ * @internal
916
+ */
917
+ static getChangedInstancesDataForTxn(db, txnId) {
918
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
919
+ const folderPath = path.join(basePath, txnId, BriefcaseManager.DATA_FOLDER);
920
+ const filePath = path.join(folderPath, BriefcaseManager.DATA_FILE_NAME);
921
+ const fileContents = IModelJsFs.readFileWithEncodingSync(filePath, "utf-8");
922
+ return JSON.parse(fileContents);
923
+ }
924
+ /**
925
+ * Checks if schema folder exists for semantic rebase for a txn
926
+ * @param db - The {@link BriefcaseDb} instance for which TO check the schema folder
927
+ * @param txnId - The txn id for which we are check the schema folder
928
+ * @returns true if exists, false otherwise
929
+ * @internal
930
+ */
931
+ static semanticRebaseSchemaFolderExists(db, txnId) {
932
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
933
+ const folderPath = path.join(basePath, txnId, BriefcaseManager.SCHEMAS_FOLDER);
934
+ return IModelJsFs.existsSync(folderPath);
935
+ }
936
+ /**
937
+ * Checks if data folder exists for semantic rebase for a txn
938
+ * @param db The {@link BriefcaseDb} instance for which to check the data folder.
939
+ * @param txnId The txn id for which to check the data folder
940
+ * @returns true if exists, false otherwise
941
+ * @internal
942
+ */
943
+ static semanticRebaseDataFolderExists(db, txnId) {
944
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
945
+ const folderPath = path.join(basePath, txnId, BriefcaseManager.DATA_FOLDER);
946
+ return IModelJsFs.existsSync(folderPath);
947
+ }
948
+ /**
949
+ * Deletes the schema folder for semantic rebase for a txn
950
+ * @param db The {@link BriefcaseDb} instance for which to delete the schema folder.
951
+ * @param txnId The txn id for which to delete the schema folder
952
+ * @internal
953
+ */
954
+ static deleteTxnSchemaFolder(db, txnId) {
955
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
956
+ const txnFolderPath = path.join(basePath, txnId);
957
+ const folderPath = path.join(txnFolderPath, BriefcaseManager.SCHEMAS_FOLDER);
958
+ if (!IModelJsFs.existsSync(folderPath))
959
+ return;
960
+ IModelJsFs.removeSync(folderPath);
961
+ if (IModelJsFs.readdirSync(txnFolderPath).length === 0) // Also delete the txn folder if empty
962
+ IModelJsFs.removeSync(txnFolderPath);
963
+ }
964
+ /**
965
+ * Deletes the data folder for semantic rebase for a txn
966
+ * @param db The {@link BriefcaseDb} instance for which to delete the data folder.
967
+ * @param txnId The txn id for which to delete the data folder
968
+ * @internal
969
+ */
970
+ static deleteTxnDataFolder(db, txnId) {
971
+ const basePath = BriefcaseManager.getBasePathForSemanticRebaseLocalFiles(db);
972
+ const txnFolderPath = path.join(basePath, txnId);
973
+ const folderPath = path.join(txnFolderPath, BriefcaseManager.DATA_FOLDER);
974
+ if (!IModelJsFs.existsSync(folderPath))
975
+ return;
976
+ IModelJsFs.removeSync(folderPath);
977
+ if (IModelJsFs.readdirSync(txnFolderPath).length === 0) // Also delete the txn folder if empty
978
+ IModelJsFs.removeSync(txnFolderPath);
979
+ }
980
+ /**
981
+ * Deletes rebase folders for semantic rebase
982
+ * @param db The {@link BriefcaseDb} instance for which to delete the rebase folders.
983
+ * @param checkIfEmpty If true, only deletes the base folder if it is empty, default is false
984
+ * @internal
985
+ */
986
+ static deleteRebaseFolders(db, checkIfEmpty = false) {
987
+ const briefcaseRebasingRoot = path.join(path.dirname(db.pathName), this.REBASING_FOLDER, db.briefcaseId.toString());
988
+ if (!IModelJsFs.existsSync(briefcaseRebasingRoot))
989
+ return;
990
+ if (checkIfEmpty) {
991
+ const basePath = this.getBasePathForSemanticRebaseLocalFiles(db);
992
+ if (IModelJsFs.existsSync(basePath) && IModelJsFs.readdirSync(basePath).length > 0)
993
+ return;
994
+ }
995
+ IModelJsFs.removeSync(briefcaseRebasingRoot);
996
+ // remove .rebasing root if it's now empty
997
+ const rebasingRoot = path.join(path.dirname(db.pathName), this.REBASING_FOLDER);
998
+ if (IModelJsFs.existsSync(rebasingRoot) && IModelJsFs.readdirSync(rebasingRoot).length === 0)
999
+ IModelJsFs.removeSync(rebasingRoot);
1000
+ }
1001
+ /**
1002
+ * Cleans up rebase folders for semantic rebase given briefcase file path and briefcase id
1003
+ * @param briefcaseFilePath The briefcase file path
1004
+ * @param briefcaseId The briefcase id
1005
+ * @internal
1006
+ */
1007
+ static cleanupRebaseFolders(briefcaseFilePath, briefcaseId) {
1008
+ const briefcaseRebasingRoot = path.join(path.dirname(briefcaseFilePath), this.REBASING_FOLDER, briefcaseId.toString());
1009
+ if (IModelJsFs.existsSync(briefcaseRebasingRoot))
1010
+ IModelJsFs.removeSync(briefcaseRebasingRoot);
1011
+ // remove .rebasing root if it's now empty
1012
+ const rebasingRoot = path.join(path.dirname(briefcaseFilePath), this.REBASING_FOLDER);
1013
+ if (IModelJsFs.existsSync(rebasingRoot) && IModelJsFs.readdirSync(rebasingRoot).length === 0)
1014
+ IModelJsFs.removeSync(rebasingRoot);
1015
+ }
681
1016
  }
682
1017
  //# sourceMappingURL=BriefcaseManager.js.map