@ifc-lite/mutations 1.14.5 → 1.15.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.
@@ -0,0 +1,89 @@
1
+ /**
2
+ * StoreEditor — high-level facade for editing a parsed `IfcDataStore` via the
3
+ * `MutablePropertyView` overlay.
4
+ *
5
+ * Implements the `store.addEntity()` / `store.removeEntity()` /
6
+ * `store.setPositionalAttribute()` API requested in LTplus-AG/ifc-lite#592.
7
+ *
8
+ * The underlying store buffer and entity index are never mutated. Changes
9
+ * accumulate in the overlay and materialise during
10
+ * `StepExporter.export({ applyMutations })`. Overlay-created entities are
11
+ * visible via `getNewEntity()` / `getNewEntities()`; they are intentionally
12
+ * NOT inserted into `store.entityIndex.byId`, because that index may be a
13
+ * `CompactEntityIndex` whose backing typed arrays are immutable.
14
+ */
15
+ import type { MutablePropertyView } from './mutable-property-view.js';
16
+ import type { IfcAttributeValue, MutationEntityRef as EntityRef, MutationStoreShape as IfcDataStore, NewEntity } from './types.js';
17
+ /** Sentinel byteOffset that flags an `EntityRef` as overlay-only (no source bytes). */
18
+ export declare const OVERLAY_BYTE_OFFSET = -1;
19
+ /**
20
+ * Schema-aware normaliser injected from outside the package.
21
+ *
22
+ * `@ifc-lite/mutations` cannot import `@ifc-lite/parser` (cycle), so
23
+ * the canonical-name registry isn't reachable here. The SDK / viewer
24
+ * boundary calls `setEntityTypeNormalizer` once at startup with the
25
+ * parser's `normalizeIfcTypeName` helper, and from then on every
26
+ * `addEntity()` call resolves to canonical PascalCase before forwarding
27
+ * to the overlay. Direct callers that don't wire a normalizer fall
28
+ * back to the lightweight regex check below — typos still surface,
29
+ * just without registry-grade rejection.
30
+ */
31
+ export type EntityTypeNormalizer = (type: string) => string;
32
+ /**
33
+ * Register the canonical-name resolver. Pass `null` to clear it (used
34
+ * by tests). Calling repeatedly is fine — last write wins.
35
+ */
36
+ export declare function setEntityTypeNormalizer(fn: EntityTypeNormalizer | null): void;
37
+ export declare class StoreEditor {
38
+ private store;
39
+ private view;
40
+ private maxExistingId;
41
+ constructor(store: IfcDataStore, view: MutablePropertyView);
42
+ /**
43
+ * Re-scan the store and bump the express-id watermark if the store has
44
+ * grown since construction (e.g. after lazy index hydration or
45
+ * federating in another model). Cheap to call — `MutablePropertyView`
46
+ * keeps the high watermark, so re-seeding with a stale value is a
47
+ * no-op.
48
+ */
49
+ refreshWatermark(): void;
50
+ /**
51
+ * Add a new entity to the store overlay. Returns a synthetic `EntityRef`
52
+ * with a freshly-allocated expressId; pass it back to other APIs (other
53
+ * `addEntity` calls, `setPositionalAttribute`, exporters) to reference
54
+ * the new record.
55
+ *
56
+ * Pass `type` as the canonical IFC EXPRESS PascalCase name
57
+ * (e.g. `'IfcRectangleProfileDef'`). UPPERCASE STEP tokens are also
58
+ * accepted — both are normalized to the same internal form.
59
+ *
60
+ * Attribute conventions (mirrors `EntityExtractor.extractEntity()` output):
61
+ * - numbers → STEP integer / REAL literal
62
+ * - `"#42"` → STEP entity reference
63
+ * - `"'literal'"` or any plain string → quoted STEP string
64
+ * - `".AREA."` (dot-wrapped) → enum
65
+ * - `null` / `undefined` → `$`
66
+ * - arrays → STEP list `(a,b,c)`
67
+ */
68
+ addEntity(type: string, attributes: IfcAttributeValue[]): EntityRef;
69
+ /**
70
+ * Remove an entity. Existing entities are tombstoned and skipped during
71
+ * export; overlay-only entities are forgotten. Returns false if the id is
72
+ * not known to the store or the overlay.
73
+ */
74
+ removeEntity(expressId: number): boolean;
75
+ /**
76
+ * Edit a positional STEP argument on any entity by zero-based index.
77
+ * Use this for non-IfcRoot edits like `IfcRectangleProfileDef.XDim`
78
+ * where the attribute has no symbolic name.
79
+ */
80
+ setPositionalAttribute(expressId: number, index: number, value: IfcAttributeValue): void;
81
+ /** Edit a named root attribute (Name, Description, ObjectType, …). */
82
+ setAttribute(expressId: number, attrName: string, value: string): void;
83
+ /** Look up the overlay record for a freshly-added entity. */
84
+ getNewEntity(expressId: number): NewEntity | null;
85
+ /** All overlay-created entities, in insertion order. */
86
+ getNewEntities(): NewEntity[];
87
+ private computeMaxExistingId;
88
+ }
89
+ //# sourceMappingURL=store-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-editor.d.ts","sourceRoot":"","sources":["../src/store-editor.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,IAAI,SAAS,EAC9B,kBAAkB,IAAI,YAAY,EAClC,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAI5D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,oBAAoB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,aAAa,CAAS;gBAElB,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB;IAO1D;;;;;;OAMG;IACH,gBAAgB,IAAI,IAAI;IAQxB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,SAAS;IAgEnE;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAQxC;;;;OAIG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAIxF,sEAAsE;IACtE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAItE,6DAA6D;IAC7D,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAIjD,wDAAwD;IACxD,cAAc,IAAI,SAAS,EAAE;IAI7B,OAAO,CAAC,oBAAoB;CAO7B"}
@@ -0,0 +1,155 @@
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
+ /** Sentinel byteOffset that flags an `EntityRef` as overlay-only (no source bytes). */
5
+ export const OVERLAY_BYTE_OFFSET = -1;
6
+ let configuredNormalizer = null;
7
+ /**
8
+ * Register the canonical-name resolver. Pass `null` to clear it (used
9
+ * by tests). Calling repeatedly is fine — last write wins.
10
+ */
11
+ export function setEntityTypeNormalizer(fn) {
12
+ configuredNormalizer = fn;
13
+ }
14
+ export class StoreEditor {
15
+ store;
16
+ view;
17
+ maxExistingId;
18
+ constructor(store, view) {
19
+ this.store = store;
20
+ this.view = view;
21
+ this.maxExistingId = this.computeMaxExistingId();
22
+ this.view.setExpressIdWatermark(this.maxExistingId);
23
+ }
24
+ /**
25
+ * Re-scan the store and bump the express-id watermark if the store has
26
+ * grown since construction (e.g. after lazy index hydration or
27
+ * federating in another model). Cheap to call — `MutablePropertyView`
28
+ * keeps the high watermark, so re-seeding with a stale value is a
29
+ * no-op.
30
+ */
31
+ refreshWatermark() {
32
+ const fresh = this.computeMaxExistingId();
33
+ if (fresh > this.maxExistingId) {
34
+ this.maxExistingId = fresh;
35
+ }
36
+ this.view.setExpressIdWatermark(this.maxExistingId);
37
+ }
38
+ /**
39
+ * Add a new entity to the store overlay. Returns a synthetic `EntityRef`
40
+ * with a freshly-allocated expressId; pass it back to other APIs (other
41
+ * `addEntity` calls, `setPositionalAttribute`, exporters) to reference
42
+ * the new record.
43
+ *
44
+ * Pass `type` as the canonical IFC EXPRESS PascalCase name
45
+ * (e.g. `'IfcRectangleProfileDef'`). UPPERCASE STEP tokens are also
46
+ * accepted — both are normalized to the same internal form.
47
+ *
48
+ * Attribute conventions (mirrors `EntityExtractor.extractEntity()` output):
49
+ * - numbers → STEP integer / REAL literal
50
+ * - `"#42"` → STEP entity reference
51
+ * - `"'literal'"` or any plain string → quoted STEP string
52
+ * - `".AREA."` (dot-wrapped) → enum
53
+ * - `null` / `undefined` → `$`
54
+ * - arrays → STEP list `(a,b,c)`
55
+ */
56
+ addEntity(type, attributes) {
57
+ // Defense in depth: reject obviously-invalid `type` at the editor
58
+ // boundary so a typo doesn't end up as an invalid STEP record on
59
+ // export. The SDK normalizes via the parser registry; this guard
60
+ // catches direct-editor callers (CLI scripts, sandbox bridge,
61
+ // unit tests) that don't go through that path.
62
+ if (typeof type !== 'string') {
63
+ throw new TypeError(`StoreEditor.addEntity: type must be a string, got ${typeof type}`);
64
+ }
65
+ const trimmed = type.trim();
66
+ if (trimmed.length === 0) {
67
+ throw new Error('StoreEditor.addEntity: type cannot be empty');
68
+ }
69
+ // STEP entity tokens always start with "IFC" / "Ifc". Accept either
70
+ // PascalCase (`IfcWall`) or the all-caps STEP form (`IFCWALL`).
71
+ // Underscore is allowed in body chars to accommodate vendor-extension
72
+ // names (e.g. `IfcVendor_Foo`). The exporter handles the case
73
+ // conversion at the file-format boundary.
74
+ if (!/^[Ii][Ff][Cc][A-Za-z][A-Za-z0-9_]*$/.test(trimmed)) {
75
+ throw new Error(`StoreEditor.addEntity: type "${type}" is not a recognizable IFC entity name (expected e.g. "IfcWall")`);
76
+ }
77
+ // When a schema-aware normaliser is configured, resolve the
78
+ // canonical PascalCase name (e.g. "IFCWALL" → "IfcWall") and
79
+ // reject typos that aren't in the registry. The `Ifc${string}`
80
+ // shape passes the regex above but `IfcWal` would slip through;
81
+ // the normaliser is what catches that.
82
+ let canonical = trimmed;
83
+ if (configuredNormalizer) {
84
+ const resolved = configuredNormalizer(trimmed);
85
+ if (!resolved) {
86
+ throw new Error(`StoreEditor.addEntity: type "${type}" is not in the IFC schema registry (typo? vendor extension?)`);
87
+ }
88
+ canonical = resolved;
89
+ }
90
+ // Re-seed every call: cheap (one comparison + at most one write inside
91
+ // the view), and recovers from `view.clear()`, which resets the
92
+ // allocator to 0 and would otherwise hand out colliding ids on the
93
+ // next addEntity().
94
+ this.view.setExpressIdWatermark(this.maxExistingId);
95
+ // Defence against a stale watermark — the store may have grown after
96
+ // construction (lazy index hydration, federated merge) without
97
+ // notifying us. Check whether the allocator's next id collides with
98
+ // the current source index BEFORE calling createEntity, so we don't
99
+ // emit phantom CREATE_ENTITY / DELETE_ENTITY pairs into the mutation
100
+ // history just to fix our own bookkeeping.
101
+ if (this.store.entityIndex.byId.has(this.view.peekNextExpressId())) {
102
+ this.refreshWatermark();
103
+ }
104
+ const created = this.view.createEntity(canonical, attributes);
105
+ return {
106
+ expressId: created.expressId,
107
+ type: created.type,
108
+ byteOffset: OVERLAY_BYTE_OFFSET,
109
+ byteLength: 0,
110
+ lineNumber: -1,
111
+ };
112
+ }
113
+ /**
114
+ * Remove an entity. Existing entities are tombstoned and skipped during
115
+ * export; overlay-only entities are forgotten. Returns false if the id is
116
+ * not known to the store or the overlay.
117
+ */
118
+ removeEntity(expressId) {
119
+ if (this.view.getNewEntity(expressId) !== null) {
120
+ return this.view.deleteEntity(expressId);
121
+ }
122
+ if (!this.store.entityIndex.byId.has(expressId))
123
+ return false;
124
+ return this.view.deleteEntity(expressId);
125
+ }
126
+ /**
127
+ * Edit a positional STEP argument on any entity by zero-based index.
128
+ * Use this for non-IfcRoot edits like `IfcRectangleProfileDef.XDim`
129
+ * where the attribute has no symbolic name.
130
+ */
131
+ setPositionalAttribute(expressId, index, value) {
132
+ this.view.setPositionalAttribute(expressId, index, value);
133
+ }
134
+ /** Edit a named root attribute (Name, Description, ObjectType, …). */
135
+ setAttribute(expressId, attrName, value) {
136
+ this.view.setAttribute(expressId, attrName, value);
137
+ }
138
+ /** Look up the overlay record for a freshly-added entity. */
139
+ getNewEntity(expressId) {
140
+ return this.view.getNewEntity(expressId);
141
+ }
142
+ /** All overlay-created entities, in insertion order. */
143
+ getNewEntities() {
144
+ return this.view.getNewEntities();
145
+ }
146
+ computeMaxExistingId() {
147
+ let max = 0;
148
+ for (const id of this.store.entityIndex.byId.keys()) {
149
+ if (id > max)
150
+ max = id;
151
+ }
152
+ return max;
153
+ }
154
+ }
155
+ //# sourceMappingURL=store-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-editor.js","sourceRoot":"","sources":["../src/store-editor.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAyB/D,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,CAAC;AAgBtC,IAAI,oBAAoB,GAAgC,IAAI,CAAC;AAE7D;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,EAA+B;IACrE,oBAAoB,GAAG,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,OAAO,WAAW;IACd,KAAK,CAAe;IACpB,IAAI,CAAsB;IAC1B,aAAa,CAAS;IAE9B,YAAY,KAAmB,EAAE,IAAyB;QACxD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1C,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAC,IAAY,EAAE,UAA+B;QACrD,kEAAkE;QAClE,iEAAiE;QACjE,iEAAiE;QACjE,8DAA8D;QAC9D,+CAA+C;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,SAAS,CAAC,qDAAqD,OAAO,IAAI,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,oEAAoE;QACpE,gEAAgE;QAChE,sEAAsE;QACtE,8DAA8D;QAC9D,0CAA0C;QAC1C,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,gCAAgC,IAAI,mEAAmE,CACxG,CAAC;QACJ,CAAC;QAED,4DAA4D;QAC5D,6DAA6D;QAC7D,+DAA+D;QAC/D,gEAAgE;QAChE,uCAAuC;QACvC,IAAI,SAAS,GAAG,OAAO,CAAC;QACxB,IAAI,oBAAoB,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;YAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACb,gCAAgC,IAAI,+DAA+D,CACpG,CAAC;YACJ,CAAC;YACD,SAAS,GAAG,QAAQ,CAAC;QACvB,CAAC;QAED,uEAAuE;QACvE,gEAAgE;QAChE,mEAAmE;QACnE,oBAAoB;QACpB,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACpD,qEAAqE;QACrE,+DAA+D;QAC/D,oEAAoE;QACpE,oEAAoE;QACpE,qEAAqE;QACrE,2CAA2C;QAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAC9D,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,mBAAmB;YAC/B,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,CAAC,CAAC;SACf,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,SAAiB;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9D,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,sBAAsB,CAAC,SAAiB,EAAE,KAAa,EAAE,KAAwB;QAC/E,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,sEAAsE;IACtE,YAAY,CAAC,SAAiB,EAAE,QAAgB,EAAE,KAAa;QAC7D,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,6DAA6D;IAC7D,YAAY,CAAC,SAAiB;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,wDAAwD;IACxD,cAAc;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;IACpC,CAAC;IAEO,oBAAoB;QAC1B,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACpD,IAAI,EAAE,GAAG,GAAG;gBAAE,GAAG,GAAG,EAAE,CAAC;QACzB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
package/dist/types.d.ts CHANGED
@@ -2,6 +2,13 @@
2
2
  * Types for IFC mutation tracking
3
3
  */
4
4
  import type { PropertyValueType } from '@ifc-lite/data';
5
+ /**
6
+ * IFC STEP attribute value, as produced by `EntityExtractor.extractEntity()`.
7
+ *
8
+ * Mirrors the parser's `IfcAttributeValue` to keep `@ifc-lite/mutations` free
9
+ * of a `@ifc-lite/parser` dependency (parser → ifcx → mutations would cycle).
10
+ */
11
+ export type IfcAttributeValue = string | number | boolean | null | IfcAttributeValue[];
5
12
  /**
6
13
  * Property value types supported by mutations
7
14
  */
@@ -9,7 +16,7 @@ export type PropertyValue = string | number | boolean | null | PropertyValue[];
9
16
  /**
10
17
  * Types of mutations that can be applied to IFC data
11
18
  */
12
- export type MutationType = 'CREATE_PROPERTY' | 'UPDATE_PROPERTY' | 'DELETE_PROPERTY' | 'CREATE_PROPERTY_SET' | 'DELETE_PROPERTY_SET' | 'CREATE_QUANTITY' | 'UPDATE_QUANTITY' | 'DELETE_QUANTITY' | 'UPDATE_ATTRIBUTE';
19
+ export type MutationType = 'CREATE_PROPERTY' | 'UPDATE_PROPERTY' | 'DELETE_PROPERTY' | 'CREATE_PROPERTY_SET' | 'DELETE_PROPERTY_SET' | 'CREATE_QUANTITY' | 'UPDATE_QUANTITY' | 'DELETE_QUANTITY' | 'UPDATE_ATTRIBUTE' | 'UPDATE_POSITIONAL_ATTRIBUTE' | 'CREATE_ENTITY' | 'DELETE_ENTITY';
13
20
  /**
14
21
  * A single mutation operation
15
22
  */
@@ -91,6 +98,50 @@ export interface AttributeMutation {
91
98
  /** Previous value (for undo) */
92
99
  oldValue?: string;
93
100
  }
101
+ /**
102
+ * In-memory record for an entity created via the overlay.
103
+ *
104
+ * `attributes` is the positional STEP argument list for the entity, in the
105
+ * same shape that `EntityExtractor.extractEntity()` produces. Numbers become
106
+ * STEP integer/REAL literals; strings/booleans/null are emitted literally;
107
+ * nested arrays are emitted as STEP lists. Use a string `"#42"` for entity
108
+ * references, `".AREA."` for enums, `"$"` for explicit unset.
109
+ */
110
+ export interface NewEntity {
111
+ expressId: number;
112
+ type: string;
113
+ attributes: IfcAttributeValue[];
114
+ }
115
+ /**
116
+ * Minimal `EntityRef` shape consumed by `StoreEditor`. Structurally compatible
117
+ * with `@ifc-lite/parser`'s `EntityRef`.
118
+ */
119
+ export interface MutationEntityRef {
120
+ expressId: number;
121
+ type: string;
122
+ byteOffset: number;
123
+ byteLength: number;
124
+ lineNumber: number;
125
+ }
126
+ /**
127
+ * Minimal entity-by-id index shape. Compatible with `Map<number, EntityRef>`
128
+ * and the parser's `CompactEntityIndex`. Only the read methods are required
129
+ * — the overlay never mutates the underlying index.
130
+ */
131
+ export interface MutationEntityByIdIndex {
132
+ get(expressId: number): MutationEntityRef | undefined;
133
+ has(expressId: number): boolean;
134
+ readonly size: number;
135
+ keys(): IterableIterator<number>;
136
+ }
137
+ /**
138
+ * Minimal `IfcDataStore` shape consumed by `StoreEditor`.
139
+ */
140
+ export interface MutationStoreShape {
141
+ entityIndex: {
142
+ byId: MutationEntityByIdIndex;
143
+ };
144
+ }
94
145
  /**
95
146
  * Generate a unique ID for mutations
96
147
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAqH/D;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB;IAC9E,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,SAAiB;IAC/E,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,aAAqB;IAClE,OAAO,GAAG,QAAQ,SAAS,aAAa,EAAE,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAqL/D;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB;IAC9E,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,QAAgB,EAAE,SAAiB;IAC/E,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,aAAqB;IAClE,OAAO,GAAG,QAAQ,SAAS,aAAa,EAAE,CAAC;AAC7C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/mutations",
3
- "version": "1.14.5",
3
+ "version": "1.15.1",
4
4
  "description": "Mutation tracking and property editing for IFC-Lite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,21 +12,21 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "@ifc-lite/data": "^1.15.1"
15
+ "@ifc-lite/data": "^2.0.0"
16
16
  },
17
17
  "devDependencies": {
18
- "typescript": "^5.3.0",
18
+ "typescript": "^6.0.3",
19
19
  "vitest": "^1.6.0"
20
20
  },
21
21
  "license": "MPL-2.0",
22
22
  "author": "Louis True",
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://github.com/louistrue/ifc-lite.git",
25
+ "url": "https://github.com/LTplus-AG/ifc-lite.git",
26
26
  "directory": "packages/mutations"
27
27
  },
28
- "homepage": "https://louistrue.github.io/ifc-lite/",
29
- "bugs": "https://github.com/louistrue/ifc-lite/issues",
28
+ "homepage": "https://ltplus-ag.github.io/ifc-lite/",
29
+ "bugs": "https://github.com/LTplus-AG/ifc-lite/issues",
30
30
  "keywords": [
31
31
  "ifc",
32
32
  "bim",