@ifc-lite/export 3.0.1 → 4.0.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 (163) hide show
  1. package/README.md +37 -1
  2. package/dist/anonymize-export.d.ts +60 -0
  3. package/dist/anonymize-export.d.ts.map +1 -0
  4. package/dist/anonymize-export.js +217 -0
  5. package/dist/anonymize-export.js.map +1 -0
  6. package/dist/anonymize-placement.d.ts +71 -0
  7. package/dist/anonymize-placement.d.ts.map +1 -0
  8. package/dist/anonymize-placement.js +266 -0
  9. package/dist/anonymize-placement.js.map +1 -0
  10. package/dist/anonymize-scrub.d.ts +64 -0
  11. package/dist/anonymize-scrub.d.ts.map +1 -0
  12. package/dist/anonymize-scrub.js +315 -0
  13. package/dist/anonymize-scrub.js.map +1 -0
  14. package/dist/anonymize-types.d.ts +235 -0
  15. package/dist/anonymize-types.d.ts.map +1 -0
  16. package/dist/anonymize-types.js +5 -0
  17. package/dist/anonymize-types.js.map +1 -0
  18. package/dist/declared-property-type.d.ts +15 -0
  19. package/dist/declared-property-type.d.ts.map +1 -1
  20. package/dist/declared-property-type.js +43 -0
  21. package/dist/declared-property-type.js.map +1 -1
  22. package/dist/entity-type-sets.d.ts +47 -0
  23. package/dist/entity-type-sets.d.ts.map +1 -0
  24. package/dist/entity-type-sets.js +91 -0
  25. package/dist/entity-type-sets.js.map +1 -0
  26. package/dist/georef-closure.d.ts +55 -0
  27. package/dist/georef-closure.d.ts.map +1 -0
  28. package/dist/georef-closure.js +95 -0
  29. package/dist/georef-closure.js.map +1 -0
  30. package/dist/glb.d.ts.map +1 -1
  31. package/dist/glb.js +26 -2
  32. package/dist/glb.js.map +1 -1
  33. package/dist/ifc5-classification.d.ts +36 -0
  34. package/dist/ifc5-classification.d.ts.map +1 -0
  35. package/dist/ifc5-classification.js +46 -0
  36. package/dist/ifc5-classification.js.map +1 -0
  37. package/dist/ifc5-export-helpers.d.ts +32 -0
  38. package/dist/ifc5-export-helpers.d.ts.map +1 -0
  39. package/dist/ifc5-export-helpers.js +84 -0
  40. package/dist/ifc5-export-helpers.js.map +1 -0
  41. package/dist/ifc5-exporter.d.ts.map +1 -1
  42. package/dist/ifc5-exporter.js +14 -86
  43. package/dist/ifc5-exporter.js.map +1 -1
  44. package/dist/ifc5-material.d.ts +38 -0
  45. package/dist/ifc5-material.d.ts.map +1 -0
  46. package/dist/ifc5-material.js +32 -0
  47. package/dist/ifc5-material.js.map +1 -0
  48. package/dist/index.d.ts +5 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +7 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/merged-context.d.ts +100 -0
  53. package/dist/merged-context.d.ts.map +1 -0
  54. package/dist/merged-context.js +211 -0
  55. package/dist/merged-context.js.map +1 -0
  56. package/dist/merged-empty-containers.d.ts +63 -0
  57. package/dist/merged-empty-containers.d.ts.map +1 -0
  58. package/dist/merged-empty-containers.js +354 -0
  59. package/dist/merged-empty-containers.js.map +1 -0
  60. package/dist/merged-exporter.d.ts +28 -67
  61. package/dist/merged-exporter.d.ts.map +1 -1
  62. package/dist/merged-exporter.js +134 -258
  63. package/dist/merged-exporter.js.map +1 -1
  64. package/dist/merged-guid.d.ts +48 -0
  65. package/dist/merged-guid.d.ts.map +1 -0
  66. package/dist/merged-guid.js +128 -0
  67. package/dist/merged-guid.js.map +1 -0
  68. package/dist/merged-rel-aggregates.d.ts +63 -0
  69. package/dist/merged-rel-aggregates.d.ts.map +1 -0
  70. package/dist/merged-rel-aggregates.js +122 -0
  71. package/dist/merged-rel-aggregates.js.map +1 -0
  72. package/dist/merged-remap.d.ts +18 -0
  73. package/dist/merged-remap.d.ts.map +1 -0
  74. package/dist/merged-remap.js +66 -0
  75. package/dist/merged-remap.js.map +1 -0
  76. package/dist/merged-subcontext.d.ts +41 -0
  77. package/dist/merged-subcontext.d.ts.map +1 -0
  78. package/dist/merged-subcontext.js +99 -0
  79. package/dist/merged-subcontext.js.map +1 -0
  80. package/dist/parquet-exporter-ondemand.d.ts +34 -0
  81. package/dist/parquet-exporter-ondemand.d.ts.map +1 -0
  82. package/dist/parquet-exporter-ondemand.js +89 -0
  83. package/dist/parquet-exporter-ondemand.js.map +1 -0
  84. package/dist/parquet-exporter.d.ts +1 -29
  85. package/dist/parquet-exporter.d.ts.map +1 -1
  86. package/dist/parquet-exporter.js +68 -90
  87. package/dist/parquet-exporter.js.map +1 -1
  88. package/dist/parquet-type-strings.d.ts +11 -0
  89. package/dist/parquet-type-strings.d.ts.map +1 -0
  90. package/dist/parquet-type-strings.js +40 -0
  91. package/dist/parquet-type-strings.js.map +1 -0
  92. package/dist/parquet-uint32-columns.d.ts +30 -0
  93. package/dist/parquet-uint32-columns.d.ts.map +1 -0
  94. package/dist/parquet-uint32-columns.js +38 -0
  95. package/dist/parquet-uint32-columns.js.map +1 -0
  96. package/dist/reference-collector.d.ts +47 -51
  97. package/dist/reference-collector.d.ts.map +1 -1
  98. package/dist/reference-collector.js +115 -171
  99. package/dist/reference-collector.js.map +1 -1
  100. package/dist/related-entities.d.ts +10 -0
  101. package/dist/related-entities.d.ts.map +1 -0
  102. package/dist/related-entities.js +274 -0
  103. package/dist/related-entities.js.map +1 -0
  104. package/dist/schema-converter-attr-remap.d.ts +53 -0
  105. package/dist/schema-converter-attr-remap.d.ts.map +1 -0
  106. package/dist/schema-converter-attr-remap.js +106 -0
  107. package/dist/schema-converter-attr-remap.js.map +1 -0
  108. package/dist/schema-converter.d.ts.map +1 -1
  109. package/dist/schema-converter.js +24 -1
  110. package/dist/schema-converter.js.map +1 -1
  111. package/dist/schema-untranslatable.d.ts +35 -0
  112. package/dist/schema-untranslatable.d.ts.map +1 -0
  113. package/dist/schema-untranslatable.js +60 -0
  114. package/dist/schema-untranslatable.js.map +1 -0
  115. package/dist/step-argument-parser.d.ts.map +1 -1
  116. package/dist/step-argument-parser.js +11 -1
  117. package/dist/step-argument-parser.js.map +1 -1
  118. package/dist/step-attribute-mutations.js +14 -11
  119. package/dist/step-attribute-mutations.js.map +1 -1
  120. package/dist/step-collection.d.ts.map +1 -1
  121. package/dist/step-collection.js +51 -8
  122. package/dist/step-collection.js.map +1 -1
  123. package/dist/step-export-types.d.ts +42 -0
  124. package/dist/step-export-types.d.ts.map +1 -1
  125. package/dist/step-export-types.js +10 -0
  126. package/dist/step-export-types.js.map +1 -1
  127. package/dist/step-exporter.d.ts.map +1 -1
  128. package/dist/step-exporter.js +9 -1
  129. package/dist/step-exporter.js.map +1 -1
  130. package/dist/step-header.d.ts +1 -1
  131. package/dist/step-header.d.ts.map +1 -1
  132. package/dist/step-header.js +2 -2
  133. package/dist/step-header.js.map +1 -1
  134. package/dist/step-map-unit.d.ts +2 -1
  135. package/dist/step-map-unit.d.ts.map +1 -1
  136. package/dist/step-map-unit.js.map +1 -1
  137. package/dist/step-serialization.d.ts +10 -30
  138. package/dist/step-serialization.d.ts.map +1 -1
  139. package/dist/step-serialization.js +10 -60
  140. package/dist/step-serialization.js.map +1 -1
  141. package/dist/step-source-iteration.d.ts.map +1 -1
  142. package/dist/step-source-iteration.js +21 -0
  143. package/dist/step-source-iteration.js.map +1 -1
  144. package/dist/style-closure.d.ts +91 -0
  145. package/dist/style-closure.d.ts.map +1 -0
  146. package/dist/style-closure.js +164 -0
  147. package/dist/style-closure.js.map +1 -0
  148. package/dist/subset-entity-reader.d.ts +104 -0
  149. package/dist/subset-entity-reader.d.ts.map +1 -0
  150. package/dist/subset-entity-reader.js +112 -0
  151. package/dist/subset-entity-reader.js.map +1 -0
  152. package/dist/subset-roots.d.ts +74 -0
  153. package/dist/subset-roots.d.ts.map +1 -0
  154. package/dist/subset-roots.js +168 -0
  155. package/dist/subset-roots.js.map +1 -0
  156. package/dist/type-owned-psets.d.ts +19 -0
  157. package/dist/type-owned-psets.d.ts.map +1 -1
  158. package/dist/type-owned-psets.js +31 -0
  159. package/dist/type-owned-psets.js.map +1 -1
  160. package/dist/unit-normalize.d.ts.map +1 -1
  161. package/dist/unit-normalize.js +10 -2
  162. package/dist/unit-normalize.js.map +1 -1
  163. package/package.json +8 -8
@@ -0,0 +1,315 @@
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 { getAttributeNamesAcrossSchemas, normalizeIfcTypeName } from '@ifc-lite/parser';
5
+ import { decodeStepStringLiteral, generateIfcGuid } from '@ifc-lite/encoding';
6
+ import { attrIndex, readEntityArgs, stepSourceSchema } from './subset-entity-reader.js';
7
+ import { IFC_ROOT_TYPES } from './subset-roots.js';
8
+ import { HAS_PROPERTY_SETS_SLOT, isTypeClass } from './type-owned-psets.js';
9
+ /** `Name`/`LongName`/`Description`/`Tag` — the `IfcRoot`-declared text
10
+ * fields a subset export pseudonymizes when the class declares them and
11
+ * the source value is actually set (not already `$`). Per the decision
12
+ * doc: "pseudonymize Name/LongName/Description/Tag on every exported
13
+ * IfcRoot as `<IfcType>-<n>`". */
14
+ const PSEUDONYM_ATTRIBUTES = ['Name', 'LongName', 'Description', 'Tag'];
15
+ /** Extra root-entity text fields covered by `pseudonymizeAllNames`:
16
+ * `IfcObject.ObjectType` (authoring tools put the family/type name there —
17
+ * "Basic Wall: <project> Exterior 300") and `IfcProject.Phase`. */
18
+ // `ElementType` must be HERE, not in NON_ROOT_NAME_ATTRIBUTES: `slotsFor`
19
+ // short-circuits on IFC_ROOT_TYPES, so that list is inert for IfcWallType (#3351).
20
+ const ROOT_ALL_NAMES_ATTRIBUTES = ['ObjectType', 'Phase', 'ElementType', 'ApplicableOccurrence'];
21
+ /** Non-`IfcRoot` text fields covered by `pseudonymizeAllNames`. Only a
22
+ * quoted-string token is ever rewritten, so an enum-valued `Name`
23
+ * (`IfcSIUnit.Name = .METRE.`) or a `$` passes through untouched. */
24
+ // `Category` is authored text in practice ("ACME Acoustic Batt") (#3351).
25
+ const NON_ROOT_NAME_ATTRIBUTES = ['Name', 'LongName', 'Description', 'ProfileName', 'LayerSetName', 'Category'];
26
+ /** Non-root classes whose `Name` is schema semantics rather than authored
27
+ * text, left alone by `pseudonymizeAllNames`: the authoring application
28
+ * (kept by decision — it is debugging signal), and property / quantity
29
+ * names (`FireRating`, `Width`), which are only exported at all under
30
+ * `keepPropertySets` and are what a property-debugging repro needs. */
31
+ function isNonRootNameExempt(typeUpper) {
32
+ return typeUpper === 'IFCAPPLICATION'
33
+ // Owner-history actors are `scrubOwnerHistory`'s job (their whole
34
+ // attribute list, not just Name), and must stay untouched when it is off.
35
+ || typeUpper === 'IFCPERSON'
36
+ || typeUpper === 'IFCORGANIZATION'
37
+ || typeUpper === 'IFCPERSONANDORGANIZATION'
38
+ || typeUpper.startsWith('IFCPROPERTY')
39
+ || typeUpper.startsWith('IFCPHYSICAL')
40
+ || typeUpper.startsWith('IFCQUANTITY');
41
+ }
42
+ /**
43
+ * Scrub `includedIds`' `IfcRoot` entities plus every owner-history entity in
44
+ * `index`, queuing every change on `view` (never writing into `store`).
45
+ *
46
+ * `index` must be the EFFECTIVE index (`getEffectiveEntityIndex`), not a
47
+ * bare source index — see that module's doc for why an overlay-created or
48
+ * retyped entity answers differently through it. `store` need only expose
49
+ * `source`: `readEntityArgs` reads SOURCE-backed records only, which is the
50
+ * entire domain of what this pass mutates (it creates no entities).
51
+ */
52
+ export function applyScrub(store, index, includedIds, view, opts = {}) {
53
+ // Model's OWN schema (#3309 review finding): the sweeps below walk
54
+ // arbitrary types, and the bundled schemas don't always agree on order.
55
+ const schema = stepSourceSchema(store.schemaVersion);
56
+ const pseudonymizeNames = opts.pseudonymizeNames ?? true;
57
+ const pseudonymizeAllNames = opts.pseudonymizeAllNames ?? true;
58
+ const regenerateGlobalIds = opts.regenerateGlobalIds ?? true;
59
+ const scrubOwnerHistory = opts.scrubOwnerHistory ?? true;
60
+ const neutralizeCurrency = opts.neutralizeCurrency ?? true;
61
+ const keepPropertySets = opts.keepPropertySets ?? false;
62
+ const guidMap = new Map();
63
+ const warnings = [];
64
+ let scrubbedCount = 0;
65
+ // Ascending expressId order, per plan A5 ("per-type counter in ascending
66
+ // expressId order") — determinism depends on this sort, not on Set
67
+ // insertion order, which `includedIds` makes no promise about.
68
+ const rootIds = [...includedIds]
69
+ .filter((id) => IFC_ROOT_TYPES.has(index.typeOf(id) ?? ''))
70
+ .sort((a, b) => a - b);
71
+ const pseudonymCounters = new Map();
72
+ for (const id of rootIds) {
73
+ const type = index.typeOf(id);
74
+ if (type === undefined)
75
+ continue; // gone from the effective model (tombstoned); nothing to scrub
76
+ const record = readEntityArgs(store, index, id);
77
+ if (!record) {
78
+ warnings.push(`Entity #${id} (${normalizeIfcTypeName(type)}): its source record could not be read, `
79
+ + 'so its name/GlobalId scrub was skipped and it is exported unmodified.');
80
+ continue;
81
+ }
82
+ let touched = false;
83
+ if (regenerateGlobalIds) {
84
+ const guidIdx = attrIndex(type, 'GlobalId', schema);
85
+ const oldGuid = guidIdx !== -1 ? decodeQuotedStepString(record.args[guidIdx]) : null;
86
+ if (oldGuid !== null) {
87
+ const newGuid = generateIfcGuid(opts.guidRandom);
88
+ // Positional: `setAttribute` re-resolves the slot by name at
89
+ // serialize time via `step-attribute-mutations.ts`'s own (still
90
+ // pinned-IFC4-first) lookup, undoing `guidIdx` above (#3309).
91
+ view.setPositionalAttribute(id, guidIdx, newGuid);
92
+ guidMap.set(oldGuid, newGuid);
93
+ touched = true;
94
+ }
95
+ else {
96
+ warnings.push(`Entity #${id} (${normalizeIfcTypeName(type)}): its GlobalId could not be read, `
97
+ + 'so it was not regenerated.');
98
+ }
99
+ }
100
+ if (pseudonymizeNames || pseudonymizeAllNames) {
101
+ const pseudonym = nextPseudonym(pseudonymCounters, type);
102
+ const attrs = [
103
+ ...(pseudonymizeNames ? PSEUDONYM_ATTRIBUTES : []),
104
+ ...(pseudonymizeAllNames ? ROOT_ALL_NAMES_ATTRIBUTES : []),
105
+ ];
106
+ for (const attr of attrs) {
107
+ const idx = attrIndex(type, attr, schema);
108
+ if (idx === -1 || idx >= record.args.length || !isQuotedStepString(record.args[idx]))
109
+ continue;
110
+ view.setPositionalAttribute(id, idx, pseudonym); // positional — see the GlobalId write above
111
+ touched = true;
112
+ }
113
+ }
114
+ if (!keepPropertySets && isTypeClass(type)) {
115
+ view.setPositionalAttribute(id, HAS_PROPERTY_SETS_SLOT, null);
116
+ touched = true;
117
+ }
118
+ if (touched)
119
+ scrubbedCount += 1;
120
+ }
121
+ if (pseudonymizeAllNames) {
122
+ scrubbedCount += pseudonymizeNonRootNames(store, index, view, pseudonymCounters);
123
+ }
124
+ if (scrubOwnerHistory || neutralizeCurrency) {
125
+ for (const [id, ref] of index) {
126
+ const type = index.typeOf(id) ?? ref.type.toUpperCase();
127
+ if (type === 'IFCMONETARYUNIT') {
128
+ if (neutralizeCurrency && neutralizeMonetaryUnit(store, index, view, id))
129
+ scrubbedCount += 1;
130
+ continue;
131
+ }
132
+ if (!scrubOwnerHistory)
133
+ continue;
134
+ // Below (and IFCMONETARYUNIT above): FIXED literal types, each
135
+ // slot checked directly against all three `ENTITIES_*` tables — no
136
+ // `schema` argument needed (unlike the arbitrary-type sweeps above).
137
+ switch (type) {
138
+ case 'IFCPERSON':
139
+ scrubPerson(view, id);
140
+ scrubbedCount += 1;
141
+ break;
142
+ case 'IFCORGANIZATION':
143
+ scrubOrganization(view, id);
144
+ scrubbedCount += 1;
145
+ break;
146
+ case 'IFCPERSONANDORGANIZATION': {
147
+ const rolesIdx = attrIndex('IFCPERSONANDORGANIZATION', 'Roles');
148
+ if (rolesIdx !== -1)
149
+ view.setPositionalAttribute(id, rolesIdx, null);
150
+ scrubbedCount += 1;
151
+ break;
152
+ }
153
+ case 'IFCOWNERHISTORY': {
154
+ // Dates pin the model to a project timeline: creation -> epoch 0
155
+ // (the attribute is mandatory, an IfcTimeStamp INTEGER), last
156
+ // modification -> $ (optional).
157
+ const createdIdx = attrIndex('IFCOWNERHISTORY', 'CreationDate');
158
+ const modifiedIdx = attrIndex('IFCOWNERHISTORY', 'LastModifiedDate');
159
+ if (createdIdx !== -1)
160
+ view.setPositionalAttribute(id, createdIdx, 0);
161
+ if (modifiedIdx !== -1)
162
+ view.setPositionalAttribute(id, modifiedIdx, null);
163
+ scrubbedCount += 1;
164
+ break;
165
+ }
166
+ case 'IFCAPPLICATION': {
167
+ // Keep ApplicationFullName/ApplicationIdentifier (the tool), drop
168
+ // Version (a vendor build string can carry the licence region).
169
+ const versionIdx = attrIndex('IFCAPPLICATION', 'Version');
170
+ if (versionIdx !== -1)
171
+ view.setPositionalAttribute(id, versionIdx, null);
172
+ scrubbedCount += 1;
173
+ break;
174
+ }
175
+ default:
176
+ break;
177
+ }
178
+ }
179
+ }
180
+ return { guidMap, scrubbedCount, warnings };
181
+ }
182
+ /**
183
+ * `IfcMonetaryUnit.Currency` -> US dollars, in the source file's own spelling:
184
+ * IFC2X3 declares it as the `IfcCurrencyEnum` (`.NOK.`), IFC4+ as an
185
+ * `IfcLabel` (`'NOK'`). Returns whether a mutation was queued.
186
+ */
187
+ function neutralizeMonetaryUnit(store, index, view, id) {
188
+ const idx = attrIndex('IFCMONETARYUNIT', 'Currency');
189
+ if (idx === -1)
190
+ return false;
191
+ const record = readEntityArgs(store, index, id);
192
+ const token = record?.args[idx];
193
+ if (token === undefined || token === '$')
194
+ return false;
195
+ const usd = token.startsWith('.') ? '.USD.' : 'USD';
196
+ if (token === '.USD.' || token === "'USD'")
197
+ return false;
198
+ view.setPositionalAttribute(id, idx, usd);
199
+ return true;
200
+ }
201
+ /** Next `<IfcType>-<n>` for `typeUpper`, advancing its per-type counter. */
202
+ function nextPseudonym(counters, typeUpper) {
203
+ const typeName = normalizeIfcTypeName(typeUpper);
204
+ const n = (counters.get(typeName) ?? 0) + 1;
205
+ counters.set(typeName, n);
206
+ return `${typeName}-${n}`;
207
+ }
208
+ function isQuotedStepString(token) {
209
+ return token !== undefined && token.length >= 2 && token[0] === "'" && token[token.length - 1] === "'";
210
+ }
211
+ /**
212
+ * `pseudonymizeAllNames` for the non-`IfcRoot` half: walk EVERY entity in
213
+ * `index` (not just `includedIds` — styles, materials, layers and profiles
214
+ * reach the export through the forward closure, which only exists after the
215
+ * exporter runs) and pseudonymize each quoted-string
216
+ * `NON_ROOT_NAME_ATTRIBUTES` slot. A mutation queued on an entity the
217
+ * closure never reaches is simply never serialized, so over-approximating
218
+ * here costs nothing but time, and the per-type slot lookup is cached so the
219
+ * walk touches source bytes only for classes that declare such a slot.
220
+ * Returns how many entities received at least one mutation.
221
+ */
222
+ function pseudonymizeNonRootNames(store, index, view, counters) {
223
+ // Same schema-aware resolution as `applyScrub`'s root pass: this walks
224
+ // every non-root type (materials, styles, layers, profiles, …), e.g.
225
+ // IFC2X3's `IfcApprovalRelationship.Name` sits at slot 3, IFC4's at 0.
226
+ const schema = stepSourceSchema(store.schemaVersion);
227
+ const slotsByType = new Map();
228
+ const slotsFor = (typeUpper) => {
229
+ let slots = slotsByType.get(typeUpper);
230
+ if (slots === undefined) {
231
+ slots = IFC_ROOT_TYPES.has(typeUpper) || isNonRootNameExempt(typeUpper)
232
+ ? []
233
+ : NON_ROOT_NAME_ATTRIBUTES
234
+ .map((name) => [name, attrIndex(typeUpper, name, schema)])
235
+ .filter(([, idx]) => idx !== -1);
236
+ slotsByType.set(typeUpper, slots);
237
+ }
238
+ return slots;
239
+ };
240
+ // Ascending expressId for the same determinism guarantee as the root pass.
241
+ const ids = [];
242
+ for (const [id] of index)
243
+ ids.push(id);
244
+ ids.sort((a, b) => a - b);
245
+ let scrubbed = 0;
246
+ for (const id of ids) {
247
+ const type = index.typeOf(id);
248
+ if (type === undefined)
249
+ continue;
250
+ const slots = slotsFor(type);
251
+ if (slots.length === 0)
252
+ continue;
253
+ const record = readEntityArgs(store, index, id);
254
+ if (!record)
255
+ continue; // overlay-created (e.g. the placement clones) or unreadable: nothing authored to scrub
256
+ let pseudonym = null;
257
+ for (const [, idx] of slots) {
258
+ if (idx >= record.args.length || !isQuotedStepString(record.args[idx]))
259
+ continue;
260
+ pseudonym ??= nextPseudonym(counters, type);
261
+ view.setPositionalAttribute(id, idx, pseudonym); // positional — same reasoning as `applyScrub`'s writes
262
+ }
263
+ if (pseudonym !== null)
264
+ scrubbed += 1;
265
+ }
266
+ return scrubbed;
267
+ }
268
+ /**
269
+ * Decode a raw STEP string-literal token (`'…'`, quotes still attached, as
270
+ * `SubsetEntityArgs.args` holds it — see `subset-entity-reader.ts`) to its
271
+ * Unicode value, or `null` when the token is not a quoted string: `$`, a
272
+ * numeric/enum/reference token, or simply absent because the record's
273
+ * trailing optional arguments were omitted short.
274
+ */
275
+ function decodeQuotedStepString(token) {
276
+ if (token === undefined || token.length < 2 || token[0] !== "'" || token[token.length - 1] !== "'") {
277
+ return null;
278
+ }
279
+ return decodeStepStringLiteral(token.slice(1, -1));
280
+ }
281
+ /** `IfcPerson.FamilyName` -> `'Anonymous'`; every other declared attribute
282
+ * (`Identification`, `GivenName`, `MiddleNames`, `PrefixTitles`,
283
+ * `SuffixTitles`, `Roles`, `Addresses`) -> `$`. Per the decision doc the
284
+ * ENTIRE attribute list is identifying fields/Roles/Addresses, but a total
285
+ * wipe emits `IFCPERSON($,$,$,$,$,$,$,$)`, which violates the schema's
286
+ * `IdentifiablePersonName` WHERE rule (`Identification`, `FamilyName`, or
287
+ * `GivenName` must be set) — a validator or strict viewer can then reject
288
+ * the very file this export exists to hand to a maintainer. Keeping one
289
+ * fixed, non-identifying `FamilyName` satisfies the rule without leaking
290
+ * anything. Schema-driven (`getAttributeNamesAcrossSchemas`) rather than a
291
+ * hardcoded slot count, the same way every other positional write in this
292
+ * package resolves slots. */
293
+ function scrubPerson(view, id) {
294
+ const names = getAttributeNamesAcrossSchemas('IFCPERSON');
295
+ const familyNameIdx = names.indexOf('FamilyName');
296
+ for (let i = 0; i < names.length; i++) {
297
+ if (i === familyNameIdx)
298
+ continue;
299
+ view.setPositionalAttribute(id, i, null);
300
+ }
301
+ view.setAttribute(id, 'FamilyName', 'Anonymous');
302
+ }
303
+ /** `IfcOrganization.Name` -> `'Anonymous'`; every other declared attribute
304
+ * (`Identification`, `Description`, `Roles`, `Addresses`) -> `$`. */
305
+ function scrubOrganization(view, id) {
306
+ const names = getAttributeNamesAcrossSchemas('IFCORGANIZATION');
307
+ const nameIdx = names.indexOf('Name');
308
+ for (let i = 0; i < names.length; i++) {
309
+ if (i === nameIdx)
310
+ continue;
311
+ view.setPositionalAttribute(id, i, null);
312
+ }
313
+ view.setAttribute(id, 'Name', 'Anonymous');
314
+ }
315
+ //# sourceMappingURL=anonymize-scrub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymize-scrub.js","sourceRoot":"","sources":["../src/anonymize-scrub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * The public vocabulary of the "anonymized isolated export" feature (#2934):
3
+ * what a caller passes to `collectRelatedEntities` / `exportAnonymizedSubset`
4
+ * and what it gets back. Declarations only, split out the same way
5
+ * `step-export-types.ts` is split from `step-exporter.ts` — so the two
6
+ * orchestrators (`related-entities.ts`, `anonymize-export.ts`) and every
7
+ * caller (viewer dialog, CLI) share one definition instead of drifting.
8
+ *
9
+ * Keyed by EXPRESS relationship name throughout (`IfcRelVoidsElement`, not
10
+ * `voids`), per this repo's IFC-schema-fidelity rule: these ARE the
11
+ * `IfcRel*` entity types the export walks, not a derived collection that
12
+ * would need its own name.
13
+ */
14
+ import type { RandomSource } from '@ifc-lite/encoding';
15
+ /**
16
+ * Which relationship kinds `collectRelatedEntities` expands from the seed
17
+ * selection, and how far. Every boolean defaults to what the doc comment
18
+ * says, not to `false` — an omitted `RelatedEntityOptions` (or an omitted
19
+ * field within one) must reproduce the bug the seed exhibits, which usually
20
+ * needs its host/opening/type/material context, not a bare, disconnected
21
+ * element.
22
+ */
23
+ export interface RelatedEntityOptions {
24
+ /** Openings of an included host element. Default `true`. */
25
+ IfcRelVoidsElement?: boolean;
26
+ /** The filler↔opening↔host chain (a window/door and the wall it sits in).
27
+ * Default `true`. */
28
+ IfcRelFillsElement?: boolean;
29
+ /**
30
+ * Aggregate parents/children (`IfcRelAggregates`): `'up'` walks to
31
+ * `RelatingObject` only, `'down'` to `RelatedObjects` only, `'both'` walks
32
+ * both directions, `'none'` skips it. Default `'both'`.
33
+ */
34
+ IfcRelAggregates?: 'up' | 'down' | 'both' | 'none';
35
+ /**
36
+ * Nesting parents/children (`IfcRelNests`) — a separate EXPRESS
37
+ * relationship from `IfcRelAggregates` even though the parser folds both
38
+ * into the same aggregation edge type on `RelationshipGraph`; this option
39
+ * is split out from the one above by REL ENTITY TYPE, not by graph edge,
40
+ * so a caller can toggle them independently. Default `'down'`.
41
+ */
42
+ IfcRelNests?: 'up' | 'down' | 'both' | 'none';
43
+ /** An included object's `IfcTypeObject` (`IfcRelDefinesByType`). Default `true`. */
44
+ IfcRelDefinesByType?: boolean;
45
+ /** An included object's material assignment (`IfcRelAssociatesMaterial`).
46
+ * Default `true`. */
47
+ IfcRelAssociatesMaterial?: boolean;
48
+ /**
49
+ * The spatial containment chain (`IfcRelContainedInSpatialStructure`) up to
50
+ * storey/building/site. Default `true`; regardless of this flag,
51
+ * `IfcProject` is ALWAYS included — a STEP file with no project is not a
52
+ * valid reproduction of anything.
53
+ */
54
+ IfcRelContainedInSpatialStructure?: boolean;
55
+ /**
56
+ * An included object's property sets (`IfcRelDefinesByProperties`).
57
+ * Default `false` — psets are the majority of what this feature exists to
58
+ * strip, so expanding them is opt-in, and turning this on still pulls in
59
+ * `ePSet_MapConversion`/`ePSet_ProjectedCRS` style georeferencing psets
60
+ * unless those are separately excluded.
61
+ */
62
+ IfcRelDefinesByProperties?: boolean;
63
+ /**
64
+ * BFS depth (both directions) to walk `IfcRelConnectsPathElements` from an
65
+ * included element — e.g. a wall's structurally-connected neighbour.
66
+ * Default `0` (no expansion).
67
+ */
68
+ IfcRelConnectsPathElementsDepth?: number;
69
+ }
70
+ /**
71
+ * One relationship kind/direction's contribution to a `collectRelatedEntities`
72
+ * result — e.g. "the openings reached via `IfcRelVoidsElement`, host role".
73
+ */
74
+ export interface RelatedEntityGroup {
75
+ /** EXPRESS relationship type name, e.g. `IfcRelVoidsElement`. */
76
+ relationship: string;
77
+ /** Which end of the relationship this group walked — e.g. `'opening'` /
78
+ * `'host'` for `IfcRelVoidsElement`, matching the doc at each walker's own
79
+ * call site rather than a fixed enum, since the meaningful roles differ
80
+ * per relationship kind. */
81
+ role: string;
82
+ /** ExpressIds of the related OBJECTS this group reached (never the
83
+ * `IfcRel*` relationship entity itself). */
84
+ expressIds: number[];
85
+ /** ExpressIds of the `IfcRel*` relationship entities that produced this
86
+ * group — these must ALSO be included in the export subset, or the
87
+ * association they represent has nothing naming it. */
88
+ relationshipIds: number[];
89
+ }
90
+ /** The full result of one `collectRelatedEntities` call. */
91
+ export interface RelatedEntities {
92
+ /** The caller's original seed selection, echoed back unfiltered. */
93
+ seeds: number[];
94
+ /** One entry per (relationship, role) that contributed anything, in walk
95
+ * order — the shape a UI groups a related-entity list by. */
96
+ groups: RelatedEntityGroup[];
97
+ /** The union of every id reached: seeds, every group's `expressIds`, and
98
+ * every group's `relationshipIds`. This — not any one group — is what a
99
+ * caller passes as `StepExportOptions.subsetEntityIds`. */
100
+ all: Set<number>;
101
+ /** `true` when the walk's work budget was exhausted before it reached a
102
+ * fixpoint (`Bounding walks over file-supplied references`, AGENTS.md) —
103
+ * the result is a valid, boundable subset of what a complete walk would
104
+ * have found, not the complete answer. */
105
+ truncated: boolean;
106
+ }
107
+ /**
108
+ * What to scrub, and how, when exporting the `subsetEntityIds` selection as
109
+ * an anonymized STEP file. Every field defaults to the value stated in its
110
+ * own doc comment (all `true`/enabled except where noted) — an anonymized
111
+ * export with no options at all is the maximally-scrubbed one, since the
112
+ * whole point of the feature is that a caller has to opt BACK IN to keep an
113
+ * identifying signal, never opt in to remove one.
114
+ */
115
+ export interface AnonymizeOptions {
116
+ /** Replace `Name`/`LongName`/`Description`/`Tag` on every exported
117
+ * `IfcRoot` with a `<IfcType>-<n>` pseudonym. Default `true`. */
118
+ pseudonymizeNames?: boolean;
119
+ /** Also pseudonymize names OUTSIDE the `IfcRoot` text fields: `ObjectType`,
120
+ * `IfcTypeObject.ApplicableOccurrence`, `IfcElementType.ElementType` and
121
+ * `IfcProject.Phase` on roots, and every quoted-string `Name` /
122
+ * `Description` / `LongName` / `ProfileName` / `LayerSetName` / `Category`
123
+ * on non-`IfcRoot` entities — `Category` on ANY non-root class declaring it,
124
+ * `IfcMaterialProfile` and `IfcMaterialConstituent` included, not only
125
+ * `IfcMaterial` / `IfcMaterialLayer` —
126
+ * (`IfcSurfaceStyle`, `IfcMaterial*`, `IfcPresentationLayerAssignment`,
127
+ * `IfcProfileDef`, `IfcColourRgb`, …).
128
+ * A surface style called after the building it belongs to identifies the
129
+ * project as surely as `IfcProject.Name` does, and `ElementType` is the
130
+ * type-side twin of `ObjectType`, carrying the same authored text
131
+ * ("Basic Wall: <project> Exterior 300"). Enum-valued `Name`s
132
+ * (`IfcSIUnit.Name = .METRE.`) are never touched, nor are property /
133
+ * quantity names (schema semantics, only present under `keepPropertySets`)
134
+ * or `IfcApplication`. Default `true`; independent of `pseudonymizeNames`. */
135
+ pseudonymizeAllNames?: boolean;
136
+ /** Keep `IfcPropertySet`/`IfcElementQuantity` entities instead of dropping
137
+ * them. Default `false`: `exportAnonymizedSubset` excludes every such id
138
+ * from `includedIds` before export, however it got there (a caller's own
139
+ * `IfcRelDefinesByProperties` walk, or a hand-built id set) — the entity
140
+ * never reaches the output, values included, at any `includedIds` (#3351
141
+ * item 2). Property/quantity VALUES are unscrubbed by design, so setting
142
+ * this `true` keeps them exactly as authored; there is no partial,
143
+ * "kept but scrubbed" state. */
144
+ keepPropertySets?: boolean;
145
+ /** Regenerate every exported `IfcRoot`'s `GlobalId` (the old→new mapping
146
+ * comes back as `AnonymizeResult.guidMap`, never written into the file
147
+ * itself). Default `true`. */
148
+ regenerateGlobalIds?: boolean;
149
+ /** Zero the translation of each root `IfcLocalPlacement`
150
+ * (`PlacementRelTo = $`), preserving `Axis`/`RefDirection` and every child
151
+ * placement untouched. Default `true`. */
152
+ zeroRootPlacement?: boolean;
153
+ /** Remove `IfcMapConversion(Scaled)`/`IfcProjectedCRS` and blank
154
+ * `IfcSite`'s georeferencing/address attributes and
155
+ * `IfcBuilding.BuildingAddress`. Default `true`. */
156
+ removeGeoreferencing?: boolean;
157
+ /** Scrub the owner-history chain: blank `IfcPerson`/`IfcOrganization`
158
+ * identifying fields, zero `IfcOwnerHistory.CreationDate` and blank
159
+ * `LastModifiedDate`, blank `IfcApplication.Version` (a vendor build
160
+ * string such as `26.0.0 NOR FULL` encodes the licence region), and blank
161
+ * the STEP header's `originating_system`. `IfcApplication`'s name and
162
+ * identifier are kept — the authoring tool is debugging signal, its
163
+ * regional build is not. Default `true`. */
164
+ scrubOwnerHistory?: boolean;
165
+ /** Rewrite every `IfcMonetaryUnit.Currency` to US dollars (`.USD.` under
166
+ * IFC2X3's enum, `'USD'` under IFC4+'s label), so a cost-loaded model does
167
+ * not reveal its country. Default `true`. */
168
+ neutralizeCurrency?: boolean;
169
+ /** Seeded randomness for regenerated `GlobalId`s (and any other id this
170
+ * export synthesizes) — omitted means the platform CSPRNG, so two runs of
171
+ * an otherwise-identical anonymization differ in exactly those bytes.
172
+ * Pass the same source across repeat runs for byte-reproducible output. */
173
+ guidRandom?: RandomSource;
174
+ /** Pin the STEP header `FILE_NAME` timestamp (STEP format, e.g.
175
+ * `20240101T000000`). Omitted = the wall clock. */
176
+ timeStamp?: string;
177
+ /** Name recorded in the exported STEP header's `FILE_NAME` field — NOT
178
+ * necessarily the name the caller writes the file to disk under. Default
179
+ * `'anonymized.ifc'`, chosen because it is neutral: a caller that passes
180
+ * the real output path or project name here (e.g. `Acme-Tower.ifc`)
181
+ * defeats the anonymization by writing the identifying name straight back
182
+ * into the header of the file this option exists to scrub it from. */
183
+ filename?: string;
184
+ }
185
+ /** The result of one `exportAnonymizedSubset` call. */
186
+ export interface AnonymizeResult {
187
+ /** The anonymized STEP file content. */
188
+ content: Uint8Array;
189
+ /** Old `GlobalId` → new `GlobalId`, for every regenerated `IfcRoot`. Kept
190
+ * out of the exported file itself — it is exactly the mapping back to the
191
+ * original, identifying model, so it is the caller's responsibility to
192
+ * keep it separate (and typically NOT share it alongside the file). */
193
+ guidMap: Map<string, string>;
194
+ stats: {
195
+ /** Total entities in the exported file. */
196
+ entityCount: number;
197
+ /** How many `IfcRoot` entities from `includedIds` actually made it into
198
+ * the export (after subset-root exclusion and relationship pruning). */
199
+ includedRootEntityCount: number;
200
+ /** ExpressIds of `IfcRel*` entities dropped because their mandatory,
201
+ * single-valued reference named an entity the exclusion left out —
202
+ * `relationshipRefsSurviveExclusion` (`reference-collector.ts`) already
203
+ * decides this for the closure walk; this is that same decision,
204
+ * reported so a caller can see WHICH associations the anonymization
205
+ * cost, not just that some file that changed. */
206
+ prunedRelationshipIds: number[];
207
+ /** ExpressIds of `IfcPropertySet`/`IfcElementQuantity` entities excluded
208
+ * from `includedIds` because `keepPropertySets` was falsy (the
209
+ * default) — reported distinctly, the same way `prunedRelationshipIds`
210
+ * is, so a caller can tell "this id is missing because it is a
211
+ * property set" from any other exclusion reason without grepping
212
+ * `warnings` text. Empty when `keepPropertySets` was `true`. */
213
+ droppedPropertySetIds: number[];
214
+ /** ExpressIds of emitted `IfcPropertyReferenceValue` entities whose
215
+ * optional `PropertyReference` was nulled because it named an entity the
216
+ * subset excluded. */
217
+ droppedPropertyReferenceIds: number[];
218
+ /** Each root `IfcLocalPlacement` this export zeroed, and the translation
219
+ * it zeroed (the ORIGINAL, pre-zero coordinates) — reported because the
220
+ * translation was real coordinate data the caller may still want to log
221
+ * or compare against, even though it is deliberately not in the file. */
222
+ zeroedPlacements: {
223
+ expressId: number;
224
+ translation: number[];
225
+ }[];
226
+ /** Non-fatal notices: a placement chain this export could not safely
227
+ * zero (e.g. an `IfcGridPlacement`/`IfcLinearPlacement` root, left
228
+ * untouched), multiple root placements collapsing onto one origin, or
229
+ * anything else `AnonymizeOptions` asked for that this export could not
230
+ * fully deliver. Same `string[]` shape as
231
+ * `StepExportResult.stats.warnings`. */
232
+ warnings: string[];
233
+ };
234
+ }
235
+ //# sourceMappingURL=anonymize-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymize-types.d.ts","sourceRoot":"","sources":["../src/anonymize-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
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
+ export {};
5
+ //# sourceMappingURL=anonymize-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymize-types.js","sourceRoot":"","sources":["../src/anonymize-types.ts"],"names":[],"mappings":"AAAA;;+DAE+D"}
@@ -35,6 +35,21 @@
35
35
  * both from the same token — the source token is the more specific of the
36
36
  * two and wins.
37
37
  *
38
+ * **Unless the caller NAMED a member** ({@link NAMED_MEMBERS}, #3715). Gate 2
39
+ * as written could not express `IfcLabel` → `IfcText`: both are STRING, so
40
+ * "the two agree" and the source token won, silently discarding the request.
41
+ * The information it was missing is whether the caller CHOSE the type or
42
+ * merely echoed the shape the extractor derived — and that is already in the
43
+ * `PropertyValueType`, because the two are different members of it.
44
+ * `String` / `Real` are SHAPES, which is all the extractor can produce (it
45
+ * collapses `IFCLABEL`, `IFCTEXT` and `IFCIDENTIFIER` to `String` and keeps
46
+ * the token only in `dataType`); `Label` / `Identifier` / `Text` NAME one
47
+ * `IfcValue` member each and no extraction path produces them, so one of
48
+ * those can only have come from a caller who asked for it. A named member is
49
+ * therefore authoritative over the source token; a shape keeps gate 2's
50
+ * precedence, which is what stops a value-only edit — the UI passes `String`
51
+ * — from rewriting a neighbouring `IFCTEXT` as `IFCLABEL` all over again.
52
+ *
38
53
  * 3. **The VALUE must be representable in that base.** `serializeTypedMarker`
39
54
  * coerces, so without this an `IFCLENGTHMEASURE` carrying a non-numeric
40
55
  * value would be written as `IFCLENGTHMEASURE(NaN)`, where the shape-derived
@@ -1 +1 @@
1
- {"version":3,"file":"declared-property-type.d.ts","sourceRoot":"","sources":["../src/declared-property-type.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAqGnD;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,MAAM,EAAoC,CAAC;AAqBhG;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,GAAG,IAAI,CAcf;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,CAIR"}
1
+ {"version":3,"file":"declared-property-type.d.ts","sourceRoot":"","sources":["../src/declared-property-type.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6GG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA0HnD;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,SAAS,MAAM,EAAoC,CAAC;AAqBhG;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,GAAG,IAAI,CAqBf;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,CAIR"}