@ifc-lite/mutations 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/bulk-query-engine.d.ts +2 -4
  2. package/dist/bulk-query-engine.d.ts.map +1 -1
  3. package/dist/bulk-query-engine.js +2 -1
  4. package/dist/bulk-query-engine.js.map +1 -1
  5. package/dist/cooperative-clone.d.ts +4 -0
  6. package/dist/cooperative-clone.d.ts.map +1 -0
  7. package/dist/cooperative-clone.js +93 -0
  8. package/dist/cooperative-clone.js.map +1 -0
  9. package/dist/cooperative-control.d.ts +17 -0
  10. package/dist/cooperative-control.d.ts.map +1 -0
  11. package/dist/cooperative-control.js +67 -0
  12. package/dist/cooperative-control.js.map +1 -0
  13. package/dist/cooperative-operation-types.d.ts +53 -0
  14. package/dist/cooperative-operation-types.d.ts.map +1 -0
  15. package/dist/cooperative-operation-types.js +2 -0
  16. package/dist/cooperative-operation-types.js.map +1 -0
  17. package/dist/cooperative-overlay-access.d.ts +14 -0
  18. package/dist/cooperative-overlay-access.d.ts.map +1 -0
  19. package/dist/cooperative-overlay-access.js +12 -0
  20. package/dist/cooperative-overlay-access.js.map +1 -0
  21. package/dist/execute-entity-operation.d.ts +6 -0
  22. package/dist/execute-entity-operation.d.ts.map +1 -0
  23. package/dist/execute-entity-operation.js +39 -0
  24. package/dist/execute-entity-operation.js.map +1 -0
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/mutable-overlay-state.d.ts +143 -0
  28. package/dist/mutable-overlay-state.d.ts.map +1 -0
  29. package/dist/mutable-overlay-state.js +115 -0
  30. package/dist/mutable-overlay-state.js.map +1 -0
  31. package/dist/mutable-property-view.d.ts +22 -84
  32. package/dist/mutable-property-view.d.ts.map +1 -1
  33. package/dist/mutable-property-view.js +86 -75
  34. package/dist/mutable-property-view.js.map +1 -1
  35. package/dist/overlay-value-equality.d.ts +3 -0
  36. package/dist/overlay-value-equality.d.ts.map +1 -0
  37. package/dist/overlay-value-equality.js +52 -0
  38. package/dist/overlay-value-equality.js.map +1 -0
  39. package/dist/prepare-entity-operations.d.ts +7 -0
  40. package/dist/prepare-entity-operations.d.ts.map +1 -0
  41. package/dist/prepare-entity-operations.js +117 -0
  42. package/dist/prepare-entity-operations.js.map +1 -0
  43. package/dist/store-editor.d.ts +12 -14
  44. package/dist/store-editor.d.ts.map +1 -1
  45. package/dist/store-editor.js +42 -0
  46. package/dist/store-editor.js.map +1 -1
  47. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutable-overlay-state.d.ts","sourceRoot":"","sources":["../src/mutable-overlay-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { sameOverlayValue } from './overlay-value-equality.js';
5
+ /** Internal mutable overlay state; source tables and extractors are never copied. */
6
+ export class MutableOverlayState {
7
+ propertyMutations = new Map();
8
+ quantityMutations = new Map();
9
+ /**
10
+ * Secondary indices: entityId → mutation keys for that entity.
11
+ *
12
+ * `getForEntity` previously iterated the entire `propertyMutations` /
13
+ * `quantityMutations` map per pset to find newly-added properties — O(M·P)
14
+ * per call. These indices keep that step O(M_entity) instead.
15
+ */
16
+ propertyKeysByEntity = new Map();
17
+ quantityKeysByEntity = new Map();
18
+ attributeKeysByEntity = new Map();
19
+ deletedPsets = new Set(); // `${entityId}:${psetName}`
20
+ deletedQsets = new Set(); // `${entityId}:${qsetName}`
21
+ newPsets = new Map(); // entityId -> psetName -> PropertySet
22
+ newQsets = new Map(); // entityId -> qsetName -> QuantitySet
23
+ attributeMutations = new Map(); // `${entityId}:attr:${attrName}`
24
+ positionalAttrMutations = new Map(); // entityId -> argIndex -> value
25
+ typeMutations = new Map(); // entityId -> retype intent
26
+ newEntities = new Map();
27
+ tombstones = new Set();
28
+ /**
29
+ * Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
30
+ * `newEntities`, per that method's "existing entities are tombstoned; new
31
+ * entities are simply forgotten" contract). Tracked separately so
32
+ * `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
33
+ * then forgotten" apart from "an ordinary source-buffer entity" — both are
34
+ * otherwise indistinguishable, being simply absent from `newEntities`.
35
+ * `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
36
+ */
37
+ forgottenCreatedEntities = new Set();
38
+ /**
39
+ * Snapshot of a forgotten-created entity's overlay rows, stashed by
40
+ * `deleteEntity` and restored by `restoreNewEntity`.
41
+ *
42
+ * `deleteEntity` on an overlay-created entity does more than drop it from
43
+ * `newEntities` — it also PURGES every other overlay entry the entity left
44
+ * behind (property/quantity/attribute/positional/type mutations, its
45
+ * `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
46
+ * Without that purge, an entity that was created, edited, then deleted
47
+ * before export left a dangling reference: `StepExporter` derives its
48
+ * property/quantity work list from `getMutations()` (the append-only
49
+ * history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
50
+ * off `newPsets` / `newQsets` — neither of which the review-side
51
+ * `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
52
+ * review dialog looked clean while the exported file still contained an
53
+ * `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
54
+ * that was never actually created (maintainer finding on #1967).
55
+ *
56
+ * The purged data is captured here, not discarded, because `restoreNewEntity`
57
+ * (undo of the delete) must bring it all back — rows AND count AND what the
58
+ * exporter would see — not just re-add the bare `NewEntity` record.
59
+ */
60
+ forgottenEntityOverlay = new Map();
61
+ /**
62
+ * Overlay-entity → source-entity aliases for property/quantity reads.
63
+ *
64
+ * When the viewer duplicates an existing entity, the new entity has
65
+ * no row in the parsed property table — `getBasePropertiesForEntity`
66
+ * would return `[]` and the property panel would show "No property
67
+ * sets". Aliasing redirects the BASE read to the source entity so
68
+ * the duplicate inherits its psets / qsets visually, while overlay
69
+ * mutations (overrides, creates, deletes) stay scoped to the
70
+ * overlay-entity's own id — so editing a property on the duplicate
71
+ * doesn't bleed into the source.
72
+ *
73
+ * Aliases follow at most one hop (no chains). They never affect
74
+ * STEP export — the export overlay emits the duplicate exactly as
75
+ * the StoreEditor recorded it, with whatever new IfcRel*ByProperties
76
+ * the caller chose to add.
77
+ */
78
+ entityAliases = new Map();
79
+ nextAllocatedId = 0;
80
+ mutationHistory = [];
81
+ /** Borrowed only for synchronous comparison; never returned to callers. */
82
+ overlayState() {
83
+ return {
84
+ propertyMutations: this.propertyMutations,
85
+ quantityMutations: this.quantityMutations,
86
+ propertyKeysByEntity: this.propertyKeysByEntity,
87
+ quantityKeysByEntity: this.quantityKeysByEntity,
88
+ attributeKeysByEntity: this.attributeKeysByEntity,
89
+ deletedPsets: this.deletedPsets,
90
+ deletedQsets: this.deletedQsets,
91
+ newPsets: this.newPsets,
92
+ newQsets: this.newQsets,
93
+ attributeMutations: this.attributeMutations,
94
+ positionalAttrMutations: this.positionalAttrMutations,
95
+ typeMutations: this.typeMutations,
96
+ newEntities: this.newEntities,
97
+ tombstones: this.tombstones,
98
+ forgottenCreatedEntities: this.forgottenCreatedEntities,
99
+ forgottenEntityOverlay: this.forgottenEntityOverlay,
100
+ entityAliases: this.entityAliases,
101
+ nextAllocatedId: this.nextAllocatedId,
102
+ mutationHistory: this.mutationHistory,
103
+ };
104
+ }
105
+ copyOverlayState() {
106
+ return structuredClone(this.overlayState());
107
+ }
108
+ restoreOverlayState(state) {
109
+ Object.assign(this, state);
110
+ }
111
+ matchesOverlayState(state) {
112
+ return sameOverlayValue(this.overlayState(), state);
113
+ }
114
+ }
115
+ //# sourceMappingURL=mutable-overlay-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutable-overlay-state.js","sourceRoot":"","sources":["../src/mutable-overlay-state.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAyB/D,qFAAqF;AACrF,MAAM,OAAO,mBAAmB;IACpB,iBAAiB,GAAkC,IAAI,GAAG,EAAE,CAAC;IAC7D,iBAAiB,GAAkC,IAAI,GAAG,EAAE,CAAC;IACvE;;;;;;OAMG;IACO,oBAAoB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC3D,oBAAoB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC3D,qBAAqB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC5D,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACnE,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACnE,QAAQ,GAA0C,IAAI,GAAG,EAAE,CAAC,CAAC,sCAAsC;IACnG,QAAQ,GAA0C,IAAI,GAAG,EAAE,CAAC,CAAC,sCAAsC;IACnG,kBAAkB,GAAmC,IAAI,GAAG,EAAE,CAAC,CAAC,iCAAiC;IACjG,uBAAuB,GAAgD,IAAI,GAAG,EAAE,CAAC,CAAC,gCAAgC;IAClH,aAAa,GAAoC,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACxF,WAAW,GAA2B,IAAI,GAAG,EAAE,CAAC;IAChD,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC9C;;;;;;;;OAQG;IACO,wBAAwB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC5D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACO,sBAAsB,GAAwC,IAAI,GAAG,EAAE,CAAC;IAClF;;;;;;;;;;;;;;;;OAgBG;IACO,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC/C,eAAe,GAAW,CAAC,CAAC;IAC5B,eAAe,GAAe,EAAE,CAAC;IAE3C,2EAA2E;IACjE,YAAY;QACpB,OAAO;YACL,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;YACjD,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;YACvD,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;YACnD,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC;IACJ,CAAC;IAES,gBAAgB;QACxB,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC;IAES,mBAAmB,CAAC,KAA0D;QACtF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAES,mBAAmB,CAAC,KAA0D;QACtF,OAAO,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -1,16 +1,8 @@
1
- /**
2
- * Mutable property view - overlay pattern for property mutations
3
- *
4
- * This class provides a mutable view over an immutable PropertyTable.
5
- * Changes are tracked separately and applied on-the-fly during reads.
6
- *
7
- * Supports both pre-built property tables and on-demand property extraction
8
- * for optimal performance with large models.
9
- */
10
1
  import type { PropertyTable, PropertySet, QuantitySet } from '@ifc-lite/data';
11
2
  import { PropertyValueType, QuantityType } from '@ifc-lite/data';
12
3
  import type { IfcAttributeValue, PropertyValue, PropertyMutation, EntityTypeMutation, Mutation, NewEntity, EffectiveChange } from './types.js';
13
4
  import { type AttributeExtractor } from './effective-changes.js';
5
+ import { MutableOverlayState } from './mutable-overlay-state.js';
14
6
  export type { AttributeExtractor } from './effective-changes.js';
15
7
  /**
16
8
  * Function type for on-demand property extraction
@@ -30,87 +22,33 @@ export type PropertyExtractor = (entityId: number) => Array<{
30
22
  * Function type for on-demand quantity extraction
31
23
  */
32
24
  export type QuantityExtractor = (entityId: number) => QuantitySet[];
33
- export declare class MutablePropertyView {
25
+ export declare class MutablePropertyView extends MutableOverlayState {
34
26
  private baseTable;
35
27
  private onDemandExtractor;
36
28
  private quantityExtractor;
37
29
  private attributeExtractor;
38
- private propertyMutations;
39
- private quantityMutations;
40
- /**
41
- * Secondary indices: entityId → mutation keys for that entity.
42
- *
43
- * `getForEntity` previously iterated the entire `propertyMutations` /
44
- * `quantityMutations` map per pset to find newly-added properties — O(M·P)
45
- * per call. These indices keep that step O(M_entity) instead.
46
- */
47
- private propertyKeysByEntity;
48
- private quantityKeysByEntity;
49
- private attributeKeysByEntity;
50
- private deletedPsets;
51
- private deletedQsets;
52
- private newPsets;
53
- private newQsets;
54
- private attributeMutations;
55
- private positionalAttrMutations;
56
- private typeMutations;
57
- private newEntities;
58
- private tombstones;
59
- /**
60
- * Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
61
- * `newEntities`, per that method's "existing entities are tombstoned; new
62
- * entities are simply forgotten" contract). Tracked separately so
63
- * `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
64
- * then forgotten" apart from "an ordinary source-buffer entity" — both are
65
- * otherwise indistinguishable, being simply absent from `newEntities`.
66
- * `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
67
- */
68
- private forgottenCreatedEntities;
69
- /**
70
- * Snapshot of a forgotten-created entity's overlay rows, stashed by
71
- * `deleteEntity` and restored by `restoreNewEntity`.
72
- *
73
- * `deleteEntity` on an overlay-created entity does more than drop it from
74
- * `newEntities` — it also PURGES every other overlay entry the entity left
75
- * behind (property/quantity/attribute/positional/type mutations, its
76
- * `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
77
- * Without that purge, an entity that was created, edited, then deleted
78
- * before export left a dangling reference: `StepExporter` derives its
79
- * property/quantity work list from `getMutations()` (the append-only
80
- * history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
81
- * off `newPsets` / `newQsets` — neither of which the review-side
82
- * `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
83
- * review dialog looked clean while the exported file still contained an
84
- * `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
85
- * that was never actually created (maintainer finding on #1967).
86
- *
87
- * The purged data is captured here, not discarded, because `restoreNewEntity`
88
- * (undo of the delete) must bring it all back — rows AND count AND what the
89
- * exporter would see — not just re-add the bare `NewEntity` record.
90
- */
91
- private forgottenEntityOverlay;
92
- /**
93
- * Overlay-entity → source-entity aliases for property/quantity reads.
94
- *
95
- * When the viewer duplicates an existing entity, the new entity has
96
- * no row in the parsed property table — `getBasePropertiesForEntity`
97
- * would return `[]` and the property panel would show "No property
98
- * sets". Aliasing redirects the BASE read to the source entity so
99
- * the duplicate inherits its psets / qsets visually, while overlay
100
- * mutations (overrides, creates, deletes) stay scoped to the
101
- * overlay-entity's own id — so editing a property on the duplicate
102
- * doesn't bleed into the source.
103
- *
104
- * Aliases follow at most one hop (no chains). They never affect
105
- * STEP export — the export overlay emits the duplicate exactly as
106
- * the StoreEditor recorded it, with whatever new IfcRel*ByProperties
107
- * the caller chose to add.
108
- */
109
- private entityAliases;
110
- private nextAllocatedId;
111
- private mutationHistory;
112
30
  private modelId;
113
31
  constructor(baseTable: PropertyTable | null, modelId: string);
32
+ /**
33
+ * Stage synchronous overlay edits and publish them together (#4243).
34
+ * Throws leave the original overlay, history and allocator untouched.
35
+ * Source tables/extractors are shared read-only; mutable state is detached
36
+ * both before editing and on commit, so an escaped draft cannot edit this view.
37
+ * External effects (files, renderer or network) belong outside this callback.
38
+ */
39
+ runAtomic<T>(edit: (draft: MutablePropertyView) => T): T;
40
+ /**
41
+ * Prepare an overlay publication without changing live IFC state (#4243).
42
+ * Use for commands that must validate other synchronous resources first.
43
+ * `validate` and `commit` reject intervening edits, including skip-history
44
+ * edits. Commit is idempotent; the prepared draft is never published by reference.
45
+ */
46
+ prepareAtomic<T>(edit: (draft: MutablePropertyView) => T): {
47
+ result: T;
48
+ validate(): void;
49
+ commit(): void;
50
+ rollback(): void;
51
+ };
114
52
  /**
115
53
  * Seed the express-ID allocator. Should be called once after parsing with
116
54
  * the highest existing expressId in the store; subsequent `createEntity`
@@ -1 +1 @@
1
- {"version":3,"file":"mutable-property-view.d.ts","sourceRoot":"","sources":["../src/mutable-property-view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mutable-property-view.d.ts","sourceRoot":"","sources":["../src/mutable-property-view.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,16 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Mutable property view - overlay pattern for property mutations
6
+ *
7
+ * This class provides a mutable view over an immutable PropertyTable.
8
+ * Changes are tracked separately and applied on-the-fly during reads.
9
+ *
10
+ * Supports both pre-built property tables and on-demand property extraction
11
+ * for optimal performance with large models.
12
+ */
13
+ import { registerCooperativeOverlay } from './cooperative-overlay-access.js';
4
14
  import { findQuantityInBaseSets } from './base-qset-lookup.js';
5
15
  import { computeSetClaims, mutatedMembersForInstance } from './same-name-set-claims.js';
6
16
  import { encodeNonFiniteNumbers, decodeNonFiniteNumbers } from './nonfinite-json.js';
@@ -8,89 +18,90 @@ import { PropertyValueType, QuantityType } from '@ifc-lite/data';
8
18
  import { propertyKey, quantityKey, attributeKey, generateMutationId } from './types.js';
9
19
  import { collectEffectiveChanges } from './effective-changes.js';
10
20
  import { applyMutationsBatch } from './apply-mutations.js';
11
- export class MutablePropertyView {
21
+ import { MutableOverlayState } from './mutable-overlay-state.js';
22
+ export class MutablePropertyView extends MutableOverlayState {
12
23
  baseTable;
13
24
  onDemandExtractor = null;
14
25
  quantityExtractor = null;
15
26
  attributeExtractor = null;
16
- propertyMutations = new Map();
17
- quantityMutations = new Map();
18
- /**
19
- * Secondary indices: entityId → mutation keys for that entity.
20
- *
21
- * `getForEntity` previously iterated the entire `propertyMutations` /
22
- * `quantityMutations` map per pset to find newly-added properties — O(M·P)
23
- * per call. These indices keep that step O(M_entity) instead.
24
- */
25
- propertyKeysByEntity = new Map();
26
- quantityKeysByEntity = new Map();
27
- attributeKeysByEntity = new Map();
28
- deletedPsets = new Set(); // `${entityId}:${psetName}`
29
- deletedQsets = new Set(); // `${entityId}:${qsetName}`
30
- newPsets = new Map(); // entityId -> psetName -> PropertySet
31
- newQsets = new Map(); // entityId -> qsetName -> QuantitySet
32
- attributeMutations = new Map(); // `${entityId}:attr:${attrName}`
33
- positionalAttrMutations = new Map(); // entityId -> argIndex -> value
34
- typeMutations = new Map(); // entityId -> retype intent
35
- newEntities = new Map();
36
- tombstones = new Set();
37
- /**
38
- * Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
39
- * `newEntities`, per that method's "existing entities are tombstoned; new
40
- * entities are simply forgotten" contract). Tracked separately so
41
- * `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
42
- * then forgotten" apart from "an ordinary source-buffer entity" — both are
43
- * otherwise indistinguishable, being simply absent from `newEntities`.
44
- * `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
45
- */
46
- forgottenCreatedEntities = new Set();
47
- /**
48
- * Snapshot of a forgotten-created entity's overlay rows, stashed by
49
- * `deleteEntity` and restored by `restoreNewEntity`.
50
- *
51
- * `deleteEntity` on an overlay-created entity does more than drop it from
52
- * `newEntities` — it also PURGES every other overlay entry the entity left
53
- * behind (property/quantity/attribute/positional/type mutations, its
54
- * `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
55
- * Without that purge, an entity that was created, edited, then deleted
56
- * before export left a dangling reference: `StepExporter` derives its
57
- * property/quantity work list from `getMutations()` (the append-only
58
- * history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
59
- * off `newPsets` / `newQsets` — neither of which the review-side
60
- * `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
61
- * review dialog looked clean while the exported file still contained an
62
- * `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
63
- * that was never actually created (maintainer finding on #1967).
64
- *
65
- * The purged data is captured here, not discarded, because `restoreNewEntity`
66
- * (undo of the delete) must bring it all back — rows AND count AND what the
67
- * exporter would see — not just re-add the bare `NewEntity` record.
68
- */
69
- forgottenEntityOverlay = new Map();
70
- /**
71
- * Overlay-entity → source-entity aliases for property/quantity reads.
72
- *
73
- * When the viewer duplicates an existing entity, the new entity has
74
- * no row in the parsed property table — `getBasePropertiesForEntity`
75
- * would return `[]` and the property panel would show "No property
76
- * sets". Aliasing redirects the BASE read to the source entity so
77
- * the duplicate inherits its psets / qsets visually, while overlay
78
- * mutations (overrides, creates, deletes) stay scoped to the
79
- * overlay-entity's own id — so editing a property on the duplicate
80
- * doesn't bleed into the source.
81
- *
82
- * Aliases follow at most one hop (no chains). They never affect
83
- * STEP export — the export overlay emits the duplicate exactly as
84
- * the StoreEditor recorded it, with whatever new IfcRel*ByProperties
85
- * the caller chose to add.
86
- */
87
- entityAliases = new Map();
88
- nextAllocatedId = 0;
89
- mutationHistory = [];
90
27
  modelId;
91
28
  constructor(baseTable, modelId) {
29
+ super();
92
30
  this.baseTable = baseTable;
93
31
  this.modelId = modelId;
32
+ registerCooperativeOverlay(this, {
33
+ capture: () => this.overlayState(),
34
+ matches: snapshot => this.matchesOverlayState(snapshot),
35
+ publish: snapshot => this.restoreOverlayState(snapshot),
36
+ draft: snapshot => {
37
+ const draft = new MutablePropertyView(this.baseTable, this.modelId);
38
+ draft.onDemandExtractor = this.onDemandExtractor;
39
+ draft.quantityExtractor = this.quantityExtractor;
40
+ draft.attributeExtractor = this.attributeExtractor;
41
+ draft.restoreOverlayState(snapshot);
42
+ return draft;
43
+ },
44
+ });
45
+ }
46
+ /**
47
+ * Stage synchronous overlay edits and publish them together (#4243).
48
+ * Throws leave the original overlay, history and allocator untouched.
49
+ * Source tables/extractors are shared read-only; mutable state is detached
50
+ * both before editing and on commit, so an escaped draft cannot edit this view.
51
+ * External effects (files, renderer or network) belong outside this callback.
52
+ */
53
+ runAtomic(edit) {
54
+ const prepared = this.prepareAtomic(edit);
55
+ prepared.commit();
56
+ return prepared.result;
57
+ }
58
+ /**
59
+ * Prepare an overlay publication without changing live IFC state (#4243).
60
+ * Use for commands that must validate other synchronous resources first.
61
+ * `validate` and `commit` reject intervening edits, including skip-history
62
+ * edits. Commit is idempotent; the prepared draft is never published by reference.
63
+ */
64
+ prepareAtomic(edit) {
65
+ const original = this.copyOverlayState();
66
+ const draft = new MutablePropertyView(this.baseTable, this.modelId);
67
+ draft.onDemandExtractor = this.onDemandExtractor;
68
+ draft.quantityExtractor = this.quantityExtractor;
69
+ draft.attributeExtractor = this.attributeExtractor;
70
+ draft.restoreOverlayState(structuredClone(original));
71
+ const result = edit(draft);
72
+ if (result !== null && (typeof result === 'object' || typeof result === 'function')
73
+ && 'then' in result && typeof result.then === 'function') {
74
+ void Promise.resolve(result).catch(error => console.error('Discarded asynchronous overlay transaction failed', error));
75
+ throw new TypeError('Overlay transactions must be synchronous; prepare asynchronous work before editing');
76
+ }
77
+ const prepared = draft.copyOverlayState();
78
+ // Keep the rollback checkpoint detached from maps published to live readers.
79
+ const publication = structuredClone(prepared);
80
+ let committed = false;
81
+ let rolledBack = false;
82
+ const validate = () => {
83
+ if (rolledBack)
84
+ throw new Error('The prepared IFC transaction was rolled back.');
85
+ if (!committed && !this.matchesOverlayState(original))
86
+ throw new Error('The IFC overlay changed during a prepared transaction.');
87
+ };
88
+ validate(); // A callback that re-enters the original view cannot erase that edit.
89
+ return { result, validate, commit: () => {
90
+ if (rolledBack)
91
+ throw new Error('The prepared IFC transaction was rolled back.');
92
+ if (committed)
93
+ return;
94
+ validate();
95
+ this.restoreOverlayState(publication);
96
+ committed = true;
97
+ }, rollback: () => {
98
+ if (!committed || rolledBack)
99
+ return;
100
+ if (!this.matchesOverlayState(prepared))
101
+ throw new Error('The IFC overlay changed after the prepared transaction committed.');
102
+ this.restoreOverlayState(original);
103
+ rolledBack = true;
104
+ } };
94
105
  }
95
106
  /**
96
107
  * Seed the express-ID allocator. Should be called once after parsing with