@ifc-lite/export 2.7.0 → 2.8.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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Zero-based positional slots on `entityType` whose declared type is an EXPRESS
3
+ * ENUMERATION.
4
+ */
5
+ export declare function getEnumTypedSlots(entityType: string): ReadonlySet<number>;
6
+ /**
7
+ * Zero-based positional slots on `entityType` whose declared type bottoms out in
8
+ * EXPRESS STRING (`IfcLabel`, `IfcText`, `IfcIdentifier`, …).
9
+ *
10
+ * These are the slots where a value must be QUOTED regardless of what it looks
11
+ * like. Entity-reference and SELECT slots deliberately stay out: a bare `#12`
12
+ * is the correct token there, and it is only in a text slot that emitting one
13
+ * is a corruption.
14
+ */
15
+ export declare function getStringTypedSlots(entityType: string): ReadonlySet<number>;
16
+ /**
17
+ * Serialize a value destined for an ENUM slot as a STEP enumeration token:
18
+ * `.USERDEFINED.`, never `'USERDEFINED'`. Accepts the bare symbol or the
19
+ * already-dotted form.
20
+ *
21
+ * Two different questions, answered differently:
22
+ *
23
+ * DOMAIN validity — "is `.FOO.` a legal value of IfcWallTypeEnum" — is NOT
24
+ * checked. That is a schema question; the domain check with its `USERDEFINED` +
25
+ * `ObjectType` fallback lives in `retype.ts`, where a carried-over value has to
26
+ * survive a class change. Here the caller named this attribute explicitly, and
27
+ * `.FOO.` is at least a well-formed token in the right lexical category.
28
+ *
29
+ * LEXICAL validity — "is this a token at all" — IS checked, because this
30
+ * function owns the token form and nothing downstream can recover from getting
31
+ * it wrong. `.A,B.` re-parses as TWO arguments and shifts every following slot;
32
+ * `.O'BRIEN.` opens a string literal that swallows the rest of the record. The
33
+ * damage is silent and spans the whole entity, not one attribute.
34
+ *
35
+ * An invalid symbol falls back to a quoted string rather than throwing or
36
+ * dropping. Dropping is the bug class this whole change exists to fix. Throwing
37
+ * would turn one odd attribute value into a failed save of the entire model —
38
+ * strictly worse than one wrongly-typed slot in a file that still parses, still
39
+ * has correct arity, and still shows the user the text they typed. A quoted
40
+ * string is also exactly what this slot got before enum detection existed.
41
+ */
42
+ export declare function serializeEnumToken(value: string): string;
43
+ /**
44
+ * Serialize a value destined for a STRING slot.
45
+ *
46
+ * Always quotes, never infers. `serializeAttributeValue` reads the token being
47
+ * replaced to decide the form, so over a `$` slot it takes a value that merely
48
+ * LOOKS like a token at face value: a `Tag` of `#12` became an entity
49
+ * reference, `.FOO.` an enumeration. In a slot the schema declares as text, the
50
+ * only legal tokens are a quoted string and the null/derived markers, so there
51
+ * is nothing to infer.
52
+ *
53
+ * `''`, `$` and `*` keep their existing meaning as those markers — that is
54
+ * unchanged behaviour, and `''` is already the caller's way to clear a value.
55
+ */
56
+ export declare function serializeStringSlot(value: string): string;
57
+ //# sourceMappingURL=attribute-slot-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-slot-types.d.ts","sourceRoot":"","sources":["../src/attribute-slot-types.ts"],"names":[],"mappings":"AAuKA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAE3E;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAaxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMzD"}
@@ -0,0 +1,236 @@
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
+ /**
5
+ * Schema-aware detection of ENUMERATION- and STRING-typed STEP attribute slots.
6
+ *
7
+ * `serializeAttributeValue` infers a named attribute's STEP form from the token
8
+ * it is replacing. That works while there IS a token to read — a current
9
+ * `.ELEMENT.` says "this slot is an enum", a current `'Wall A'` says "this slot
10
+ * is text and the new value must be quoted" — and fails silently when the slot
11
+ * holds `$`, where there is nothing to read. Two ways it fails:
12
+ *
13
+ * - an enum came out quoted (`'USERDEFINED'`, not `.USERDEFINED.`);
14
+ * - a value that merely LOOKS like a token is emitted as one, so a `Tag` or
15
+ * `Name` of `#12` became an entity reference and `.FOO.` an enumeration.
16
+ * A room or tag literally named `#12` is ordinary on a real project.
17
+ *
18
+ * Both write a schema-invalid record rather than a wrong value, and the second
19
+ * got wider when overlay-created records started padding missing slots with `$`
20
+ * (#2006 review).
21
+ *
22
+ * A slot's declared type is statically known, so resolve it from the schema
23
+ * instead of guessing from the previous value. Indices come from exactly the
24
+ * resolution {@link getAttributeNamesAcrossSchemas} uses — the pinned IFC4
25
+ * registry first, the bundled 2X3+4+4X3 union only when the pin knows the class
26
+ * not at all — so an index from one is always an index into the other.
27
+ * `attribute-slot-types.test.ts` asserts that alignment over every class in the
28
+ * registry rather than trusting it.
29
+ *
30
+ * Deliberately NOT version-parameterized: both sources are version-invariant
31
+ * here (the pin is IFC4, the union merges every bundled schema), so adding a
32
+ * version would suggest a precision this data cannot deliver.
33
+ *
34
+ * The one remaining gap is a leaf-declared, non-PredefinedType enum on a class
35
+ * the pin does not carry. `IfcEntityInfo` records attribute NAMES only —
36
+ * "types/optional flags are out of scope for the auditor (and not exposed by
37
+ * the upstream SchemaInfo data)" — so those types do not exist in this repo to
38
+ * be read, in the generated tables or anywhere else; closing that would take a
39
+ * codegen change to `@ifc-lite/data`. Everything reachable without one is
40
+ * covered: inherited slots via the nearest pinned ancestor, PredefinedType via
41
+ * the declared domain.
42
+ */
43
+ import { SCHEMA_REGISTRY, getAllAttributesForEntity, getAttributeNamesAcrossSchemas, resolveEntityNameAlias, } from '@ifc-lite/parser';
44
+ import { ENTITIES_IFC2X3, ENTITIES_IFC4, ENTITIES_IFC4X3 } from '@ifc-lite/data';
45
+ import { escapeStepString, resolveExpressBase } from './step-serialization.js';
46
+ /** Union of every bundled schema, later schemas winning — mirrors the fallback
47
+ * inside `getAttributeNamesAcrossSchemas` so the two agree on indices. */
48
+ const UNION_BY_UPPER = (() => {
49
+ const map = new Map();
50
+ for (const list of [ENTITIES_IFC2X3, ENTITIES_IFC4, ENTITIES_IFC4X3]) {
51
+ for (const entity of list)
52
+ map.set(entity.name.toUpperCase(), entity);
53
+ }
54
+ return map;
55
+ })();
56
+ const slotTypeCache = new Map();
57
+ /**
58
+ * Declared attribute types of the nearest ancestor the pinned registry DOES
59
+ * carry, as a name → EXPRESS type map, for a class it does not.
60
+ *
61
+ * The union data set records attribute names but no per-attribute type, so the
62
+ * types of a leaf's INHERITED attributes have to come from an ancestor. Walks
63
+ * the union's `parent` chain because the pin cannot see the intermediate
64
+ * classes either (IfcRoad → IfcFacility → IfcSpatialStructureElement: only the
65
+ * last is pinned).
66
+ */
67
+ function pinnedAncestorAttributeTypes(info) {
68
+ const seen = new Set();
69
+ let cursor = info.parent
70
+ ? UNION_BY_UPPER.get(info.parent.toUpperCase())
71
+ : undefined;
72
+ while (cursor && !seen.has(cursor.name)) {
73
+ seen.add(cursor.name);
74
+ const attributes = getAllAttributesForEntity(cursor.name);
75
+ if (attributes.length > 0) {
76
+ return new Map(attributes.map((a) => [a.name, a.type]));
77
+ }
78
+ cursor = cursor.parent ? UNION_BY_UPPER.get(cursor.parent.toUpperCase()) : undefined;
79
+ }
80
+ return null;
81
+ }
82
+ /** Classify one slot by its declared EXPRESS type. */
83
+ function classify(declaredType, index, enums, strings) {
84
+ if (SCHEMA_REGISTRY.enums[declaredType]) {
85
+ enums.add(index);
86
+ }
87
+ else if (resolveExpressBase(declaredType) === 'STRING') {
88
+ strings.add(index);
89
+ }
90
+ }
91
+ /**
92
+ * Declared-type classification of `entityType`'s positional slots.
93
+ *
94
+ * Returns empty sets for classes neither source knows (vendor extensions),
95
+ * which leaves those slots on the previous-token inference exactly as before.
96
+ * Empty sets can never MISPLACE a value, so degrading to them is always safe.
97
+ */
98
+ function getSlotTypes(entityType) {
99
+ // Canonicalize FIRST, and cache on the canonical name: `getAttributeNames-
100
+ // AcrossSchemas` resolves stratum aliases (IFCSOLIDSTRATUM →
101
+ // IfcGeotechnicalStratum) before indexing the union, so a lookup that did not
102
+ // would answer about a different attribute list than the one these indices
103
+ // index into — and every alias of one class would get its own cache entry.
104
+ const canonical = resolveEntityNameAlias(entityType);
105
+ const upper = canonical.toUpperCase();
106
+ const cached = slotTypeCache.get(upper);
107
+ if (cached)
108
+ return cached;
109
+ const enums = new Set();
110
+ const strings = new Set();
111
+ const pinned = getAllAttributesForEntity(canonical);
112
+ if (pinned.length > 0) {
113
+ for (let i = 0; i < pinned.length; i++)
114
+ classify(pinned[i].type, i, enums, strings);
115
+ }
116
+ else {
117
+ const info = UNION_BY_UPPER.get(upper);
118
+ if (info) {
119
+ // Inherited slots: take the declared type from the nearest pinned
120
+ // ancestor, matched BY NAME against this class's own attribute list.
121
+ //
122
+ // Not by index. The ancestor's list is not always a prefix of the leaf's
123
+ // (measured: 30 of the 169 classes with a pinned ancestor), and reusing
124
+ // its indices would classify the wrong slot — e.g. on
125
+ // IfcStructuralLinearActionVarying index 10 is `ProjectedOrTrue` in the
126
+ // ancestor and `CausedBy` in the leaf, so an edit to a reference slot
127
+ // would be written as `.SOMETHING.`. Name matching places
128
+ // `ProjectedOrTrue` at the leaf's index 11, where it belongs.
129
+ const names = getAttributeNamesAcrossSchemas(canonical);
130
+ const ancestorTypes = pinnedAncestorAttributeTypes(info);
131
+ if (ancestorTypes) {
132
+ for (let i = 0; i < names.length; i++) {
133
+ const declared = ancestorTypes.get(names[i]);
134
+ if (declared)
135
+ classify(declared, i, enums, strings);
136
+ }
137
+ }
138
+ // Leaf-declared PredefinedType: no ancestor declares it, and its enum
139
+ // type name is not in the union data — but a non-empty domain says the
140
+ // slot is an enumeration, which is all this needs to know.
141
+ if (info.predefinedTypes.length > 0) {
142
+ const index = names.indexOf('PredefinedType');
143
+ if (index >= 0)
144
+ enums.add(index);
145
+ }
146
+ }
147
+ }
148
+ const resolved = { enums, strings };
149
+ slotTypeCache.set(upper, resolved);
150
+ return resolved;
151
+ }
152
+ /**
153
+ * Zero-based positional slots on `entityType` whose declared type is an EXPRESS
154
+ * ENUMERATION.
155
+ */
156
+ export function getEnumTypedSlots(entityType) {
157
+ return getSlotTypes(entityType).enums;
158
+ }
159
+ /**
160
+ * Zero-based positional slots on `entityType` whose declared type bottoms out in
161
+ * EXPRESS STRING (`IfcLabel`, `IfcText`, `IfcIdentifier`, …).
162
+ *
163
+ * These are the slots where a value must be QUOTED regardless of what it looks
164
+ * like. Entity-reference and SELECT slots deliberately stay out: a bare `#12`
165
+ * is the correct token there, and it is only in a text slot that emitting one
166
+ * is a corruption.
167
+ */
168
+ export function getStringTypedSlots(entityType) {
169
+ return getSlotTypes(entityType).strings;
170
+ }
171
+ /**
172
+ * ISO 10303-21 enumeration token body: a letter, then letters, digits or
173
+ * underscores. Anything else is not an enumeration token at all.
174
+ */
175
+ const ENUM_SYMBOL = /^[A-Z][A-Z0-9_]*$/;
176
+ /**
177
+ * Serialize a value destined for an ENUM slot as a STEP enumeration token:
178
+ * `.USERDEFINED.`, never `'USERDEFINED'`. Accepts the bare symbol or the
179
+ * already-dotted form.
180
+ *
181
+ * Two different questions, answered differently:
182
+ *
183
+ * DOMAIN validity — "is `.FOO.` a legal value of IfcWallTypeEnum" — is NOT
184
+ * checked. That is a schema question; the domain check with its `USERDEFINED` +
185
+ * `ObjectType` fallback lives in `retype.ts`, where a carried-over value has to
186
+ * survive a class change. Here the caller named this attribute explicitly, and
187
+ * `.FOO.` is at least a well-formed token in the right lexical category.
188
+ *
189
+ * LEXICAL validity — "is this a token at all" — IS checked, because this
190
+ * function owns the token form and nothing downstream can recover from getting
191
+ * it wrong. `.A,B.` re-parses as TWO arguments and shifts every following slot;
192
+ * `.O'BRIEN.` opens a string literal that swallows the rest of the record. The
193
+ * damage is silent and spans the whole entity, not one attribute.
194
+ *
195
+ * An invalid symbol falls back to a quoted string rather than throwing or
196
+ * dropping. Dropping is the bug class this whole change exists to fix. Throwing
197
+ * would turn one odd attribute value into a failed save of the entire model —
198
+ * strictly worse than one wrongly-typed slot in a file that still parses, still
199
+ * has correct arity, and still shows the user the text they typed. A quoted
200
+ * string is also exactly what this slot got before enum detection existed.
201
+ */
202
+ export function serializeEnumToken(value) {
203
+ const trimmed = value.trim();
204
+ if (trimmed === '*')
205
+ return '*';
206
+ const symbol = trimmed.replace(/^\./, '').replace(/\.$/, '').trim().toUpperCase();
207
+ if (symbol === '' || symbol === '$')
208
+ return '$';
209
+ if (!ENUM_SYMBOL.test(symbol)) {
210
+ console.warn(`[StepExporter] "${value}" is not a valid STEP enumeration symbol; writing it as a quoted string. `
211
+ + 'The record stays parseable, but the slot now holds text where the schema declares an enumeration.');
212
+ return serializeStringSlot(trimmed);
213
+ }
214
+ return `.${symbol}.`;
215
+ }
216
+ /**
217
+ * Serialize a value destined for a STRING slot.
218
+ *
219
+ * Always quotes, never infers. `serializeAttributeValue` reads the token being
220
+ * replaced to decide the form, so over a `$` slot it takes a value that merely
221
+ * LOOKS like a token at face value: a `Tag` of `#12` became an entity
222
+ * reference, `.FOO.` an enumeration. In a slot the schema declares as text, the
223
+ * only legal tokens are a quoted string and the null/derived markers, so there
224
+ * is nothing to infer.
225
+ *
226
+ * `''`, `$` and `*` keep their existing meaning as those markers — that is
227
+ * unchanged behaviour, and `''` is already the caller's way to clear a value.
228
+ */
229
+ export function serializeStringSlot(value) {
230
+ const trimmed = value.trim();
231
+ if (value === '' || trimmed === '$' || trimmed === '*') {
232
+ return trimmed === '*' ? '*' : '$';
233
+ }
234
+ return `'${escapeStepString(value)}'`;
235
+ }
236
+ //# sourceMappingURL=attribute-slot-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-slot-types.js","sourceRoot":"","sources":["../src/attribute-slot-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The effective model: what the file WILL say, not what it said when parsed.
3
+ *
4
+ * `IfcDataStore` answers for the source buffer. The `MutablePropertyView`
5
+ * overlay knows what the session has since created, retyped and deleted, and
6
+ * never writes back into the store (its buffer and `CompactEntityIndex` are
7
+ * immutable by construction — see `StoreEditor`). So every export pass that
8
+ * asked `dataStore` a question the overlay owns produced a saved file that
9
+ * disagreed with what the user did (#2012):
10
+ *
11
+ * - a `visibleOnly` closure computed from `entityIndex.byId` can never make an
12
+ * overlay-created entity a root, nor walk into one, so a created wall was
13
+ * silently absent from the export;
14
+ * - `endsWith('TYPE')` on the source record's class misses an overlay-created
15
+ * `IfcWallType`, so its psets were emitted as occurrence relations;
16
+ * - and a tombstoned entity still looked alive to the pset/quantity passes.
17
+ *
18
+ * This module is the one place those questions are answered. Every consumer
19
+ * takes the index rather than reaching for `dataStore`, so a new pass cannot
20
+ * reintroduce the defect by forgetting to ask the overlay: there is nothing
21
+ * else to ask.
22
+ *
23
+ * Three distinctions the shape deliberately keeps:
24
+ *
25
+ * - {@link EffectiveEntityIndex.get} answers *as authored or parsed* — the
26
+ * source record's class and byte range, or the creation payload's class.
27
+ * {@link EffectiveEntityIndex.typeOf} answers the *effective* class, with
28
+ * retypes applied and normalised to the UPPERCASE form the store uses.
29
+ * The source-iteration pass needs the former (it hands the original class
30
+ * to `retypeStepLine` as the from-type); every classification needs the
31
+ * latter.
32
+ * - a tombstoned id does not exist: `get` returns undefined, `has` is false,
33
+ * and iteration skips it. `isDeleted` is what distinguishes "deleted" from
34
+ * "never existed" for callers that must tell them apart.
35
+ * - an overlay-created record has no bytes, so its outgoing references are
36
+ * read from its authored attributes by {@link EffectiveEntityIndex.refsOf}
37
+ * instead of scanned out of the source buffer.
38
+ */
39
+ import type { IfcDataStore } from '@ifc-lite/parser';
40
+ import { type IfcAttributeValue, type MutablePropertyView } from '@ifc-lite/mutations';
41
+ import { type CompleteEntityIndex } from './entity-iteration.js';
42
+ /**
43
+ * The complete source index (`byId` + any deferred property atoms) with the
44
+ * overlay folded in. Extends {@link CompleteEntityIndex}, so anything that
45
+ * already takes the source view takes this one.
46
+ */
47
+ export interface EffectiveEntityIndex extends CompleteEntityIndex {
48
+ /** Effective IFC class, UPPERCASE, retype applied. Undefined when the id does
49
+ * not exist in the effective model (unknown, or tombstoned). */
50
+ typeOf(id: number): string | undefined;
51
+ /**
52
+ * The same answer for an id whose record you are already holding — on an
53
+ * iteration path, where the extra `get` is not free.
54
+ *
55
+ * `CompactEntityIndex.get` binary-searches and allocates an `EntityRef` per
56
+ * call, so re-deriving the class from the id while iterating would cost
57
+ * O(E log E) plus one allocation per entity for a string the loop already has.
58
+ */
59
+ effectiveType(id: number, recordType: string): string;
60
+ /** Created by the overlay this session (no source record). */
61
+ isOverlayCreated(id: number): boolean;
62
+ /** Tombstoned by the overlay this session. True for a source entity the
63
+ * session deleted AND for one it created and then deleted. */
64
+ isDeleted(id: number): boolean;
65
+ /** Outgoing `#id` references of an OVERLAY-created record, or undefined when
66
+ * the id has source bytes to scan instead. */
67
+ refsOf(id: number): readonly number[] | undefined;
68
+ /** Effective UPPERCASE-type → ids index: tombstones removed, retypes moved to
69
+ * their new class, overlay creations added. */
70
+ readonly byType: Map<string, number[]>;
71
+ }
72
+ /**
73
+ * Build the effective view over a store plus its overlay.
74
+ *
75
+ * Passing no view, or `applyMutations: false`, returns the source view
76
+ * unchanged — the same object `getCompleteEntityIndex` would hand back, with no
77
+ * per-entity wrapper and no extra allocation on the common export path. An
78
+ * overlay that has queued nothing structural (no creates, no deletes, no
79
+ * retypes) takes the same fast path: attribute and property edits do not change
80
+ * which entities exist or what class they are.
81
+ */
82
+ export declare function getEffectiveEntityIndex(dataStore: IfcDataStore, mutationView: MutablePropertyView | null | undefined, applyMutations: boolean): EffectiveEntityIndex;
83
+ /**
84
+ * Every express id an AUTHORED attribute value references, recursing into lists.
85
+ *
86
+ * `'#42'` is the documented `StoreEditor.addEntity` form for a reference; a
87
+ * value that merely contains one ('detail #999') is text, and a bare number is a
88
+ * measure, not an id. That is the same distinction the byte scanner makes for
89
+ * source records, and the reason this cannot be shared with the source path:
90
+ * there a reference IS a number, because the parser already resolved it.
91
+ */
92
+ export declare function authoredEntityRefs(value: IfcAttributeValue | string | undefined): number[];
93
+ //# sourceMappingURL=effective-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effective-index.d.ts","sourceRoot":"","sources":["../src/effective-index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D;qEACiE;IACjE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACvC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IACtD,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACtC;mEAC+D;IAC/D,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B;mDAC+C;IAC/C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAClD;oDACgD;IAChD,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,mBAAmB,GAAG,IAAI,GAAG,SAAS,EACpD,cAAc,EAAE,OAAO,GACtB,oBAAoB,CAiBtB;AA2KD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ1F"}
@@ -0,0 +1,218 @@
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 { OVERLAY_BYTE_OFFSET, } from '@ifc-lite/mutations';
5
+ import { getCompleteEntityIndex, } from './entity-iteration.js';
6
+ /**
7
+ * Build the effective view over a store plus its overlay.
8
+ *
9
+ * Passing no view, or `applyMutations: false`, returns the source view
10
+ * unchanged — the same object `getCompleteEntityIndex` would hand back, with no
11
+ * per-entity wrapper and no extra allocation on the common export path. An
12
+ * overlay that has queued nothing structural (no creates, no deletes, no
13
+ * retypes) takes the same fast path: attribute and property edits do not change
14
+ * which entities exist or what class they are.
15
+ */
16
+ export function getEffectiveEntityIndex(dataStore, mutationView, applyMutations) {
17
+ const base = getCompleteEntityIndex(dataStore);
18
+ const view = applyMutations ? (mutationView ?? null) : null;
19
+ const created = new Map();
20
+ if (view && typeof view.getNewEntities === 'function') {
21
+ for (const entity of view.getNewEntities())
22
+ created.set(entity.expressId, entity);
23
+ }
24
+ const tombstones = view && typeof view.getTombstones === 'function' ? view.getTombstones() : EMPTY_IDS;
25
+ const retypes = view && typeof view.getTypeMutations === 'function' ? view.getTypeMutations() : EMPTY_RETYPES;
26
+ if (created.size === 0 && tombstones.size === 0 && retypes.size === 0) {
27
+ return sourceOnly(base, dataStore.entityIndex.byType);
28
+ }
29
+ return new OverlayIndex(base, dataStore.entityIndex.byType, view, created, tombstones, retypes);
30
+ }
31
+ const EMPTY_IDS = new Set();
32
+ const EMPTY_RETYPES = new Map();
33
+ /** The no-overlay answer: the source view, with the extra questions answered
34
+ * the only way the buffer can answer them. */
35
+ function sourceOnly(base, byType) {
36
+ return {
37
+ get: (id) => base.get(id),
38
+ has: (id) => base.has(id),
39
+ get size() {
40
+ return base.size;
41
+ },
42
+ [Symbol.iterator]: () => base[Symbol.iterator](),
43
+ typeOf: (id) => base.get(id)?.type.toUpperCase(),
44
+ effectiveType: (_id, recordType) => recordType.toUpperCase(),
45
+ isOverlayCreated: () => false,
46
+ isDeleted: () => false,
47
+ refsOf: () => undefined,
48
+ byType,
49
+ };
50
+ }
51
+ class OverlayIndex {
52
+ base;
53
+ sourceByType;
54
+ view;
55
+ created;
56
+ tombstones;
57
+ retypes;
58
+ cachedByType = null;
59
+ cachedRefs = new Map();
60
+ constructor(base, sourceByType, view, created, tombstones, retypes) {
61
+ this.base = base;
62
+ this.sourceByType = sourceByType;
63
+ this.view = view;
64
+ this.created = created;
65
+ this.tombstones = tombstones;
66
+ this.retypes = retypes;
67
+ }
68
+ get(id) {
69
+ if (this.tombstones.has(id))
70
+ return undefined;
71
+ const overlay = this.created.get(id);
72
+ if (overlay) {
73
+ return { type: overlay.type, byteOffset: OVERLAY_BYTE_OFFSET, byteLength: 0 };
74
+ }
75
+ return this.base.get(id);
76
+ }
77
+ has(id) {
78
+ if (this.tombstones.has(id))
79
+ return false;
80
+ return this.created.has(id) || this.base.has(id);
81
+ }
82
+ get size() {
83
+ let live = 0;
84
+ for (const id of this.tombstones)
85
+ if (this.base.has(id))
86
+ live++;
87
+ return this.base.size - live + this.created.size;
88
+ }
89
+ *[Symbol.iterator]() {
90
+ for (const entry of this.base) {
91
+ if (this.tombstones.has(entry[0]))
92
+ continue;
93
+ yield entry;
94
+ }
95
+ for (const [id, entity] of this.created) {
96
+ yield [id, { type: entity.type, byteOffset: OVERLAY_BYTE_OFFSET, byteLength: 0 }];
97
+ }
98
+ }
99
+ typeOf(id) {
100
+ const ref = this.get(id);
101
+ if (!ref)
102
+ return undefined;
103
+ return this.effectiveType(id, ref.type);
104
+ }
105
+ effectiveType(id, recordType) {
106
+ return (this.retypes.get(id)?.newType ?? recordType).toUpperCase();
107
+ }
108
+ isOverlayCreated(id) {
109
+ return this.created.has(id);
110
+ }
111
+ isDeleted(id) {
112
+ return this.tombstones.has(id);
113
+ }
114
+ /**
115
+ * A created record's outgoing references, read off the authored payload.
116
+ *
117
+ * The UNION of the creation payload and every queued override, not the
118
+ * override applied on top of it. Over-inclusion keeps an entity in an export
119
+ * closure that a later edit may have stopped pointing at — harmless, it is
120
+ * one extra record. Under-inclusion drops one the file still references,
121
+ * which is a broken file. The asymmetry decides it.
122
+ */
123
+ refsOf(id) {
124
+ const entity = this.created.get(id);
125
+ if (!entity || this.tombstones.has(id))
126
+ return undefined;
127
+ const cached = this.cachedRefs.get(id);
128
+ if (cached)
129
+ return cached;
130
+ const out = [];
131
+ for (const value of entity.attributes)
132
+ out.push(...authoredEntityRefs(value));
133
+ if (typeof this.view.getPositionalMutationsForEntity === 'function') {
134
+ const positional = this.view.getPositionalMutationsForEntity(id);
135
+ if (positional)
136
+ for (const value of positional.values())
137
+ out.push(...authoredEntityRefs(value));
138
+ }
139
+ if (typeof this.view.getAttributeMutationsForEntity === 'function') {
140
+ for (const { value } of this.view.getAttributeMutationsForEntity(id)) {
141
+ out.push(...authoredEntityRefs(value));
142
+ }
143
+ }
144
+ this.cachedRefs.set(id, out);
145
+ return out;
146
+ }
147
+ get byType() {
148
+ if (this.cachedByType)
149
+ return this.cachedByType;
150
+ // Shallow copy: the arrays are SHARED with the store until a key actually
151
+ // changes, and every key that changes is replaced with a fresh array. The
152
+ // store's own index is never mutated.
153
+ const out = new Map(this.sourceByType);
154
+ const removeByType = new Map();
155
+ const markRemoved = (id) => {
156
+ const sourceType = this.base.get(id)?.type.toUpperCase();
157
+ if (!sourceType)
158
+ return;
159
+ let bucket = removeByType.get(sourceType);
160
+ if (!bucket)
161
+ removeByType.set(sourceType, (bucket = new Set()));
162
+ bucket.add(id);
163
+ };
164
+ for (const id of this.tombstones)
165
+ markRemoved(id);
166
+ for (const [id, retype] of this.retypes) {
167
+ if (this.created.has(id))
168
+ continue;
169
+ if (this.base.get(id)?.type.toUpperCase() !== retype.newType.toUpperCase())
170
+ markRemoved(id);
171
+ }
172
+ for (const [type, ids] of removeByType) {
173
+ const arr = out.get(type);
174
+ if (arr)
175
+ out.set(type, arr.filter((id) => !ids.has(id)));
176
+ }
177
+ const append = (type, id) => {
178
+ const arr = out.get(type);
179
+ out.set(type, arr ? [...arr, id] : [id]);
180
+ };
181
+ for (const id of this.created.keys()) {
182
+ const type = this.typeOf(id);
183
+ if (type)
184
+ append(type, id);
185
+ }
186
+ for (const [id, retype] of this.retypes) {
187
+ if (this.created.has(id) || this.tombstones.has(id) || !this.base.has(id))
188
+ continue;
189
+ const target = retype.newType.toUpperCase();
190
+ if (this.base.get(id)?.type.toUpperCase() !== target)
191
+ append(target, id);
192
+ }
193
+ this.cachedByType = out;
194
+ return out;
195
+ }
196
+ }
197
+ /**
198
+ * Every express id an AUTHORED attribute value references, recursing into lists.
199
+ *
200
+ * `'#42'` is the documented `StoreEditor.addEntity` form for a reference; a
201
+ * value that merely contains one ('detail #999') is text, and a bare number is a
202
+ * measure, not an id. That is the same distinction the byte scanner makes for
203
+ * source records, and the reason this cannot be shared with the source path:
204
+ * there a reference IS a number, because the parser already resolved it.
205
+ */
206
+ export function authoredEntityRefs(value) {
207
+ if (Array.isArray(value))
208
+ return value.flatMap((item) => authoredEntityRefs(item));
209
+ if (typeof value !== 'string')
210
+ return [];
211
+ const trimmed = value.trim();
212
+ if (trimmed.length < 2 || trimmed[0] !== '#')
213
+ return [];
214
+ const digits = trimmed.slice(1);
215
+ const id = Number.parseInt(digits, 10);
216
+ return Number.isInteger(id) && id > 0 && String(id) === digits ? [id] : [];
217
+ }
218
+ //# sourceMappingURL=effective-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effective-index.js","sourceRoot":"","sources":["../src/effective-index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lod1-generator.d.ts","sourceRoot":"","sources":["../src/lod1-generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAA4B,MAAM,oBAAoB,CAAC;AAIpF,OAAO,KAAK,EAAE,kBAAkB,EAA0B,QAAQ,EAAQ,MAAM,yBAAyB,CAAC;AAG1G,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,CAAC;AAsGF,wBAAsB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAqElH"}
1
+ {"version":3,"file":"lod1-generator.d.ts","sourceRoot":"","sources":["../src/lod1-generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAA4B,MAAM,oBAAoB,CAAC;AAIpF,OAAO,KAAK,EAAE,kBAAkB,EAA0B,QAAQ,EAAQ,MAAM,yBAAyB,CAAC;AAG1G,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,CAAC;AAsGF,wBAAsB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiFlH"}