@itwin/core-backend 5.2.0-dev.3 → 5.2.0-dev.31

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 (193) hide show
  1. package/CHANGELOG.md +79 -1
  2. package/lib/cjs/BackendHubAccess.d.ts +2 -0
  3. package/lib/cjs/BackendHubAccess.d.ts.map +1 -1
  4. package/lib/cjs/BackendHubAccess.js.map +1 -1
  5. package/lib/cjs/BackendLoggerCategory.d.ts +6 -0
  6. package/lib/cjs/BackendLoggerCategory.d.ts.map +1 -1
  7. package/lib/cjs/BackendLoggerCategory.js +6 -0
  8. package/lib/cjs/BackendLoggerCategory.js.map +1 -1
  9. package/lib/cjs/BriefcaseManager.d.ts +57 -3
  10. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  11. package/lib/cjs/BriefcaseManager.js +153 -44
  12. package/lib/cjs/BriefcaseManager.js.map +1 -1
  13. package/lib/cjs/ClassRegistry.js +2 -2
  14. package/lib/cjs/ClassRegistry.js.map +1 -1
  15. package/lib/cjs/CloudSqlite.d.ts +4 -0
  16. package/lib/cjs/CloudSqlite.d.ts.map +1 -1
  17. package/lib/cjs/CloudSqlite.js.map +1 -1
  18. package/lib/cjs/ECDb.d.ts +8 -0
  19. package/lib/cjs/ECDb.d.ts.map +1 -1
  20. package/lib/cjs/ECDb.js +22 -0
  21. package/lib/cjs/ECDb.js.map +1 -1
  22. package/lib/cjs/IModelDb.d.ts +54 -3
  23. package/lib/cjs/IModelDb.d.ts.map +1 -1
  24. package/lib/cjs/IModelDb.js +88 -10
  25. package/lib/cjs/IModelDb.js.map +1 -1
  26. package/lib/cjs/IModelHost.d.ts +11 -1
  27. package/lib/cjs/IModelHost.d.ts.map +1 -1
  28. package/lib/cjs/IModelHost.js +5 -0
  29. package/lib/cjs/IModelHost.js.map +1 -1
  30. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts +1 -5
  31. package/lib/cjs/IModelIncrementalSchemaLocater.d.ts.map +1 -1
  32. package/lib/cjs/IModelIncrementalSchemaLocater.js +0 -6
  33. package/lib/cjs/IModelIncrementalSchemaLocater.js.map +1 -1
  34. package/lib/cjs/StashManager.d.ts +175 -0
  35. package/lib/cjs/StashManager.d.ts.map +1 -0
  36. package/lib/cjs/StashManager.js +306 -0
  37. package/lib/cjs/StashManager.js.map +1 -0
  38. package/lib/cjs/TxnManager.d.ts +226 -15
  39. package/lib/cjs/TxnManager.d.ts.map +1 -1
  40. package/lib/cjs/TxnManager.js +249 -23
  41. package/lib/cjs/TxnManager.js.map +1 -1
  42. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +10 -1
  43. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  44. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js +12 -1
  45. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  46. package/lib/cjs/annotations/LeaderGeometry.d.ts +3 -2
  47. package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
  48. package/lib/cjs/annotations/LeaderGeometry.js +4 -3
  49. package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
  50. package/lib/cjs/annotations/TextAnnotationElement.d.ts +52 -24
  51. package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
  52. package/lib/cjs/annotations/TextAnnotationElement.js +49 -59
  53. package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
  54. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts +2 -0
  55. package/lib/cjs/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  56. package/lib/cjs/annotations/TextAnnotationGeometry.js +2 -2
  57. package/lib/cjs/annotations/TextAnnotationGeometry.js.map +1 -1
  58. package/lib/cjs/annotations/TextBlockLayout.d.ts +3 -9
  59. package/lib/cjs/annotations/TextBlockLayout.d.ts.map +1 -1
  60. package/lib/cjs/annotations/TextBlockLayout.js +3 -22
  61. package/lib/cjs/annotations/TextBlockLayout.js.map +1 -1
  62. package/lib/cjs/internal/ChannelAdmin.js +1 -1
  63. package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
  64. package/lib/cjs/internal/Symbols.d.ts +1 -0
  65. package/lib/cjs/internal/Symbols.d.ts.map +1 -1
  66. package/lib/cjs/internal/Symbols.js +2 -1
  67. package/lib/cjs/internal/Symbols.js.map +1 -1
  68. package/lib/cjs/internal/annotations/fields.d.ts +2 -12
  69. package/lib/cjs/internal/annotations/fields.d.ts.map +1 -1
  70. package/lib/cjs/internal/annotations/fields.js +47 -40
  71. package/lib/cjs/internal/annotations/fields.js.map +1 -1
  72. package/lib/cjs/internal/workspace/SettingsImpl.js +1 -1
  73. package/lib/cjs/internal/workspace/SettingsImpl.js.map +1 -1
  74. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js +2 -2
  75. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  76. package/lib/cjs/workspace/Workspace.d.ts +1 -1
  77. package/lib/cjs/workspace/Workspace.js.map +1 -1
  78. package/lib/esm/BackendHubAccess.d.ts +2 -0
  79. package/lib/esm/BackendHubAccess.d.ts.map +1 -1
  80. package/lib/esm/BackendHubAccess.js.map +1 -1
  81. package/lib/esm/BackendLoggerCategory.d.ts +6 -0
  82. package/lib/esm/BackendLoggerCategory.d.ts.map +1 -1
  83. package/lib/esm/BackendLoggerCategory.js +6 -0
  84. package/lib/esm/BackendLoggerCategory.js.map +1 -1
  85. package/lib/esm/BriefcaseManager.d.ts +57 -3
  86. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  87. package/lib/esm/BriefcaseManager.js +154 -45
  88. package/lib/esm/BriefcaseManager.js.map +1 -1
  89. package/lib/esm/ClassRegistry.js +2 -2
  90. package/lib/esm/ClassRegistry.js.map +1 -1
  91. package/lib/esm/CloudSqlite.d.ts +4 -0
  92. package/lib/esm/CloudSqlite.d.ts.map +1 -1
  93. package/lib/esm/CloudSqlite.js.map +1 -1
  94. package/lib/esm/ECDb.d.ts +8 -0
  95. package/lib/esm/ECDb.d.ts.map +1 -1
  96. package/lib/esm/ECDb.js +22 -0
  97. package/lib/esm/ECDb.js.map +1 -1
  98. package/lib/esm/IModelDb.d.ts +54 -3
  99. package/lib/esm/IModelDb.d.ts.map +1 -1
  100. package/lib/esm/IModelDb.js +89 -11
  101. package/lib/esm/IModelDb.js.map +1 -1
  102. package/lib/esm/IModelHost.d.ts +11 -1
  103. package/lib/esm/IModelHost.d.ts.map +1 -1
  104. package/lib/esm/IModelHost.js +5 -0
  105. package/lib/esm/IModelHost.js.map +1 -1
  106. package/lib/esm/IModelIncrementalSchemaLocater.d.ts +1 -5
  107. package/lib/esm/IModelIncrementalSchemaLocater.d.ts.map +1 -1
  108. package/lib/esm/IModelIncrementalSchemaLocater.js +0 -6
  109. package/lib/esm/IModelIncrementalSchemaLocater.js.map +1 -1
  110. package/lib/esm/StashManager.d.ts +175 -0
  111. package/lib/esm/StashManager.d.ts.map +1 -0
  112. package/lib/esm/StashManager.js +301 -0
  113. package/lib/esm/StashManager.js.map +1 -0
  114. package/lib/esm/TxnManager.d.ts +226 -15
  115. package/lib/esm/TxnManager.d.ts.map +1 -1
  116. package/lib/esm/TxnManager.js +247 -21
  117. package/lib/esm/TxnManager.js.map +1 -1
  118. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +10 -1
  119. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts.map +1 -1
  120. package/lib/esm/annotations/ElementDrivesTextAnnotation.js +10 -0
  121. package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  122. package/lib/esm/annotations/LeaderGeometry.d.ts +3 -2
  123. package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
  124. package/lib/esm/annotations/LeaderGeometry.js +4 -3
  125. package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
  126. package/lib/esm/annotations/TextAnnotationElement.d.ts +52 -24
  127. package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
  128. package/lib/esm/annotations/TextAnnotationElement.js +51 -61
  129. package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
  130. package/lib/esm/annotations/TextAnnotationGeometry.d.ts +2 -0
  131. package/lib/esm/annotations/TextAnnotationGeometry.d.ts.map +1 -1
  132. package/lib/esm/annotations/TextAnnotationGeometry.js +2 -2
  133. package/lib/esm/annotations/TextAnnotationGeometry.js.map +1 -1
  134. package/lib/esm/annotations/TextBlockLayout.d.ts +3 -9
  135. package/lib/esm/annotations/TextBlockLayout.d.ts.map +1 -1
  136. package/lib/esm/annotations/TextBlockLayout.js +3 -22
  137. package/lib/esm/annotations/TextBlockLayout.js.map +1 -1
  138. package/lib/esm/internal/ChannelAdmin.js +1 -1
  139. package/lib/esm/internal/ChannelAdmin.js.map +1 -1
  140. package/lib/esm/internal/Symbols.d.ts +1 -0
  141. package/lib/esm/internal/Symbols.d.ts.map +1 -1
  142. package/lib/esm/internal/Symbols.js +1 -0
  143. package/lib/esm/internal/Symbols.js.map +1 -1
  144. package/lib/esm/internal/annotations/fields.d.ts +2 -12
  145. package/lib/esm/internal/annotations/fields.d.ts.map +1 -1
  146. package/lib/esm/internal/annotations/fields.js +50 -43
  147. package/lib/esm/internal/annotations/fields.js.map +1 -1
  148. package/lib/esm/internal/workspace/SettingsImpl.js +1 -1
  149. package/lib/esm/internal/workspace/SettingsImpl.js.map +1 -1
  150. package/lib/esm/internal/workspace/SettingsSchemasImpl.js +2 -2
  151. package/lib/esm/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  152. package/lib/esm/test/AnnotationTestUtils.d.ts +5 -1
  153. package/lib/esm/test/AnnotationTestUtils.d.ts.map +1 -1
  154. package/lib/esm/test/AnnotationTestUtils.js +6 -1
  155. package/lib/esm/test/AnnotationTestUtils.js.map +1 -1
  156. package/lib/esm/test/annotations/Fields.test.js +158 -43
  157. package/lib/esm/test/annotations/Fields.test.js.map +1 -1
  158. package/lib/esm/test/annotations/LeaderGeometry.test.js +12 -10
  159. package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
  160. package/lib/esm/test/annotations/TextAnnotation.test.js +299 -43
  161. package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
  162. package/lib/esm/test/annotations/TextBlock.test.js +39 -35
  163. package/lib/esm/test/annotations/TextBlock.test.js.map +1 -1
  164. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts +46 -0
  165. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.d.ts.map +1 -1
  166. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js +20 -2
  167. package/lib/esm/test/assets/IncrementalSchemaLocater/configs/simple.config.js.map +1 -1
  168. package/lib/esm/test/ecdb/ECDb.test.js +71 -1
  169. package/lib/esm/test/ecdb/ECDb.test.js.map +1 -1
  170. package/lib/esm/test/ecsql/dataset/ECSqlDatasets.d.ts.map +1 -1
  171. package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js +8 -2
  172. package/lib/esm/test/ecsql/dataset/ECSqlDatasets.js.map +1 -1
  173. package/lib/esm/test/hubaccess/Rebase.test.d.ts +2 -0
  174. package/lib/esm/test/hubaccess/Rebase.test.d.ts.map +1 -0
  175. package/lib/esm/test/hubaccess/Rebase.test.js +640 -0
  176. package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -0
  177. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js +20 -20
  178. package/lib/esm/test/incrementalSchemaLocater/ECSqlQueries.test.js.map +1 -1
  179. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js +3 -3
  180. package/lib/esm/test/incrementalSchemaLocater/IncrementalLoading.test.js.map +1 -1
  181. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts +16 -1
  182. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.d.ts.map +1 -1
  183. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js +47 -0
  184. package/lib/esm/test/incrementalSchemaLocater/utils/TestSqlSchemaLocater.js.map +1 -1
  185. package/lib/esm/test/standalone/ChangeMerge.test.js +15 -19
  186. package/lib/esm/test/standalone/ChangeMerge.test.js.map +1 -1
  187. package/lib/esm/test/standalone/MergeConflict.test.js +3 -3
  188. package/lib/esm/test/standalone/MergeConflict.test.js.map +1 -1
  189. package/lib/esm/test/standalone/NativeAppStorage.test.js +2 -2
  190. package/lib/esm/test/standalone/NativeAppStorage.test.js.map +1 -1
  191. package/lib/esm/workspace/Workspace.d.ts +1 -1
  192. package/lib/esm/workspace/Workspace.js.map +1 -1
  193. package/package.json +14 -14
@@ -0,0 +1,301 @@
1
+ import { DbResult, Logger, OpenMode } from "@itwin/core-bentley";
2
+ import { LockState } from "@itwin/core-common";
3
+ import { existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from "node:fs";
4
+ import * as path from "node:path";
5
+ import { BriefcaseManager } from "./BriefcaseManager";
6
+ import { _elementWasCreated, _hubAccess, _nativeDb, _resetIModelDb } from "./internal/Symbols";
7
+ import { SQLiteDb } from "./SQLiteDb";
8
+ import { IModelHost } from "./IModelHost";
9
+ import { BackendLoggerCategory } from "./BackendLoggerCategory";
10
+ const loggerCategory = BackendLoggerCategory.StashManager;
11
+ /**
12
+ * Custom error class for stash-related errors.
13
+ * @internal
14
+ */
15
+ export class StashError extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = "StashError";
19
+ Logger.logError(loggerCategory, message);
20
+ }
21
+ }
22
+ var LockOrigin;
23
+ (function (LockOrigin) {
24
+ LockOrigin[LockOrigin["Acquired"] = 0] = "Acquired";
25
+ LockOrigin[LockOrigin["NewElement"] = 1] = "NewElement";
26
+ LockOrigin[LockOrigin["Discovered"] = 2] = "Discovered";
27
+ })(LockOrigin || (LockOrigin = {}));
28
+ ;
29
+ /**
30
+ * Stash manager allow stash, drop, apply and merge stashes
31
+ * @internal
32
+ */
33
+ export class StashManager {
34
+ static STASHES_ROOT_DIR_NAME = ".stashes";
35
+ /**
36
+ * Retrieves the root folder path for stash files associated with the specified BriefcaseDb.
37
+ *
38
+ * @param db - The BriefcaseDb instance for which to determine the stash root folder.
39
+ * @param ensureExists - If true, the stash root directory will be created if it does not already exist.
40
+ * @returns The absolute path to the stash root directory.
41
+ */
42
+ static getStashRootFolder(db, ensureExists) {
43
+ if (!db.isOpen || db.isReadonly)
44
+ throw new StashError("Database is not open or is readonly");
45
+ if (!existsSync(db[_nativeDb].getFilePath())) {
46
+ throw new StashError("Could not determine briefcase path");
47
+ }
48
+ const stashDir = path.join(path.dirname(db[_nativeDb].getFilePath()), this.STASHES_ROOT_DIR_NAME, `${db.briefcaseId}`);
49
+ if (ensureExists && !existsSync(stashDir)) {
50
+ mkdirSync(stashDir, { recursive: true });
51
+ }
52
+ return stashDir;
53
+ }
54
+ /**
55
+ * Retrieves the stash ID from the provided arguments.
56
+ *
57
+ * If the `stash` property of `args` is a string, it returns the string in lowercase.
58
+ * If the `stash` property is an object, it returns the `id` property of the object in lowercase.
59
+ *
60
+ * @param args - The arguments containing the stash information, which can be either a string or an object with an `id` property.
61
+ * @returns The stash ID as a lowercase string.
62
+ */
63
+ static getStashId(args) {
64
+ return (typeof args.stash === "string" ? args.stash : args.stash.id).toLowerCase();
65
+ }
66
+ /**
67
+ * Retrieves the file path to the stash file associated with the provided arguments.
68
+ *
69
+ * @param args - The arguments required to identify the stash, including the database reference.
70
+ * @returns The absolute path to the stash file.
71
+ */
72
+ static getStashFilePath(args) {
73
+ const stashRoot = this.getStashRootFolder(args.db, false);
74
+ if (!existsSync(stashRoot)) {
75
+ throw new StashError("Invalid stash");
76
+ }
77
+ const stashFilePath = path.join(stashRoot, `${this.getStashId(args)}.stash`);
78
+ if (!existsSync(stashFilePath)) {
79
+ throw new StashError("Invalid stash");
80
+ }
81
+ return stashFilePath;
82
+ }
83
+ /**
84
+ * Queries the stash database for lock IDs matching the specified state and origin.
85
+ *
86
+ * @param args - The arguments required to access the stash database.
87
+ * @param state - The lock state to filter by.
88
+ * @param origin - The lock origin to filter by.
89
+ * @returns An array of lock IDs (`Id64Array`) that match the given state and origin.
90
+ */
91
+ static queryLocks(args, state, origin) {
92
+ return this.withStash(args, (stashDb) => {
93
+ const query = `SELECT JSON_GROUP_ARRAY(FORMAT('0x%x', Id)) FROM [locks] WHERE State = ${state} AND origin = ${origin}`;
94
+ return stashDb.withPreparedSqliteStatement(query, (stmt) => {
95
+ if (stmt.step() === DbResult.BE_SQLITE_ROW) {
96
+ return JSON.parse(stmt.getValueString(0));
97
+ }
98
+ return [];
99
+ });
100
+ });
101
+ }
102
+ /**
103
+ * Acquire locks for the specified stash. If this fail then stash should not be applied.
104
+ * @param args The stash arguments.
105
+ */
106
+ static async acquireLocks(args) {
107
+ const shared = this.queryLocks(args, LockState.Shared, LockOrigin.Acquired);
108
+ await args.db.locks.acquireLocks({ shared });
109
+ const exclusive = this.queryLocks(args, LockState.Exclusive, LockOrigin.Acquired);
110
+ await args.db.locks.acquireLocks({ exclusive });
111
+ const newElements = this.queryLocks(args, LockState.Shared, LockOrigin.NewElement);
112
+ for (const id of newElements) {
113
+ if (!args.db.locks.holdsExclusiveLock(id)) {
114
+ args.db.locks[_elementWasCreated](id);
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Creates a stash of changes for the specified briefcase.
120
+ *
121
+ * This method generates a stash in the stash root directory for the given briefcase, using the provided description and iModelId.
122
+ * Optionally, it can reset the briefcase by releasing all locks after stashing.
123
+ *
124
+ * @param args - The properties required to create a stash, including the briefcase, description, iModelId, and an optional resetBriefcase flag.
125
+ * @returns A promise that resolves to the properties of the created stash.
126
+ */
127
+ static async stash(args) {
128
+ if (!args.db.txns.hasPendingTxns) {
129
+ throw new StashError("nothing to stash");
130
+ }
131
+ if (args.db.txns.hasUnsavedChanges) {
132
+ throw new StashError("Unsaved changes exist");
133
+ }
134
+ if (args.db.txns.hasPendingSchemaChanges) {
135
+ throw new StashError("Pending schema changeset. Stashing is not currently supported for schema changes");
136
+ }
137
+ const stashRootDir = this.getStashRootFolder(args.db, true);
138
+ const iModelId = args.db.iModelId;
139
+ const stash = args.db[_nativeDb].stashChanges({ stashRootDir, description: args.description, iModelId });
140
+ if (args.discardLocalChanges) {
141
+ await args.db.discardChanges({ retainLocks: args.retainLocks });
142
+ }
143
+ Logger.logInfo(loggerCategory, `Stashed changes`, () => stash);
144
+ return stash;
145
+ }
146
+ /**
147
+ * Retrieves the stash properties from the database for the given arguments.
148
+ *
149
+ * @param args - The arguments required to locate and access the stash.
150
+ * @returns The stash file properties if found; otherwise, `undefined`.
151
+ */
152
+ static tryGetStash(args) {
153
+ try {
154
+ return this.getStash(args);
155
+ }
156
+ catch (error) {
157
+ Logger.logError(loggerCategory, `Error getting stash with ${this.getStashId(args)}: ${error.message}`);
158
+ }
159
+ return undefined;
160
+ }
161
+ /**
162
+ * Retrieves the stash properties from the database using the provided arguments.
163
+ *
164
+ * @param args - The arguments required to access the stash.
165
+ * @returns The stash properties parsed from the database.
166
+ */
167
+ static getStash(args) {
168
+ return this.withStash(args, (stashDb) => {
169
+ const stashProps = stashDb.withPreparedSqliteStatement("SELECT [val] FROM [be_Local] WHERE [name]='$stash_info'", (stmt) => {
170
+ if (stmt.step() !== DbResult.BE_SQLITE_ROW)
171
+ throw new StashError("Invalid stash");
172
+ return JSON.parse(stmt.getValueString(0));
173
+ });
174
+ return stashProps;
175
+ });
176
+ }
177
+ /**
178
+ * Executes a callback function with a read-only SQLite database connection to a stash file.
179
+ *
180
+ * @typeParam T - The return type of the callback function.
181
+ * @param args - Arguments required to determine the stash file path.
182
+ * @param callback - A function that receives an open {@link SQLiteDb} instance connected to the stash file.
183
+ * @returns The value returned by the callback function.
184
+ */
185
+ static withStash(args, callback) {
186
+ const stashFile = this.getStashFilePath(args);
187
+ if (!existsSync(stashFile)) {
188
+ throw new StashError("Invalid stash");
189
+ }
190
+ const stashDb = new SQLiteDb();
191
+ stashDb.openDb(stashFile, OpenMode.Readonly);
192
+ try {
193
+ return callback(stashDb);
194
+ }
195
+ finally {
196
+ stashDb.closeDb();
197
+ }
198
+ }
199
+ /**
200
+ * Retrieves all stash files associated with the specified {@link BriefcaseDb}.
201
+ * @param db - The {@link BriefcaseDb} instance for which to retrieve stash files.
202
+ * @returns An array of `StashProps` representing the found stash files, sorted by timestamp.
203
+ */
204
+ static getStashes(db) {
205
+ const stashes = [];
206
+ const stashDir = this.getStashRootFolder(db, false);
207
+ if (!existsSync(stashDir)) {
208
+ return stashes;
209
+ }
210
+ readdirSync(stashDir).filter((file) => {
211
+ const filePath = path.join(stashDir, file);
212
+ if (existsSync(filePath) && statSync(filePath).isFile() && file.endsWith(".stash")) {
213
+ const id = file.slice(0, -path.extname(file).length);
214
+ const stash = this.tryGetStash({ db, stash: id });
215
+ if (stash) {
216
+ stashes.push(stash);
217
+ }
218
+ }
219
+ });
220
+ stashes.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
221
+ return stashes;
222
+ }
223
+ /**
224
+ * Deletes the stash file associated with the specified stash ID or properties from the given {@link BriefcaseDb}.
225
+ *
226
+ * @param db - The {@link BriefcaseDb} instance from which the stash should be dropped.
227
+ * @param stashId - The unique identifier (GuidString) or properties (StashProps) of the stash to be deleted.
228
+ * @returns Returns `true` if the stash file was successfully deleted, otherwise returns `false`.
229
+ */
230
+ static dropStash(args) {
231
+ try {
232
+ const stashFile = this.getStashFilePath(args);
233
+ unlinkSync(stashFile);
234
+ return true;
235
+ }
236
+ catch (error) {
237
+ Logger.logError(loggerCategory, `Error dropping stash: ${error}`);
238
+ }
239
+ return false;
240
+ }
241
+ /**
242
+ * Removes all stashes associated with the specified {@link BriefcaseDb}.
243
+ *
244
+ * @param db - The {@link BriefcaseDb} instance from which all stashes will be removed.
245
+ */
246
+ static dropAllStashes(db) {
247
+ this.getStashes(db).forEach((stash) => {
248
+ this.dropStash({ db, stash });
249
+ });
250
+ }
251
+ /**
252
+ * Queries the hub for the changeset information associated with the given stash.
253
+ *
254
+ * @param args - The arguments including the stash properties.
255
+ * @returns A promise resolving to the changeset ID and index.
256
+ */
257
+ static async queryChangeset(args) {
258
+ return IModelHost[_hubAccess].queryChangeset({
259
+ iModelId: args.stash.iModelId,
260
+ changeset: args.stash.parentChangeset,
261
+ accessToken: await IModelHost.getAccessToken()
262
+ });
263
+ }
264
+ /**
265
+ * Restores the specified stash to the given {@link BriefcaseDb}. This operation will discard any local changes made to db and reverse the tip to the state of the stash and then apply stash. This will restore the undo stack.
266
+ *
267
+ * @param args - The arguments including the target database and stash properties.
268
+ */
269
+ static async restore(args) {
270
+ const { db } = args;
271
+ Logger.logInfo(loggerCategory, `Restoring stash: ${this.getStashId(args)}`);
272
+ const stash = this.tryGetStash(args);
273
+ if (!stash) {
274
+ throw new StashError(`Stash not found ${this.getStashId(args)}`);
275
+ }
276
+ if (db.txns.hasUnsavedChanges) {
277
+ throw new StashError(`Unsaved changes present`);
278
+ }
279
+ if (db.iModelId !== stash.iModelId) {
280
+ throw new StashError(`Stash does not belong to this iModel`);
281
+ }
282
+ if (db.briefcaseId !== stash.briefcaseId) {
283
+ throw new StashError(`Stash does not belong to this briefcase`);
284
+ }
285
+ const stashFile = this.getStashFilePath({ db, stash });
286
+ // we need to retain lock that overlapped with stash locks instead of all locks
287
+ await db.discardChanges({ retainLocks: true });
288
+ await this.acquireLocks(args);
289
+ if (db.changeset.id !== stash.parentChangeset.id) {
290
+ // Changeset ID mismatch
291
+ Logger.logWarning(loggerCategory, "Changeset ID mismatch");
292
+ const stashChangeset = await this.queryChangeset({ db, stash });
293
+ await BriefcaseManager.pullAndApplyChangesets(db, { toIndex: stashChangeset.index });
294
+ }
295
+ db[_nativeDb].stashRestore(stashFile);
296
+ db[_resetIModelDb]();
297
+ db.saveChanges();
298
+ Logger.logInfo(loggerCategory, `Restored stash: ${this.getStashId(args)}`);
299
+ }
300
+ }
301
+ //# sourceMappingURL=StashManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StashManager.js","sourceRoot":"","sources":["../../src/StashManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { DbResult, GuidString, Id64Array, Id64String, Logger, OpenMode } from \"@itwin/core-bentley\";\nimport { ChangesetIdWithIndex, LocalDirName, LockState } from \"@itwin/core-common\";\nimport { existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { BriefcaseManager } from \"./BriefcaseManager\";\nimport { BriefcaseDb } from \"./IModelDb\";\nimport { _elementWasCreated, _getHubAccess, _hubAccess, _nativeDb, _resetIModelDb } from \"./internal/Symbols\";\nimport { SQLiteDb } from \"./SQLiteDb\";\nimport { TxnProps } from \"./TxnManager\";\nimport { IModelHost } from \"./IModelHost\";\nimport { BackendLoggerCategory } from \"./BackendLoggerCategory\";\n\nconst loggerCategory = BackendLoggerCategory.StashManager;\n\n/**\n * Custom error class for stash-related errors.\n * @internal\n */\nexport class StashError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StashError\";\n Logger.logError(loggerCategory, message);\n }\n}\n\n/**\n * Properties of a stash\n * @internal\n */\nexport interface StashProps {\n /** Unique identifier for the stash */\n readonly id: GuidString;\n\n /** ID of the iModel being stashed */\n readonly iModelId: GuidString;\n\n /** ID of the briefcase being stashed */\n readonly briefcaseId: number;\n\n /** ISO local Timestamp of the stash */\n readonly timestamp: string;\n\n /** Description of the stash */\n readonly description: string;\n\n /** Hash of the stash */\n readonly hash: string;\n\n /** Parent changeset of the stash */\n readonly parentChangeset: ChangesetIdWithIndex;\n\n /** ID sequences for the stash */\n readonly idSequences: {\n element: Id64String;\n instance: Id64String;\n };\n\n /** Transaction properties for the stash */\n readonly txns: TxnProps[];\n\n /** Number of locks acquired by the stash */\n readonly acquiredLocks: number;\n}\n\n/**\n * Properties for creating a stash\n * @internal\n */\nexport interface CreateStashProps {\n /** Briefcase database instance */\n readonly db: BriefcaseDb;\n /** description of the stash */\n readonly description: string;\n /** discard all local changes and unless retainLocks flag is set, all locks will be released */\n readonly discardLocalChanges?: true;\n /** retains all locks after discarding local changes */\n readonly retainLocks?: true;\n}\n\n/**\n * Arguments for stash operations\n * @internal\n */\nexport interface StashArgs {\n readonly db: BriefcaseDb;\n readonly stash: Id64String | StashProps;\n}\n\nenum LockOrigin {\n Acquired = 0,\n NewElement = 1,\n Discovered = 2,\n};\n\n/**\n * Stash manager allow stash, drop, apply and merge stashes\n * @internal\n */\nexport class StashManager {\n\n private static readonly STASHES_ROOT_DIR_NAME: string = \".stashes\";\n /**\n * Retrieves the root folder path for stash files associated with the specified BriefcaseDb.\n *\n * @param db - The BriefcaseDb instance for which to determine the stash root folder.\n * @param ensureExists - If true, the stash root directory will be created if it does not already exist.\n * @returns The absolute path to the stash root directory.\n */\n private static getStashRootFolder(db: BriefcaseDb, ensureExists: boolean): LocalDirName {\n if (!db.isOpen || db.isReadonly)\n throw new StashError(\"Database is not open or is readonly\");\n\n if (!existsSync(db[_nativeDb].getFilePath())) {\n throw new StashError(\"Could not determine briefcase path\");\n }\n\n const stashDir = path.join(path.dirname(db[_nativeDb].getFilePath()), this.STASHES_ROOT_DIR_NAME, `${db.briefcaseId}`);\n if (ensureExists && !existsSync(stashDir)) {\n mkdirSync(stashDir, { recursive: true });\n }\n return stashDir;\n }\n\n /**\n * Retrieves the stash ID from the provided arguments.\n *\n * If the `stash` property of `args` is a string, it returns the string in lowercase.\n * If the `stash` property is an object, it returns the `id` property of the object in lowercase.\n *\n * @param args - The arguments containing the stash information, which can be either a string or an object with an `id` property.\n * @returns The stash ID as a lowercase string.\n */\n private static getStashId(args: StashArgs) {\n return (typeof args.stash === \"string\" ? args.stash : args.stash.id).toLowerCase();\n }\n\n /**\n * Retrieves the file path to the stash file associated with the provided arguments.\n *\n * @param args - The arguments required to identify the stash, including the database reference.\n * @returns The absolute path to the stash file.\n */\n private static getStashFilePath(args: StashArgs) {\n const stashRoot = this.getStashRootFolder(args.db, false);\n if (!existsSync(stashRoot)) {\n throw new StashError(\"Invalid stash\");\n }\n\n const stashFilePath = path.join(stashRoot, `${this.getStashId(args)}.stash`);\n if (!existsSync(stashFilePath)) {\n throw new StashError(\"Invalid stash\");\n }\n return stashFilePath;\n }\n\n /**\n * Queries the stash database for lock IDs matching the specified state and origin.\n *\n * @param args - The arguments required to access the stash database.\n * @param state - The lock state to filter by.\n * @param origin - The lock origin to filter by.\n * @returns An array of lock IDs (`Id64Array`) that match the given state and origin.\n */\n private static queryLocks(args: StashArgs, state: LockState, origin: LockOrigin): Id64Array {\n return this.withStash(args, (stashDb) => {\n const query = `SELECT JSON_GROUP_ARRAY(FORMAT('0x%x', Id)) FROM [locks] WHERE State = ${state} AND origin = ${origin}`;\n return stashDb.withPreparedSqliteStatement(query, (stmt) => {\n if (stmt.step() === DbResult.BE_SQLITE_ROW) {\n return JSON.parse(stmt.getValueString(0)) as Id64Array;\n }\n return [];\n });\n });\n }\n\n /**\n * Acquire locks for the specified stash. If this fail then stash should not be applied.\n * @param args The stash arguments.\n */\n private static async acquireLocks(args: StashArgs) {\n const shared = this.queryLocks(args, LockState.Shared, LockOrigin.Acquired);\n await args.db.locks.acquireLocks({ shared });\n\n const exclusive = this.queryLocks(args, LockState.Exclusive, LockOrigin.Acquired);\n await args.db.locks.acquireLocks({ exclusive });\n\n const newElements = this.queryLocks(args, LockState.Shared, LockOrigin.NewElement);\n for (const id of newElements) {\n if (!args.db.locks.holdsExclusiveLock(id)) {\n args.db.locks[_elementWasCreated](id);\n }\n }\n }\n /**\n * Creates a stash of changes for the specified briefcase.\n *\n * This method generates a stash in the stash root directory for the given briefcase, using the provided description and iModelId.\n * Optionally, it can reset the briefcase by releasing all locks after stashing.\n *\n * @param args - The properties required to create a stash, including the briefcase, description, iModelId, and an optional resetBriefcase flag.\n * @returns A promise that resolves to the properties of the created stash.\n */\n public static async stash(args: CreateStashProps): Promise<StashProps> {\n if (!args.db.txns.hasPendingTxns) {\n throw new StashError(\"nothing to stash\");\n }\n\n if (args.db.txns.hasUnsavedChanges) {\n throw new StashError(\"Unsaved changes exist\");\n }\n\n if (args.db.txns.hasPendingSchemaChanges) {\n throw new StashError(\"Pending schema changeset. Stashing is not currently supported for schema changes\");\n }\n\n const stashRootDir = this.getStashRootFolder(args.db, true);\n const iModelId = args.db.iModelId;\n const stash = args.db[_nativeDb].stashChanges({ stashRootDir, description: args.description, iModelId }) as StashProps;\n if (args.discardLocalChanges) {\n await args.db.discardChanges({ retainLocks: args.retainLocks });\n }\n\n Logger.logInfo(loggerCategory, `Stashed changes`, () => stash);\n return stash;\n }\n\n /**\n * Retrieves the stash properties from the database for the given arguments.\n *\n * @param args - The arguments required to locate and access the stash.\n * @returns The stash file properties if found; otherwise, `undefined`.\n */\n public static tryGetStash(args: StashArgs): StashProps | undefined {\n try {\n return this.getStash(args);\n } catch (error: any) {\n Logger.logError(loggerCategory, `Error getting stash with ${this.getStashId(args)}: ${error.message}`);\n }\n return undefined;\n }\n\n /**\n * Retrieves the stash properties from the database using the provided arguments.\n *\n * @param args - The arguments required to access the stash.\n * @returns The stash properties parsed from the database.\n */\n public static getStash(args: StashArgs): StashProps {\n return this.withStash(args, (stashDb) => {\n const stashProps = stashDb.withPreparedSqliteStatement(\"SELECT [val] FROM [be_Local] WHERE [name]='$stash_info'\", (stmt) => {\n if (stmt.step() !== DbResult.BE_SQLITE_ROW)\n throw new StashError(\"Invalid stash\");\n return JSON.parse(stmt.getValueString(0)) as StashProps;\n });\n return stashProps;\n });\n }\n\n /**\n * Executes a callback function with a read-only SQLite database connection to a stash file.\n *\n * @typeParam T - The return type of the callback function.\n * @param args - Arguments required to determine the stash file path.\n * @param callback - A function that receives an open {@link SQLiteDb} instance connected to the stash file.\n * @returns The value returned by the callback function.\n */\n private static withStash<T>(args: StashArgs, callback: (stashDb: SQLiteDb) => T): T {\n const stashFile = this.getStashFilePath(args);\n if (!existsSync(stashFile)) {\n throw new StashError(\"Invalid stash\");\n }\n\n const stashDb = new SQLiteDb();\n stashDb.openDb(stashFile, OpenMode.Readonly);\n try {\n return callback(stashDb);\n } finally {\n stashDb.closeDb();\n }\n }\n\n /**\n * Retrieves all stash files associated with the specified {@link BriefcaseDb}.\n * @param db - The {@link BriefcaseDb} instance for which to retrieve stash files.\n * @returns An array of `StashProps` representing the found stash files, sorted by timestamp.\n */\n public static getStashes(db: BriefcaseDb): StashProps[] {\n const stashes: StashProps[] = [];\n const stashDir = this.getStashRootFolder(db, false);\n if (!existsSync(stashDir)) {\n return stashes;\n }\n readdirSync(stashDir).filter((file) => {\n const filePath = path.join(stashDir, file);\n if (existsSync(filePath) && statSync(filePath).isFile() && file.endsWith(\".stash\")) {\n const id = file.slice(0, -path.extname(file).length)\n const stash = this.tryGetStash({ db, stash: id });\n if (stash) {\n stashes.push(stash);\n }\n }\n });\n stashes.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));\n return stashes;\n }\n\n /**\n * Deletes the stash file associated with the specified stash ID or properties from the given {@link BriefcaseDb}.\n *\n * @param db - The {@link BriefcaseDb} instance from which the stash should be dropped.\n * @param stashId - The unique identifier (GuidString) or properties (StashProps) of the stash to be deleted.\n * @returns Returns `true` if the stash file was successfully deleted, otherwise returns `false`.\n */\n public static dropStash(args: StashArgs): boolean {\n try {\n const stashFile = this.getStashFilePath(args);\n unlinkSync(stashFile);\n return true;\n } catch (error: any) {\n Logger.logError(loggerCategory, `Error dropping stash: ${error}`);\n }\n return false;\n }\n\n /**\n * Removes all stashes associated with the specified {@link BriefcaseDb}.\n *\n * @param db - The {@link BriefcaseDb} instance from which all stashes will be removed.\n */\n public static dropAllStashes(db: BriefcaseDb): void {\n this.getStashes(db).forEach((stash) => {\n this.dropStash({ db, stash });\n });\n }\n\n /**\n * Queries the hub for the changeset information associated with the given stash.\n *\n * @param args - The arguments including the stash properties.\n * @returns A promise resolving to the changeset ID and index.\n */\n private static async queryChangeset(args: StashArgs & { stash: StashProps }): Promise<ChangesetIdWithIndex> {\n return IModelHost[_hubAccess].queryChangeset({\n iModelId: args.stash.iModelId,\n changeset: args.stash.parentChangeset,\n accessToken: await IModelHost.getAccessToken()\n });\n }\n /**\n * Restores the specified stash to the given {@link BriefcaseDb}. This operation will discard any local changes made to db and reverse the tip to the state of the stash and then apply stash. This will restore the undo stack.\n *\n * @param args - The arguments including the target database and stash properties.\n */\n public static async restore(args: StashArgs): Promise<void> {\n const { db } = args;\n Logger.logInfo(loggerCategory, `Restoring stash: ${this.getStashId(args)}`);\n\n const stash = this.tryGetStash(args);\n if (!stash) {\n throw new StashError(`Stash not found ${this.getStashId(args)}`);\n }\n\n if (db.txns.hasUnsavedChanges) {\n throw new StashError(`Unsaved changes present`);\n }\n\n if (db.iModelId !== stash.iModelId) {\n throw new StashError(`Stash does not belong to this iModel`);\n }\n\n if (db.briefcaseId !== stash.briefcaseId) {\n throw new StashError(`Stash does not belong to this briefcase`);\n }\n\n const stashFile = this.getStashFilePath({ db, stash });\n // we need to retain lock that overlapped with stash locks instead of all locks\n await db.discardChanges({ retainLocks: true });\n await this.acquireLocks(args);\n if (db.changeset.id !== stash.parentChangeset.id) {\n // Changeset ID mismatch\n Logger.logWarning(loggerCategory, \"Changeset ID mismatch\");\n const stashChangeset = await this.queryChangeset({ db, stash });\n await BriefcaseManager.pullAndApplyChangesets(db, { toIndex: stashChangeset.index });\n }\n\n db[_nativeDb].stashRestore(stashFile);\n db[_resetIModelDb]();\n db.saveChanges();\n Logger.logInfo(loggerCategory, `Restored stash: ${this.getStashId(args)}`);\n }\n}\n"]}
@@ -3,9 +3,9 @@
3
3
  */
4
4
  import { BeEvent, DbConflictResolution, DbResult, Id64String, IModelStatus } from "@itwin/core-bentley";
5
5
  import { EntityIdAndClassIdIterable, ModelGeometryChangesProps, ModelIdAndGeometryGuid } from "@itwin/core-common";
6
- import { BriefcaseDb, StandaloneDb } from "./IModelDb";
6
+ import { BriefcaseDb, SaveChangesArgs, StandaloneDb } from "./IModelDb";
7
7
  import { RelationshipProps } from "./Relationship";
8
- import { DbRebaseChangesetConflictArgs, RebaseChangesetConflictArgs, TxnArgs } from "./internal/ChangesetConflictArgs";
8
+ import { DbRebaseChangesetConflictArgs, RebaseChangesetConflictArgs } from "./internal/ChangesetConflictArgs";
9
9
  /** A string that identifies a Txn.
10
10
  * @public @preview
11
11
  */
@@ -58,20 +58,163 @@ export interface ChangeInstanceKey {
58
58
  /** Strictly for tests. @internal */
59
59
  export declare function setMaxEntitiesPerEvent(max: number): number;
60
60
  /**
61
- * @internal
62
- * Manages conflict resolution during a merge operation.
63
- */
64
- export declare class ChangeMergeManager {
61
+ * @alpha
62
+ * Transaction types
63
+ */
64
+ export type TxnType = "Data" | "ECSchema" | "Ddl";
65
+ /**
66
+ * @alpha
67
+ * Transaction modes
68
+ */
69
+ export type TxnMode = "direct" | "indirect";
70
+ /**
71
+ * @alpha
72
+ * Represents the properties of a transaction within the transaction manager.
73
+ *
74
+ * @property id - The unique identifier for the transaction.
75
+ * @property sessionId - The identifier of the session to which the transaction belongs.
76
+ * @property nextId - (Optional) The identifier of the next transaction in the sequence.
77
+ * @property prevId - (Optional) The identifier of the previous transaction in the sequence.
78
+ * @property props - The arguments or properties associated with the save changes operation.
79
+ * @property type - The type of transaction, which can be "Data", "ECSchema", or "Ddl".
80
+ * @property reversed - Indicates whether the transaction has been reversed.
81
+ * @property grouped - Indicates whether the transaction is grouped with others.
82
+ * @property timestamp - The timestamp when the transaction was created.
83
+ */
84
+ export interface TxnProps {
85
+ id: TxnIdString;
86
+ sessionId: number;
87
+ nextId?: TxnIdString;
88
+ prevId?: TxnIdString;
89
+ props: SaveChangesArgs;
90
+ type: TxnType;
91
+ reversed: boolean;
92
+ grouped: boolean;
93
+ timestamp: string;
94
+ }
95
+ /**
96
+ * Manages the process of merging and rebasing local changes (transactions) in a [[BriefcaseDb]] or [[StandaloneDb]].
97
+ *
98
+ * The `RebaseManager` coordinates the rebase of local transactions when pulling and merging changes from other sources,
99
+ * such as remote repositories or other users. It provides mechanisms to handle transaction conflicts, register custom conflict
100
+ * handlers, and manage the rebase workflow. This includes resuming rebases, invoking user-defined handlers for conflict resolution,
101
+ * and tracking the current merge/rebase state.
102
+ *
103
+ * Key responsibilities:
104
+ * - Orchestrates the rebase of local transactions after a pull/merge operation.
105
+ * - Allows registration and removal of custom conflict handlers to resolve changeset conflicts during rebase.
106
+ * - Provides methods to check the current merge/rebase state.
107
+ * - Raises events before and after each transaction is rebased.
108
+ * - Ensures changes are saved or aborted appropriately based on the outcome of the rebase process.
109
+ *
110
+ * @alpha
111
+ */
112
+ export declare class RebaseManager {
65
113
  private _iModel;
66
114
  private _conflictHandlers?;
115
+ private _customHandler?;
67
116
  constructor(_iModel: BriefcaseDb | StandaloneDb);
68
- resume(): void;
117
+ /**
118
+ * Resumes the rebase process for the current iModel, applying any pending local changes
119
+ * on top of the latest pulled changes from the remote source.
120
+ *
121
+ * This method performs the following steps:
122
+ * 1. Begins the rebase process using the native database.
123
+ * 2. Iterates through each transaction that needs to be rebased:
124
+ * - Retrieves transaction properties.
125
+ * - Raises events before and after rebasing each transaction.
126
+ * - Optionally reinstates local changes based on the rebase handler.
127
+ * - Optionally recomputes transaction data using the rebase handler.
128
+ * - Updates the transaction in the native database.
129
+ * 3. Ends the rebase process and saves changes if the database is not read-only.
130
+ * 4. Drops any restore point associated with the pull-merge operation.
131
+ *
132
+ * If an error occurs during the process, the rebase is aborted and the error is rethrown.
133
+ *
134
+ * @throws {Error} If a transaction cannot be found or if any step in the rebase process fails.
135
+ */
136
+ resume(): Promise<void>;
137
+ /**
138
+ * Determines whether the current transaction can be aborted.
139
+ *
140
+ * This method checks if a transaction is currently in progress and if a specific restore point,
141
+ * identified by `BriefcaseManager.PULL_MERGE_RESTORE_POINT_NAME`, exists in the briefcase manager.
142
+ *
143
+ * @returns {boolean} Returns `true` if a transaction is in progress and the required restore point exists; otherwise, returns `false`.
144
+ */
145
+ canAbort(): boolean;
146
+ /**
147
+ * Aborts the current transaction by restoring the iModel to a predefined restore point.
148
+ *
149
+ * If a restore point is available (as determined by `canAbort()`), this method restores the iModel
150
+ * to the state saved at the restore point named by `BriefcaseManager.PULL_MERGE_RESTORE_POINT_NAME`.
151
+ * If no restore point is available, an error is thrown.
152
+ *
153
+ * @returns A promise that resolves when the restore operation is complete.
154
+ * @throws {Error} If there is no restore point to abort to.
155
+ */
156
+ abort(): Promise<void>;
157
+ /**
158
+ * Sets the handler to be invoked for rebase operations.
159
+ *
160
+ * @param handler - The {@link RebaseHandler} to handle rebase events.
161
+ */
162
+ setCustomHandler(handler: RebaseHandler): void;
163
+ /**
164
+ * Determines whether a transaction is currently in progress.
165
+ *
166
+ * @returns {boolean} Returns `true` if there is an active transaction stage, otherwise `false`.
167
+ */
69
168
  inProgress(): boolean;
169
+ /**
170
+ * Indicates whether the current transaction manager is in the "Rebasing" stage.
171
+ *
172
+ * This property checks the internal native database's merge stage to determine if a rebase operation is in progress.
173
+ *
174
+ * @returns `true` if the transaction manager is currently rebasing; otherwise, `false`.
175
+ */
176
+ get isRebasing(): boolean;
177
+ /**
178
+ * Indicates whether the current iModel is in the process of merging changes from a pull operation.
179
+ *
180
+ * @returns `true` if the iModel is currently merging changes; otherwise, `false`.
181
+ */
182
+ get isMerging(): boolean;
183
+ /**
184
+ * Attempts to resolve a changeset conflict by invoking registered conflict handlers in sequence.
185
+ *
186
+ * Iterates through the linked list of conflict handlers, passing the provided conflict arguments to each handler.
187
+ * If a handler returns a defined resolution, logs the resolution and returns it immediately.
188
+ * If no handler resolves the conflict, returns `undefined`.
189
+ *
190
+ * @param args - The arguments describing the changeset conflict to resolve.
191
+ * @returns The conflict resolution provided by a handler, or `undefined` if no handler resolves the conflict.
192
+ */
70
193
  onConflict(args: RebaseChangesetConflictArgs): DbConflictResolution | undefined;
194
+ /**
195
+ * Registers a new conflict handler for rebase changeset conflicts.
196
+ *
197
+ * @param args - An object containing:
198
+ * - `id`: A unique identifier for the conflict handler.
199
+ * - `handler`: A function that handles rebase changeset conflicts and returns a `DbConflictResolution` or `undefined`.
200
+ * @throws IModelError if a conflict handler with the same `id` already exists.
201
+ *
202
+ * @remarks
203
+ * Conflict handlers are used during changeset rebase operations to resolve conflicts.
204
+ * Each handler must have a unique `id`. Attempting to register a handler with a duplicate `id` will result in an error.
205
+ */
71
206
  addConflictHandler(args: {
72
207
  id: string;
73
208
  handler: (args: RebaseChangesetConflictArgs) => DbConflictResolution | undefined;
74
209
  }): void;
210
+ /**
211
+ * Removes a conflict handler from the internal linked list by its identifier.
212
+ *
213
+ * @param id - The unique identifier of the conflict handler to remove.
214
+ *
215
+ * If the handler with the specified `id` exists in the list, it will be removed.
216
+ * If no handler with the given `id` is found, the method does nothing.
217
+ */
75
218
  removeConflictHandler(id: string): void;
76
219
  }
77
220
  /** Manages local changes to a [[BriefcaseDb]] or [[StandaloneDb]] via [Txns]($docs/learning/InteractiveEditing.md)
@@ -84,7 +227,7 @@ export declare class TxnManager {
84
227
  /** @internal */
85
228
  get isDisposed(): boolean;
86
229
  /** @internal */
87
- readonly changeMergeManager: ChangeMergeManager;
230
+ readonly rebaser: RebaseManager;
88
231
  /** @internal */
89
232
  constructor(_iModel: BriefcaseDb | StandaloneDb);
90
233
  /** Array of errors from dependency propagation */
@@ -129,9 +272,29 @@ export declare class TxnManager {
129
272
  protected _onBeforeUndoRedo(isUndo: boolean): void;
130
273
  /** @internal */
131
274
  protected _onAfterUndoRedo(isUndo: boolean): void;
132
- private _onRebaseTxnBegin;
133
- private _onRebaseTxnEnd;
134
275
  private _onRebaseLocalTxnConflict;
276
+ /**
277
+ * @alpha
278
+ * Retrieves the txn properties for a given txn ID.
279
+ *
280
+ * @param id - The unique identifier of the transaction.
281
+ * @returns The properties of the transaction if found; otherwise, `undefined`.
282
+ */
283
+ getTxnProps(id: TxnIdString): TxnProps | undefined;
284
+ /**
285
+ * @alpha
286
+ * Iterates over all transactions in the sequence, yielding each transaction's properties.
287
+ *
288
+ * @yields {TxnProps} The properties of each transaction in the sequence.
289
+ */
290
+ queryTxns(): Generator<TxnProps>;
291
+ /**
292
+ * @alpha
293
+ * Retrieves the properties of the last saved txn via `IModelDb.saveChanges()`, if available.
294
+ *
295
+ * @returns The properties of the last saved txn, or `undefined` if none exist.
296
+ */
297
+ getLastSavedTxnProps(): TxnProps | undefined;
135
298
  /** Dependency handlers may call method this to report a validation error.
136
299
  * @param error The error. If error.fatal === true, the transaction will cancel rather than commit.
137
300
  */
@@ -178,12 +341,18 @@ export declare class TxnManager {
178
341
  * @see [[onReplayExternalTxns]] for the event raised before the changes are applied.
179
342
  */
180
343
  readonly onReplayedExternalTxns: BeEvent<() => void>;
181
- /** @internal */
182
- readonly onRebaseTxnBegin: BeEvent<(txn: TxnArgs) => void>;
183
- /** @internal */
184
- readonly onRebaseTxnEnd: BeEvent<(txn: TxnArgs) => void>;
185
344
  /**
186
- * if handler is set and it does not return undefiend then default handler will not be called
345
+ * @alpha
346
+ * Event raised when a rebase transaction begins.
347
+ */
348
+ readonly onRebaseTxnBegin: BeEvent<(txn: TxnProps) => void>;
349
+ /**
350
+ * @alpha
351
+ * Event raised when a rebase transaction ends.
352
+ */
353
+ readonly onRebaseTxnEnd: BeEvent<(txn: TxnProps) => void>;
354
+ /**
355
+ * if handler is set and it does not return undefined then default handler will not be called
187
356
  * @internal
188
357
  * */
189
358
  appCustomConflictHandler?: (args: DbRebaseChangesetConflictArgs) => DbConflictResolution | undefined;
@@ -259,6 +428,11 @@ export declare class TxnManager {
259
428
  queryPreviousTxnId(txnId: TxnIdString): TxnIdString;
260
429
  /** Get the Id of the current (tip) transaction. */
261
430
  getCurrentTxnId(): TxnIdString;
431
+ /**
432
+ * @alpha
433
+ * Get the Id of the current session.
434
+ */
435
+ getCurrentSessionId(): number;
262
436
  /** Get the description that was supplied when the specified transaction was saved. */
263
437
  getTxnDescription(txnId: TxnIdString): string;
264
438
  /** Test if a TxnId is valid */
@@ -272,6 +446,11 @@ export declare class TxnManager {
272
446
  * @see [[IModelDb.saveChanges]]
273
447
  */
274
448
  get hasUnsavedChanges(): boolean;
449
+ /**
450
+ * @alpha
451
+ * Query if there are any pending schema changes in this IModelDb.
452
+ */
453
+ get hasPendingSchemaChanges(): boolean;
275
454
  /**
276
455
  * Query if there are changes in memory that have not been saved to the iModelDb or if there are Txns that are waiting to be pushed.
277
456
  * @see [[IModelDb.saveChanges]]
@@ -292,5 +471,37 @@ export declare class TxnManager {
292
471
  * changes to the iModel, for debugging/diagnostic purposes, as reported by [sqlite3session_memory_used](https://www.sqlite.org/session/sqlite3session_memory_used.html).
293
472
  */
294
473
  getChangeTrackingMemoryUsed(): number;
474
+ /**
475
+ * @alpha
476
+ * Get the current transaction mode.
477
+ * @returns The current transaction mode, either "direct" or "indirect".
478
+ */
479
+ getMode(): TxnMode;
480
+ /**
481
+ * @alpha
482
+ * Execute a series of changes in an indirect transaction.
483
+ * @param callback The function containing the changes to make.
484
+ */
485
+ withIndirectTxnMode(callback: () => void): void;
486
+ }
487
+ /**
488
+ * Interface for handling rebase operations on transactions.
489
+ * @alpha
490
+ */
491
+ export interface RebaseHandler {
492
+ /**
493
+ * Determine whether a transaction should be reinstated during a rebase operation.
494
+ * @param txn The transaction to check.
495
+ *
496
+ * @alpha
497
+ */
498
+ shouldReinstate(txn: TxnProps): boolean;
499
+ /**
500
+ * Recompute the changes for a given transaction.
501
+ * @param txn The transaction to recompute.
502
+ *
503
+ * @alpha
504
+ */
505
+ recompute(txn: TxnProps): Promise<void>;
295
506
  }
296
507
  //# sourceMappingURL=TxnManager.d.ts.map