@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.
- package/README.md +141 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mutable-property-view.d.ts +123 -2
- package/dist/mutable-property-view.d.ts.map +1 -1
- package/dist/mutable-property-view.js +372 -23
- package/dist/mutable-property-view.js.map +1 -1
- package/dist/store-editor.d.ts +89 -0
- package/dist/store-editor.d.ts.map +1 -0
- package/dist/store-editor.js +155 -0
- package/dist/store-editor.js.map +1 -0
- package/dist/types.d.ts +52 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
|
@@ -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":"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"}
|
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
|
*/
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,aAAa,EAAE,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,qBAAqB,GACrB,qBAAqB,GACrB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,CAAC;
|
|
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;
|
|
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.
|
|
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": "^
|
|
15
|
+
"@ifc-lite/data": "^2.0.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"typescript": "^
|
|
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/
|
|
25
|
+
"url": "https://github.com/LTplus-AG/ifc-lite.git",
|
|
26
26
|
"directory": "packages/mutations"
|
|
27
27
|
},
|
|
28
|
-
"homepage": "https://
|
|
29
|
-
"bugs": "https://github.com/
|
|
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",
|