@itwin/core-backend 5.10.0-dev.9 → 5.10.1

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 (278) hide show
  1. package/CHANGELOG.md +50 -1
  2. package/lib/cjs/BriefcaseManager.d.ts +8 -1
  3. package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
  4. package/lib/cjs/BriefcaseManager.js.map +1 -1
  5. package/lib/cjs/Category.d.ts +4 -4
  6. package/lib/cjs/Category.js.map +1 -1
  7. package/lib/cjs/ChangesetECAdaptor.d.ts +6 -6
  8. package/lib/cjs/ChangesetECAdaptor.js +4 -4
  9. package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
  10. package/lib/cjs/ChangesetReader.d.ts +84 -1
  11. package/lib/cjs/ChangesetReader.d.ts.map +1 -1
  12. package/lib/cjs/ChangesetReader.js +108 -12
  13. package/lib/cjs/ChangesetReader.js.map +1 -1
  14. package/lib/cjs/ClassRegistry.d.ts +3 -3
  15. package/lib/cjs/ClassRegistry.js +3 -3
  16. package/lib/cjs/ClassRegistry.js.map +1 -1
  17. package/lib/cjs/CodeSpecs.d.ts +3 -3
  18. package/lib/cjs/CodeSpecs.js.map +1 -1
  19. package/lib/cjs/DisplayStyle.d.ts +2 -2
  20. package/lib/cjs/DisplayStyle.js.map +1 -1
  21. package/lib/cjs/ECSqlStatement.d.ts.map +1 -1
  22. package/lib/cjs/ECSqlStatement.js +4 -0
  23. package/lib/cjs/ECSqlStatement.js.map +1 -1
  24. package/lib/cjs/ECSqlSyncReader.d.ts.map +1 -1
  25. package/lib/cjs/ECSqlSyncReader.js +1 -0
  26. package/lib/cjs/ECSqlSyncReader.js.map +1 -1
  27. package/lib/cjs/Element.d.ts +16 -13
  28. package/lib/cjs/Element.d.ts.map +1 -1
  29. package/lib/cjs/Element.js +8 -5
  30. package/lib/cjs/Element.js.map +1 -1
  31. package/lib/cjs/ElementAspect.d.ts +1 -1
  32. package/lib/cjs/ElementAspect.js.map +1 -1
  33. package/lib/cjs/ElementTreeWalker.d.ts +5 -5
  34. package/lib/cjs/ElementTreeWalker.js.map +1 -1
  35. package/lib/cjs/Entity.d.ts +13 -5
  36. package/lib/cjs/Entity.d.ts.map +1 -1
  37. package/lib/cjs/Entity.js +13 -5
  38. package/lib/cjs/Entity.js.map +1 -1
  39. package/lib/cjs/ExternalSource.d.ts +2 -2
  40. package/lib/cjs/ExternalSource.js.map +1 -1
  41. package/lib/cjs/IModelDb.d.ts +112 -40
  42. package/lib/cjs/IModelDb.d.ts.map +1 -1
  43. package/lib/cjs/IModelDb.js +215 -42
  44. package/lib/cjs/IModelDb.js.map +1 -1
  45. package/lib/cjs/LineStyle.d.ts +6 -6
  46. package/lib/cjs/LineStyle.js.map +1 -1
  47. package/lib/cjs/LocalHub.d.ts +6 -0
  48. package/lib/cjs/LocalHub.d.ts.map +1 -1
  49. package/lib/cjs/LocalHub.js +23 -0
  50. package/lib/cjs/LocalHub.js.map +1 -1
  51. package/lib/cjs/Material.d.ts +1 -1
  52. package/lib/cjs/Material.js.map +1 -1
  53. package/lib/cjs/Model.d.ts +6 -6
  54. package/lib/cjs/Model.js.map +1 -1
  55. package/lib/cjs/Relationship.d.ts +13 -11
  56. package/lib/cjs/Relationship.d.ts.map +1 -1
  57. package/lib/cjs/Relationship.js +9 -7
  58. package/lib/cjs/Relationship.js.map +1 -1
  59. package/lib/cjs/SheetIndex.d.ts +4 -4
  60. package/lib/cjs/SheetIndex.js.map +1 -1
  61. package/lib/cjs/Texture.d.ts +1 -1
  62. package/lib/cjs/Texture.js.map +1 -1
  63. package/lib/cjs/TxnManager.d.ts.map +1 -1
  64. package/lib/cjs/TxnManager.js +7 -0
  65. package/lib/cjs/TxnManager.js.map +1 -1
  66. package/lib/cjs/ViewDefinition.d.ts +6 -6
  67. package/lib/cjs/ViewDefinition.js.map +1 -1
  68. package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +1 -1
  69. package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  70. package/lib/cjs/annotations/FrameGeometry.d.ts.map +1 -1
  71. package/lib/cjs/annotations/FrameGeometry.js +2 -3
  72. package/lib/cjs/annotations/FrameGeometry.js.map +1 -1
  73. package/lib/cjs/assets/Settings/Schemas/Base.Schema.json +6 -2
  74. package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +1 -0
  75. package/lib/cjs/domains/FunctionalElements.d.ts +1 -1
  76. package/lib/cjs/domains/FunctionalElements.js.map +1 -1
  77. package/lib/cjs/domains/GenericElements.d.ts +2 -2
  78. package/lib/cjs/domains/GenericElements.js.map +1 -1
  79. package/lib/cjs/internal/ChannelAdmin.d.ts +2 -2
  80. package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
  81. package/lib/cjs/internal/ElementLRUCache.d.ts.map +1 -1
  82. package/lib/cjs/internal/ElementLRUCache.js +23 -4
  83. package/lib/cjs/internal/ElementLRUCache.js.map +1 -1
  84. package/lib/cjs/internal/HubMock.d.ts +24 -1
  85. package/lib/cjs/internal/HubMock.d.ts.map +1 -1
  86. package/lib/cjs/internal/HubMock.js +60 -39
  87. package/lib/cjs/internal/HubMock.js.map +1 -1
  88. package/lib/cjs/internal/ServerBasedLocks.d.ts +19 -1
  89. package/lib/cjs/internal/ServerBasedLocks.d.ts.map +1 -1
  90. package/lib/cjs/internal/ServerBasedLocks.js +55 -1
  91. package/lib/cjs/internal/ServerBasedLocks.js.map +1 -1
  92. package/lib/cjs/internal/cross-package.d.ts +1 -1
  93. package/lib/cjs/internal/cross-package.d.ts.map +1 -1
  94. package/lib/cjs/internal/cross-package.js +1 -2
  95. package/lib/cjs/internal/cross-package.js.map +1 -1
  96. package/lib/cjs/internal/workspace/SettingsSchemasImpl.d.ts.map +1 -1
  97. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js +55 -9
  98. package/lib/cjs/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  99. package/lib/cjs/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  100. package/lib/cjs/internal/workspace/WorkspaceImpl.js +7 -11
  101. package/lib/cjs/internal/workspace/WorkspaceImpl.js.map +1 -1
  102. package/lib/cjs/workspace/SettingsSchemas.d.ts +20 -3
  103. package/lib/cjs/workspace/SettingsSchemas.d.ts.map +1 -1
  104. package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
  105. package/lib/cjs/workspace/Workspace.d.ts +3 -1
  106. package/lib/cjs/workspace/Workspace.d.ts.map +1 -1
  107. package/lib/cjs/workspace/Workspace.js.map +1 -1
  108. package/lib/esm/BriefcaseManager.d.ts +8 -1
  109. package/lib/esm/BriefcaseManager.d.ts.map +1 -1
  110. package/lib/esm/BriefcaseManager.js.map +1 -1
  111. package/lib/esm/Category.d.ts +4 -4
  112. package/lib/esm/Category.js.map +1 -1
  113. package/lib/esm/ChangesetECAdaptor.d.ts +6 -6
  114. package/lib/esm/ChangesetECAdaptor.js +4 -4
  115. package/lib/esm/ChangesetECAdaptor.js.map +1 -1
  116. package/lib/esm/ChangesetReader.d.ts +84 -1
  117. package/lib/esm/ChangesetReader.d.ts.map +1 -1
  118. package/lib/esm/ChangesetReader.js +108 -12
  119. package/lib/esm/ChangesetReader.js.map +1 -1
  120. package/lib/esm/ClassRegistry.d.ts +3 -3
  121. package/lib/esm/ClassRegistry.js +3 -3
  122. package/lib/esm/ClassRegistry.js.map +1 -1
  123. package/lib/esm/CodeSpecs.d.ts +3 -3
  124. package/lib/esm/CodeSpecs.js.map +1 -1
  125. package/lib/esm/DisplayStyle.d.ts +2 -2
  126. package/lib/esm/DisplayStyle.js.map +1 -1
  127. package/lib/esm/ECSqlStatement.d.ts.map +1 -1
  128. package/lib/esm/ECSqlStatement.js +4 -0
  129. package/lib/esm/ECSqlStatement.js.map +1 -1
  130. package/lib/esm/ECSqlSyncReader.d.ts.map +1 -1
  131. package/lib/esm/ECSqlSyncReader.js +1 -0
  132. package/lib/esm/ECSqlSyncReader.js.map +1 -1
  133. package/lib/esm/Element.d.ts +16 -13
  134. package/lib/esm/Element.d.ts.map +1 -1
  135. package/lib/esm/Element.js +8 -5
  136. package/lib/esm/Element.js.map +1 -1
  137. package/lib/esm/ElementAspect.d.ts +1 -1
  138. package/lib/esm/ElementAspect.js.map +1 -1
  139. package/lib/esm/ElementTreeWalker.d.ts +5 -5
  140. package/lib/esm/ElementTreeWalker.js.map +1 -1
  141. package/lib/esm/Entity.d.ts +13 -5
  142. package/lib/esm/Entity.d.ts.map +1 -1
  143. package/lib/esm/Entity.js +13 -5
  144. package/lib/esm/Entity.js.map +1 -1
  145. package/lib/esm/ExternalSource.d.ts +2 -2
  146. package/lib/esm/ExternalSource.js.map +1 -1
  147. package/lib/esm/IModelDb.d.ts +112 -40
  148. package/lib/esm/IModelDb.d.ts.map +1 -1
  149. package/lib/esm/IModelDb.js +216 -43
  150. package/lib/esm/IModelDb.js.map +1 -1
  151. package/lib/esm/LineStyle.d.ts +6 -6
  152. package/lib/esm/LineStyle.js.map +1 -1
  153. package/lib/esm/LocalHub.d.ts +6 -0
  154. package/lib/esm/LocalHub.d.ts.map +1 -1
  155. package/lib/esm/LocalHub.js +23 -0
  156. package/lib/esm/LocalHub.js.map +1 -1
  157. package/lib/esm/Material.d.ts +1 -1
  158. package/lib/esm/Material.js.map +1 -1
  159. package/lib/esm/Model.d.ts +6 -6
  160. package/lib/esm/Model.js.map +1 -1
  161. package/lib/esm/Relationship.d.ts +13 -11
  162. package/lib/esm/Relationship.d.ts.map +1 -1
  163. package/lib/esm/Relationship.js +9 -7
  164. package/lib/esm/Relationship.js.map +1 -1
  165. package/lib/esm/SheetIndex.d.ts +4 -4
  166. package/lib/esm/SheetIndex.js.map +1 -1
  167. package/lib/esm/Texture.d.ts +1 -1
  168. package/lib/esm/Texture.js.map +1 -1
  169. package/lib/esm/TxnManager.d.ts.map +1 -1
  170. package/lib/esm/TxnManager.js +7 -0
  171. package/lib/esm/TxnManager.js.map +1 -1
  172. package/lib/esm/ViewDefinition.d.ts +6 -6
  173. package/lib/esm/ViewDefinition.js.map +1 -1
  174. package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +1 -1
  175. package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
  176. package/lib/esm/annotations/FrameGeometry.d.ts.map +1 -1
  177. package/lib/esm/annotations/FrameGeometry.js +2 -3
  178. package/lib/esm/annotations/FrameGeometry.js.map +1 -1
  179. package/lib/esm/domains/FunctionalElements.d.ts +1 -1
  180. package/lib/esm/domains/FunctionalElements.js.map +1 -1
  181. package/lib/esm/domains/GenericElements.d.ts +2 -2
  182. package/lib/esm/domains/GenericElements.js.map +1 -1
  183. package/lib/esm/internal/ChannelAdmin.d.ts +2 -2
  184. package/lib/esm/internal/ChannelAdmin.js.map +1 -1
  185. package/lib/esm/internal/ElementLRUCache.d.ts.map +1 -1
  186. package/lib/esm/internal/ElementLRUCache.js +23 -4
  187. package/lib/esm/internal/ElementLRUCache.js.map +1 -1
  188. package/lib/esm/internal/HubMock.d.ts +24 -1
  189. package/lib/esm/internal/HubMock.d.ts.map +1 -1
  190. package/lib/esm/internal/HubMock.js +61 -40
  191. package/lib/esm/internal/HubMock.js.map +1 -1
  192. package/lib/esm/internal/ServerBasedLocks.d.ts +19 -1
  193. package/lib/esm/internal/ServerBasedLocks.d.ts.map +1 -1
  194. package/lib/esm/internal/ServerBasedLocks.js +55 -1
  195. package/lib/esm/internal/ServerBasedLocks.js.map +1 -1
  196. package/lib/esm/internal/cross-package.d.ts +1 -1
  197. package/lib/esm/internal/cross-package.d.ts.map +1 -1
  198. package/lib/esm/internal/cross-package.js +1 -1
  199. package/lib/esm/internal/cross-package.js.map +1 -1
  200. package/lib/esm/internal/workspace/SettingsSchemasImpl.d.ts.map +1 -1
  201. package/lib/esm/internal/workspace/SettingsSchemasImpl.js +55 -9
  202. package/lib/esm/internal/workspace/SettingsSchemasImpl.js.map +1 -1
  203. package/lib/esm/internal/workspace/WorkspaceImpl.d.ts.map +1 -1
  204. package/lib/esm/internal/workspace/WorkspaceImpl.js +7 -11
  205. package/lib/esm/internal/workspace/WorkspaceImpl.js.map +1 -1
  206. package/lib/esm/test/ElementLRUCache.test.js +60 -0
  207. package/lib/esm/test/ElementLRUCache.test.js.map +1 -1
  208. package/lib/esm/test/SchemaChangesetCanBeReversed.test.d.ts +2 -0
  209. package/lib/esm/test/SchemaChangesetCanBeReversed.test.d.ts.map +1 -0
  210. package/lib/esm/test/SchemaChangesetCanBeReversed.test.js +239 -0
  211. package/lib/esm/test/SchemaChangesetCanBeReversed.test.js.map +1 -0
  212. package/lib/esm/test/annotations/FrameGeometry.test.js +2 -1
  213. package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
  214. package/lib/esm/test/ecdb/CTE.test.js +1 -0
  215. package/lib/esm/test/ecdb/CTE.test.js.map +1 -1
  216. package/lib/esm/test/ecdb/ECSqlQuery.test.js +10 -2
  217. package/lib/esm/test/ecdb/ECSqlQuery.test.js.map +1 -1
  218. package/lib/esm/test/ecdb/ECSqlStatement.test.js +10 -0
  219. package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
  220. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js +1 -0
  221. package/lib/esm/test/ecdb/ECSqlSyncReader.test.js.map +1 -1
  222. package/lib/esm/test/ecdb/QueryReaders.test.js +13 -0
  223. package/lib/esm/test/ecdb/QueryReaders.test.js.map +1 -1
  224. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js +1 -0
  225. package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
  226. package/lib/esm/test/element/DeleteDefinitionElements.test.js +6 -2
  227. package/lib/esm/test/element/DeleteDefinitionElements.test.js.map +1 -1
  228. package/lib/esm/test/element/ElementRoundTrip.test.js +5 -0
  229. package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
  230. package/lib/esm/test/element/ExcludedElements.test.js +1 -0
  231. package/lib/esm/test/element/ExcludedElements.test.js.map +1 -1
  232. package/lib/esm/test/hubaccess/ApplyChangeset.test.js +10 -0
  233. package/lib/esm/test/hubaccess/ApplyChangeset.test.js.map +1 -1
  234. package/lib/esm/test/hubaccess/SemanticRebase.test.js +1 -0
  235. package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
  236. package/lib/esm/test/imodel/IModel.test.js +31 -0
  237. package/lib/esm/test/imodel/IModel.test.js.map +1 -1
  238. package/lib/esm/test/schema/ClassRegistry.test.js +3 -0
  239. package/lib/esm/test/schema/ClassRegistry.test.js.map +1 -1
  240. package/lib/esm/test/schema/IModelSchemaContext.test.js +2 -0
  241. package/lib/esm/test/schema/IModelSchemaContext.test.js.map +1 -1
  242. package/lib/esm/test/schema/SchemaViewHidden.test.d.ts +2 -0
  243. package/lib/esm/test/schema/SchemaViewHidden.test.d.ts.map +1 -0
  244. package/lib/esm/test/schema/SchemaViewHidden.test.js +275 -0
  245. package/lib/esm/test/schema/SchemaViewHidden.test.js.map +1 -0
  246. package/lib/esm/test/schema/SchemaViewKoQ.test.d.ts +2 -0
  247. package/lib/esm/test/schema/SchemaViewKoQ.test.d.ts.map +1 -0
  248. package/lib/esm/test/schema/SchemaViewKoQ.test.js +184 -0
  249. package/lib/esm/test/schema/SchemaViewKoQ.test.js.map +1 -0
  250. package/lib/esm/test/schema/SchemaViewLifecycle.test.d.ts +2 -0
  251. package/lib/esm/test/schema/SchemaViewLifecycle.test.d.ts.map +1 -0
  252. package/lib/esm/test/schema/SchemaViewLifecycle.test.js +141 -0
  253. package/lib/esm/test/schema/SchemaViewLifecycle.test.js.map +1 -0
  254. package/lib/esm/test/schema/SchemaViewValidation.test.d.ts +2 -0
  255. package/lib/esm/test/schema/SchemaViewValidation.test.d.ts.map +1 -0
  256. package/lib/esm/test/schema/SchemaViewValidation.test.js +475 -0
  257. package/lib/esm/test/schema/SchemaViewValidation.test.js.map +1 -0
  258. package/lib/esm/test/standalone/ChangesetReader.test.js +945 -337
  259. package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
  260. package/lib/esm/test/standalone/DeleteElements.test.js +45 -0
  261. package/lib/esm/test/standalone/DeleteElements.test.js.map +1 -1
  262. package/lib/esm/test/standalone/IModelWrite.test.js +6 -0
  263. package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
  264. package/lib/esm/test/standalone/ServerBasedLocks.test.js +62 -0
  265. package/lib/esm/test/standalone/ServerBasedLocks.test.js.map +1 -1
  266. package/lib/esm/test/standalone/Settings.test.js +2 -0
  267. package/lib/esm/test/standalone/Settings.test.js.map +1 -1
  268. package/lib/esm/test/standalone/SettingsSchemas.test.js +397 -0
  269. package/lib/esm/test/standalone/SettingsSchemas.test.js.map +1 -1
  270. package/lib/esm/test/standalone/Workspace.test.js +23 -0
  271. package/lib/esm/test/standalone/Workspace.test.js.map +1 -1
  272. package/lib/esm/workspace/SettingsSchemas.d.ts +20 -3
  273. package/lib/esm/workspace/SettingsSchemas.d.ts.map +1 -1
  274. package/lib/esm/workspace/SettingsSchemas.js.map +1 -1
  275. package/lib/esm/workspace/Workspace.d.ts +3 -1
  276. package/lib/esm/workspace/Workspace.d.ts.map +1 -1
  277. package/lib/esm/workspace/Workspace.js.map +1 -1
  278. package/package.json +15 -15
@@ -221,16 +221,15 @@ describe("ChangesetReader insert-full", () => {
221
221
  // Object.keys
222
222
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
223
223
  // $meta keys
224
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
224
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
225
225
  assert.equal(modelNew.$meta.op, "Updated");
226
226
  assert.equal(modelNew.$meta.stage, "New");
227
- assert.deepEqual([...modelNew.$meta.tables].sort(), ["bis_Model"].sort());
228
- assert.deepEqual([...modelNew.$meta.changeIndexes].sort(), [3].sort());
227
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
228
+ assert.deepEqual(modelNew.$meta.changeIndexes, [3]);
229
229
  assert.isString(modelNew.$meta.instanceKey);
230
230
  assert.equal(modelNew.$meta.instanceKey.split(`-`).length, 2);
231
231
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
232
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
233
- assert.deepEqual(modelNew.$meta.rowOptions, {});
232
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
234
233
  assert.equal(modelNew.$meta.isIndirectChange, true);
235
234
  // --- instances[1]: DrawingModel Updated Old ---
236
235
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -240,13 +239,12 @@ describe("ChangesetReader insert-full", () => {
240
239
  // Object.keys
241
240
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
242
241
  // $meta keys
243
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
242
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
244
243
  assert.equal(modelOld.$meta.op, "Updated");
245
244
  assert.equal(modelOld.$meta.stage, "Old");
246
- assert.deepEqual([...modelOld.$meta.tables].sort(), ["bis_Model"].sort());
245
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
247
246
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
248
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
249
- assert.deepEqual(modelOld.$meta.rowOptions, {});
247
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
250
248
  assert.equal(modelOld.$meta.isIndirectChange, true);
251
249
  // --- instances[2]: Test2dElement Inserted New ---
252
250
  const elem = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "New");
@@ -294,15 +292,15 @@ describe("ChangesetReader insert-full", () => {
294
292
  "Pt2dProp", "Pt3dProp", "StructProp", "IntArrProp", "StrArrProp", "StructArrProp", "RelatedElem", "BinProp"
295
293
  ].sort());
296
294
  // $meta keys
297
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
295
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
298
296
  assert.equal(elem.$meta.op, "Inserted");
299
297
  assert.equal(elem.$meta.stage, "New");
300
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
301
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
298
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
299
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
302
300
  assert.isString(elem.$meta.instanceKey);
303
301
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
304
302
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
305
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
303
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
306
304
  'BBoxHigh', 'BBoxLow', 'BinProp', 'BoolProp', 'Category.Id', 'CodeScope.Id',
307
305
  'CodeSpec.Id', 'CodeValue', 'DblProp', 'DtProp', 'ECClassId', 'ECInstanceId',
308
306
  'FederationGuid', 'GeometryStream', 'IntArrProp', 'IntProp', 'JsonProperties',
@@ -311,7 +309,6 @@ describe("ChangesetReader insert-full", () => {
311
309
  'StructProp.Pt2d', 'StructProp.Pt3d', 'StructProp.X', 'StructProp.Y', 'StructProp.Z',
312
310
  'TypeDefinition', 'UserLabel'
313
311
  ].sort());
314
- assert.deepEqual(elem.$meta.rowOptions, {});
315
312
  assert.equal(elem.$meta.isIndirectChange, false);
316
313
  });
317
314
  it("txn1 insert-full | All_Properties | default rowOptions | invert", () => {
@@ -327,16 +324,15 @@ describe("ChangesetReader insert-full", () => {
327
324
  // Object.keys
328
325
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
329
326
  // $meta keys
330
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
327
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
331
328
  assert.equal(modelNew.$meta.op, "Updated");
332
329
  assert.equal(modelNew.$meta.stage, "New");
333
- assert.deepEqual([...modelNew.$meta.tables].sort(), ["bis_Model"].sort());
334
- assert.deepEqual([...modelNew.$meta.changeIndexes].sort(), [3].sort());
330
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
331
+ assert.deepEqual(modelNew.$meta.changeIndexes, [3]);
335
332
  assert.isString(modelNew.$meta.instanceKey);
336
333
  assert.equal(modelNew.$meta.instanceKey.split(`-`).length, 2);
337
334
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
338
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
339
- assert.deepEqual(modelNew.$meta.rowOptions, {});
335
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
340
336
  assert.equal(modelNew.$meta.isIndirectChange, true);
341
337
  // --- instances[1]: DrawingModel Updated Old ---
342
338
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -348,13 +344,12 @@ describe("ChangesetReader insert-full", () => {
348
344
  // Object.keys
349
345
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta", "LastMod", "GeometryGuid"].sort());
350
346
  // $meta keys
351
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
347
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
352
348
  assert.equal(modelOld.$meta.op, "Updated");
353
349
  assert.equal(modelOld.$meta.stage, "Old");
354
- assert.deepEqual([...modelOld.$meta.tables].sort(), ["bis_Model"].sort());
350
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
355
351
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
356
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
357
- assert.deepEqual(modelOld.$meta.rowOptions, {});
352
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
358
353
  assert.equal(modelOld.$meta.isIndirectChange, true);
359
354
  // --- instances[2]: Test2dElement Inserted New ---
360
355
  const elem = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "Old");
@@ -402,15 +397,15 @@ describe("ChangesetReader insert-full", () => {
402
397
  "Pt2dProp", "Pt3dProp", "StructProp", "IntArrProp", "StrArrProp", "StructArrProp", "RelatedElem", "BinProp"
403
398
  ].sort());
404
399
  // $meta keys
405
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
400
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
406
401
  assert.equal(elem.$meta.op, "Deleted");
407
402
  assert.equal(elem.$meta.stage, "Old");
408
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
409
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
403
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
404
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
410
405
  assert.isString(elem.$meta.instanceKey);
411
406
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
412
407
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
413
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
408
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
414
409
  'BBoxHigh', 'BBoxLow', 'BinProp', 'BoolProp', 'Category.Id', 'CodeScope.Id',
415
410
  'CodeSpec.Id', 'CodeValue', 'DblProp', 'DtProp', 'ECClassId', 'ECInstanceId',
416
411
  'FederationGuid', 'GeometryStream', 'IntArrProp', 'IntProp', 'JsonProperties',
@@ -419,7 +414,6 @@ describe("ChangesetReader insert-full", () => {
419
414
  'StructProp.Pt2d', 'StructProp.Pt3d', 'StructProp.X', 'StructProp.Y', 'StructProp.Z',
420
415
  'TypeDefinition', 'UserLabel'
421
416
  ].sort());
422
- assert.deepEqual(elem.$meta.rowOptions, {});
423
417
  assert.equal(elem.$meta.isIndirectChange, false);
424
418
  });
425
419
  it("txn1 insert-full | Bis_Element_Properties", () => {
@@ -437,7 +431,7 @@ describe("ChangesetReader insert-full", () => {
437
431
  assert.equal(modelNew.$meta.op, "Updated");
438
432
  assert.equal(modelNew.$meta.stage, "New");
439
433
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.BisCoreElement);
440
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
434
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
441
435
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
442
436
  assert.equal(modelNew.$meta.isIndirectChange, true);
443
437
  // --- instances[1]: DrawingModel Updated Old ---
@@ -450,7 +444,7 @@ describe("ChangesetReader insert-full", () => {
450
444
  assert.equal(modelOld.$meta.op, "Updated");
451
445
  assert.equal(modelOld.$meta.stage, "Old");
452
446
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.BisCoreElement);
453
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
447
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
454
448
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true });
455
449
  assert.equal(modelOld.$meta.isIndirectChange, true);
456
450
  // --- instances[2]: Test2dElement Inserted New (Bis_Element_Properties: no custom props) ---
@@ -481,12 +475,12 @@ describe("ChangesetReader insert-full", () => {
481
475
  assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
482
476
  assert.equal(elem.$meta.op, "Inserted");
483
477
  assert.equal(elem.$meta.stage, "New");
484
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
485
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
478
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
479
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
486
480
  assert.isString(elem.$meta.instanceKey);
487
481
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
488
482
  assert.equal(elem.$meta.propFilter, PropertyFilter.BisCoreElement);
489
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "ECClassId", "CodeScope.Id", "CodeSpec.Id",
483
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "ECClassId", "CodeScope.Id", "CodeSpec.Id",
490
484
  "CodeValue", "FederationGuid", "JsonProperties", "LastMod", "Model.Id", "Parent", "UserLabel"].sort());
491
485
  assert.deepEqual(elem.$meta.rowOptions, { classIdsToClassNames: true });
492
486
  assert.equal(elem.$meta.isIndirectChange, false);
@@ -500,16 +494,15 @@ describe("ChangesetReader insert-full", () => {
500
494
  assert.equal(modelNew.ECInstanceId, drawingModelId);
501
495
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelNew.ECClassId));
502
496
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
503
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
497
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
504
498
  assert.equal(modelNew.$meta.op, "Updated");
505
499
  assert.equal(modelNew.$meta.stage, "New");
506
- assert.deepEqual([...modelNew.$meta.tables].sort(), ["bis_Model"].sort());
507
- assert.deepEqual([...modelNew.$meta.changeIndexes].sort(), [3].sort());
500
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
501
+ assert.deepEqual(modelNew.$meta.changeIndexes, [3]);
508
502
  assert.isString(modelNew.$meta.instanceKey);
509
503
  assert.equal(modelNew.$meta.instanceKey.split(`-`).length, 2);
510
504
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.InstanceKey);
511
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
512
- assert.deepEqual(modelNew.$meta.rowOptions, {});
505
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames, ["ECInstanceId"]);
513
506
  assert.equal(modelNew.$meta.isIndirectChange, true);
514
507
  // --- instances[1]: DrawingModel Updated Old ---
515
508
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -517,12 +510,11 @@ describe("ChangesetReader insert-full", () => {
517
510
  assert.equal(modelOld.ECInstanceId, drawingModelId);
518
511
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
519
512
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
520
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
513
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
521
514
  assert.equal(modelOld.$meta.op, "Updated");
522
515
  assert.equal(modelOld.$meta.stage, "Old");
523
516
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.InstanceKey);
524
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
525
- assert.deepEqual(modelOld.$meta.rowOptions, {});
517
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames, ["ECInstanceId"]);
526
518
  assert.equal(modelOld.$meta.isIndirectChange, true);
527
519
  // --- instances[2]: Test2dElement Inserted New (only ECInstanceId + ECClassId) ---
528
520
  const elem = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "New");
@@ -534,16 +526,15 @@ describe("ChangesetReader insert-full", () => {
534
526
  assert.isUndefined(elem.Category);
535
527
  assert.isUndefined(elem.LastMod);
536
528
  assert.deepEqual(Object.keys(elem).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
537
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
529
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
538
530
  assert.equal(elem.$meta.op, "Inserted");
539
531
  assert.equal(elem.$meta.stage, "New");
540
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
541
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
532
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
533
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
542
534
  assert.isString(elem.$meta.instanceKey);
543
535
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
544
536
  assert.equal(elem.$meta.propFilter, PropertyFilter.InstanceKey);
545
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "ECClassId"].sort());
546
- assert.deepEqual(elem.$meta.rowOptions, {});
537
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "ECClassId"].sort());
547
538
  assert.equal(elem.$meta.isIndirectChange, false);
548
539
  });
549
540
  it("txn1 | rowOptions: classIdsToClassNames", () => {
@@ -561,7 +552,7 @@ describe("ChangesetReader insert-full", () => {
561
552
  assert.equal(modelNew.$meta.op, "Updated");
562
553
  assert.equal(modelNew.$meta.stage, "New");
563
554
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
564
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
555
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
565
556
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
566
557
  assert.equal(modelNew.$meta.isIndirectChange, true);
567
558
  // --- instances[1]: DrawingModel Updated Old ---
@@ -574,7 +565,7 @@ describe("ChangesetReader insert-full", () => {
574
565
  assert.equal(modelOld.$meta.op, "Updated");
575
566
  assert.equal(modelOld.$meta.stage, "Old");
576
567
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
577
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
568
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
578
569
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true });
579
570
  assert.equal(modelOld.$meta.isIndirectChange, true);
580
571
  // --- instances[2]: Test2dElement Inserted New (ECClassId + all RelECClassId = class names) ---
@@ -618,7 +609,7 @@ describe("ChangesetReader insert-full", () => {
618
609
  assert.equal(elem.$meta.stage, "New");
619
610
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
620
611
  assert.deepEqual(elem.$meta.rowOptions, { classIdsToClassNames: true });
621
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "ECClassId", "Model.Id", "LastMod", "CodeSpec.Id", "CodeScope.Id",
612
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "ECClassId", "Model.Id", "LastMod", "CodeSpec.Id", "CodeScope.Id",
622
613
  "CodeValue", "UserLabel", "Parent", "FederationGuid", "JsonProperties", "Category.Id",
623
614
  "Origin", "Rotation", "BBoxLow", "BBoxHigh", "GeometryStream", "TypeDefinition", "StrProp",
624
615
  "IntProp", "LongProp", "DblProp", "BoolProp", "DtProp", "BinProp", "Pt2dProp", "Pt3dProp",
@@ -643,7 +634,7 @@ describe("ChangesetReader insert-full", () => {
643
634
  assert.equal(modelNew.$meta.op, "Updated");
644
635
  assert.equal(modelNew.$meta.stage, "New");
645
636
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
646
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
637
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
647
638
  assert.deepEqual(modelNew.$meta.rowOptions, { useJsName: true });
648
639
  assert.equal(modelNew.$meta.isIndirectChange, true);
649
640
  // --- instances[1]: DrawingModel Updated Old ---
@@ -657,7 +648,7 @@ describe("ChangesetReader insert-full", () => {
657
648
  assert.equal(modelOld.$meta.op, "Updated");
658
649
  assert.equal(modelOld.$meta.stage, "Old");
659
650
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
660
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
651
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
661
652
  assert.deepEqual(modelOld.$meta.rowOptions, { useJsName: true });
662
653
  assert.equal(modelOld.$meta.isIndirectChange, true);
663
654
  // --- instances[2]: Test2dElement Inserted New (camelCase keys + class names for nav) ---
@@ -704,7 +695,7 @@ describe("ChangesetReader insert-full", () => {
704
695
  assert.equal(elem.$meta.op, "Inserted");
705
696
  assert.equal(elem.$meta.stage, "New");
706
697
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
707
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
698
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
708
699
  'BBoxHigh', 'BBoxLow', 'BinProp', 'BoolProp', 'Category.Id', 'CodeScope.Id',
709
700
  'CodeSpec.Id', 'CodeValue', 'DblProp', 'DtProp', 'ECClassId',
710
701
  'ECInstanceId', 'FederationGuid', 'GeometryStream', 'IntArrProp', 'IntProp',
@@ -731,7 +722,7 @@ describe("ChangesetReader insert-full", () => {
731
722
  assert.equal(modelNew.$meta.op, "Updated");
732
723
  assert.equal(modelNew.$meta.stage, "New");
733
724
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
734
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
725
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
735
726
  assert.deepEqual(modelNew.$meta.rowOptions, { abbreviateBlobs: true });
736
727
  assert.equal(modelNew.$meta.isIndirectChange, true);
737
728
  // --- instances[1]: DrawingModel Updated Old ---
@@ -744,7 +735,7 @@ describe("ChangesetReader insert-full", () => {
744
735
  assert.equal(modelOld.$meta.op, "Updated");
745
736
  assert.equal(modelOld.$meta.stage, "Old");
746
737
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
747
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
738
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
748
739
  assert.deepEqual(modelOld.$meta.rowOptions, { abbreviateBlobs: true });
749
740
  assert.equal(modelOld.$meta.isIndirectChange, true);
750
741
  // --- instances[2]: Test2dElement Inserted New ---
@@ -811,7 +802,7 @@ describe("ChangesetReader insert-full", () => {
811
802
  assert.equal(modelNew.$meta.op, "Updated");
812
803
  assert.equal(modelNew.$meta.stage, "New");
813
804
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
814
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
805
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
815
806
  assert.deepEqual(modelNew.$meta.rowOptions, { abbreviateBlobs: false });
816
807
  assert.equal(modelNew.$meta.isIndirectChange, true);
817
808
  // --- instances[1]: DrawingModel Updated Old ---
@@ -824,7 +815,7 @@ describe("ChangesetReader insert-full", () => {
824
815
  assert.equal(modelOld.$meta.op, "Updated");
825
816
  assert.equal(modelOld.$meta.stage, "Old");
826
817
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
827
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
818
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
828
819
  assert.deepEqual(modelOld.$meta.rowOptions, { abbreviateBlobs: false });
829
820
  assert.equal(modelOld.$meta.isIndirectChange, true);
830
821
  // --- instances[2]: Test2dElement Inserted New ---
@@ -917,7 +908,7 @@ describe("ChangesetReader insert-full", () => {
917
908
  assert.equal(modelNew.$meta.op, "Updated");
918
909
  assert.equal(modelNew.$meta.stage, "New");
919
910
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
920
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
911
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
921
912
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true, useJsName: true });
922
913
  assert.equal(modelNew.$meta.isIndirectChange, true);
923
914
  // --- instances[1]: DrawingModel Updated Old ---
@@ -931,7 +922,7 @@ describe("ChangesetReader insert-full", () => {
931
922
  assert.equal(modelOld.$meta.op, "Updated");
932
923
  assert.equal(modelOld.$meta.stage, "Old");
933
924
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
934
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
925
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
935
926
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true, useJsName: true });
936
927
  assert.equal(modelOld.$meta.isIndirectChange, true);
937
928
  // --- instances[2]: Test2dElement Inserted New (camelCase + class names) ---
@@ -977,7 +968,7 @@ describe("ChangesetReader insert-full", () => {
977
968
  assert.equal(elem.$meta.op, "Inserted");
978
969
  assert.equal(elem.$meta.stage, "New");
979
970
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
980
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
971
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
981
972
  'BBoxHigh', 'BBoxLow', 'BinProp', 'BoolProp', 'Category.Id',
982
973
  'CodeScope.Id', 'CodeSpec.Id',
983
974
  'CodeValue', 'DblProp', 'DtProp',
@@ -1011,12 +1002,12 @@ describe("ChangesetReader insert-full", () => {
1011
1002
  assert.deepEqual(Object.keys(inMemoryModelNew.$meta).sort(), Object.keys(sqliteBackedModelNew.$meta).sort());
1012
1003
  assert.equal(inMemoryModelNew.$meta.op, sqliteBackedModelNew.$meta.op);
1013
1004
  assert.equal(inMemoryModelNew.$meta.stage, sqliteBackedModelNew.$meta.stage);
1014
- assert.deepEqual([...inMemoryModelNew.$meta.tables].sort(), [...sqliteBackedModelNew.$meta.tables].sort());
1015
- assert.deepEqual([...inMemoryModelNew.$meta.changeIndexes].sort(), [...sqliteBackedModelNew.$meta.changeIndexes].sort());
1005
+ assert.deepEqual(inMemoryModelNew.$meta.tables.sort(), sqliteBackedModelNew.$meta.tables.sort());
1006
+ assert.deepEqual(inMemoryModelNew.$meta.changeIndexes.sort(), sqliteBackedModelNew.$meta.changeIndexes.sort());
1016
1007
  assert.isString(inMemoryModelNew.$meta.instanceKey);
1017
1008
  assert.equal(inMemoryModelNew.$meta.instanceKey.split(`-`).length, 2);
1018
1009
  assert.equal(inMemoryModelNew.$meta.propFilter, sqliteBackedModelNew.$meta.propFilter);
1019
- assert.deepEqual([...inMemoryModelNew.$meta.changeFetchedPropNames].sort(), [...sqliteBackedModelNew.$meta.changeFetchedPropNames].sort());
1010
+ assert.deepEqual(inMemoryModelNew.$meta.changeFetchedPropNames.sort(), sqliteBackedModelNew.$meta.changeFetchedPropNames.sort());
1020
1011
  assert.deepEqual(inMemoryModelNew.$meta.rowOptions, sqliteBackedModelNew.$meta.rowOptions);
1021
1012
  assert.equal(inMemoryModelNew.$meta.isIndirectChange, sqliteBackedModelNew.$meta.isIndirectChange);
1022
1013
  // --- instances[1]: DrawingModel Updated Old ---
@@ -1032,9 +1023,9 @@ describe("ChangesetReader insert-full", () => {
1032
1023
  assert.deepEqual(Object.keys(inMemoryModelOld.$meta).sort(), Object.keys(sqliteBackedModelOld.$meta).sort());
1033
1024
  assert.equal(inMemoryModelOld.$meta.op, sqliteBackedModelOld.$meta.op);
1034
1025
  assert.equal(inMemoryModelOld.$meta.stage, sqliteBackedModelOld.$meta.stage);
1035
- assert.deepEqual([...inMemoryModelOld.$meta.tables].sort(), [...sqliteBackedModelOld.$meta.tables].sort());
1026
+ assert.deepEqual(inMemoryModelOld.$meta.tables.sort(), sqliteBackedModelOld.$meta.tables.sort());
1036
1027
  assert.equal(inMemoryModelOld.$meta.propFilter, sqliteBackedModelOld.$meta.propFilter);
1037
- assert.deepEqual([...inMemoryModelOld.$meta.changeFetchedPropNames].sort(), [...sqliteBackedModelOld.$meta.changeFetchedPropNames].sort());
1028
+ assert.deepEqual(inMemoryModelOld.$meta.changeFetchedPropNames.sort(), sqliteBackedModelOld.$meta.changeFetchedPropNames.sort());
1038
1029
  assert.deepEqual(inMemoryModelOld.$meta.rowOptions, sqliteBackedModelOld.$meta.rowOptions);
1039
1030
  assert.equal(inMemoryModelOld.$meta.isIndirectChange, sqliteBackedModelOld.$meta.isIndirectChange);
1040
1031
  // --- instances[2]: Test2dElement Inserted New ---
@@ -1080,10 +1071,10 @@ describe("ChangesetReader insert-full", () => {
1080
1071
  assert.deepEqual(Object.keys(inMemoryElem.$meta).sort(), Object.keys(sqliteBackedElem.$meta).sort());
1081
1072
  assert.equal(inMemoryElem.$meta.op, sqliteBackedElem.$meta.op);
1082
1073
  assert.equal(inMemoryElem.$meta.stage, sqliteBackedElem.$meta.stage);
1083
- assert.deepEqual([...inMemoryElem.$meta.tables].sort(), [...sqliteBackedElem.$meta.tables].sort());
1084
- assert.deepEqual([...inMemoryElem.$meta.changeIndexes].sort(), [...sqliteBackedElem.$meta.changeIndexes].sort());
1074
+ assert.deepEqual(inMemoryElem.$meta.tables.sort(), sqliteBackedElem.$meta.tables.sort());
1075
+ assert.deepEqual(inMemoryElem.$meta.changeIndexes.sort(), sqliteBackedElem.$meta.changeIndexes.sort());
1085
1076
  assert.equal(inMemoryElem.$meta.instanceKey, sqliteBackedElem.$meta.instanceKey);
1086
- assert.deepEqual([...inMemoryElem.$meta.changeFetchedPropNames].sort(), [...sqliteBackedElem.$meta.changeFetchedPropNames].sort());
1077
+ assert.deepEqual(inMemoryElem.$meta.changeFetchedPropNames.sort(), sqliteBackedElem.$meta.changeFetchedPropNames.sort());
1087
1078
  assert.deepEqual(inMemoryElem.$meta.rowOptions, sqliteBackedElem.$meta.rowOptions);
1088
1079
  assert.equal(inMemoryElem.$meta.isIndirectChange, sqliteBackedElem.$meta.isIndirectChange);
1089
1080
  });
@@ -1258,12 +1249,11 @@ describe("ChangesetReader insert-partial", () => {
1258
1249
  assert.isString(modelNew.LastMod);
1259
1250
  assert.isString(modelNew.GeometryGuid);
1260
1251
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
1261
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1252
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1262
1253
  assert.equal(modelNew.$meta.op, "Updated");
1263
1254
  assert.equal(modelNew.$meta.stage, "New");
1264
1255
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
1265
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1266
- assert.deepEqual(modelNew.$meta.rowOptions, {});
1256
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1267
1257
  assert.equal(modelNew.$meta.isIndirectChange, true);
1268
1258
  // --- instances[1]: DrawingModel Updated Old ---
1269
1259
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -1272,12 +1262,11 @@ describe("ChangesetReader insert-partial", () => {
1272
1262
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
1273
1263
  // Model Old has LastMod and GeometryGuid when previous txn's model New values survive
1274
1264
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
1275
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1265
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1276
1266
  assert.equal(modelOld.$meta.op, "Updated");
1277
1267
  assert.equal(modelOld.$meta.stage, "Old");
1278
1268
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
1279
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1280
- assert.deepEqual(modelOld.$meta.rowOptions, {});
1269
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1281
1270
  assert.equal(modelOld.$meta.isIndirectChange, true);
1282
1271
  // --- instances[2]: Test2dElement (partial) Inserted New ---
1283
1272
  const elem = instances.find((i) => i.ECInstanceId === partialElementId && i.$meta.stage === "New");
@@ -1315,15 +1304,15 @@ describe("ChangesetReader insert-partial", () => {
1315
1304
  "Category",
1316
1305
  ].sort());
1317
1306
  // $meta keys
1318
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1307
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1319
1308
  assert.equal(elem.$meta.op, "Inserted");
1320
1309
  assert.equal(elem.$meta.stage, "New");
1321
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1322
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
1310
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1311
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
1323
1312
  assert.isString(elem.$meta.instanceKey);
1324
1313
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
1325
1314
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
1326
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
1315
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
1327
1316
  'ECInstanceId', 'ECClassId', 'Model.Id', 'LastMod', 'CodeSpec.Id',
1328
1317
  'CodeScope.Id', 'CodeValue', 'UserLabel', 'Parent', 'FederationGuid',
1329
1318
  'JsonProperties', 'Category.Id', 'Origin', 'Rotation', 'BBoxLow', 'BBoxHigh',
@@ -1333,7 +1322,6 @@ describe("ChangesetReader insert-partial", () => {
1333
1322
  'StructProp.Pt2d', 'StructProp.Pt3d', 'IntArrProp', 'StrArrProp',
1334
1323
  'StructArrProp', 'RelatedElem'
1335
1324
  ].sort());
1336
- assert.deepEqual(elem.$meta.rowOptions, {});
1337
1325
  assert.isUndefined(elem.BinProp);
1338
1326
  assert.equal(elem.$meta.isIndirectChange, false);
1339
1327
  });
@@ -1348,12 +1336,11 @@ describe("ChangesetReader insert-partial", () => {
1348
1336
  assert.isUndefined(modelNew.LastMod);
1349
1337
  assert.isUndefined(modelNew.GeometryGuid);
1350
1338
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
1351
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1339
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1352
1340
  assert.equal(modelNew.$meta.op, "Updated");
1353
1341
  assert.equal(modelNew.$meta.stage, "New");
1354
1342
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
1355
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1356
- assert.deepEqual(modelNew.$meta.rowOptions, {});
1343
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1357
1344
  assert.equal(modelNew.$meta.isIndirectChange, true);
1358
1345
  // --- instances[1]: DrawingModel Updated Old ---
1359
1346
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -1364,12 +1351,11 @@ describe("ChangesetReader insert-partial", () => {
1364
1351
  assert.isString(modelOld.GeometryGuid);
1365
1352
  // Model Old has LastMod and GeometryGuid when previous txn's model New values survive
1366
1353
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta", "LastMod", "GeometryGuid"].sort());
1367
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1354
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1368
1355
  assert.equal(modelOld.$meta.op, "Updated");
1369
1356
  assert.equal(modelOld.$meta.stage, "Old");
1370
1357
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
1371
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1372
- assert.deepEqual(modelOld.$meta.rowOptions, {});
1358
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1373
1359
  assert.equal(modelOld.$meta.isIndirectChange, true);
1374
1360
  const elem = instances.find((i) => i.ECInstanceId === partialElementId && i.$meta.stage === "Old");
1375
1361
  expect(elem).to.exist;
@@ -1406,15 +1392,15 @@ describe("ChangesetReader insert-partial", () => {
1406
1392
  "Category",
1407
1393
  ].sort());
1408
1394
  // $meta keys
1409
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1395
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1410
1396
  assert.equal(elem.$meta.op, "Deleted");
1411
1397
  assert.equal(elem.$meta.stage, "Old");
1412
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1413
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
1398
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1399
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
1414
1400
  assert.isString(elem.$meta.instanceKey);
1415
1401
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
1416
1402
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
1417
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
1403
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
1418
1404
  'ECInstanceId', 'ECClassId', 'Model.Id', 'LastMod', 'CodeSpec.Id',
1419
1405
  'CodeScope.Id', 'CodeValue', 'UserLabel', 'Parent', 'FederationGuid',
1420
1406
  'JsonProperties', 'Category.Id', 'Origin', 'Rotation', 'BBoxLow', 'BBoxHigh',
@@ -1424,7 +1410,6 @@ describe("ChangesetReader insert-partial", () => {
1424
1410
  'StructProp.Pt2d', 'StructProp.Pt3d', 'IntArrProp', 'StrArrProp',
1425
1411
  'StructArrProp', 'RelatedElem'
1426
1412
  ].sort());
1427
- assert.deepEqual(elem.$meta.rowOptions, {});
1428
1413
  assert.isUndefined(elem.BinProp);
1429
1414
  assert.equal(elem.$meta.isIndirectChange, false);
1430
1415
  });
@@ -1443,7 +1428,7 @@ describe("ChangesetReader insert-partial", () => {
1443
1428
  assert.equal(modelNew.$meta.op, "Updated");
1444
1429
  assert.equal(modelNew.$meta.stage, "New");
1445
1430
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.BisCoreElement);
1446
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1431
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1447
1432
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
1448
1433
  assert.equal(modelNew.$meta.isIndirectChange, true);
1449
1434
  // --- instances[1]: DrawingModel Updated Old ---
@@ -1456,7 +1441,7 @@ describe("ChangesetReader insert-partial", () => {
1456
1441
  assert.equal(modelOld.$meta.op, "Updated");
1457
1442
  assert.equal(modelOld.$meta.stage, "Old");
1458
1443
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.BisCoreElement);
1459
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1444
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
1460
1445
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true });
1461
1446
  assert.equal(modelOld.$meta.isIndirectChange, true);
1462
1447
  // --- instances[2]: Test2dElement (partial) Inserted New ---
@@ -1475,12 +1460,12 @@ describe("ChangesetReader insert-partial", () => {
1475
1460
  assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1476
1461
  assert.equal(elem.$meta.op, "Inserted");
1477
1462
  assert.equal(elem.$meta.stage, "New");
1478
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1479
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
1463
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1464
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
1480
1465
  assert.isString(elem.$meta.instanceKey);
1481
1466
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
1482
1467
  assert.equal(elem.$meta.propFilter, PropertyFilter.BisCoreElement);
1483
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "ECClassId", "CodeScope.Id",
1468
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "ECClassId", "CodeScope.Id",
1484
1469
  "CodeSpec.Id", "CodeValue", "FederationGuid", "JsonProperties", "LastMod", "Model.Id", "Parent", "UserLabel"].sort());
1485
1470
  assert.deepEqual(elem.$meta.rowOptions, { classIdsToClassNames: true });
1486
1471
  assert.equal(elem.$meta.isIndirectChange, false);
@@ -1494,12 +1479,11 @@ describe("ChangesetReader insert-partial", () => {
1494
1479
  assert.equal(modelNew.ECInstanceId, drawingModelId);
1495
1480
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelNew.ECClassId));
1496
1481
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
1497
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1482
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1498
1483
  assert.equal(modelNew.$meta.op, "Updated");
1499
1484
  assert.equal(modelNew.$meta.stage, "New");
1500
1485
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.InstanceKey);
1501
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
1502
- assert.deepEqual(modelNew.$meta.rowOptions, {});
1486
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames, ["ECInstanceId"]);
1503
1487
  assert.equal(modelNew.$meta.isIndirectChange, true);
1504
1488
  // --- instances[1]: DrawingModel Updated Old ---
1505
1489
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -1507,12 +1491,11 @@ describe("ChangesetReader insert-partial", () => {
1507
1491
  assert.equal(modelOld.ECInstanceId, drawingModelId);
1508
1492
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
1509
1493
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
1510
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1494
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1511
1495
  assert.equal(modelOld.$meta.op, "Updated");
1512
1496
  assert.equal(modelOld.$meta.stage, "Old");
1513
1497
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.InstanceKey);
1514
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
1515
- assert.deepEqual(modelOld.$meta.rowOptions, {});
1498
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames, ["ECInstanceId"]);
1516
1499
  assert.equal(modelOld.$meta.isIndirectChange, true);
1517
1500
  // --- instances[2]: Test2dElement (partial) Inserted New ---
1518
1501
  const elem = instances.find((i) => i.ECInstanceId === partialElementId && i.$meta.stage === "New");
@@ -1523,16 +1506,15 @@ describe("ChangesetReader insert-partial", () => {
1523
1506
  assert.isUndefined(elem.Model);
1524
1507
  assert.isUndefined(elem.LastMod);
1525
1508
  assert.deepEqual(Object.keys(elem).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
1526
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1509
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1527
1510
  assert.equal(elem.$meta.op, "Inserted");
1528
1511
  assert.equal(elem.$meta.stage, "New");
1529
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1530
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
1512
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
1513
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
1531
1514
  assert.isString(elem.$meta.instanceKey);
1532
1515
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
1533
1516
  assert.equal(elem.$meta.propFilter, PropertyFilter.InstanceKey);
1534
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "ECClassId"].sort());
1535
- assert.deepEqual(elem.$meta.rowOptions, {});
1517
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "ECClassId"].sort());
1536
1518
  assert.equal(elem.$meta.isIndirectChange, false);
1537
1519
  });
1538
1520
  it("txn2 insert-partial | rowOptions: classIdsToClassNames", () => {
@@ -1849,12 +1831,11 @@ describe("ChangesetReader update-full", () => {
1849
1831
  assert.isString(modelNew.LastMod);
1850
1832
  assert.isUndefined(modelNew.GeometryGuid); // no GeometryGuid in update txn model row
1851
1833
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta"].sort());
1852
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1834
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1853
1835
  assert.equal(modelNew.$meta.op, "Updated");
1854
1836
  assert.equal(modelNew.$meta.stage, "New");
1855
1837
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
1856
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
1857
- assert.deepEqual(modelNew.$meta.rowOptions, {});
1838
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
1858
1839
  assert.equal(modelNew.$meta.isIndirectChange, true);
1859
1840
  // --- instances[1]: DrawingModel Updated Old ---
1860
1841
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -1862,12 +1843,11 @@ describe("ChangesetReader update-full", () => {
1862
1843
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
1863
1844
  assert.isString(modelOld.LastMod);
1864
1845
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta"].sort());
1865
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1846
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1866
1847
  assert.equal(modelOld.$meta.op, "Updated");
1867
1848
  assert.equal(modelOld.$meta.stage, "Old");
1868
1849
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
1869
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
1870
- assert.deepEqual(modelOld.$meta.rowOptions, {});
1850
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
1871
1851
  assert.equal(modelOld.$meta.isIndirectChange, true);
1872
1852
  // --- instances[2]: Test2dElement Updated New ---
1873
1853
  const elemNew = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "New");
@@ -1901,21 +1881,20 @@ describe("ChangesetReader update-full", () => {
1901
1881
  "Pt2dProp", "Pt3dProp", "StructProp", "IntArrProp", "StrArrProp", "StructArrProp", "RelatedElem",
1902
1882
  "$meta", "LastMod", "BinProp"
1903
1883
  ].sort());
1904
- assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1884
+ assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1905
1885
  assert.equal(elemNew.$meta.op, "Updated");
1906
1886
  assert.equal(elemNew.$meta.stage, "New");
1907
- assert.deepEqual([...elemNew.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
1908
- assert.deepEqual([...elemNew.$meta.changeIndexes].sort(), [1, 2].sort());
1887
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
1888
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
1909
1889
  assert.isString(elemNew.$meta.instanceKey);
1910
1890
  assert.equal(elemNew.$meta.instanceKey.split(`-`).length, 2);
1911
1891
  assert.equal(elemNew.$meta.propFilter, PropertyFilter.All);
1912
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), [
1892
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), [
1913
1893
  "BoolProp", "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
1914
1894
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp",
1915
1895
  "StrProp", "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
1916
1896
  "StructProp.Y", "StructProp.Z", "BinProp"
1917
1897
  ].sort());
1918
- assert.deepEqual(elemNew.$meta.rowOptions, {});
1919
1898
  assert.equal(elemNew.$meta.isIndirectChange, false);
1920
1899
  // --- instances[3]: Test2dElement Updated Old ---
1921
1900
  const elemOld = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "Old");
@@ -1947,18 +1926,17 @@ describe("ChangesetReader update-full", () => {
1947
1926
  "Pt2dProp", "Pt3dProp", "StructProp", "IntArrProp", "StrArrProp", "StructArrProp", "RelatedElem",
1948
1927
  "$meta", "LastMod", "BinProp"
1949
1928
  ].sort());
1950
- assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
1929
+ assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
1951
1930
  assert.equal(elemOld.$meta.op, "Updated");
1952
1931
  assert.equal(elemOld.$meta.stage, "Old");
1953
- assert.deepEqual([...elemOld.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
1932
+ assert.deepEqual(elemOld.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
1954
1933
  assert.equal(elemOld.$meta.propFilter, PropertyFilter.All);
1955
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), [
1934
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), [
1956
1935
  "BoolProp", "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
1957
1936
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp",
1958
1937
  "StrProp", "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
1959
1938
  "StructProp.Y", "StructProp.Z", "BinProp"
1960
1939
  ].sort());
1961
- assert.deepEqual(elemOld.$meta.rowOptions, {});
1962
1940
  assert.equal(elemOld.$meta.isIndirectChange, false);
1963
1941
  });
1964
1942
  it("txn3 update-full | Bis_Element_Properties", () => {
@@ -1975,7 +1953,7 @@ describe("ChangesetReader update-full", () => {
1975
1953
  assert.equal(modelNew.$meta.op, "Updated");
1976
1954
  assert.equal(modelNew.$meta.stage, "New");
1977
1955
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.BisCoreElement);
1978
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
1956
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
1979
1957
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
1980
1958
  assert.equal(modelNew.$meta.isIndirectChange, true);
1981
1959
  // --- instances[1]: DrawingModel Updated Old ---
@@ -1989,7 +1967,7 @@ describe("ChangesetReader update-full", () => {
1989
1967
  assert.equal(modelOld.$meta.op, "Updated");
1990
1968
  assert.equal(modelOld.$meta.stage, "Old");
1991
1969
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.BisCoreElement);
1992
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
1970
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
1993
1971
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true });
1994
1972
  assert.equal(modelOld.$meta.isIndirectChange, true);
1995
1973
  // --- instances[2]: Test2dElement Updated New (no custom props) ---
@@ -2006,12 +1984,12 @@ describe("ChangesetReader update-full", () => {
2006
1984
  assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2007
1985
  assert.equal(elemNew.$meta.op, "Updated");
2008
1986
  assert.equal(elemNew.$meta.stage, "New");
2009
- assert.deepEqual([...elemNew.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2010
- assert.deepEqual([...elemNew.$meta.changeIndexes].sort(), [1, 2].sort());
1987
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
1988
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
2011
1989
  assert.isString(elemNew.$meta.instanceKey);
2012
1990
  assert.equal(elemNew.$meta.instanceKey.split(`-`).length, 2);
2013
1991
  assert.equal(elemNew.$meta.propFilter, PropertyFilter.BisCoreElement);
2014
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
1992
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
2015
1993
  assert.deepEqual(elemNew.$meta.rowOptions, { classIdsToClassNames: true });
2016
1994
  assert.equal(elemNew.$meta.isIndirectChange, false);
2017
1995
  // --- instances[3]: Test2dElement Updated Old ---
@@ -2026,9 +2004,9 @@ describe("ChangesetReader update-full", () => {
2026
2004
  assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2027
2005
  assert.equal(elemOld.$meta.op, "Updated");
2028
2006
  assert.equal(elemOld.$meta.stage, "Old");
2029
- assert.deepEqual([...elemOld.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2007
+ assert.deepEqual(elemOld.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2030
2008
  assert.equal(elemOld.$meta.propFilter, PropertyFilter.BisCoreElement);
2031
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
2009
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
2032
2010
  assert.deepEqual(elemOld.$meta.rowOptions, { classIdsToClassNames: true });
2033
2011
  assert.equal(elemOld.$meta.isIndirectChange, false);
2034
2012
  });
@@ -2041,12 +2019,11 @@ describe("ChangesetReader update-full", () => {
2041
2019
  assert.equal(modelNew.ECInstanceId, drawingModelId);
2042
2020
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelNew.ECClassId));
2043
2021
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2044
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2022
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2045
2023
  assert.equal(modelNew.$meta.op, "Updated");
2046
2024
  assert.equal(modelNew.$meta.stage, "New");
2047
2025
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.InstanceKey);
2048
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2049
- assert.deepEqual(modelNew.$meta.rowOptions, {});
2026
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2050
2027
  assert.equal(modelNew.$meta.isIndirectChange, true);
2051
2028
  // --- instances[1]: DrawingModel Updated Old ---
2052
2029
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -2054,12 +2031,11 @@ describe("ChangesetReader update-full", () => {
2054
2031
  assert.equal(modelOld.ECInstanceId, drawingModelId);
2055
2032
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
2056
2033
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2057
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2034
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2058
2035
  assert.equal(modelOld.$meta.op, "Updated");
2059
2036
  assert.equal(modelOld.$meta.stage, "Old");
2060
2037
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.InstanceKey);
2061
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2062
- assert.deepEqual(modelOld.$meta.rowOptions, {});
2038
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2063
2039
  assert.equal(modelOld.$meta.isIndirectChange, true);
2064
2040
  // --- instances[2]: Test2dElement Updated New ---
2065
2041
  const elemNew = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "New");
@@ -2070,16 +2046,15 @@ describe("ChangesetReader update-full", () => {
2070
2046
  assert.isUndefined(elemNew.Model);
2071
2047
  assert.isUndefined(elemNew.LastMod);
2072
2048
  assert.deepEqual(Object.keys(elemNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2073
- assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2049
+ assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2074
2050
  assert.equal(elemNew.$meta.op, "Updated");
2075
2051
  assert.equal(elemNew.$meta.stage, "New");
2076
- assert.deepEqual([...elemNew.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2077
- assert.deepEqual([...elemNew.$meta.changeIndexes].sort(), [1, 2].sort());
2052
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2053
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
2078
2054
  assert.isString(elemNew.$meta.instanceKey);
2079
2055
  assert.equal(elemNew.$meta.instanceKey.split(`-`).length, 2);
2080
2056
  assert.equal(elemNew.$meta.propFilter, PropertyFilter.InstanceKey);
2081
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2082
- assert.deepEqual(elemNew.$meta.rowOptions, {});
2057
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2083
2058
  assert.equal(elemNew.$meta.isIndirectChange, false);
2084
2059
  // --- instances[3]: Test2dElement Updated Old ---
2085
2060
  const elemOld = instances.find((i) => i.ECInstanceId === fullElementId && i.$meta.stage === "Old");
@@ -2089,13 +2064,12 @@ describe("ChangesetReader update-full", () => {
2089
2064
  assert.isUndefined(elemOld.StrProp);
2090
2065
  assert.isUndefined(elemOld.Model);
2091
2066
  assert.deepEqual(Object.keys(elemOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2092
- assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2067
+ assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2093
2068
  assert.equal(elemOld.$meta.op, "Updated");
2094
2069
  assert.equal(elemOld.$meta.stage, "Old");
2095
- assert.deepEqual([...elemOld.$meta.tables].sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2070
+ assert.deepEqual(elemOld.$meta.tables.sort(), ["bis_GeometricElement2d", "bis_Element"].sort());
2096
2071
  assert.equal(elemOld.$meta.propFilter, PropertyFilter.InstanceKey);
2097
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2098
- assert.deepEqual(elemOld.$meta.rowOptions, {});
2072
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2099
2073
  assert.equal(elemOld.$meta.isIndirectChange, false);
2100
2074
  });
2101
2075
  it("txn3 update-full | rowOptions: useJsName", () => {
@@ -2126,7 +2100,7 @@ describe("ChangesetReader update-full", () => {
2126
2100
  assert.deepEqual(Object.keys(elemNew).sort(), ["$meta", "binProp", "boolProp", "className",
2127
2101
  "dblProp", "dtProp", "id", "intArrProp", "intProp", "lastMod", "longProp", "pt2dProp",
2128
2102
  "pt3dProp", "relatedElem", "strArrProp", "strProp", "structArrProp", "structProp"].sort());
2129
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2103
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2130
2104
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2131
2105
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2132
2106
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2143,7 +2117,7 @@ describe("ChangesetReader update-full", () => {
2143
2117
  assert.deepEqual(Object.keys(elemOld).sort(), ["$meta", "binProp", "boolProp", "className",
2144
2118
  "dblProp", "dtProp", "id", "intArrProp", "intProp", "lastMod", "longProp", "pt2dProp",
2145
2119
  "pt3dProp", "relatedElem", "strArrProp", "strProp", "structArrProp", "structProp"].sort());
2146
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2120
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2147
2121
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2148
2122
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2149
2123
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2171,7 +2145,7 @@ describe("ChangesetReader update-full", () => {
2171
2145
  assert.deepEqual(Object.keys(elemNew).sort(), ["$meta", "BinProp", "BoolProp",
2172
2146
  "DblProp", "DtProp", "IntArrProp", "IntProp", "LastMod", "LongProp",
2173
2147
  "Pt2dProp", "Pt3dProp", "RelatedElem", "StrArrProp", "StrProp", "StructArrProp", "StructProp", "ECClassId", "ECInstanceId"].sort());
2174
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2148
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2175
2149
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2176
2150
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2177
2151
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2185,7 +2159,7 @@ describe("ChangesetReader update-full", () => {
2185
2159
  assert.deepEqual(Object.keys(elemOld).sort(), ["$meta", "BinProp", "BoolProp",
2186
2160
  "DblProp", "DtProp", "IntArrProp", "IntProp", "LastMod", "LongProp",
2187
2161
  "Pt2dProp", "Pt3dProp", "RelatedElem", "StrArrProp", "StrProp", "StructArrProp", "StructProp", "ECClassId", "ECInstanceId"].sort());
2188
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2162
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2189
2163
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2190
2164
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2191
2165
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2216,7 +2190,7 @@ describe("ChangesetReader update-full", () => {
2216
2190
  assert.deepEqual(Object.keys(elemNew).sort(), ["$meta", "binProp", "boolProp", "className",
2217
2191
  "dblProp", "dtProp", "id", "intArrProp", "intProp", "lastMod", "longProp", "pt2dProp",
2218
2192
  "pt3dProp", "relatedElem", "strArrProp", "strProp", "structArrProp", "structProp"].sort());
2219
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2193
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2220
2194
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2221
2195
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2222
2196
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2232,7 +2206,7 @@ describe("ChangesetReader update-full", () => {
2232
2206
  assert.deepEqual(Object.keys(elemOld).sort(), ["$meta", "binProp", "boolProp", "className",
2233
2207
  "dblProp", "dtProp", "id", "intArrProp", "intProp", "lastMod", "longProp", "pt2dProp",
2234
2208
  "pt3dProp", "relatedElem", "strArrProp", "strProp", "structArrProp", "structProp"].sort());
2235
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2209
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2236
2210
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2237
2211
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2238
2212
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2262,7 +2236,7 @@ describe("ChangesetReader update-full", () => {
2262
2236
  assert.deepEqual(Object.keys(elemNew).sort(), ["$meta", "BinProp", "BoolProp",
2263
2237
  "DblProp", "DtProp", "IntArrProp", "IntProp", "LastMod", "LongProp",
2264
2238
  "Pt2dProp", "Pt3dProp", "RelatedElem", "StrArrProp", "StrProp", "StructArrProp", "StructProp", "ECClassId", "ECInstanceId"].sort());
2265
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2239
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2266
2240
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2267
2241
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2268
2242
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2279,7 +2253,7 @@ describe("ChangesetReader update-full", () => {
2279
2253
  assert.deepEqual(Object.keys(elemOld).sort(), ["$meta", "BinProp", "BoolProp",
2280
2254
  "DblProp", "DtProp", "IntArrProp", "IntProp", "LastMod", "LongProp",
2281
2255
  "Pt2dProp", "Pt3dProp", "RelatedElem", "StrArrProp", "StrProp", "StructArrProp", "StructProp", "ECClassId", "ECInstanceId"].sort());
2282
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["BinProp", "BoolProp",
2256
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["BinProp", "BoolProp",
2283
2257
  "DblProp", "DtProp", "ECInstanceId", "IntArrProp", "IntProp", "LastMod",
2284
2258
  "LongProp", "Pt2dProp", "Pt3dProp.X", "Pt3dProp.Y", "RelatedElem.Id", "StrArrProp", "StrProp",
2285
2259
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X",
@@ -2428,12 +2402,11 @@ describe("ChangesetReader delete-partial", () => {
2428
2402
  assert.isString(modelNew.LastMod);
2429
2403
  assert.isString(modelNew.GeometryGuid);
2430
2404
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
2431
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2405
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2432
2406
  assert.equal(modelNew.$meta.op, "Updated");
2433
2407
  assert.equal(modelNew.$meta.stage, "New");
2434
2408
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
2435
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2436
- assert.deepEqual(modelNew.$meta.rowOptions, {});
2409
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2437
2410
  assert.equal(modelNew.$meta.isIndirectChange, true);
2438
2411
  // --- instances[1]: DrawingModel Updated Old ---
2439
2412
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -2443,12 +2416,11 @@ describe("ChangesetReader delete-partial", () => {
2443
2416
  assert.isString(modelOld.LastMod);
2444
2417
  assert.isString(modelOld.GeometryGuid);
2445
2418
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
2446
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2419
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2447
2420
  assert.equal(modelOld.$meta.op, "Updated");
2448
2421
  assert.equal(modelOld.$meta.stage, "Old");
2449
2422
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
2450
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2451
- assert.deepEqual(modelOld.$meta.rowOptions, {});
2423
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2452
2424
  assert.equal(modelOld.$meta.isIndirectChange, true);
2453
2425
  // --- instances[2]: Test2dElement (partial) Deleted Old ---
2454
2426
  const elem = instances.find((i) => i.ECInstanceId === partialElementId && i.$meta.stage === "Old");
@@ -2475,20 +2447,19 @@ describe("ChangesetReader delete-partial", () => {
2475
2447
  "ECInstanceId", "ECClassId", "Model", "LastMod", "CodeSpec", "CodeScope", "FederationGuid", "$meta",
2476
2448
  "Category",
2477
2449
  ].sort());
2478
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2450
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2479
2451
  assert.equal(elem.$meta.op, "Deleted");
2480
2452
  assert.equal(elem.$meta.stage, "Old");
2481
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2482
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
2453
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2454
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
2483
2455
  assert.isString(elem.$meta.instanceKey);
2484
2456
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
2485
2457
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
2486
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["BBoxHigh", "BBoxLow", "BinProp", "BoolProp",
2458
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["BBoxHigh", "BBoxLow", "BinProp", "BoolProp",
2487
2459
  "Category.Id", "CodeScope.Id", "CodeSpec.Id", "CodeValue", "DblProp", "DtProp", "ECClassId", "ECInstanceId", "FederationGuid", "GeometryStream",
2488
2460
  "IntArrProp", "IntProp", "JsonProperties", "LastMod", "LongProp", "Model.Id", "Origin", "Parent", "Pt2dProp", "Pt3dProp", "RelatedElem", "Rotation", "StrArrProp", "StrProp",
2489
2461
  "StructArrProp", "StructProp.Label", "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X", "StructProp.Y", "StructProp.Z", "TypeDefinition", "UserLabel"
2490
2462
  ].sort());
2491
- assert.deepEqual(elem.$meta.rowOptions, {});
2492
2463
  assert.equal(elem.$meta.isIndirectChange, false);
2493
2464
  });
2494
2465
  it("txn4 delete-partial | Bis_Element_Properties", () => {
@@ -2506,7 +2477,7 @@ describe("ChangesetReader delete-partial", () => {
2506
2477
  assert.equal(modelNew.$meta.op, "Updated");
2507
2478
  assert.equal(modelNew.$meta.stage, "New");
2508
2479
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.BisCoreElement);
2509
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2480
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2510
2481
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
2511
2482
  assert.equal(modelNew.$meta.isIndirectChange, true);
2512
2483
  // --- instances[1]: DrawingModel Updated Old ---
@@ -2521,7 +2492,7 @@ describe("ChangesetReader delete-partial", () => {
2521
2492
  assert.equal(modelOld.$meta.op, "Updated");
2522
2493
  assert.equal(modelOld.$meta.stage, "Old");
2523
2494
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.BisCoreElement);
2524
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2495
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2525
2496
  assert.deepEqual(modelOld.$meta.rowOptions, { classIdsToClassNames: true });
2526
2497
  assert.equal(modelOld.$meta.isIndirectChange, true);
2527
2498
  // --- instances[2]: Test2dElement (partial) Deleted Old ---
@@ -2540,12 +2511,12 @@ describe("ChangesetReader delete-partial", () => {
2540
2511
  assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2541
2512
  assert.equal(elem.$meta.op, "Deleted");
2542
2513
  assert.equal(elem.$meta.stage, "Old");
2543
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2544
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
2514
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2515
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
2545
2516
  assert.isString(elem.$meta.instanceKey);
2546
2517
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
2547
2518
  assert.equal(elem.$meta.propFilter, PropertyFilter.BisCoreElement);
2548
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ["CodeScope.Id", "CodeSpec.Id", "CodeValue", "ECClassId", "ECInstanceId",
2519
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ["CodeScope.Id", "CodeSpec.Id", "CodeValue", "ECClassId", "ECInstanceId",
2549
2520
  "FederationGuid", "JsonProperties", "LastMod", "Model.Id", "Parent", "UserLabel"].sort());
2550
2521
  assert.deepEqual(elem.$meta.rowOptions, { classIdsToClassNames: true });
2551
2522
  assert.equal(elem.$meta.isIndirectChange, false);
@@ -2559,12 +2530,11 @@ describe("ChangesetReader delete-partial", () => {
2559
2530
  assert.equal(modelNew.ECInstanceId, drawingModelId);
2560
2531
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelNew.ECClassId));
2561
2532
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2562
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2533
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2563
2534
  assert.equal(modelNew.$meta.op, "Updated");
2564
2535
  assert.equal(modelNew.$meta.stage, "New");
2565
2536
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.InstanceKey);
2566
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2567
- assert.deepEqual(modelNew.$meta.rowOptions, {});
2537
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2568
2538
  assert.equal(modelNew.$meta.isIndirectChange, true);
2569
2539
  // --- instances[1]: DrawingModel Updated Old ---
2570
2540
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -2572,12 +2542,11 @@ describe("ChangesetReader delete-partial", () => {
2572
2542
  assert.equal(modelOld.ECInstanceId, drawingModelId);
2573
2543
  assert.equal("BisCore:DrawingModel", rwIModel.getClassNameFromId(modelOld.ECClassId));
2574
2544
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2575
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2545
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2576
2546
  assert.equal(modelOld.$meta.op, "Updated");
2577
2547
  assert.equal(modelOld.$meta.stage, "Old");
2578
2548
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.InstanceKey);
2579
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId"].sort());
2580
- assert.deepEqual(modelOld.$meta.rowOptions, {});
2549
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames, ["ECInstanceId"]);
2581
2550
  assert.equal(modelOld.$meta.isIndirectChange, true);
2582
2551
  // --- instances[2]: Test2dElement (partial) Deleted Old ---
2583
2552
  const elem = instances.find((i) => i.ECInstanceId === partialElementId && i.$meta.stage === "Old");
@@ -2588,16 +2557,15 @@ describe("ChangesetReader delete-partial", () => {
2588
2557
  assert.isUndefined(elem.Model);
2589
2558
  assert.isUndefined(elem.LastMod);
2590
2559
  assert.deepEqual(Object.keys(elem).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2591
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2560
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2592
2561
  assert.equal(elem.$meta.op, "Deleted");
2593
2562
  assert.equal(elem.$meta.stage, "Old");
2594
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2595
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
2563
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2564
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
2596
2565
  assert.isString(elem.$meta.instanceKey);
2597
2566
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
2598
2567
  assert.equal(elem.$meta.propFilter, PropertyFilter.InstanceKey);
2599
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), ['ECClassId', 'ECInstanceId'].sort());
2600
- assert.deepEqual(elem.$meta.rowOptions, {});
2568
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), ['ECClassId', 'ECInstanceId'].sort());
2601
2569
  assert.equal(elem.$meta.isIndirectChange, false);
2602
2570
  });
2603
2571
  it("txn4 delete-partial | rowOptions: classIdsToClassNames", () => {
@@ -2885,16 +2853,15 @@ describe("ChangesetReader filters", () => {
2885
2853
  // Object.keys
2886
2854
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
2887
2855
  // $meta keys
2888
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2856
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2889
2857
  assert.equal(modelNew.$meta.op, "Updated");
2890
2858
  assert.equal(modelNew.$meta.stage, "New");
2891
- assert.deepEqual([...modelNew.$meta.tables].sort(), ["bis_Model"].sort());
2892
- assert.deepEqual([...modelNew.$meta.changeIndexes].sort(), [1].sort());
2859
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
2860
+ assert.deepEqual(modelNew.$meta.changeIndexes, [1]);
2893
2861
  assert.isString(modelNew.$meta.instanceKey);
2894
2862
  assert.equal(modelNew.$meta.instanceKey.split(`-`).length, 2);
2895
2863
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
2896
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2897
- assert.deepEqual(modelNew.$meta.rowOptions, {});
2864
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2898
2865
  assert.equal(modelNew.$meta.isIndirectChange, true);
2899
2866
  // --- instances[1]: DrawingModel Updated Old ---
2900
2867
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -2904,13 +2871,12 @@ describe("ChangesetReader filters", () => {
2904
2871
  // Object.keys
2905
2872
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
2906
2873
  // $meta keys
2907
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2874
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2908
2875
  assert.equal(modelOld.$meta.op, "Updated");
2909
2876
  assert.equal(modelOld.$meta.stage, "Old");
2910
- assert.deepEqual([...modelOld.$meta.tables].sort(), ["bis_Model"].sort());
2877
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
2911
2878
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
2912
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2913
- assert.deepEqual(modelOld.$meta.rowOptions, {});
2879
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
2914
2880
  assert.equal(modelOld.$meta.isIndirectChange, true);
2915
2881
  }
2916
2882
  catch (e_11) {
@@ -2976,15 +2942,15 @@ describe("ChangesetReader filters", () => {
2976
2942
  "Pt2dProp", "Pt3dProp", "StructProp", "IntArrProp", "StrArrProp", "StructArrProp", "RelatedElem", "BinProp"
2977
2943
  ].sort());
2978
2944
  // $meta keys
2979
- assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2945
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
2980
2946
  assert.equal(elem.$meta.op, "Inserted");
2981
2947
  assert.equal(elem.$meta.stage, "New");
2982
- assert.deepEqual([...elem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2983
- assert.deepEqual([...elem.$meta.changeIndexes].sort(), [1, 2].sort());
2948
+ assert.deepEqual(elem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
2949
+ assert.deepEqual(elem.$meta.changeIndexes.sort(), [1, 2].sort());
2984
2950
  assert.isString(elem.$meta.instanceKey);
2985
2951
  assert.equal(elem.$meta.instanceKey.split(`-`).length, 2);
2986
2952
  assert.equal(elem.$meta.propFilter, PropertyFilter.All);
2987
- assert.deepEqual([...elem.$meta.changeFetchedPropNames].sort(), [
2953
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.sort(), [
2988
2954
  'BBoxHigh', 'BBoxLow', 'BinProp', 'BoolProp', 'Category.Id', 'CodeScope.Id',
2989
2955
  'CodeSpec.Id', 'CodeValue', 'DblProp', 'DtProp', 'ECClassId', 'ECInstanceId',
2990
2956
  'FederationGuid', 'GeometryStream', 'IntArrProp', 'IntProp', 'JsonProperties',
@@ -2993,7 +2959,6 @@ describe("ChangesetReader filters", () => {
2993
2959
  'StructProp.Pt2d', 'StructProp.Pt3d', 'StructProp.X', 'StructProp.Y', 'StructProp.Z',
2994
2960
  'TypeDefinition', 'UserLabel'
2995
2961
  ].sort());
2996
- assert.deepEqual(elem.$meta.rowOptions, {});
2997
2962
  assert.equal(elem.$meta.isIndirectChange, false);
2998
2963
  }
2999
2964
  catch (e_12) {
@@ -3024,16 +2989,15 @@ describe("ChangesetReader filters", () => {
3024
2989
  // Object.keys
3025
2990
  assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
3026
2991
  // $meta keys
3027
- assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
2992
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
3028
2993
  assert.equal(modelNew.$meta.op, "Updated");
3029
2994
  assert.equal(modelNew.$meta.stage, "New");
3030
- assert.deepEqual([...modelNew.$meta.tables].sort(), ["bis_Model"].sort());
3031
- assert.deepEqual([...modelNew.$meta.changeIndexes].sort(), [1].sort());
2995
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
2996
+ assert.deepEqual(modelNew.$meta.changeIndexes, [1]);
3032
2997
  assert.isString(modelNew.$meta.instanceKey);
3033
2998
  assert.equal(modelNew.$meta.instanceKey.split(`-`).length, 2);
3034
2999
  assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
3035
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
3036
- assert.deepEqual(modelNew.$meta.rowOptions, {});
3000
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
3037
3001
  assert.equal(modelNew.$meta.isIndirectChange, true);
3038
3002
  // --- instances[1]: DrawingModel Updated Old ---
3039
3003
  const modelOld = instances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
@@ -3043,13 +3007,12 @@ describe("ChangesetReader filters", () => {
3043
3007
  // Object.keys
3044
3008
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
3045
3009
  // $meta keys
3046
- assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "rowOptions", "isIndirectChange"].sort());
3010
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
3047
3011
  assert.equal(modelOld.$meta.op, "Updated");
3048
3012
  assert.equal(modelOld.$meta.stage, "Old");
3049
- assert.deepEqual([...modelOld.$meta.tables].sort(), ["bis_Model"].sort());
3013
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
3050
3014
  assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
3051
- assert.deepEqual([...modelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
3052
- assert.deepEqual(modelOld.$meta.rowOptions, {});
3015
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
3053
3016
  assert.equal(modelOld.$meta.isIndirectChange, true);
3054
3017
  }
3055
3018
  catch (e_13) {
@@ -3060,6 +3023,21 @@ describe("ChangesetReader filters", () => {
3060
3023
  __disposeResources(env_13);
3061
3024
  }
3062
3025
  });
3026
+ it("read txn1 to some extent not the entire txn from the spill file and then close should happen without any issue", () => {
3027
+ const env_14 = { stack: [], error: void 0, hasError: false };
3028
+ try {
3029
+ const reader = __addDisposableResource(env_14, ChangesetReader.openTxn({ db: rwIModel, txnId }), false);
3030
+ assert.isTrue(reader.step());
3031
+ expect(() => reader.close()).to.not.throw();
3032
+ }
3033
+ catch (e_14) {
3034
+ env_14.error = e_14;
3035
+ env_14.hasError = true;
3036
+ }
3037
+ finally {
3038
+ __disposeResources(env_14);
3039
+ }
3040
+ });
3063
3041
  });
3064
3042
  describe("ChangesetReader — openFile + openGroup", () => {
3065
3043
  let rwIModel;
@@ -3130,10 +3108,10 @@ describe("ChangesetReader — openFile + openGroup", () => {
3130
3108
  const insertCs = changesets[1];
3131
3109
  // === openFile: insert changeset ===
3132
3110
  {
3133
- const env_14 = { stack: [], error: void 0, hasError: false };
3111
+ const env_15 = { stack: [], error: void 0, hasError: false };
3134
3112
  try {
3135
- const reader = __addDisposableResource(env_14, ChangesetReader.openFile({ db: rwIModel, fileName: insertCs.pathname, rowOptions: { abbreviateBlobs: false } }), false);
3136
- const pcu = __addDisposableResource(env_14, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3113
+ const reader = __addDisposableResource(env_15, ChangesetReader.openFile({ db: rwIModel, fileName: insertCs.pathname, rowOptions: { abbreviateBlobs: false } }), false);
3114
+ const pcu = __addDisposableResource(env_15, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3137
3115
  while (reader.step())
3138
3116
  pcu.appendFrom(reader);
3139
3117
  const instances = Array.from(pcu.instances);
@@ -3163,18 +3141,18 @@ describe("ChangesetReader — openFile + openGroup", () => {
3163
3141
  assert.deepEqual(Object.keys(elemNew).sort(), ["ECInstanceId", "ECClassId", "Model", "CodeSpec",
3164
3142
  "CodeScope", "FederationGuid", "$meta", "Category", "LastMod",
3165
3143
  "BinProp", "GuidArrProp"].sort());
3166
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp',
3144
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp',
3167
3145
  'Category.Id', 'CodeScope.Id', 'CodeSpec.Id', 'CodeValue',
3168
3146
  'ECClassId', 'ECInstanceId', 'FederationGuid', 'GeometryStream', 'GuidArrProp',
3169
3147
  'JsonProperties', 'LastMod', 'Model.Id', 'Origin', 'Parent', 'Pt3dProp', 'Rotation',
3170
3148
  'TypeDefinition', 'UserLabel'].sort());
3171
3149
  }
3172
- catch (e_14) {
3173
- env_14.error = e_14;
3174
- env_14.hasError = true;
3150
+ catch (e_15) {
3151
+ env_15.error = e_15;
3152
+ env_15.hasError = true;
3175
3153
  }
3176
3154
  finally {
3177
- __disposeResources(env_14);
3155
+ __disposeResources(env_15);
3178
3156
  }
3179
3157
  }
3180
3158
  // Wait so that LastMod on bis_Model gets a distinct timestamp before the update txn
@@ -3197,10 +3175,10 @@ describe("ChangesetReader — openFile + openGroup", () => {
3197
3175
  const updateCs = changesets[2];
3198
3176
  // === openFile: update changeset ===
3199
3177
  {
3200
- const env_15 = { stack: [], error: void 0, hasError: false };
3178
+ const env_16 = { stack: [], error: void 0, hasError: false };
3201
3179
  try {
3202
- const reader = __addDisposableResource(env_15, ChangesetReader.openFile({ db: rwIModel, fileName: updateCs.pathname, rowOptions: { abbreviateBlobs: false } }), false);
3203
- const pcu = __addDisposableResource(env_15, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3180
+ const reader = __addDisposableResource(env_16, ChangesetReader.openFile({ db: rwIModel, fileName: updateCs.pathname, rowOptions: { abbreviateBlobs: false } }), false);
3181
+ const pcu = __addDisposableResource(env_16, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3204
3182
  while (reader.step())
3205
3183
  pcu.appendFrom(reader);
3206
3184
  const instances = Array.from(pcu.instances);
@@ -3223,7 +3201,7 @@ describe("ChangesetReader — openFile + openGroup", () => {
3223
3201
  assert.deepEqual(elemNew.BBoxHigh, { X: 0, Y: 0 });
3224
3202
  assert.deepEqual(elemNew.Rotation, 0);
3225
3203
  expect(elemNew.LastMod).to.exist;
3226
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3204
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3227
3205
  assert.equal(elemOld.$meta.op, "Updated");
3228
3206
  assert.equal(elemOld.$meta.stage, "Old");
3229
3207
  assert.deepEqual(Object.keys(elemOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "propFilter", "rowOptions", "changeFetchedPropNames", "instanceKey", "isIndirectChange"].sort());
@@ -3236,25 +3214,22 @@ describe("ChangesetReader — openFile + openGroup", () => {
3236
3214
  ]);
3237
3215
  assert.equal(elemOld.$meta.isIndirectChange, false);
3238
3216
  expect(elemOld.LastMod).to.exist;
3239
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3217
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3240
3218
  }
3241
- catch (e_15) {
3242
- env_15.error = e_15;
3243
- env_15.hasError = true;
3219
+ catch (e_16) {
3220
+ env_16.error = e_16;
3221
+ env_16.hasError = true;
3244
3222
  }
3245
3223
  finally {
3246
- __disposeResources(env_15);
3224
+ __disposeResources(env_16);
3247
3225
  }
3248
3226
  }
3249
- // === openGroup: insert + update as a single stream ===
3250
- // After merging, the elem New key is shared between insert-New and update-New;
3251
- // the update-New wins on overlapping props, so the final New reflects the updated state.
3252
- // elem Old only comes from the update changeset.
3227
+ // === openGroup: insert + update as a single stream becomes just insert ===
3253
3228
  {
3254
- const env_16 = { stack: [], error: void 0, hasError: false };
3229
+ const env_17 = { stack: [], error: void 0, hasError: false };
3255
3230
  try {
3256
- const reader = __addDisposableResource(env_16, ChangesetReader.openGroup({ db: rwIModel, changesetFiles: [insertCs.pathname, updateCs.pathname], rowOptions: { abbreviateBlobs: false } }), false);
3257
- const pcu = __addDisposableResource(env_16, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3231
+ const reader = __addDisposableResource(env_17, ChangesetReader.openGroup({ db: rwIModel, changesetFiles: [insertCs.pathname, updateCs.pathname], rowOptions: { abbreviateBlobs: false } }), false);
3232
+ const pcu = __addDisposableResource(env_17, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3258
3233
  while (reader.step())
3259
3234
  pcu.appendFrom(reader);
3260
3235
  const instances = Array.from(pcu.instances);
@@ -3287,19 +3262,19 @@ describe("ChangesetReader — openFile + openGroup", () => {
3287
3262
  assert.deepEqual(Object.keys(elemNew).sort(), ["ECInstanceId", "ECClassId", "Model", "CodeSpec",
3288
3263
  "CodeScope", "FederationGuid", "$meta", "Category", "LastMod",
3289
3264
  "BinProp", "GuidArrProp", "Origin", "Rotation", "BBoxLow", "BBoxHigh", "Pt3dProp"].sort());
3290
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow',
3265
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow',
3291
3266
  'BinProp', 'Category.Id', 'CodeScope.Id', 'CodeSpec.Id',
3292
3267
  'CodeValue', 'ECClassId', 'ECInstanceId', 'FederationGuid', 'GeometryStream',
3293
3268
  'GuidArrProp', 'JsonProperties', 'LastMod', 'Model.Id', 'Origin', 'Parent', 'Pt3dProp',
3294
3269
  'Rotation', 'TypeDefinition', 'UserLabel'].sort());
3295
3270
  assert.equal(elemNew.$meta.isIndirectChange, false);
3296
3271
  }
3297
- catch (e_16) {
3298
- env_16.error = e_16;
3299
- env_16.hasError = true;
3272
+ catch (e_17) {
3273
+ env_17.error = e_17;
3274
+ env_17.hasError = true;
3300
3275
  }
3301
3276
  finally {
3302
- __disposeResources(env_16);
3277
+ __disposeResources(env_17);
3303
3278
  }
3304
3279
  }
3305
3280
  });
@@ -3364,12 +3339,11 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3364
3339
  ],
3365
3340
  });
3366
3341
  txn.saveChanges("insert element");
3367
- // === openFile: insert changeset ===
3368
3342
  {
3369
- const env_17 = { stack: [], error: void 0, hasError: false };
3343
+ const env_18 = { stack: [], error: void 0, hasError: false };
3370
3344
  try {
3371
- const reader = __addDisposableResource(env_17, ChangesetReader.openLocalChanges({ db: rwIModel, rowOptions: { abbreviateBlobs: false } }), false);
3372
- const pcu = __addDisposableResource(env_17, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3345
+ const reader = __addDisposableResource(env_18, ChangesetReader.openLocalChanges({ db: rwIModel, rowOptions: { abbreviateBlobs: false } }), false);
3346
+ const pcu = __addDisposableResource(env_18, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3373
3347
  while (reader.step())
3374
3348
  pcu.appendFrom(reader);
3375
3349
  const instances = Array.from(pcu.instances);
@@ -3399,23 +3373,22 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3399
3373
  assert.deepEqual(Object.keys(elemNew).sort(), ["ECInstanceId", "ECClassId", "Model", "CodeSpec",
3400
3374
  "CodeScope", "FederationGuid", "$meta", "Category", "LastMod",
3401
3375
  "BinProp", "GuidArrProp"].sort());
3402
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp',
3376
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp',
3403
3377
  'Category.Id', 'CodeScope.Id', 'CodeSpec.Id', 'CodeValue',
3404
3378
  'ECClassId', 'ECInstanceId', 'FederationGuid', 'GeometryStream', 'GuidArrProp',
3405
3379
  'JsonProperties', 'LastMod', 'Model.Id', 'Origin', 'Parent', 'Pt3dProp', 'Rotation',
3406
3380
  'TypeDefinition', 'UserLabel'].sort());
3407
3381
  }
3408
- catch (e_17) {
3409
- env_17.error = e_17;
3410
- env_17.hasError = true;
3382
+ catch (e_18) {
3383
+ env_18.error = e_18;
3384
+ env_18.hasError = true;
3411
3385
  }
3412
3386
  finally {
3413
- __disposeResources(env_17);
3387
+ __disposeResources(env_18);
3414
3388
  }
3415
3389
  }
3416
3390
  // Wait so that LastMod on bis_Model gets a distinct timestamp before the update txn
3417
3391
  await new Promise((resolve) => setTimeout(resolve, 300));
3418
- // --- Push 3: update element — change all custom props ---
3419
3392
  await rwIModel.locks.acquireLocks({ exclusive: elementId });
3420
3393
  txn.updateElement({
3421
3394
  ...rwIModel.elements.getElementProps(elementId),
@@ -3425,12 +3398,11 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3425
3398
  "ffffffff-0000-1111-2222-333344445555",
3426
3399
  ],
3427
3400
  });
3428
- // === openFile: update changeset ===
3429
3401
  {
3430
- const env_18 = { stack: [], error: void 0, hasError: false };
3402
+ const env_19 = { stack: [], error: void 0, hasError: false };
3431
3403
  try {
3432
- const reader = __addDisposableResource(env_18, ChangesetReader.openInMemoryChanges({ db: rwIModel, rowOptions: { abbreviateBlobs: false } }), false);
3433
- const pcu = __addDisposableResource(env_18, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3404
+ const reader = __addDisposableResource(env_19, ChangesetReader.openInMemoryChanges({ db: rwIModel, rowOptions: { abbreviateBlobs: false } }), false);
3405
+ const pcu = __addDisposableResource(env_19, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3434
3406
  while (reader.step())
3435
3407
  pcu.appendFrom(reader);
3436
3408
  const instances = Array.from(pcu.instances);
@@ -3452,7 +3424,7 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3452
3424
  assert.deepEqual(elemNew.BBoxHigh, { X: 0, Y: 0 });
3453
3425
  assert.deepEqual(elemNew.Rotation, 0);
3454
3426
  expect(elemNew.LastMod).to.exist;
3455
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3427
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3456
3428
  assert.equal(elemNew.$meta.isIndirectChange, false);
3457
3429
  assert.equal(elemOld.$meta.op, "Updated");
3458
3430
  assert.equal(elemOld.$meta.stage, "Old");
@@ -3466,25 +3438,22 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3466
3438
  ]);
3467
3439
  expect(elemOld.LastMod).to.exist;
3468
3440
  assert.equal(elemOld.$meta.isIndirectChange, false);
3469
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3441
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow', 'BinProp', 'ECInstanceId', 'GuidArrProp', 'LastMod', 'Origin', 'Pt3dProp', 'Rotation'].sort());
3470
3442
  }
3471
- catch (e_18) {
3472
- env_18.error = e_18;
3473
- env_18.hasError = true;
3443
+ catch (e_19) {
3444
+ env_19.error = e_19;
3445
+ env_19.hasError = true;
3474
3446
  }
3475
3447
  finally {
3476
- __disposeResources(env_18);
3448
+ __disposeResources(env_19);
3477
3449
  }
3478
3450
  }
3479
- // === openGroup: insert + update as a single stream ===
3480
- // After merging, the elem New key is shared between insert-New and update-New;
3481
- // the update-New wins on overlapping props, so the final New reflects the updated state.
3482
- // elem Old only comes from the update changeset.
3451
+ // === openLocalChanges: insert + update as a single stream so becomes insert ===
3483
3452
  {
3484
- const env_19 = { stack: [], error: void 0, hasError: false };
3453
+ const env_20 = { stack: [], error: void 0, hasError: false };
3485
3454
  try {
3486
- const reader = __addDisposableResource(env_19, ChangesetReader.openLocalChanges({ db: rwIModel, includeInMemoryChanges: true, rowOptions: { abbreviateBlobs: false } }), false);
3487
- const pcu = __addDisposableResource(env_19, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3455
+ const reader = __addDisposableResource(env_20, ChangesetReader.openLocalChanges({ db: rwIModel, includeInMemoryChanges: true, rowOptions: { abbreviateBlobs: false } }), false);
3456
+ const pcu = __addDisposableResource(env_20, new PartialChangeUnifier(ChangeUnifierCache.createSqliteBackedCache()), false);
3488
3457
  while (reader.step())
3489
3458
  pcu.appendFrom(reader);
3490
3459
  const instances = Array.from(pcu.instances);
@@ -3517,19 +3486,19 @@ describe("ChangesetReader — openLocalChanges + openInmemoryChanges", () => {
3517
3486
  assert.deepEqual(Object.keys(elemNew).sort(), ["ECInstanceId", "ECClassId", "Model", "CodeSpec",
3518
3487
  "CodeScope", "FederationGuid", "$meta", "Category", "LastMod",
3519
3488
  "BinProp", "GuidArrProp", "Origin", "Rotation", "BBoxLow", "BBoxHigh", "Pt3dProp"].sort());
3520
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ['BBoxHigh', 'BBoxLow',
3489
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ['BBoxHigh', 'BBoxLow',
3521
3490
  'BinProp', 'Category.Id', 'CodeScope.Id', 'CodeSpec.Id',
3522
3491
  'CodeValue', 'ECClassId', 'ECInstanceId', 'FederationGuid', 'GeometryStream',
3523
3492
  'GuidArrProp', 'JsonProperties', 'LastMod', 'Model.Id', 'Origin', 'Parent', 'Pt3dProp',
3524
3493
  'Rotation', 'TypeDefinition', 'UserLabel'].sort());
3525
3494
  assert.equal(elemNew.$meta.isIndirectChange, false);
3526
3495
  }
3527
- catch (e_19) {
3528
- env_19.error = e_19;
3529
- env_19.hasError = true;
3496
+ catch (e_20) {
3497
+ env_20.error = e_20;
3498
+ env_20.hasError = true;
3530
3499
  }
3531
3500
  finally {
3532
- __disposeResources(env_19);
3501
+ __disposeResources(env_20);
3533
3502
  }
3534
3503
  }
3535
3504
  });
@@ -3578,7 +3547,7 @@ describe("ChangesetReader: behaviour in case imodel is not in sync with changese
3578
3547
  HubMock.shutdown();
3579
3548
  });
3580
3549
  it("openFile() reads the middle changeset of an insert → update → delete lifecycle", async () => {
3581
- const env_20 = { stack: [], error: void 0, hasError: false };
3550
+ const env_21 = { stack: [], error: void 0, hasError: false };
3582
3551
  try {
3583
3552
  const adminToken = "super manager token";
3584
3553
  // Push 2 (insert): insert element with category1
@@ -3626,8 +3595,8 @@ describe("ChangesetReader: behaviour in case imodel is not in sync with changese
3626
3595
  const changesets = await HubMock.downloadChangesets({ iModelId: rwIModelId, targetDir });
3627
3596
  expect(changesets.length).to.equal(4);
3628
3597
  const middleChangeset = changesets[Math.floor(changesets.length / 2)]; // index 2 = update
3629
- const reader = __addDisposableResource(env_20, ChangesetReader.openFile({ db: rwIModel, fileName: middleChangeset.pathname, propFilter: PropertyFilter.InstanceKey, rowOptions: { classIdsToClassNames: true } }), false);
3630
- const pcu = __addDisposableResource(env_20, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3598
+ const reader = __addDisposableResource(env_21, ChangesetReader.openFile({ db: rwIModel, fileName: middleChangeset.pathname, propFilter: PropertyFilter.InstanceKey, rowOptions: { classIdsToClassNames: true } }), false);
3599
+ const pcu = __addDisposableResource(env_21, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3631
3600
  while (reader.step())
3632
3601
  pcu.appendFrom(reader);
3633
3602
  const instances = Array.from(pcu.instances);
@@ -3646,16 +3615,16 @@ describe("ChangesetReader: behaviour in case imodel is not in sync with changese
3646
3615
  expect(bisElementNew.map((i => i.ECClassId)).sort()).to.deep.equal(["BisCore.GeometricElement2d", "BisCore.Element"].sort());
3647
3616
  expect(bisElementOld.map((i => i.ECClassId)).sort()).to.deep.equal(["BisCore.GeometricElement2d", "BisCore.Element"].sort());
3648
3617
  }
3649
- catch (e_20) {
3650
- env_20.error = e_20;
3651
- env_20.hasError = true;
3618
+ catch (e_21) {
3619
+ env_21.error = e_21;
3620
+ env_21.hasError = true;
3652
3621
  }
3653
3622
  finally {
3654
- __disposeResources(env_20);
3623
+ __disposeResources(env_21);
3655
3624
  }
3656
3625
  });
3657
3626
  it("openTxn() reads the middle txn of an insert → update → update lifecycle", async () => {
3658
- const env_21 = { stack: [], error: void 0, hasError: false };
3627
+ const env_22 = { stack: [], error: void 0, hasError: false };
3659
3628
  try {
3660
3629
  // Push 2 (insert): insert element with category1
3661
3630
  const geomArray = [
@@ -3697,8 +3666,8 @@ describe("ChangesetReader: behaviour in case imodel is not in sync with changese
3697
3666
  s: { x: 100.0, y: 200.0 },
3698
3667
  });
3699
3668
  txn.saveChanges("update element");
3700
- const reader = __addDisposableResource(env_21, ChangesetReader.openTxn({ db: rwIModel, txnId }), false);
3701
- const pcu = __addDisposableResource(env_21, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3669
+ const reader = __addDisposableResource(env_22, ChangesetReader.openTxn({ db: rwIModel, txnId }), false);
3670
+ const pcu = __addDisposableResource(env_22, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
3702
3671
  while (reader.step())
3703
3672
  pcu.appendFrom(reader);
3704
3673
  const instances = Array.from(pcu.instances);
@@ -3720,12 +3689,12 @@ describe("ChangesetReader: behaviour in case imodel is not in sync with changese
3720
3689
  expect(elementOld.$meta.changeFetchedPropNames).to.include("s.X");
3721
3690
  expect(elementOld.$meta.changeFetchedPropNames).to.not.include("s.Y");
3722
3691
  }
3723
- catch (e_21) {
3724
- env_21.error = e_21;
3725
- env_21.hasError = true;
3692
+ catch (e_22) {
3693
+ env_22.error = e_22;
3694
+ env_22.hasError = true;
3726
3695
  }
3727
3696
  finally {
3728
- __disposeResources(env_21);
3697
+ __disposeResources(env_22);
3729
3698
  }
3730
3699
  });
3731
3700
  });
@@ -3808,7 +3777,7 @@ describe("ChangesetReader: overflow table graceful recovery when ExclusiveRootCl
3808
3777
  HubMock.shutdown();
3809
3778
  });
3810
3779
  it("openFile() recovers gracefully when ExclusiveRootClassId is NULL for overflow table", () => {
3811
- const env_22 = { stack: [], error: void 0, hasError: false };
3780
+ const env_23 = { stack: [], error: void 0, hasError: false };
3812
3781
  try {
3813
3782
  /**
3814
3783
  * Simulate the broken state: clear ExclusiveRootClassId so the reader cannot
@@ -3818,7 +3787,7 @@ describe("ChangesetReader: overflow table graceful recovery when ExclusiveRootCl
3818
3787
  */
3819
3788
  expect(rwIModel[_nativeDb].executeSql("UPDATE ec_Table SET ExclusiveRootClassId=NULL WHERE Name='bis_GeometricElement2d_Overflow'")).to.equal(DbResult.BE_SQLITE_OK);
3820
3789
  let assertedOnOverflowTable = false;
3821
- const reader = __addDisposableResource(env_22, ChangesetReader.openFile({ db: rwIModel, fileName: updateChangesetPathname }), false);
3790
+ const reader = __addDisposableResource(env_23, ChangesetReader.openFile({ db: rwIModel, fileName: updateChangesetPathname }), false);
3822
3791
  while (reader.step()) {
3823
3792
  if (reader.tableName !== "bis_GeometricElement2d_Overflow")
3824
3793
  continue;
@@ -3841,18 +3810,18 @@ describe("ChangesetReader: overflow table graceful recovery when ExclusiveRootCl
3841
3810
  }
3842
3811
  assert.isTrue(assertedOnOverflowTable, "Expected at least one row from the overflow table");
3843
3812
  }
3844
- catch (e_22) {
3845
- env_22.error = e_22;
3846
- env_22.hasError = true;
3813
+ catch (e_23) {
3814
+ env_23.error = e_23;
3815
+ env_23.hasError = true;
3847
3816
  }
3848
3817
  finally {
3849
- __disposeResources(env_22);
3818
+ __disposeResources(env_23);
3850
3819
  }
3851
3820
  });
3852
3821
  });
3853
3822
  describe("ChangesetReader: instance reused with a different class (class change in Updated row)", () => {
3854
3823
  it("openFile() correctly identifies ECClassId change from T1 to T2 in a buggy changeset", async () => {
3855
- const env_23 = { stack: [], error: void 0, hasError: false };
3824
+ const env_24 = { stack: [], error: void 0, hasError: false };
3856
3825
  try {
3857
3826
  /**
3858
3827
  * Same scenario as ChangesetReader.test.ts: "Instance update to a different class (bug)".
@@ -3957,7 +3926,7 @@ describe("ChangesetReader: instance reused with a different class (class change
3957
3926
  // so it correctly sees T2 for the new (inserted) side and T1 for the old (deleted) side.
3958
3927
  let bisElementAsserted = false;
3959
3928
  let bisGeomElement2dAsserted = false;
3960
- const reader = __addDisposableResource(env_23, ChangesetReader.openFile({ db: b1, fileName: changesets[1].pathname }), false);
3929
+ const reader = __addDisposableResource(env_24, ChangesetReader.openFile({ db: b1, fileName: changesets[1].pathname }), false);
3961
3930
  while (reader.step()) {
3962
3931
  if (reader.tableName === "bis_Element" && reader.op === "Updated") {
3963
3932
  bisElementAsserted = true;
@@ -3987,12 +3956,12 @@ describe("ChangesetReader: instance reused with a different class (class change
3987
3956
  b1.close();
3988
3957
  HubMock.shutdown();
3989
3958
  }
3990
- catch (e_23) {
3991
- env_23.error = e_23;
3992
- env_23.hasError = true;
3959
+ catch (e_24) {
3960
+ env_24.error = e_24;
3961
+ env_24.hasError = true;
3993
3962
  }
3994
3963
  finally {
3995
- __disposeResources(env_23);
3964
+ __disposeResources(env_24);
3996
3965
  }
3997
3966
  });
3998
3967
  });
@@ -4078,8 +4047,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4078
4047
  assert.equal(updateModelNew.$meta.op, "Updated");
4079
4048
  assert.isString(updateModelNew.LastMod);
4080
4049
  assert.deepEqual(Object.keys(updateModelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta"].sort());
4081
- assert.deepEqual([...updateModelNew.$meta.tables], ["bis_Model"]);
4082
- assert.deepEqual([...updateModelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
4050
+ assert.deepEqual(updateModelNew.$meta.tables, ["bis_Model"]);
4051
+ assert.deepEqual(updateModelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
4083
4052
  assert.deepEqual(updateModelNew.$meta.rowOptions, { classIdsToClassNames: true });
4084
4053
  assert.equal(updateModelNew.$meta.isIndirectChange, true);
4085
4054
  // DrawingModel Updated Old
@@ -4088,8 +4057,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4088
4057
  assert.equal(updateModelOld.$meta.op, "Updated");
4089
4058
  assert.isString(updateModelOld.LastMod);
4090
4059
  assert.deepEqual(Object.keys(updateModelOld).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta"].sort());
4091
- assert.deepEqual([...updateModelOld.$meta.tables], ["bis_Model"]);
4092
- assert.deepEqual([...updateModelOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod"].sort());
4060
+ assert.deepEqual(updateModelOld.$meta.tables, ["bis_Model"]);
4061
+ assert.deepEqual(updateModelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod"].sort());
4093
4062
  assert.equal(updateModelOld.$meta.isIndirectChange, true);
4094
4063
  // OverflowElement Updated New
4095
4064
  const elemNew = updateInstances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "New");
@@ -4099,10 +4068,10 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4099
4068
  assert.equal(elemNew.$meta.isIndirectChange, false);
4100
4069
  assert.deepEqual(elemNew.$meta.rowOptions, { classIdsToClassNames: true });
4101
4070
  // Only bis_Element (LastMod) and bis_GeometricElement2d_Overflow (p34, p35) were touched
4102
- assert.deepEqual([...elemNew.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d_Overflow"].sort());
4103
- assert.deepEqual([...elemNew.$meta.changeIndexes].sort(), [1, 2].sort());
4071
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d_Overflow"].sort());
4072
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
4104
4073
  // changeFetchedPropNames: only the props that changed
4105
- assert.deepEqual([...elemNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "p34", "p35"].sort());
4074
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "p34", "p35"].sort());
4106
4075
  // New stage has updated values for the two overflow props
4107
4076
  assert.equal(elemNew[propName(34)], updateVal(34));
4108
4077
  assert.equal(elemNew[propName(35)], updateVal(35));
@@ -4115,8 +4084,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4115
4084
  assert.equal(elemOld.ECClassId, "TestDomain.OverflowElement");
4116
4085
  assert.equal(elemOld.$meta.op, "Updated");
4117
4086
  assert.equal(elemOld.$meta.isIndirectChange, false);
4118
- assert.deepEqual([...elemOld.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d_Overflow"].sort());
4119
- assert.deepEqual([...elemOld.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "p34", "p35"].sort());
4087
+ assert.deepEqual(elemOld.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d_Overflow"].sort());
4088
+ assert.deepEqual(elemOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "p34", "p35"].sort());
4120
4089
  // Old stage has the pre-update (insert) values for the two overflow props
4121
4090
  assert.equal(elemOld[propName(34)], insertVal(34));
4122
4091
  assert.equal(elemOld[propName(35)], insertVal(35));
@@ -4131,8 +4100,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4131
4100
  assert.equal(modelNew.$meta.op, "Updated");
4132
4101
  assert.isString(modelNew.LastMod);
4133
4102
  assert.isString(modelNew.GeometryGuid);
4134
- assert.deepEqual([...modelNew.$meta.tables], ["bis_Model"]);
4135
- assert.deepEqual([...modelNew.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4103
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
4104
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4136
4105
  assert.deepEqual(modelNew.$meta.rowOptions, { classIdsToClassNames: true });
4137
4106
  assert.equal(modelNew.$meta.isIndirectChange, true);
4138
4107
  // DrawingModel Updated Old
@@ -4140,7 +4109,7 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4140
4109
  expect(modelOld).to.exist;
4141
4110
  assert.equal(modelOld.$meta.op, "Updated");
4142
4111
  assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
4143
- assert.deepEqual([...modelOld.$meta.tables], ["bis_Model"]);
4112
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
4144
4113
  assert.equal(modelOld.$meta.isIndirectChange, true);
4145
4114
  // OverflowElement Inserted New — key assertions
4146
4115
  const insertElem = insertInstances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "New");
@@ -4151,10 +4120,10 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4151
4120
  assert.equal(insertElem.$meta.isIndirectChange, false);
4152
4121
  assert.deepEqual(insertElem.$meta.rowOptions, { classIdsToClassNames: true });
4153
4122
  // All three physical tables (including overflow) contributed to this insert
4154
- assert.deepEqual([...insertElem.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d", "bis_GeometricElement2d_Overflow"].sort());
4155
- assert.deepEqual([...insertElem.$meta.changeIndexes].sort(), [1, 2, 3].sort());
4123
+ assert.deepEqual(insertElem.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d", "bis_GeometricElement2d_Overflow"].sort());
4124
+ assert.deepEqual(insertElem.$meta.changeIndexes.sort(), [1, 2, 3].sort());
4156
4125
  // changeFetchedPropNames includes all 36 domain props
4157
- const fetchedProps = [...insertElem.$meta.changeFetchedPropNames];
4126
+ const fetchedProps = insertElem.$meta.changeFetchedPropNames;
4158
4127
  for (let i = 0; i < nProps; i++) {
4159
4128
  assert.include(fetchedProps, propName(i), `changeFetchedPropNames should contain p${i}`);
4160
4129
  }
@@ -4195,8 +4164,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4195
4164
  assert.isString(updateModelNewForDelete.LastMod);
4196
4165
  assert.isString(updateModelNewForDelete.GeometryGuid);
4197
4166
  assert.deepEqual(Object.keys(updateModelNewForDelete).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta", "GeometryGuid"].sort());
4198
- assert.deepEqual([...updateModelNewForDelete.$meta.tables], ["bis_Model"]);
4199
- assert.deepEqual([...updateModelNewForDelete.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4167
+ assert.deepEqual(updateModelNewForDelete.$meta.tables, ["bis_Model"]);
4168
+ assert.deepEqual(updateModelNewForDelete.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4200
4169
  assert.deepEqual(updateModelNewForDelete.$meta.rowOptions, { classIdsToClassNames: true });
4201
4170
  assert.equal(updateModelNewForDelete.$meta.isIndirectChange, true);
4202
4171
  // DrawingModel Updated Old
@@ -4206,8 +4175,8 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4206
4175
  assert.isString(updateModelOldForDelete.LastMod);
4207
4176
  assert.isString(updateModelNewForDelete.GeometryGuid);
4208
4177
  assert.deepEqual(Object.keys(updateModelOldForDelete).sort(), ["ECInstanceId", "ECClassId", "LastMod", "$meta", "GeometryGuid"].sort());
4209
- assert.deepEqual([...updateModelOldForDelete.$meta.tables], ["bis_Model"]);
4210
- assert.deepEqual([...updateModelOldForDelete.$meta.changeFetchedPropNames].sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4178
+ assert.deepEqual(updateModelOldForDelete.$meta.tables, ["bis_Model"]);
4179
+ assert.deepEqual(updateModelOldForDelete.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4211
4180
  assert.equal(updateModelOldForDelete.$meta.isIndirectChange, true);
4212
4181
  // OverflowElement Deleted Old
4213
4182
  const deletedElemOld = deleteInstances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "Old");
@@ -4218,9 +4187,9 @@ describe("ChangesetReader: overflow table insert and update and delete", () => {
4218
4187
  assert.equal(deletedElemOld.$meta.isIndirectChange, false);
4219
4188
  assert.deepEqual(deletedElemOld.$meta.rowOptions, { classIdsToClassNames: true });
4220
4189
  // All three physical tables contributed to the delete row
4221
- assert.deepEqual([...deletedElemOld.$meta.tables].sort(), ["bis_Element", "bis_GeometricElement2d", "bis_GeometricElement2d_Overflow"].sort());
4190
+ assert.deepEqual(deletedElemOld.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d", "bis_GeometricElement2d_Overflow"].sort());
4222
4191
  // All 36 domain props are recorded in changeFetchedPropNames
4223
- const deleteFetchedProps = [...deletedElemOld.$meta.changeFetchedPropNames];
4192
+ const deleteFetchedProps = deletedElemOld.$meta.changeFetchedPropNames;
4224
4193
  for (let i = 0; i < nProps; i++) {
4225
4194
  assert.include(deleteFetchedProps, propName(i), `changeFetchedPropNames should contain p${i}`);
4226
4195
  }
@@ -4286,23 +4255,25 @@ describe("ChangesetReader: invalid inputs", () => {
4286
4255
  expect(() => ChangesetReader.openFile({ db: iModel, fileName: KnownTestLocations.outputDir })).to.throw();
4287
4256
  });
4288
4257
  it("openFile: path points to a plain text file (not .changeset) throws", () => {
4289
- const env_24 = { stack: [], error: void 0, hasError: false };
4258
+ const env_25 = { stack: [], error: void 0, hasError: false };
4290
4259
  try {
4291
4260
  const txtFile = path.join(KnownTestLocations.outputDir, "not_a_changeset.txt");
4261
+ if (fs.existsSync(txtFile))
4262
+ fs.unlinkSync(txtFile);
4292
4263
  // Write a small non-changeset file and expect the reader to reject it.
4293
4264
  fs.writeFileSync(txtFile, "this is not a changeset");
4294
- const reader = __addDisposableResource(env_24, ChangesetReader.openFile({ db: iModel, fileName: txtFile }), false);
4265
+ const reader = __addDisposableResource(env_25, ChangesetReader.openFile({ db: iModel, fileName: txtFile }), false);
4295
4266
  assert.equal(reader.step(), false, "Expected step() to return false for an invalid changeset file");
4296
4267
  assert.equal(reader.step(), false, "Expected step() to return false for an invalid changeset file");
4297
4268
  assert.equal(reader.step(), false, "Expected step() to return false for an invalid changeset file");
4298
4269
  assert.equal(reader.step(), false, "Expected step() to return false for an invalid changeset file");
4299
4270
  }
4300
- catch (e_24) {
4301
- env_24.error = e_24;
4302
- env_24.hasError = true;
4271
+ catch (e_25) {
4272
+ env_25.error = e_25;
4273
+ env_25.hasError = true;
4303
4274
  }
4304
4275
  finally {
4305
- __disposeResources(env_24);
4276
+ __disposeResources(env_25);
4306
4277
  }
4307
4278
  });
4308
4279
  // --- openGroup ---
@@ -4322,17 +4293,17 @@ describe("ChangesetReader: invalid inputs", () => {
4322
4293
  // Passing the same changeset file twice is unusual but not necessarily an error at open time.
4323
4294
  // The reader should open and step without throwing; the caller is responsible for any semantic issues.
4324
4295
  expect(() => {
4325
- const env_25 = { stack: [], error: void 0, hasError: false };
4296
+ const env_26 = { stack: [], error: void 0, hasError: false };
4326
4297
  try {
4327
- const reader = __addDisposableResource(env_25, ChangesetReader.openGroup({ db: iModel, changesetFiles: [validChangesetPath, validChangesetPath] }), false);
4298
+ const reader = __addDisposableResource(env_26, ChangesetReader.openGroup({ db: iModel, changesetFiles: [validChangesetPath, validChangesetPath] }), false);
4328
4299
  while (reader.step()) { /* drain */ }
4329
4300
  }
4330
- catch (e_25) {
4331
- env_25.error = e_25;
4332
- env_25.hasError = true;
4301
+ catch (e_26) {
4302
+ env_26.error = e_26;
4303
+ env_26.hasError = true;
4333
4304
  }
4334
4305
  finally {
4335
- __disposeResources(env_25);
4306
+ __disposeResources(env_26);
4336
4307
  }
4337
4308
  }).to.not.throw();
4338
4309
  });
@@ -4345,24 +4316,10 @@ describe("ChangesetReader: invalid inputs", () => {
4345
4316
  });
4346
4317
  // --- property accessors before step() ---
4347
4318
  it("accessing tableName before step() throws", () => {
4348
- const env_26 = { stack: [], error: void 0, hasError: false };
4349
- try {
4350
- const reader = __addDisposableResource(env_26, ChangesetReader.openFile({ db: iModel, fileName: validChangesetPath }), false);
4351
- expect(() => reader.tableName).to.throw();
4352
- }
4353
- catch (e_26) {
4354
- env_26.error = e_26;
4355
- env_26.hasError = true;
4356
- }
4357
- finally {
4358
- __disposeResources(env_26);
4359
- }
4360
- });
4361
- it("accessing isECTable before step() throws", () => {
4362
4319
  const env_27 = { stack: [], error: void 0, hasError: false };
4363
4320
  try {
4364
4321
  const reader = __addDisposableResource(env_27, ChangesetReader.openFile({ db: iModel, fileName: validChangesetPath }), false);
4365
- expect(() => reader.isECTable).to.throw();
4322
+ expect(() => reader.tableName).to.throw();
4366
4323
  }
4367
4324
  catch (e_27) {
4368
4325
  env_27.error = e_27;
@@ -4372,11 +4329,11 @@ describe("ChangesetReader: invalid inputs", () => {
4372
4329
  __disposeResources(env_27);
4373
4330
  }
4374
4331
  });
4375
- it("accessing isIndirectChange before step() throws", () => {
4332
+ it("accessing isECTable before step() throws", () => {
4376
4333
  const env_28 = { stack: [], error: void 0, hasError: false };
4377
4334
  try {
4378
4335
  const reader = __addDisposableResource(env_28, ChangesetReader.openFile({ db: iModel, fileName: validChangesetPath }), false);
4379
- expect(() => reader.isIndirectChange).to.throw();
4336
+ expect(() => reader.isECTable).to.throw();
4380
4337
  }
4381
4338
  catch (e_28) {
4382
4339
  env_28.error = e_28;
@@ -4386,5 +4343,656 @@ describe("ChangesetReader: invalid inputs", () => {
4386
4343
  __disposeResources(env_28);
4387
4344
  }
4388
4345
  });
4346
+ it("accessing isIndirectChange before step() throws", () => {
4347
+ const env_29 = { stack: [], error: void 0, hasError: false };
4348
+ try {
4349
+ const reader = __addDisposableResource(env_29, ChangesetReader.openFile({ db: iModel, fileName: validChangesetPath }), false);
4350
+ expect(() => reader.isIndirectChange).to.throw();
4351
+ }
4352
+ catch (e_29) {
4353
+ env_29.error = e_29;
4354
+ env_29.hasError = true;
4355
+ }
4356
+ finally {
4357
+ __disposeResources(env_29);
4358
+ }
4359
+ });
4360
+ it("openGroup: should throw if spillThresholdInBytes is negative", () => {
4361
+ expect(() => {
4362
+ ChangesetReader.openGroup({ db: iModel, changesetFiles: [validChangesetPath, validChangesetPath], spillThresholdInBytes: -1 });
4363
+ }).to.throw();
4364
+ });
4365
+ it("openGroup: should throw if spillThresholdInBytes is extremely large", () => {
4366
+ // 2**64 is a very large value, even 1 TB = 1024**4 bytes, but that is just around 2**40.
4367
+ expect(() => {
4368
+ ChangesetReader.openGroup({ db: iModel, changesetFiles: [validChangesetPath, validChangesetPath], spillThresholdInBytes: 2 ** 64 });
4369
+ }).to.throw();
4370
+ });
4371
+ });
4372
+ describe("ChangesetReader — spillThresholdInBytes (spill-to-disk)", () => {
4373
+ const TEST_DOMAIN_SCHEMA = `<?xml version="1.0" encoding="UTF-8"?>
4374
+ <ECSchema schemaName="TestDomain" alias="ts" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
4375
+ <ECSchemaReference name="BisCore" version="01.00" alias="bis"/>
4376
+ <ECStructClass typeName="RichPoint" modifier="Sealed">
4377
+ <ECProperty propertyName="X" typeName="double"/>
4378
+ <ECProperty propertyName="Y" typeName="double"/>
4379
+ <ECProperty propertyName="Z" typeName="double"/>
4380
+ <ECProperty propertyName="Label" typeName="string"/>
4381
+ <ECProperty propertyName="Pt2d" typeName="point2d"/>
4382
+ <ECProperty propertyName="Pt3d" typeName="point3d"/>
4383
+ </ECStructClass>
4384
+ <ECRelationshipClass typeName="Test2dUsesElement" strength="referencing" modifier="None">
4385
+ <Source multiplicity="(0..*)" roleLabel="uses" polymorphic="true"><Class class="Test2dElement"/></Source>
4386
+ <Target multiplicity="(0..1)" roleLabel="is used by" polymorphic="true"><Class class="bis:Element"/></Target>
4387
+ </ECRelationshipClass>
4388
+ <ECEntityClass typeName="Test2dElement">
4389
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
4390
+ <ECProperty propertyName="StrProp" typeName="string"/>
4391
+ <ECProperty propertyName="IntProp" typeName="int"/>
4392
+ <ECProperty propertyName="LongProp" typeName="long"/>
4393
+ <ECProperty propertyName="DblProp" typeName="double"/>
4394
+ <ECProperty propertyName="BoolProp" typeName="boolean"/>
4395
+ <ECProperty propertyName="DtProp" typeName="dateTime"/>
4396
+ <ECProperty propertyName="BinProp" typeName="binary"/>
4397
+ <ECProperty propertyName="Pt2dProp" typeName="point2d"/>
4398
+ <ECProperty propertyName="Pt3dProp" typeName="point3d"/>
4399
+ <ECStructProperty propertyName="StructProp" typeName="RichPoint"/>
4400
+ <ECArrayProperty propertyName="IntArrProp" typeName="int" minOccurs="0" maxOccurs="unbounded"/>
4401
+ <ECArrayProperty propertyName="StrArrProp" typeName="string" minOccurs="0" maxOccurs="unbounded"/>
4402
+ <ECStructArrayProperty propertyName="StructArrProp" typeName="RichPoint" minOccurs="0" maxOccurs="unbounded"/>
4403
+ <ECNavigationProperty propertyName="RelatedElem" relationshipName="Test2dUsesElement" direction="forward"/>
4404
+ </ECEntityClass>
4405
+ </ECSchema>`;
4406
+ /** Boots HubMock, opens a briefcase, starts a txn, and tears everything down after `fn` resolves or throws. */
4407
+ async function withSpillTestIModel(hubName, iModelName, fn) {
4408
+ HubMock.startup(hubName, KnownTestLocations.outputDir);
4409
+ const adminToken = "super manager token";
4410
+ const iTwinId = HubMock.iTwinId;
4411
+ const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName, description: iModelName, accessToken: adminToken });
4412
+ const rwIModel = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId, accessToken: adminToken });
4413
+ const txn = startTestTxn(rwIModel, `ChangesetReader spill ${iModelName}`);
4414
+ rwIModel.channels.addAllowedChannel(ChannelControl.sharedChannelName);
4415
+ try {
4416
+ await fn({ rwIModel, txn, iModelId, adminToken });
4417
+ }
4418
+ finally {
4419
+ txn.end();
4420
+ rwIModel.close();
4421
+ HubMock.shutdown();
4422
+ }
4423
+ }
4424
+ /** Imports TestDomain schema and pushes a drawing model + category as an initial setup changeset. Returns the ids. */
4425
+ async function pushInitialModelSetup(ctx, catName) {
4426
+ const { rwIModel, txn, adminToken } = ctx;
4427
+ await importSchemaStrings(txn, [TEST_DOMAIN_SCHEMA]);
4428
+ await rwIModel.locks.acquireLocks({ shared: IModel.dictionaryId });
4429
+ const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(txn, Code.createEmpty(), true);
4430
+ const drawingCategoryId = DrawingCategory.insert(txn, IModel.dictionaryId, catName, new SubCategoryAppearance({ color: ColorDef.fromString("rgb(0,128,255)").toJSON() }));
4431
+ txn.saveChanges("setup");
4432
+ await rwIModel.pushChanges({ description: "setup", accessToken: adminToken });
4433
+ return { drawingModelId, drawingCategoryId };
4434
+ }
4435
+ /** Inserts a TestDomain:Test2dElement with all EC primitive types populated and returns its id. */
4436
+ function insertTestElement(txn, drawingModelId, drawingCategoryId) {
4437
+ const geom = [
4438
+ Arc3d.createXY(Point3d.create(0, 0), 5),
4439
+ ].map((a) => IModelJson.Writer.toIModelJson(a));
4440
+ return txn.insertElement({
4441
+ classFullName: "TestDomain:Test2dElement",
4442
+ model: drawingModelId,
4443
+ category: drawingCategoryId,
4444
+ code: Code.createEmpty(),
4445
+ geom,
4446
+ StrProp: "hello",
4447
+ IntProp: 42,
4448
+ LongProp: 9_007_199_254_740_991,
4449
+ DblProp: 3.14159265358979,
4450
+ BoolProp: true,
4451
+ DtProp: "2024-01-15T12:00:00.000",
4452
+ BinProp: new Uint8Array([1, 2, 3, 4]),
4453
+ Pt2dProp: { x: 1.5, y: 2.5 },
4454
+ Pt3dProp: { x: 3.0, y: 4.0, z: 5.0 },
4455
+ StructProp: {
4456
+ X: 1.0, Y: 2.0, Z: 3.0, Label: "origin",
4457
+ Pt2d: { x: 0.5, y: 0.5 },
4458
+ Pt3d: { x: 1.0, y: 2.0, z: 3.0 },
4459
+ },
4460
+ IntArrProp: [10, 20, 30],
4461
+ StrArrProp: ["alpha", "beta", "gamma"],
4462
+ StructArrProp: [
4463
+ { X: 0.0, Y: 1.0, Z: 2.0, Label: "a", Pt2d: { x: 0.0, y: 0.0 }, Pt3d: { x: 0.0, y: 0.0, z: 0.0 } },
4464
+ { X: 3.0, Y: 4.0, Z: 5.0, Label: "b", Pt2d: { x: 1.0, y: 1.0 }, Pt3d: { x: 1.0, y: 1.0, z: 1.0 } },
4465
+ ],
4466
+ RelatedElem: { id: drawingCategoryId, relClassName: "TestDomain:Test2dUsesElement" },
4467
+ });
4468
+ }
4469
+ /** Reads all instances from a reader using an in-memory unifier cache. */
4470
+ function drainReader(reader) {
4471
+ const env_30 = { stack: [], error: void 0, hasError: false };
4472
+ try {
4473
+ const pcu = __addDisposableResource(env_30, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
4474
+ while (reader.step())
4475
+ pcu.appendFrom(reader);
4476
+ return Array.from(pcu.instances);
4477
+ }
4478
+ catch (e_30) {
4479
+ env_30.error = e_30;
4480
+ env_30.hasError = true;
4481
+ }
4482
+ finally {
4483
+ __disposeResources(env_30);
4484
+ }
4485
+ }
4486
+ /** Sorts instances by a stable key for deterministic deep-equality comparisons. */
4487
+ function sortInstances(instances) {
4488
+ return instances.slice().sort((a, b) => `${a.ECInstanceId}-${a.$meta.stage}`.localeCompare(`${b.ECInstanceId}-${b.$meta.stage}`));
4489
+ }
4490
+ /**
4491
+ * Asserts that spill instances are non-empty, verifies the DrawingModel indirect-update fields
4492
+ * and every field of each inserted Test2dElement one by one, then confirms the spill output is
4493
+ * bit-for-bit identical to the default output.
4494
+ */
4495
+ function assertSpillEquivalence(iModel, defaultInstances, spillInstances, elementIds, drawingModelId, drawingCategoryId, isModelUpdated) {
4496
+ expect(defaultInstances.length).to.be.greaterThan(0, "defaultInstances should be non-empty");
4497
+ expect(spillInstances.length).to.be.greaterThan(0, "spillInstances should be non-empty");
4498
+ if (isModelUpdated) {
4499
+ // --- DrawingModel Updated New (indirect side-effect of element insert) ---
4500
+ const modelNew = spillInstances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "New");
4501
+ expect(modelNew).to.exist;
4502
+ assert.equal(modelNew.ECInstanceId, drawingModelId);
4503
+ assert.equal(iModel.getClassNameFromId(modelNew.ECClassId), "BisCore:DrawingModel");
4504
+ assert.isString(modelNew.LastMod);
4505
+ assert.isString(modelNew.GeometryGuid);
4506
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4507
+ assert.equal(modelNew.$meta.op, "Updated");
4508
+ assert.equal(modelNew.$meta.stage, "New");
4509
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
4510
+ expect(modelNew.$meta.changeIndexes.length).to.be.greaterThan(0);
4511
+ assert.isString(modelNew.$meta.instanceKey);
4512
+ assert.equal(modelNew.$meta.instanceKey.split("-").length, 2);
4513
+ assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
4514
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.slice().sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4515
+ assert.equal(modelNew.$meta.isIndirectChange, true);
4516
+ // --- DrawingModel Updated Old ---
4517
+ const modelOld = spillInstances.find((i) => i.ECInstanceId === drawingModelId && i.$meta.stage === "Old");
4518
+ expect(modelOld).to.exist;
4519
+ assert.equal(modelOld.ECInstanceId, drawingModelId);
4520
+ assert.equal(iModel.getClassNameFromId(modelOld.ECClassId), "BisCore:DrawingModel");
4521
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4522
+ assert.equal(modelOld.$meta.op, "Updated");
4523
+ assert.equal(modelOld.$meta.stage, "Old");
4524
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
4525
+ expect(modelOld.$meta.changeIndexes.length).to.be.greaterThan(0);
4526
+ assert.isString(modelOld.$meta.instanceKey);
4527
+ assert.equal(modelOld.$meta.instanceKey.split("-").length, 2);
4528
+ assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
4529
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.slice().sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4530
+ assert.equal(modelOld.$meta.isIndirectChange, true);
4531
+ }
4532
+ // --- Test2dElement Inserted New — assert every field for each inserted element ---
4533
+ for (const elementId of elementIds) {
4534
+ const elem = spillInstances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "New");
4535
+ expect(elem).to.exist;
4536
+ assert.equal(elem.ECInstanceId, elementId);
4537
+ assert.equal(iModel.getClassNameFromId(elem.ECClassId), "TestDomain:Test2dElement");
4538
+ assert.equal(elem.Model.Id, drawingModelId);
4539
+ assert.equal(iModel.getClassNameFromId(elem.Model.RelECClassId), "BisCore:ModelContainsElements");
4540
+ assert.isString(elem.LastMod);
4541
+ assert.equal(elem.CodeSpec.Id, "0x1");
4542
+ assert.equal(iModel.getClassNameFromId(elem.CodeSpec.RelECClassId), "BisCore:CodeSpecSpecifiesCode");
4543
+ assert.equal(elem.CodeScope.Id, "0x1");
4544
+ assert.equal(iModel.getClassNameFromId(elem.CodeScope.RelECClassId), "BisCore:ElementScopesCode");
4545
+ assert.isString(elem.FederationGuid);
4546
+ assert.equal(elem.Category.Id, drawingCategoryId);
4547
+ assert.equal(iModel.getClassNameFromId(elem.Category.RelECClassId), "BisCore:GeometricElement2dIsInCategory");
4548
+ assert.deepEqual(elem.Origin, { X: 0, Y: 0 });
4549
+ assert.equal(elem.Rotation, 0);
4550
+ assert.deepEqual(elem.BBoxLow, { X: -5, Y: -5 });
4551
+ assert.deepEqual(elem.BBoxHigh, { X: 5, Y: 5 });
4552
+ assert.include(String(elem.GeometryStream), "\"bytes\"");
4553
+ assert.include(String(elem.BinProp), "\"bytes\"");
4554
+ assert.equal(elem.StrProp, "hello");
4555
+ assert.equal(elem.IntProp, 42);
4556
+ assert.equal(elem.LongProp, 9007199254740991);
4557
+ assert.closeTo(elem.DblProp, 3.14159265358979, 1e-10);
4558
+ assert.equal(elem.BoolProp, true);
4559
+ assert.equal(elem.DtProp, "2024-01-15T12:00:00.000");
4560
+ assert.deepEqual(elem.Pt2dProp, { X: 1.5, Y: 2.5 });
4561
+ assert.deepEqual(elem.Pt3dProp, { X: 3, Y: 4, Z: 5 });
4562
+ assert.deepEqual(elem.StructProp, { X: 1, Y: 2, Z: 3, Label: "origin", Pt2d: { X: 0.5, Y: 0.5 }, Pt3d: { X: 1, Y: 2, Z: 3 } });
4563
+ assert.deepEqual(elem.IntArrProp, [10, 20, 30]);
4564
+ assert.deepEqual(elem.StrArrProp, ["alpha", "beta", "gamma"]);
4565
+ assert.deepEqual(elem.StructArrProp, [
4566
+ { X: 0, Y: 1, Z: 2, Label: "a", Pt2d: { X: 0, Y: 0 }, Pt3d: { X: 0, Y: 0, Z: 0 } },
4567
+ { X: 3, Y: 4, Z: 5, Label: "b", Pt2d: { X: 1, Y: 1 }, Pt3d: { X: 1, Y: 1, Z: 1 } },
4568
+ ]);
4569
+ assert.equal(elem.RelatedElem.Id, drawingCategoryId);
4570
+ assert.equal(iModel.getClassNameFromId(elem.RelatedElem.RelECClassId), "TestDomain:Test2dUsesElement");
4571
+ assert.deepEqual(Object.keys(elem.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4572
+ assert.equal(elem.$meta.op, "Inserted");
4573
+ assert.equal(elem.$meta.stage, "New");
4574
+ assert.deepEqual(elem.$meta.tables.slice().sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
4575
+ expect(elem.$meta.changeIndexes.length).to.be.greaterThan(0);
4576
+ assert.isString(elem.$meta.instanceKey);
4577
+ assert.equal(elem.$meta.instanceKey.split("-").length, 2);
4578
+ assert.equal(elem.$meta.propFilter, PropertyFilter.All);
4579
+ assert.deepEqual(elem.$meta.changeFetchedPropNames.slice().sort(), [
4580
+ "BBoxHigh", "BBoxLow", "BinProp", "BoolProp", "Category.Id", "CodeScope.Id",
4581
+ "CodeSpec.Id", "CodeValue", "DblProp", "DtProp", "ECClassId", "ECInstanceId",
4582
+ "FederationGuid", "GeometryStream", "IntArrProp", "IntProp", "JsonProperties",
4583
+ "LastMod", "LongProp", "Model.Id", "Origin", "Parent", "Pt2dProp", "Pt3dProp",
4584
+ "RelatedElem", "Rotation", "StrArrProp", "StrProp", "StructArrProp", "StructProp.Label",
4585
+ "StructProp.Pt2d", "StructProp.Pt3d", "StructProp.X", "StructProp.Y", "StructProp.Z",
4586
+ "TypeDefinition", "UserLabel",
4587
+ ].sort());
4588
+ assert.equal(elem.$meta.isIndirectChange, false);
4589
+ }
4590
+ // --- spill output must exactly match default output ---
4591
+ assert.deepEqual(sortInstances(spillInstances), sortInstances(defaultInstances));
4592
+ }
4593
+ // ---- openGroup ----
4594
+ it("openGroup: spillThresholdInBytes = 1 (forces disk spill) yields same instances as default", async () => {
4595
+ await withSpillTestIModel("ECChangesetSpillGroup", "spillGroup", async (ctx) => {
4596
+ const { rwIModel, txn, iModelId, adminToken } = ctx;
4597
+ const { drawingModelId, drawingCategoryId } = await pushInitialModelSetup(ctx, "SpillGroupCat");
4598
+ // Wait so that LastMod on bis_Model gets a distinct timestamp before the insert txn
4599
+ await new Promise((resolve) => setTimeout(resolve, 300));
4600
+ await rwIModel.locks.acquireLocks({ shared: drawingModelId });
4601
+ // Push 1: insert element 1
4602
+ const element1Id = insertTestElement(txn, drawingModelId, drawingCategoryId);
4603
+ txn.saveChanges("insert element 1");
4604
+ await rwIModel.pushChanges({ description: "changeset 1: element 1", accessToken: adminToken });
4605
+ await rwIModel.locks.acquireLocks({ shared: drawingModelId });
4606
+ // Push 2: insert element 2
4607
+ const element2Id = insertTestElement(txn, drawingModelId, drawingCategoryId);
4608
+ txn.saveChanges("insert element 2");
4609
+ await rwIModel.pushChanges({ description: "changeset 2: element 2", accessToken: adminToken });
4610
+ const targetDir = path.join(KnownTestLocations.outputDir, iModelId, "changesets");
4611
+ const changesets = await HubMock.downloadChangesets({ iModelId, targetDir });
4612
+ assert.equal(changesets.length, 3);
4613
+ const changesetPaths = changesets.slice(1).map((cs) => cs.pathname); // The insert element changesets are the 2nd and 3rd changesets (1st is the initial setup)
4614
+ assertSpillEquivalence(rwIModel, drainReader(ChangesetReader.openGroup({ db: rwIModel, changesetFiles: changesetPaths })), drainReader(ChangesetReader.openGroup({ db: rwIModel, changesetFiles: changesetPaths, spillThresholdInBytes: 1 })), [element1Id, element2Id], drawingModelId, drawingCategoryId, true);
4615
+ });
4616
+ });
4617
+ // ---- openTxn ----
4618
+ it("openTxn: spillThresholdInBytes = 1 (forces disk spill) yields same instances as default", async () => {
4619
+ await withSpillTestIModel("ECChangesetSpillTxn", "spillTxn", async (ctx) => {
4620
+ const { rwIModel, txn } = ctx;
4621
+ const { drawingModelId, drawingCategoryId } = await pushInitialModelSetup(ctx, "SpillTxnCat");
4622
+ await rwIModel.locks.acquireLocks({ shared: drawingModelId });
4623
+ // Txn 1: insert element 1 (an earlier local txn)
4624
+ insertTestElement(txn, drawingModelId, drawingCategoryId);
4625
+ txn.saveChanges("insert element 1");
4626
+ // Txn 2: insert element 2 — the last txn, whose id is used for openTxn
4627
+ const element2Id = insertTestElement(txn, drawingModelId, drawingCategoryId);
4628
+ txn.saveChanges("insert element 2");
4629
+ const lastTxnId = rwIModel.txns.getLastSavedTxnProps().id;
4630
+ assertSpillEquivalence(rwIModel, drainReader(ChangesetReader.openTxn({ db: rwIModel, txnId: lastTxnId })), drainReader(ChangesetReader.openTxn({ db: rwIModel, txnId: lastTxnId, spillThresholdInBytes: 1 })), [element2Id], drawingModelId, drawingCategoryId, false);
4631
+ });
4632
+ });
4633
+ // ---- openLocalChanges ----
4634
+ it("openLocalChanges: spillThresholdInBytes = 1 (forces disk spill) yields same instances as default", async () => {
4635
+ await withSpillTestIModel("ECChangesetSpillLocal", "spillLocal", async (ctx) => {
4636
+ const { rwIModel, txn } = ctx;
4637
+ const { drawingModelId, drawingCategoryId } = await pushInitialModelSetup(ctx, "SpillLocalCat");
4638
+ // Wait so that LastMod on bis_Model gets a distinct timestamp before the insert txn
4639
+ await new Promise((resolve) => setTimeout(resolve, 300));
4640
+ await rwIModel.locks.acquireLocks({ shared: drawingModelId });
4641
+ // Local txn 1: saved but not pushed
4642
+ const element1Id = insertTestElement(txn, drawingModelId, drawingCategoryId);
4643
+ txn.saveChanges("local insert 1");
4644
+ // Local txn 2: saved but not pushed
4645
+ const element2Id = insertTestElement(txn, drawingModelId, drawingCategoryId);
4646
+ txn.saveChanges("local insert 2");
4647
+ assertSpillEquivalence(rwIModel, drainReader(ChangesetReader.openLocalChanges({ db: rwIModel })), drainReader(ChangesetReader.openLocalChanges({ db: rwIModel, spillThresholdInBytes: 1 })), [element1Id, element2Id], drawingModelId, drawingCategoryId, true);
4648
+ });
4649
+ });
4650
+ // ---- openInMemoryChanges ----
4651
+ it("openInMemoryChanges: spillThresholdInBytes = 1 (forces disk spill) yields same instances as default", async () => {
4652
+ await withSpillTestIModel("ECChangesetSpillInMemory", "spillInMemory", async (ctx) => {
4653
+ const { rwIModel, txn } = ctx;
4654
+ const { drawingModelId, drawingCategoryId } = await pushInitialModelSetup(ctx, "SpillInMemoryCat");
4655
+ await rwIModel.locks.acquireLocks({ shared: drawingModelId });
4656
+ // Insert without saveChanges — read raw in-memory changes
4657
+ const elementId = insertTestElement(txn, drawingModelId, drawingCategoryId);
4658
+ assertSpillEquivalence(rwIModel, drainReader(ChangesetReader.openInMemoryChanges({ db: rwIModel })), drainReader(ChangesetReader.openInMemoryChanges({ db: rwIModel, spillThresholdInBytes: 1 })), [elementId], drawingModelId, drawingCategoryId, false // saveChanges is not called, so DrawingModel should not be updated and thus no indirect changes
4659
+ );
4660
+ });
4661
+ });
4662
+ });
4663
+ describe("ChangesetReader: strict mode (column-count mismatch)", () => {
4664
+ const STRICT_MODE_SCHEMA_V1 = `<?xml version="1.0" encoding="UTF-8"?>
4665
+ <ECSchema schemaName="TestDomain" alias="ts" version="01.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
4666
+ <ECSchemaReference name="BisCore" version="01.00" alias="bis"/>
4667
+ <ECEntityClass typeName="SimpleElement">
4668
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
4669
+ <ECProperty propertyName="p1" typeName="string"/>
4670
+ <ECProperty propertyName="p2" typeName="string"/>
4671
+ </ECEntityClass>
4672
+ </ECSchema>`;
4673
+ const STRICT_MODE_SCHEMA_V2 = `<?xml version="1.0" encoding="UTF-8"?>
4674
+ <ECSchema schemaName="TestDomain" alias="ts" version="01.01" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
4675
+ <ECSchemaReference name="BisCore" version="01.00" alias="bis"/>
4676
+ <ECEntityClass typeName="SimpleElement">
4677
+ <BaseClass>bis:GraphicalElement2d</BaseClass>
4678
+ <ECProperty propertyName="p1" typeName="string"/>
4679
+ <ECProperty propertyName="p2" typeName="string"/>
4680
+ <ECProperty propertyName="p3" typeName="string"/>
4681
+ <ECProperty propertyName="p4" typeName="string"/>
4682
+ </ECEntityClass>
4683
+ </ECSchema>`;
4684
+ it("openTxn: strict mode ON throws when txn was captured with fewer columns than the current live table, strict mode OFF does not throw", async () => {
4685
+ HubMock.startup("StrictModeOldTxnStrict", KnownTestLocations.outputDir);
4686
+ const adminToken = "super manager token";
4687
+ const iTwinId = HubMock.iTwinId;
4688
+ const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName: "strictOldTxn", description: "strict", accessToken: adminToken });
4689
+ const db = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId, accessToken: adminToken });
4690
+ const txn = startTestTxn(db, "strict mode scenario 1 strict");
4691
+ db.channels.addAllowedChannel(ChannelControl.sharedChannelName);
4692
+ try {
4693
+ // Setup: v1 schema + drawing model + category
4694
+ await importSchemaStrings(txn, [STRICT_MODE_SCHEMA_V1]);
4695
+ await db.locks.acquireLocks({ shared: IModel.dictionaryId });
4696
+ const [, modelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(txn, Code.createEmpty(), true);
4697
+ const catId = DrawingCategory.insert(txn, IModel.dictionaryId, "Cat", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(128,0,128)").toJSON() }));
4698
+ txn.saveChanges("setup");
4699
+ await db.pushChanges({ description: "setup", accessToken: adminToken });
4700
+ // Wait so that LastMod on bis_Model gets a distinct timestamp before the insert txn
4701
+ await new Promise((resolve) => setTimeout(resolve, 300));
4702
+ await db.locks.acquireLocks({ shared: modelId });
4703
+ const geom = [Arc3d.createXY(Point3d.create(0, 0), 5)].map((a) => IModelJson.Writer.toIModelJson(a));
4704
+ const elementId = txn.insertElement({ classFullName: "TestDomain:SimpleElement", model: modelId, category: catId, code: Code.createEmpty(), geom, p1: "hello", p2: "world" });
4705
+ txn.saveChanges("insert v1 element");
4706
+ const txnId = db.txns.getLastSavedTxnProps().id;
4707
+ // Upgrade schema to v2 — appends one column in the live DB.
4708
+ await importSchemaStrings(txn, [STRICT_MODE_SCHEMA_V2]);
4709
+ // Strict mode ON: binary has one column less than the live table.
4710
+ {
4711
+ const env_31 = { stack: [], error: void 0, hasError: false };
4712
+ try {
4713
+ const reader = __addDisposableResource(env_31, ChangesetReader.openTxn({ db, txnId }), false);
4714
+ reader.enableStrictMode();
4715
+ expect(() => { while (reader.step()) { /* drain */ } }).to.throw();
4716
+ }
4717
+ catch (e_31) {
4718
+ env_31.error = e_31;
4719
+ env_31.hasError = true;
4720
+ }
4721
+ finally {
4722
+ __disposeResources(env_31);
4723
+ }
4724
+ }
4725
+ {
4726
+ const env_32 = { stack: [], error: void 0, hasError: false };
4727
+ try {
4728
+ const reader = __addDisposableResource(env_32, ChangesetReader.openTxn({ db, txnId }), false);
4729
+ reader.disableStrictMode(); // no-op when already off — verifies the API does not throw
4730
+ const pcu = __addDisposableResource(env_32, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
4731
+ while (reader.step())
4732
+ pcu.appendFrom(reader);
4733
+ const instances = Array.from(pcu.instances);
4734
+ assert.equal(instances.length, 3, "should have 3 change instances: model (New + Old) + element (New)");
4735
+ // --- Model indirect update — New stage ---
4736
+ const modelNew = instances.find((i) => i.ECInstanceId === modelId && i.$meta.stage === "New");
4737
+ expect(modelNew).to.exist;
4738
+ assert.equal(modelNew.ECInstanceId, modelId);
4739
+ assert.equal(db.getClassNameFromId(modelNew.ECClassId), "BisCore:DrawingModel");
4740
+ assert.isString(modelNew.LastMod);
4741
+ assert.isString(modelNew.GeometryGuid);
4742
+ assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
4743
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4744
+ assert.equal(modelNew.$meta.op, "Updated");
4745
+ assert.equal(modelNew.$meta.stage, "New");
4746
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
4747
+ assert.deepEqual(modelNew.$meta.changeIndexes, [3]);
4748
+ assert.isString(modelNew.$meta.instanceKey);
4749
+ assert.equal(modelNew.$meta.instanceKey.split("-").length, 2);
4750
+ assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
4751
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4752
+ assert.equal(modelNew.$meta.isIndirectChange, true);
4753
+ // --- Model indirect update — Old stage (only key columns, no data properties) ---
4754
+ const modelOld = instances.find((i) => i.ECInstanceId === modelId && i.$meta.stage === "Old");
4755
+ expect(modelOld).to.exist;
4756
+ assert.equal(modelOld.ECInstanceId, modelId);
4757
+ assert.equal(db.getClassNameFromId(modelOld.ECClassId), "BisCore:DrawingModel");
4758
+ assert.isUndefined(modelOld.LastMod, "Old stage carries only the key — no data properties");
4759
+ assert.isUndefined(modelOld.GeometryGuid, "Old stage carries only the key — no data properties");
4760
+ assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
4761
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4762
+ assert.equal(modelOld.$meta.op, "Updated");
4763
+ assert.equal(modelOld.$meta.stage, "Old");
4764
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
4765
+ assert.deepEqual(modelOld.$meta.changeIndexes, [3]);
4766
+ assert.isString(modelOld.$meta.instanceKey);
4767
+ assert.equal(modelOld.$meta.instanceKey.split("-").length, 2);
4768
+ assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
4769
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4770
+ assert.equal(modelOld.$meta.isIndirectChange, true);
4771
+ // --- Element insert — New stage ---
4772
+ const elemNew = instances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "New");
4773
+ expect(elemNew).to.exist;
4774
+ assert.equal(elemNew.ECInstanceId, elementId);
4775
+ assert.equal(db.getClassNameFromId(elemNew.ECClassId), "TestDomain:SimpleElement");
4776
+ assert.equal(elemNew.Model.Id, modelId);
4777
+ assert.equal(db.getClassNameFromId(elemNew.Model.RelECClassId), "BisCore:ModelContainsElements");
4778
+ assert.isString(elemNew.LastMod);
4779
+ assert.equal(elemNew.CodeSpec.Id, "0x1");
4780
+ assert.equal(db.getClassNameFromId(elemNew.CodeSpec.RelECClassId), "BisCore:CodeSpecSpecifiesCode");
4781
+ assert.equal(elemNew.CodeScope.Id, "0x1");
4782
+ assert.equal(db.getClassNameFromId(elemNew.CodeScope.RelECClassId), "BisCore:ElementScopesCode");
4783
+ assert.isString(elemNew.FederationGuid);
4784
+ assert.equal(elemNew.Category.Id, catId);
4785
+ assert.equal(db.getClassNameFromId(elemNew.Category.RelECClassId), "BisCore:GeometricElement2dIsInCategory");
4786
+ assert.deepEqual(elemNew.Origin, { X: 0, Y: 0 });
4787
+ assert.equal(elemNew.Rotation, 0);
4788
+ assert.deepEqual(elemNew.BBoxLow, { X: -5, Y: -5 });
4789
+ assert.deepEqual(elemNew.BBoxHigh, { X: 5, Y: 5 });
4790
+ assert.include(String(elemNew.GeometryStream), "\"bytes\"");
4791
+ assert.equal(elemNew.p1, "hello", "p1 from the txn binary must be readable in lenient mode");
4792
+ assert.equal(elemNew.p2, "world", "p2 from the txn binary must be readable in lenient mode");
4793
+ // Object.keys — p3 is absent because the txn binary predates the v2 schema upgrade
4794
+ assert.deepEqual(Object.keys(elemNew).sort(), [
4795
+ "ECInstanceId", "ECClassId", "Model", "LastMod", "CodeSpec", "CodeScope",
4796
+ "FederationGuid", "Category", "Origin", "Rotation", "BBoxLow", "BBoxHigh",
4797
+ "GeometryStream", "p1", "p2", "$meta",
4798
+ ].sort());
4799
+ // $meta keys
4800
+ assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4801
+ assert.equal(elemNew.$meta.op, "Inserted");
4802
+ assert.equal(elemNew.$meta.stage, "New");
4803
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
4804
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
4805
+ assert.isString(elemNew.$meta.instanceKey);
4806
+ assert.equal(elemNew.$meta.instanceKey.split("-").length, 2);
4807
+ assert.equal(elemNew.$meta.propFilter, PropertyFilter.All);
4808
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), [
4809
+ "ECInstanceId", "ECClassId", "Model.Id", "LastMod", "CodeSpec.Id", "CodeScope.Id",
4810
+ "CodeValue", "UserLabel", "Parent", "FederationGuid", "JsonProperties",
4811
+ "Category.Id", "Origin", "Rotation", "BBoxLow", "BBoxHigh", "GeometryStream",
4812
+ "TypeDefinition", "p1", "p2",
4813
+ ].sort());
4814
+ assert.equal(elemNew.$meta.isIndirectChange, false);
4815
+ }
4816
+ catch (e_32) {
4817
+ env_32.error = e_32;
4818
+ env_32.hasError = true;
4819
+ }
4820
+ finally {
4821
+ __disposeResources(env_32);
4822
+ }
4823
+ }
4824
+ }
4825
+ finally {
4826
+ txn.end();
4827
+ db.close();
4828
+ HubMock.shutdown();
4829
+ }
4830
+ });
4831
+ it("openFile: strict mode ON throws when changeset was created with more columns than the live table", async () => {
4832
+ HubMock.startup("StrictModeNewCsStrict", KnownTestLocations.outputDir);
4833
+ const adminToken = "super manager token";
4834
+ const iTwinId = HubMock.iTwinId;
4835
+ const iModelId = await HubMock.createNewIModel({ iTwinId, iModelName: "strictNewCs", description: "strict", accessToken: adminToken });
4836
+ const b1 = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId, accessToken: adminToken });
4837
+ const txn1 = startTestTxn(b1, "strict mode b1 strict");
4838
+ b1.channels.addAllowedChannel(ChannelControl.sharedChannelName);
4839
+ try {
4840
+ // Push 1 (B1): v1 schema + drawing model + category.
4841
+ await importSchemaStrings(txn1, [STRICT_MODE_SCHEMA_V1]);
4842
+ await b1.locks.acquireLocks({ shared: IModel.dictionaryId });
4843
+ const [, modelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(txn1, Code.createEmpty(), true);
4844
+ const catId = DrawingCategory.insert(txn1, IModel.dictionaryId, "Cat", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(128,0,128)").toJSON() }));
4845
+ txn1.saveChanges("setup");
4846
+ await b1.pushChanges({ description: "setup", accessToken: adminToken });
4847
+ let elementId;
4848
+ // B2: open iModel (picks up B1's v1 schema + model + category), upgrade to v2, insert element, push.
4849
+ {
4850
+ const b2 = await HubWrappers.downloadAndOpenBriefcase({ iTwinId, iModelId, accessToken: adminToken });
4851
+ const txn2 = startTestTxn(b2, "strict mode b2 strict");
4852
+ b2.channels.addAllowedChannel(ChannelControl.sharedChannelName);
4853
+ try {
4854
+ // Push 2 (B2): upgrade schema to v2 (appends a column).
4855
+ await importSchemaStrings(txn2, [STRICT_MODE_SCHEMA_V2]);
4856
+ await b2.pushChanges({ description: "schema v2", accessToken: adminToken });
4857
+ // Wait so that LastMod on bis_Model gets a distinct timestamp before the insert txn
4858
+ await new Promise((resolve) => setTimeout(resolve, 50));
4859
+ // Push 3 (B2): insert element.
4860
+ await b2.locks.acquireLocks({ shared: modelId });
4861
+ const geom = [Arc3d.createXY(Point3d.create(0, 0), 5)].map((a) => IModelJson.Writer.toIModelJson(a));
4862
+ elementId = txn2.insertElement({ classFullName: "TestDomain:SimpleElement", model: modelId, category: catId, code: Code.createEmpty(), geom, p1: "hi", p2: "world", p3: "!", p4: "?" });
4863
+ txn2.saveChanges("insert v2 element");
4864
+ await b2.pushChanges({ description: "insert v2 element", accessToken: adminToken });
4865
+ }
4866
+ finally {
4867
+ txn2.end();
4868
+ b2.close();
4869
+ }
4870
+ }
4871
+ // Download all changesets. The last one is B2's element insert.
4872
+ const targetDir = path.join(KnownTestLocations.outputDir, iModelId, "changesets");
4873
+ const changesets = await HubMock.downloadChangesets({ iModelId, targetDir });
4874
+ const newCs = changesets[changesets.length - 1];
4875
+ // Strict mode ON: binary has more cols, throws.
4876
+ {
4877
+ const env_33 = { stack: [], error: void 0, hasError: false };
4878
+ try {
4879
+ const reader = __addDisposableResource(env_33, ChangesetReader.openFile({ db: b1, fileName: newCs.pathname }), false);
4880
+ reader.enableStrictMode();
4881
+ expect(() => { while (reader.step()) { /* drain */ } }).to.throw();
4882
+ }
4883
+ catch (e_33) {
4884
+ env_33.error = e_33;
4885
+ env_33.hasError = true;
4886
+ }
4887
+ finally {
4888
+ __disposeResources(env_33);
4889
+ }
4890
+ }
4891
+ // Strict mode OFF: binary has more cols, does not throw.
4892
+ {
4893
+ const env_34 = { stack: [], error: void 0, hasError: false };
4894
+ try {
4895
+ const reader = __addDisposableResource(env_34, ChangesetReader.openFile({ db: b1, fileName: newCs.pathname }), false);
4896
+ const pcu = __addDisposableResource(env_34, new PartialChangeUnifier(ChangeUnifierCache.createInMemoryCache()), false);
4897
+ while (reader.step())
4898
+ pcu.appendFrom(reader);
4899
+ const instances = Array.from(pcu.instances);
4900
+ assert.equal(instances.length, 3, "should have 3 change instances: model (New + Old) + element (New)");
4901
+ // --- Model indirect update — New stage ---
4902
+ const modelNew = instances.find((i) => i.ECInstanceId === modelId && i.$meta.stage === "New");
4903
+ expect(modelNew).to.exist;
4904
+ assert.equal(modelNew.ECInstanceId, modelId);
4905
+ assert.equal(b1.getClassNameFromId(modelNew.ECClassId), "BisCore:DrawingModel");
4906
+ assert.isString(modelNew.LastMod);
4907
+ assert.isString(modelNew.GeometryGuid);
4908
+ assert.deepEqual(Object.keys(modelNew).sort(), ["ECInstanceId", "ECClassId", "LastMod", "GeometryGuid", "$meta"].sort());
4909
+ assert.deepEqual(Object.keys(modelNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4910
+ assert.equal(modelNew.$meta.op, "Updated");
4911
+ assert.equal(modelNew.$meta.stage, "New");
4912
+ assert.deepEqual(modelNew.$meta.tables, ["bis_Model"]);
4913
+ assert.deepEqual(modelNew.$meta.changeIndexes, [3]);
4914
+ assert.isString(modelNew.$meta.instanceKey);
4915
+ assert.equal(modelNew.$meta.instanceKey.split("-").length, 2);
4916
+ assert.equal(modelNew.$meta.propFilter, PropertyFilter.All);
4917
+ assert.deepEqual(modelNew.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4918
+ assert.equal(modelNew.$meta.isIndirectChange, true);
4919
+ // --- Model indirect update — Old stage (only key columns, no data properties) ---
4920
+ const modelOld = instances.find((i) => i.ECInstanceId === modelId && i.$meta.stage === "Old");
4921
+ expect(modelOld).to.exist;
4922
+ assert.equal(modelOld.ECInstanceId, modelId);
4923
+ assert.equal(b1.getClassNameFromId(modelOld.ECClassId), "BisCore:DrawingModel");
4924
+ assert.isUndefined(modelOld.LastMod, "Old stage carries only the key — no data properties");
4925
+ assert.isUndefined(modelOld.GeometryGuid, "Old stage carries only the key — no data properties");
4926
+ assert.deepEqual(Object.keys(modelOld).sort(), ["ECInstanceId", "ECClassId", "$meta"].sort());
4927
+ assert.deepEqual(Object.keys(modelOld.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4928
+ assert.equal(modelOld.$meta.op, "Updated");
4929
+ assert.equal(modelOld.$meta.stage, "Old");
4930
+ assert.deepEqual(modelOld.$meta.tables, ["bis_Model"]);
4931
+ assert.deepEqual(modelOld.$meta.changeIndexes, [3]);
4932
+ assert.isString(modelOld.$meta.instanceKey);
4933
+ assert.equal(modelOld.$meta.instanceKey.split("-").length, 2);
4934
+ assert.equal(modelOld.$meta.propFilter, PropertyFilter.All);
4935
+ assert.deepEqual(modelOld.$meta.changeFetchedPropNames.sort(), ["ECInstanceId", "LastMod", "GeometryGuid"].sort());
4936
+ assert.equal(modelOld.$meta.isIndirectChange, true);
4937
+ // --- Element insert — New stage ---
4938
+ const elemNew = instances.find((i) => i.ECInstanceId === elementId && i.$meta.stage === "New");
4939
+ expect(elemNew).to.exist;
4940
+ assert.equal(elemNew.ECInstanceId, elementId);
4941
+ assert.equal(b1.getClassNameFromId(elemNew.ECClassId), "TestDomain:SimpleElement");
4942
+ assert.equal(elemNew.Model.Id, modelId);
4943
+ assert.equal(b1.getClassNameFromId(elemNew.Model.RelECClassId), "BisCore:ModelContainsElements");
4944
+ assert.isString(elemNew.LastMod);
4945
+ assert.equal(elemNew.CodeSpec.Id, "0x1");
4946
+ assert.equal(b1.getClassNameFromId(elemNew.CodeSpec.RelECClassId), "BisCore:CodeSpecSpecifiesCode");
4947
+ assert.equal(elemNew.CodeScope.Id, "0x1");
4948
+ assert.equal(b1.getClassNameFromId(elemNew.CodeScope.RelECClassId), "BisCore:ElementScopesCode");
4949
+ assert.isString(elemNew.FederationGuid);
4950
+ assert.equal(elemNew.Category.Id, catId);
4951
+ assert.equal(b1.getClassNameFromId(elemNew.Category.RelECClassId), "BisCore:GeometricElement2dIsInCategory");
4952
+ assert.deepEqual(elemNew.Origin, { X: 0, Y: 0 });
4953
+ assert.equal(elemNew.Rotation, 0);
4954
+ assert.deepEqual(elemNew.BBoxLow, { X: -5, Y: -5 });
4955
+ assert.deepEqual(elemNew.BBoxHigh, { X: 5, Y: 5 });
4956
+ assert.include(String(elemNew.GeometryStream), "\"bytes\"");
4957
+ assert.equal(elemNew.p1, "hi", "p1 from the txn binary must be readable in lenient mode");
4958
+ assert.equal(elemNew.p2, "world", "p2 from the txn binary must be readable in lenient mode");
4959
+ // Object.keys — p3, p4 are absent because the binary txn has them but the live table does not
4960
+ assert.deepEqual(Object.keys(elemNew).sort(), [
4961
+ "ECInstanceId", "ECClassId", "Model", "LastMod", "CodeSpec", "CodeScope",
4962
+ "FederationGuid", "Category", "Origin", "Rotation", "BBoxLow", "BBoxHigh",
4963
+ "GeometryStream", "p1", "p2", "$meta",
4964
+ ].sort());
4965
+ // $meta keys
4966
+ assert.deepEqual(Object.keys(elemNew.$meta).sort(), ["op", "tables", "changeIndexes", "stage", "instanceKey", "propFilter", "changeFetchedPropNames", "isIndirectChange"].sort());
4967
+ assert.equal(elemNew.$meta.op, "Inserted");
4968
+ assert.equal(elemNew.$meta.stage, "New");
4969
+ assert.deepEqual(elemNew.$meta.tables.sort(), ["bis_Element", "bis_GeometricElement2d"].sort());
4970
+ assert.deepEqual(elemNew.$meta.changeIndexes.sort(), [1, 2].sort());
4971
+ assert.isString(elemNew.$meta.instanceKey);
4972
+ assert.equal(elemNew.$meta.instanceKey.split("-").length, 2);
4973
+ assert.equal(elemNew.$meta.propFilter, PropertyFilter.All);
4974
+ assert.deepEqual(elemNew.$meta.changeFetchedPropNames.sort(), [
4975
+ "ECInstanceId", "ECClassId", "Model.Id", "LastMod", "CodeSpec.Id", "CodeScope.Id",
4976
+ "CodeValue", "UserLabel", "Parent", "FederationGuid", "JsonProperties",
4977
+ "Category.Id", "Origin", "Rotation", "BBoxLow", "BBoxHigh", "GeometryStream",
4978
+ "TypeDefinition", "p1", "p2",
4979
+ ].sort());
4980
+ assert.equal(elemNew.$meta.isIndirectChange, false);
4981
+ }
4982
+ catch (e_34) {
4983
+ env_34.error = e_34;
4984
+ env_34.hasError = true;
4985
+ }
4986
+ finally {
4987
+ __disposeResources(env_34);
4988
+ }
4989
+ }
4990
+ }
4991
+ finally {
4992
+ txn1.end();
4993
+ b1.close();
4994
+ HubMock.shutdown();
4995
+ }
4996
+ });
4389
4997
  });
4390
4998
  //# sourceMappingURL=ChangesetReader.test.js.map