@ifc-lite/parser 5.1.0 → 6.1.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 (199) hide show
  1. package/dist/classification-resolver.d.ts.map +1 -1
  2. package/dist/classification-resolver.js +35 -10
  3. package/dist/classification-resolver.js.map +1 -1
  4. package/dist/columnar-entity-preparation.d.ts +25 -0
  5. package/dist/columnar-entity-preparation.d.ts.map +1 -0
  6. package/dist/columnar-entity-preparation.js +282 -0
  7. package/dist/columnar-entity-preparation.js.map +1 -0
  8. package/dist/columnar-parser-indexes.d.ts +17 -1
  9. package/dist/columnar-parser-indexes.d.ts.map +1 -1
  10. package/dist/columnar-parser-indexes.js +31 -21
  11. package/dist/columnar-parser-indexes.js.map +1 -1
  12. package/dist/columnar-parser-root-attributes.d.ts +66 -0
  13. package/dist/columnar-parser-root-attributes.d.ts.map +1 -0
  14. package/dist/columnar-parser-root-attributes.js +245 -0
  15. package/dist/columnar-parser-root-attributes.js.map +1 -0
  16. package/dist/columnar-parser.d.ts +26 -63
  17. package/dist/columnar-parser.d.ts.map +1 -1
  18. package/dist/columnar-parser.js +384 -751
  19. package/dist/columnar-parser.js.map +1 -1
  20. package/dist/compact-entity-index-columns.d.ts +17 -0
  21. package/dist/compact-entity-index-columns.d.ts.map +1 -0
  22. package/dist/compact-entity-index-columns.js +15 -0
  23. package/dist/compact-entity-index-columns.js.map +1 -0
  24. package/dist/compact-entity-index-transport.d.ts +2 -12
  25. package/dist/compact-entity-index-transport.d.ts.map +1 -1
  26. package/dist/compact-entity-index-transport.js +1 -11
  27. package/dist/compact-entity-index-transport.js.map +1 -1
  28. package/dist/compact-entity-index.d.ts +6 -0
  29. package/dist/compact-entity-index.d.ts.map +1 -1
  30. package/dist/compact-entity-index.js +12 -20
  31. package/dist/compact-entity-index.js.map +1 -1
  32. package/dist/cost-extractor.d.ts +10 -0
  33. package/dist/cost-extractor.d.ts.map +1 -0
  34. package/dist/cost-extractor.js +369 -0
  35. package/dist/cost-extractor.js.map +1 -0
  36. package/dist/cost-schedule-2x3.d.ts +31 -0
  37. package/dist/cost-schedule-2x3.d.ts.map +1 -0
  38. package/dist/cost-schedule-2x3.js +75 -0
  39. package/dist/cost-schedule-2x3.js.map +1 -0
  40. package/dist/cost-types.d.ts +105 -0
  41. package/dist/cost-types.d.ts.map +1 -0
  42. package/dist/cost-types.js +5 -0
  43. package/dist/cost-types.js.map +1 -0
  44. package/dist/data-store-transport.d.ts +3 -2
  45. package/dist/data-store-transport.d.ts.map +1 -1
  46. package/dist/data-store-transport.js +10 -34
  47. package/dist/data-store-transport.js.map +1 -1
  48. package/dist/drop-census.d.ts +136 -0
  49. package/dist/drop-census.d.ts.map +1 -0
  50. package/dist/drop-census.js +53 -0
  51. package/dist/drop-census.js.map +1 -0
  52. package/dist/entity-refs-from-index.d.ts +10 -0
  53. package/dist/entity-refs-from-index.d.ts.map +1 -1
  54. package/dist/entity-refs-from-index.js +52 -36
  55. package/dist/entity-refs-from-index.js.map +1 -1
  56. package/dist/entity-scanner.d.ts +5 -0
  57. package/dist/entity-scanner.d.ts.map +1 -1
  58. package/dist/entity-scanner.js +30 -12
  59. package/dist/entity-scanner.js.map +1 -1
  60. package/dist/entity-type-byte-interner.d.ts +12 -0
  61. package/dist/entity-type-byte-interner.d.ts.map +1 -0
  62. package/dist/entity-type-byte-interner.js +66 -0
  63. package/dist/entity-type-byte-interner.js.map +1 -0
  64. package/dist/generated/ifc2x3/schema-registry.d.ts +50 -0
  65. package/dist/generated/ifc2x3/schema-registry.d.ts.map +1 -0
  66. package/dist/generated/ifc2x3/schema-registry.js +50052 -0
  67. package/dist/generated/ifc2x3/schema-registry.js.map +1 -0
  68. package/dist/generated/ifc4x3/schema-registry.d.ts +50 -0
  69. package/dist/generated/ifc4x3/schema-registry.d.ts.map +1 -0
  70. package/dist/generated/ifc4x3/schema-registry.js +71299 -0
  71. package/dist/generated/ifc4x3/schema-registry.js.map +1 -0
  72. package/dist/generated/schema-registry-by-version.d.ts +61 -0
  73. package/dist/generated/schema-registry-by-version.d.ts.map +1 -0
  74. package/dist/generated/schema-registry-by-version.js +86 -0
  75. package/dist/generated/schema-registry-by-version.js.map +1 -0
  76. package/dist/group-assignment-factor.d.ts +13 -0
  77. package/dist/group-assignment-factor.d.ts.map +1 -0
  78. package/dist/group-assignment-factor.js +30 -0
  79. package/dist/group-assignment-factor.js.map +1 -0
  80. package/dist/ifczip.d.ts +6 -0
  81. package/dist/ifczip.d.ts.map +1 -1
  82. package/dist/ifczip.js +20 -11
  83. package/dist/ifczip.js.map +1 -1
  84. package/dist/index.d.ts +10 -6
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +17 -7
  87. package/dist/index.js.map +1 -1
  88. package/dist/on-demand-extractors.d.ts +1 -0
  89. package/dist/on-demand-extractors.d.ts.map +1 -1
  90. package/dist/on-demand-extractors.js +2 -1
  91. package/dist/on-demand-extractors.js.map +1 -1
  92. package/dist/parser.worker.d.ts +6 -3
  93. package/dist/parser.worker.d.ts.map +1 -1
  94. package/dist/parser.worker.js +24 -12
  95. package/dist/parser.worker.js.map +1 -1
  96. package/dist/prepass-source-fingerprint.d.ts +3 -0
  97. package/dist/prepass-source-fingerprint.d.ts.map +1 -0
  98. package/dist/prepass-source-fingerprint.js +13 -0
  99. package/dist/prepass-source-fingerprint.js.map +1 -0
  100. package/dist/property-value-parser.d.ts +10 -0
  101. package/dist/property-value-parser.d.ts.map +1 -1
  102. package/dist/property-value-parser.js +40 -1
  103. package/dist/property-value-parser.js.map +1 -1
  104. package/dist/scan-entities-balanced.d.ts.map +1 -1
  105. package/dist/scan-entities-balanced.js +8 -6
  106. package/dist/scan-entities-balanced.js.map +1 -1
  107. package/dist/scan-worker-lexing.d.ts +14 -0
  108. package/dist/scan-worker-lexing.d.ts.map +1 -0
  109. package/dist/scan-worker-lexing.js +101 -0
  110. package/dist/scan-worker-lexing.js.map +1 -0
  111. package/dist/scan-worker-source.d.ts +1 -1
  112. package/dist/scan-worker-source.d.ts.map +1 -1
  113. package/dist/scan-worker-source.js +61 -59
  114. package/dist/scan-worker-source.js.map +1 -1
  115. package/dist/schedule-extractor.d.ts +2 -80
  116. package/dist/schedule-extractor.d.ts.map +1 -1
  117. package/dist/schedule-extractor.js +100 -225
  118. package/dist/schedule-extractor.js.map +1 -1
  119. package/dist/schedule-serializer-builders.d.ts +28 -0
  120. package/dist/schedule-serializer-builders.d.ts.map +1 -0
  121. package/dist/schedule-serializer-builders.js +163 -0
  122. package/dist/schedule-serializer-builders.js.map +1 -0
  123. package/dist/schedule-serializer.d.ts +6 -0
  124. package/dist/schedule-serializer.d.ts.map +1 -1
  125. package/dist/schedule-serializer.js +26 -165
  126. package/dist/schedule-serializer.js.map +1 -1
  127. package/dist/schedule-types.d.ts +211 -0
  128. package/dist/schedule-types.d.ts.map +1 -0
  129. package/dist/schedule-types.js +221 -0
  130. package/dist/schedule-types.js.map +1 -0
  131. package/dist/select-entity-columns.d.ts +7 -0
  132. package/dist/select-entity-columns.d.ts.map +1 -0
  133. package/dist/select-entity-columns.js +43 -0
  134. package/dist/select-entity-columns.js.map +1 -0
  135. package/dist/spatial-hierarchy-ambiguity.d.ts +39 -0
  136. package/dist/spatial-hierarchy-ambiguity.d.ts.map +1 -0
  137. package/dist/spatial-hierarchy-ambiguity.js +25 -0
  138. package/dist/spatial-hierarchy-ambiguity.js.map +1 -0
  139. package/dist/spatial-hierarchy-attributes.d.ts +54 -0
  140. package/dist/spatial-hierarchy-attributes.d.ts.map +1 -0
  141. package/dist/spatial-hierarchy-attributes.js +145 -0
  142. package/dist/spatial-hierarchy-attributes.js.map +1 -0
  143. package/dist/spatial-hierarchy-builder.d.ts +6 -38
  144. package/dist/spatial-hierarchy-builder.d.ts.map +1 -1
  145. package/dist/spatial-hierarchy-builder.js +48 -166
  146. package/dist/spatial-hierarchy-builder.js.map +1 -1
  147. package/dist/spatial-hierarchy-canonical-parent.d.ts +86 -0
  148. package/dist/spatial-hierarchy-canonical-parent.d.ts.map +1 -0
  149. package/dist/spatial-hierarchy-canonical-parent.js +212 -0
  150. package/dist/spatial-hierarchy-canonical-parent.js.map +1 -0
  151. package/dist/step-lexing.d.ts +1 -1
  152. package/dist/step-lexing.d.ts.map +1 -1
  153. package/dist/step-lexing.js +1 -56
  154. package/dist/step-lexing.js.map +1 -1
  155. package/dist/step-record-boundary.d.ts +28 -0
  156. package/dist/step-record-boundary.d.ts.map +1 -0
  157. package/dist/step-record-boundary.js +108 -0
  158. package/dist/step-record-boundary.js.map +1 -0
  159. package/dist/step-record-boundary.vectors.d.ts +58 -0
  160. package/dist/step-record-boundary.vectors.d.ts.map +1 -0
  161. package/dist/step-record-boundary.vectors.js +80 -0
  162. package/dist/step-record-boundary.vectors.js.map +1 -0
  163. package/dist/structural-extractor.d.ts +9 -0
  164. package/dist/structural-extractor.d.ts.map +1 -0
  165. package/dist/structural-extractor.js +310 -0
  166. package/dist/structural-extractor.js.map +1 -0
  167. package/dist/structural-load-extractor.d.ts +147 -0
  168. package/dist/structural-load-extractor.d.ts.map +1 -0
  169. package/dist/structural-load-extractor.js +178 -0
  170. package/dist/structural-load-extractor.js.map +1 -0
  171. package/dist/structural-step-values.d.ts +51 -0
  172. package/dist/structural-step-values.d.ts.map +1 -0
  173. package/dist/structural-step-values.js +109 -0
  174. package/dist/structural-step-values.js.map +1 -0
  175. package/dist/structural-types.d.ts +145 -0
  176. package/dist/structural-types.d.ts.map +1 -0
  177. package/dist/structural-types.js +5 -0
  178. package/dist/structural-types.js.map +1 -0
  179. package/dist/tokenizer.d.ts +11 -5
  180. package/dist/tokenizer.d.ts.map +1 -1
  181. package/dist/tokenizer.js +75 -21
  182. package/dist/tokenizer.js.map +1 -1
  183. package/dist/wasm-init-retry.d.ts +6 -42
  184. package/dist/wasm-init-retry.d.ts.map +1 -1
  185. package/dist/wasm-init-retry.js +6 -99
  186. package/dist/wasm-init-retry.js.map +1 -1
  187. package/dist/wasm-panic-forward.d.ts +7 -63
  188. package/dist/wasm-panic-forward.d.ts.map +1 -1
  189. package/dist/wasm-panic-forward.js +7 -100
  190. package/dist/wasm-panic-forward.js.map +1 -1
  191. package/dist/worker-index-publication.d.ts +43 -0
  192. package/dist/worker-index-publication.d.ts.map +1 -0
  193. package/dist/worker-index-publication.js +129 -0
  194. package/dist/worker-index-publication.js.map +1 -0
  195. package/dist/worker-parser.d.ts +5 -2
  196. package/dist/worker-parser.d.ts.map +1 -1
  197. package/dist/worker-parser.js +22 -10
  198. package/dist/worker-parser.js.map +1 -1
  199. package/package.json +5 -4
@@ -0,0 +1,310 @@
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
+ * Structural analysis extractor — parses IfcStructuralAnalysisModel,
6
+ * IfcStructuralMember / IfcStructuralConnection subtypes, IfcStructuralAction /
7
+ * IfcStructuralReaction subtypes, IfcStructuralLoadGroup / IfcStructuralLoadCase,
8
+ * IfcStructuralResultGroup, IfcBoundaryCondition, IfcRelConnectsStructuralMember,
9
+ * IfcRelConnectsStructuralActivity and IfcRelAssignsToGroup from a parsed
10
+ * IfcDataStore into a connected `StructuralExtraction`.
11
+ *
12
+ * On-demand, like the schedule extractor: nothing here runs during a normal
13
+ * parse, and a model with no structural entity costs one `byType` sweep.
14
+ *
15
+ * The two structural connects-relationships are read from the type index
16
+ * directly rather than from the relationship graph, because that graph's
17
+ * `REL_TYPE_MAP` carries neither of them — the rows are retained, but nothing
18
+ * indexes member↔connection or item↔activity edges for a query traversal to
19
+ * follow.
20
+ *
21
+ * Two things are schema-derived rather than hand-tabulated, because the
22
+ * alternative is a table that silently mis-reads the next subtype to appear:
23
+ *
24
+ * - **Which types count.** Every `IFCSTRUCTURAL*` key in the type index is
25
+ * classified by its inheritance chain, so `IfcStructuralCurveMemberVarying`
26
+ * is a member and `IfcStructuralLinearAction` is an action without either
27
+ * being named here.
28
+ * - **Where each attribute sits.** Positions come from the generated registry
29
+ * by EXPRESS attribute name, never from a literal index.
30
+ *
31
+ * IFC2X3 support is best-effort and the divergences are known, not assumed:
32
+ * 2X3 has no IfcStructuralCurveAction, IfcStructuralSurfaceAction,
33
+ * IfcStructuralCurveReaction, IfcStructuralLoadCase or
34
+ * IfcStructuralLoadConfiguration at all, and its IfcStructuralCurveMember has
35
+ * no `Axis`. Positions resolve against the parser's IFC4 registry pin, which
36
+ * agrees with 2X3 on the attributes both schemas share for every type read
37
+ * here; a 2X3-only attribute reads as absent rather than as the wrong slot.
38
+ */
39
+ import { EntityExtractor } from './entity-extractor.js';
40
+ import { getInheritanceChain } from './ifc-schema.js';
41
+ import { extractBoundaryCondition, extractStructuralLoad, } from './structural-load-extractor.js';
42
+ import { addUnique, asBoolean, asEnum, asNumber, asNumberList, asRef, asRefList, asString, readAttr, readEntities, } from './structural-step-values.js';
43
+ function emptyExtraction() {
44
+ return {
45
+ analysisModels: [],
46
+ members: [],
47
+ connections: [],
48
+ activities: [],
49
+ loadGroups: [],
50
+ resultGroups: [],
51
+ hasStructural: false,
52
+ loadsTruncated: false,
53
+ };
54
+ }
55
+ /** Chain marker → role. Every marker is disjoint, so match order is not load-bearing. */
56
+ const ROLE_BY_SUPERTYPE = [
57
+ ['IFCSTRUCTURALANALYSISMODEL', 'analysisModel'],
58
+ ['IFCSTRUCTURALRESULTGROUP', 'resultGroup'],
59
+ ['IFCSTRUCTURALLOADGROUP', 'loadGroup'],
60
+ ['IFCSTRUCTURALMEMBER', 'member'],
61
+ ['IFCSTRUCTURALCONNECTION', 'connection'],
62
+ ['IFCSTRUCTURALACTIVITY', 'activity'],
63
+ ];
64
+ /**
65
+ * Classify a concrete type by inheritance, not by name. Returns undefined for
66
+ * an `IFCSTRUCTURAL*` type that is none of the six roles — `IfcStructuralLoad`
67
+ * leaves and `IfcStructuralProfileProperties` reach here and are read through
68
+ * their owners instead.
69
+ */
70
+ function roleOf(type) {
71
+ const chain = getInheritanceChain(type).map((c) => c.toUpperCase());
72
+ for (const [marker, role] of ROLE_BY_SUPERTYPE) {
73
+ if (chain.includes(marker))
74
+ return role;
75
+ }
76
+ return undefined;
77
+ }
78
+ function activityKind(type) {
79
+ const chain = getInheritanceChain(type).map((c) => c.toUpperCase());
80
+ if (chain.includes('IFCSTRUCTURALACTION'))
81
+ return 'Action';
82
+ if (chain.includes('IFCSTRUCTURALREACTION'))
83
+ return 'Reaction';
84
+ return 'Unknown';
85
+ }
86
+ /** IfcRoot attribute 2 is Name, 3 Description; IfcObject adds ObjectType at 4. */
87
+ function rootFields(e) {
88
+ return {
89
+ name: asString(e.attrs[2]),
90
+ description: asString(e.attrs[3]),
91
+ objectType: asString(e.attrs[4]),
92
+ };
93
+ }
94
+ /**
95
+ * Extract all structural analysis data from a parsed IFC store.
96
+ */
97
+ export function extractStructuralOnDemand(store) {
98
+ if (!store.source?.length)
99
+ return emptyExtraction();
100
+ const byType = store.entityIndex.byType;
101
+ // Partition every IFCSTRUCTURAL* type present into the six roles.
102
+ const idsByRole = new Map();
103
+ for (const [typeKey, ids] of byType) {
104
+ if (!typeKey.startsWith('IFCSTRUCTURAL'))
105
+ continue;
106
+ const role = roleOf(typeKey);
107
+ if (!role)
108
+ continue;
109
+ const bucket = idsByRole.get(role);
110
+ if (bucket)
111
+ bucket.push(...ids);
112
+ else
113
+ idsByRole.set(role, [...ids]);
114
+ }
115
+ const relMemberIds = byType.get('IFCRELCONNECTSSTRUCTURALMEMBER') ?? [];
116
+ const relActivityIds = byType.get('IFCRELCONNECTSSTRUCTURALACTIVITY') ?? [];
117
+ const relGroupIds = byType.get('IFCRELASSIGNSTOGROUP') ?? [];
118
+ // Behaviour-neutral early-out, not a guard: with no structural entity the
119
+ // passes below already produce an empty extraction. It exists so the common
120
+ // case — a model with no structural analysis at all — never constructs an
121
+ // EntityExtractor over the whole source buffer.
122
+ if (idsByRole.size === 0)
123
+ return emptyExtraction();
124
+ const extractor = new EntityExtractor(store.source);
125
+ const read = (role) => readEntities(extractor, store, idsByRole.get(role) ?? []);
126
+ const memberRaw = read('member');
127
+ const connectionRaw = read('connection');
128
+ const activityRaw = read('activity');
129
+ const loadGroupRaw = read('loadGroup');
130
+ const resultGroupRaw = read('resultGroup');
131
+ const analysisModelRaw = read('analysisModel');
132
+ /** expressId → globalId, over every structural entity we resolved. */
133
+ const globalIdById = new Map();
134
+ for (const list of [
135
+ memberRaw,
136
+ connectionRaw,
137
+ activityRaw,
138
+ loadGroupRaw,
139
+ resultGroupRaw,
140
+ analysisModelRaw,
141
+ ]) {
142
+ for (const e of list)
143
+ if (e.globalId)
144
+ globalIdById.set(e.expressId, e.globalId);
145
+ }
146
+ // ── Relationship passes ────────────────────────────────────────────────
147
+ const connectionsOfMember = new Map();
148
+ const membersOfConnection = new Map();
149
+ for (const rel of readEntities(extractor, store, relMemberIds)) {
150
+ const memberId = asRef(readAttr(rel.type, rel.attrs, 'RelatingStructuralMember'));
151
+ const connectionId = asRef(readAttr(rel.type, rel.attrs, 'RelatedStructuralConnection'));
152
+ if (memberId === undefined || connectionId === undefined)
153
+ continue;
154
+ const memberGid = globalIdById.get(memberId);
155
+ const connectionGid = globalIdById.get(connectionId);
156
+ if (connectionGid)
157
+ addUnique(connectionsOfMember, memberId, connectionGid);
158
+ if (memberGid)
159
+ addUnique(membersOfConnection, connectionId, memberGid);
160
+ }
161
+ const activitiesOfItem = new Map();
162
+ /** activity expressId → the item globalId it applies to. */
163
+ const itemOfActivity = new Map();
164
+ for (const rel of readEntities(extractor, store, relActivityIds)) {
165
+ const itemId = asRef(readAttr(rel.type, rel.attrs, 'RelatingElement'));
166
+ const activityId = asRef(readAttr(rel.type, rel.attrs, 'RelatedStructuralActivity'));
167
+ if (itemId === undefined || activityId === undefined)
168
+ continue;
169
+ const activityGid = globalIdById.get(activityId);
170
+ const itemGid = globalIdById.get(itemId);
171
+ if (activityGid)
172
+ addUnique(activitiesOfItem, itemId, activityGid);
173
+ if (itemGid)
174
+ itemOfActivity.set(activityId, itemGid);
175
+ }
176
+ // IfcRelAssignsToGroup is shared with every other grouping in the file, so
177
+ // only the rows whose RelatingGroup is a structural group are read.
178
+ const groupsOfObject = new Map();
179
+ const objectsOfGroup = new Map();
180
+ for (const rel of readEntities(extractor, store, relGroupIds)) {
181
+ const groupId = asRef(readAttr(rel.type, rel.attrs, 'RelatingGroup'));
182
+ if (groupId === undefined)
183
+ continue;
184
+ const groupGid = globalIdById.get(groupId);
185
+ if (!groupGid)
186
+ continue;
187
+ for (const objectId of asRefList(readAttr(rel.type, rel.attrs, 'RelatedObjects'))) {
188
+ addUnique(groupsOfObject, objectId, groupGid);
189
+ const objectGid = globalIdById.get(objectId);
190
+ if (objectGid)
191
+ addUnique(objectsOfGroup, groupId, objectGid);
192
+ }
193
+ }
194
+ /**
195
+ * A group's `RelatedObjects` may hold anything, and IfcRelAssignsToGroup is
196
+ * not structural-specific, so each of the three directions below is narrowed
197
+ * to the role its field name promises rather than reporting the raw set.
198
+ */
199
+ const gidsOf = (lists) => new Set(lists.flat().map((e) => e.globalId).filter((g) => g.length > 0));
200
+ const analysisModelGids = gidsOf([analysisModelRaw]);
201
+ const activityGids = gidsOf([activityRaw]);
202
+ const itemGids = gidsOf([memberRaw, connectionRaw]);
203
+ /** Only those of `expressId`'s groups that are analysis models. */
204
+ const modelsOf = (expressId) => (groupsOfObject.get(expressId) ?? []).filter((g) => analysisModelGids.has(g));
205
+ /** Only the activities assigned into the group `expressId`. */
206
+ const activitiesIn = (expressId) => (objectsOfGroup.get(expressId) ?? []).filter((g) => activityGids.has(g));
207
+ /** Only the members and connections assigned into the group `expressId`. */
208
+ const itemsIn = (expressId) => (objectsOfGroup.get(expressId) ?? []).filter((g) => itemGids.has(g));
209
+ const resolveGids = (value) => asRefList(value)
210
+ .map((id) => globalIdById.get(id))
211
+ .filter((g) => g !== undefined);
212
+ // ── Assemble ───────────────────────────────────────────────────────────
213
+ const members = memberRaw.map((e) => ({
214
+ expressId: e.expressId,
215
+ globalId: e.globalId,
216
+ type: e.type,
217
+ ...rootFields(e),
218
+ predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
219
+ thickness: asNumber(readAttr(e.type, e.attrs, 'Thickness')),
220
+ connectionGlobalIds: connectionsOfMember.get(e.expressId) ?? [],
221
+ activityGlobalIds: activitiesOfItem.get(e.expressId) ?? [],
222
+ analysisModelGlobalIds: modelsOf(e.expressId),
223
+ }));
224
+ const connections = connectionRaw.map((e) => {
225
+ const conditionId = asRef(readAttr(e.type, e.attrs, 'AppliedCondition'));
226
+ return {
227
+ expressId: e.expressId,
228
+ globalId: e.globalId,
229
+ type: e.type,
230
+ ...rootFields(e),
231
+ appliedCondition: conditionId === undefined
232
+ ? undefined
233
+ : extractBoundaryCondition(extractor, store, conditionId),
234
+ memberGlobalIds: membersOfConnection.get(e.expressId) ?? [],
235
+ activityGlobalIds: activitiesOfItem.get(e.expressId) ?? [],
236
+ analysisModelGlobalIds: modelsOf(e.expressId),
237
+ };
238
+ });
239
+ const activities = activityRaw.map((e) => {
240
+ const loadId = asRef(readAttr(e.type, e.attrs, 'AppliedLoad'));
241
+ return {
242
+ expressId: e.expressId,
243
+ globalId: e.globalId,
244
+ type: e.type,
245
+ kind: activityKind(e.type),
246
+ ...rootFields(e),
247
+ predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
248
+ globalOrLocal: asEnum(readAttr(e.type, e.attrs, 'GlobalOrLocal')),
249
+ destabilizingLoad: asBoolean(readAttr(e.type, e.attrs, 'DestabilizingLoad')),
250
+ appliedLoad: loadId === undefined ? undefined : extractStructuralLoad(extractor, store, loadId),
251
+ appliesToGlobalId: itemOfActivity.get(e.expressId),
252
+ groupGlobalIds: groupsOfObject.get(e.expressId) ?? [],
253
+ };
254
+ });
255
+ const loadGroups = loadGroupRaw.map((e) => ({
256
+ expressId: e.expressId,
257
+ globalId: e.globalId,
258
+ type: e.type,
259
+ ...rootFields(e),
260
+ predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
261
+ actionType: asEnum(readAttr(e.type, e.attrs, 'ActionType')),
262
+ actionSource: asEnum(readAttr(e.type, e.attrs, 'ActionSource')),
263
+ coefficient: asNumber(readAttr(e.type, e.attrs, 'Coefficient')),
264
+ purpose: asString(readAttr(e.type, e.attrs, 'Purpose')),
265
+ selfWeightCoefficients: asNumberList(readAttr(e.type, e.attrs, 'SelfWeightCoefficients')),
266
+ activityGlobalIds: activitiesIn(e.expressId),
267
+ }));
268
+ const resultGroups = resultGroupRaw.map((e) => {
269
+ const forLoadGroup = asRef(readAttr(e.type, e.attrs, 'ResultForLoadGroup'));
270
+ return {
271
+ expressId: e.expressId,
272
+ globalId: e.globalId,
273
+ ...rootFields(e),
274
+ theoryType: asEnum(readAttr(e.type, e.attrs, 'TheoryType')),
275
+ isLinear: asBoolean(readAttr(e.type, e.attrs, 'IsLinear')),
276
+ resultForLoadGroupGlobalId: forLoadGroup === undefined ? undefined : globalIdById.get(forLoadGroup),
277
+ activityGlobalIds: activitiesIn(e.expressId),
278
+ };
279
+ });
280
+ const analysisModels = analysisModelRaw.map((e) => ({
281
+ expressId: e.expressId,
282
+ globalId: e.globalId,
283
+ ...rootFields(e),
284
+ predefinedType: asEnum(readAttr(e.type, e.attrs, 'PredefinedType')),
285
+ loadGroupGlobalIds: resolveGids(readAttr(e.type, e.attrs, 'LoadedBy')),
286
+ resultGroupGlobalIds: resolveGids(readAttr(e.type, e.attrs, 'HasResults')),
287
+ itemGlobalIds: itemsIn(e.expressId),
288
+ }));
289
+ return {
290
+ analysisModels,
291
+ members,
292
+ connections,
293
+ activities,
294
+ loadGroups,
295
+ resultGroups,
296
+ hasStructural: analysisModels.length +
297
+ members.length +
298
+ connections.length +
299
+ activities.length +
300
+ loadGroups.length +
301
+ resultGroups.length >
302
+ 0,
303
+ // Derived from the loads rather than tracked alongside them, so the
304
+ // extraction cannot claim a completeness its own tree contradicts. A
305
+ // nested configuration propagates its truncation to its parent, so the
306
+ // top-level load carries the whole subtree's answer.
307
+ loadsTruncated: activities.some((a) => a.appliedLoad?.configuration?.truncated === true),
308
+ };
309
+ }
310
+ //# sourceMappingURL=structural-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural-extractor.js","sourceRoot":"","sources":["../src/structural-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Structural load and boundary-condition readers — the leaf resources an
3
+ * activity's `AppliedLoad` and a connection's `AppliedCondition` point at.
4
+ *
5
+ * Both readers are **schema-derived**: they ask the generated registry for the
6
+ * entity's attribute names in STEP positional order and emit every numeric
7
+ * component under its exact EXPRESS name, rather than carrying a hand-written
8
+ * table per `IfcStructuralLoadStatic` / `IfcBoundaryCondition` subtype. A
9
+ * subtype the registry knows therefore reads correctly the day it appears in a
10
+ * file, and `IfcStructuralLoadSingleForceWarping.WarpingMoment` needs no
11
+ * separate case from `IfcStructuralLoadSingleForce.ForceX`.
12
+ */
13
+ import type { EntityExtractor } from './entity-extractor.js';
14
+ import type { IfcDataStore } from './columnar-parser.js';
15
+ /**
16
+ * One `IfcStructuralLoadOrResult` leaf — a force, displacement, temperature or
17
+ * planar/linear force — reduced to its named numeric components.
18
+ */
19
+ export interface StructuralLoadInfo {
20
+ expressId: number;
21
+ /** Canonical EXPRESS type name, e.g. `IfcStructuralLoadSingleForce`. */
22
+ type: string;
23
+ name?: string;
24
+ /**
25
+ * Numeric components keyed by their exact EXPRESS attribute name
26
+ * (`ForceX`, `MomentZ`, `DisplacementY`, `DeltaTConstant`, …). Only
27
+ * attributes the file actually carries a finite number for appear; an
28
+ * omitted (`$`) optional is absent rather than zero, because zero is a
29
+ * meaningful load value and conflating the two would invent data.
30
+ */
31
+ components: Record<string, number>;
32
+ /**
33
+ * Present only for `IfcStructuralLoadConfiguration`: the nested loads and
34
+ * the parametric locations they apply at, as {@link StructuralLoadConfigurationInfo}.
35
+ */
36
+ configuration?: StructuralLoadConfigurationInfo;
37
+ }
38
+ /**
39
+ * Why one `Values` slot carries no nested load.
40
+ *
41
+ * The first three are **our** bounds firing — the file may hold more than we
42
+ * agreed to read, and {@link StructuralLoadConfigurationInfo.truncated} is set.
43
+ * The last three are the file's own data: there is nothing further to read, so
44
+ * they are not truncation.
45
+ */
46
+ export type StructuralLoadDropReason =
47
+ /** Below the nesting cap: the chain is longer than this reader follows. */
48
+ 'depth'
49
+ /** The slot re-enters a configuration already open on this path. */
50
+ | 'cycle'
51
+ /** The node budget for this top-level load was spent before this slot. */
52
+ | 'budget'
53
+ /** The slot is not an entity reference at all (`$`, an inline value, …). */
54
+ | 'invalid-reference'
55
+ /** The referenced expressId is in no index — a dangling reference. */
56
+ | 'unresolved'
57
+ /** The referenced record is indexed but did not parse. */
58
+ | 'unreadable';
59
+ /** One `Values` slot of an `IfcStructuralLoadConfiguration`, with its location. */
60
+ export interface StructuralLoadConfigurationEntry {
61
+ /** The nested load, absent when the slot could not be read. */
62
+ value?: StructuralLoadInfo;
63
+ /** Why {@link value} is absent; absent whenever `value` is present. */
64
+ dropped?: StructuralLoadDropReason;
65
+ /**
66
+ * The `Locations` row at this same slot, when the file carries one. Absent
67
+ * when the file omits the optional `Locations`, lists fewer rows than
68
+ * `Values` has slots, or writes this row as `$` / with a non-numeric cell
69
+ * (the row keeps its position as an empty placeholder in `locations`).
70
+ */
71
+ location?: number[];
72
+ }
73
+ /** The `Values`/`Locations` pair of an `IfcStructuralLoadConfiguration`. */
74
+ export interface StructuralLoadConfigurationInfo {
75
+ /**
76
+ * One entry per `Values` slot, in file order. The pairing the schema
77
+ * requires — the i-th location positions the i-th value — is carried inside
78
+ * the entry rather than across two arrays, so a slot this reader could not
79
+ * resolve keeps its place with `value` absent and `dropped` naming why. A
80
+ * dropped slot that instead shifted its successors left would report a later
81
+ * load as applied at an earlier station, which reads as real data.
82
+ */
83
+ entries: StructuralLoadConfigurationEntry[];
84
+ /**
85
+ * `Locations` as the file writes it, absent when the file omits it or writes
86
+ * it unusably. Kept beside {@link entries} for the malformed case where it is
87
+ * longer than `Values`: those extra rows belong to no slot and would
88
+ * otherwise be lost. Consumers pairing a load with its station read
89
+ * `entries[i].location`, never this list.
90
+ */
91
+ locations?: number[][];
92
+ /**
93
+ * True when a bound of this reader — the depth cap, the node budget, or the
94
+ * cycle guard — dropped a slot in this configuration or anywhere beneath it.
95
+ * It separates "the file holds no more" from "we stopped reading", which a
96
+ * truncated tree otherwise reports identically to a genuinely small one.
97
+ */
98
+ truncated: boolean;
99
+ }
100
+ /** An `IfcBoundaryCondition` leaf reduced to its named stiffness components. */
101
+ export interface BoundaryConditionInfo {
102
+ expressId: number;
103
+ /** Canonical EXPRESS type name, e.g. `IfcBoundaryNodeCondition`. */
104
+ type: string;
105
+ name?: string;
106
+ /**
107
+ * Stiffness components keyed by their exact EXPRESS attribute name
108
+ * (`TranslationalStiffnessX`, `RotationalStiffnessZ`, …).
109
+ *
110
+ * The value is a number when the file gives a stiffness magnitude, and a
111
+ * boolean when it uses the select's `IfcBoolean` branch — which is how a
112
+ * fully fixed or fully free degree of freedom is written (`.T.` = fixed).
113
+ * Collapsing the boolean branch to a number would report a rigid support as
114
+ * stiffness 1.
115
+ */
116
+ components: Record<string, number | boolean>;
117
+ }
118
+ /**
119
+ * Read one `IfcStructuralLoad` entity by expressId, resolving an
120
+ * `IfcStructuralLoadConfiguration` down through the loads its `Values` name.
121
+ *
122
+ * The `Values` edge is the only recursive one here, and it is
123
+ * exporter-controlled, so it is bounded three ways — none of which is
124
+ * redundant:
125
+ *
126
+ * - a **path-local** cycle set stops a configuration that reaches itself. It
127
+ * has to be path-local rather than shared across siblings, because `Values`
128
+ * is a LIST and may legitimately name one load twice; a shared set would
129
+ * suppress the repeat as if it were a cycle and report one load where the
130
+ * file applies two.
131
+ * - a **depth cap** bounds one chain's length, which the cycle set alone does
132
+ * not for a long acyclic chain.
133
+ * - a **node budget** bounds total work. The first two still admit `k`
134
+ * children each recursing `k` deep, which is O(k^depth) — an abort turned
135
+ * into a hang, and a hang reports nothing.
136
+ *
137
+ * All three bounds, and every reference this reader cannot follow for the
138
+ * file's own reasons, keep the `Values` slot they gave up on: the slot becomes
139
+ * an entry with no `value` and a `dropped` reason naming which it was, so
140
+ * the station a `Locations` row names still belongs to the load the file put
141
+ * there. Only the three bounds set `truncated`, since only they mean the file
142
+ * holds more than this reader agreed to walk.
143
+ */
144
+ export declare function extractStructuralLoad(extractor: EntityExtractor, store: IfcDataStore, expressId: number): StructuralLoadInfo | undefined;
145
+ /** Read one `IfcBoundaryCondition` entity by expressId. */
146
+ export declare function extractBoundaryCondition(extractor: EntityExtractor, store: IfcDataStore, expressId: number): BoundaryConditionInfo | undefined;
147
+ //# sourceMappingURL=structural-load-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural-load-extractor.d.ts","sourceRoot":"","sources":["../src/structural-load-extractor.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAkBzD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,+BAA+B,CAAC;CACjD;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB;AAClC,2EAA2E;AACzE,OAAO;AACT,oEAAoE;GAClE,OAAO;AACT,0EAA0E;GACxE,QAAQ;AACV,4EAA4E;GAC1E,mBAAmB;AACrB,sEAAsE;GACpE,YAAY;AACd,0DAA0D;GACxD,YAAY,CAAC;AAEjB,mFAAmF;AACnF,MAAM,WAAW,gCAAgC;IAC/C,+DAA+D;IAC/D,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,uEAAuE;IACvE,OAAO,CAAC,EAAE,wBAAwB,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,4EAA4E;AAC5E,MAAM,WAAW,+BAA+B;IAC9C;;;;;;;OAOG;IACH,OAAO,EAAE,gCAAgC,EAAE,CAAC;IAC5C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACvB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CAC9C;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,kBAAkB,GAAG,SAAS,CAEhC;AA8FD,2DAA2D;AAC3D,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,GAChB,qBAAqB,GAAG,SAAS,CA0BnC"}
@@ -0,0 +1,178 @@
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 { getAttributeNames, normalizeIfcTypeName } from './ifc-schema.js';
5
+ import { asBoolean, asNumber, asString } from './structural-step-values.js';
6
+ /** Attributes that every load/condition carries from its supertype, not a component. */
7
+ const NAME_ATTR = 'Name';
8
+ /**
9
+ * `IfcStructuralLoadConfiguration` positional attributes. Named here rather
10
+ * than resolved by name because this is the one load whose components are
11
+ * references and lists instead of measures.
12
+ */
13
+ const LOAD_CONFIGURATION_ATTR = {
14
+ Name: 0,
15
+ Values: 1,
16
+ Locations: 2,
17
+ };
18
+ /**
19
+ * Read the `Locations` attribute of an `IfcStructuralLoadConfiguration`: a
20
+ * list of 1..2-element lists of `IfcLengthMeasure`.
21
+ */
22
+ function readLocations(value) {
23
+ if (!Array.isArray(value))
24
+ return undefined;
25
+ // A flat scalar list (`(0.,4.5)` instead of `((0.),(4.5))`) is unusable as
26
+ // a whole. Otherwise keep one row per slot so `Values[i]` still pairs with
27
+ // `Locations[i]`: a `$` row or a row with a non-numeric cell becomes an
28
+ // EMPTY placeholder rather than being dropped (which would shift every
29
+ // later row onto the wrong slot) or compacted.
30
+ if (!value.some((row) => Array.isArray(row)))
31
+ return undefined;
32
+ return value.map((row) => {
33
+ if (!Array.isArray(row))
34
+ return [];
35
+ const nums = row.map(asNumber);
36
+ return nums.every((n) => n !== undefined) ? nums : [];
37
+ });
38
+ }
39
+ /** Longest chain of nested configurations followed before giving up. */
40
+ const MAX_LOAD_DEPTH = 4;
41
+ /** Ceiling on entities expanded by one top-level load read. */
42
+ const MAX_LOAD_NODES = 256;
43
+ /**
44
+ * Read one `IfcStructuralLoad` entity by expressId, resolving an
45
+ * `IfcStructuralLoadConfiguration` down through the loads its `Values` name.
46
+ *
47
+ * The `Values` edge is the only recursive one here, and it is
48
+ * exporter-controlled, so it is bounded three ways — none of which is
49
+ * redundant:
50
+ *
51
+ * - a **path-local** cycle set stops a configuration that reaches itself. It
52
+ * has to be path-local rather than shared across siblings, because `Values`
53
+ * is a LIST and may legitimately name one load twice; a shared set would
54
+ * suppress the repeat as if it were a cycle and report one load where the
55
+ * file applies two.
56
+ * - a **depth cap** bounds one chain's length, which the cycle set alone does
57
+ * not for a long acyclic chain.
58
+ * - a **node budget** bounds total work. The first two still admit `k`
59
+ * children each recursing `k` deep, which is O(k^depth) — an abort turned
60
+ * into a hang, and a hang reports nothing.
61
+ *
62
+ * All three bounds, and every reference this reader cannot follow for the
63
+ * file's own reasons, keep the `Values` slot they gave up on: the slot becomes
64
+ * an entry with no `value` and a `dropped` reason naming which it was, so
65
+ * the station a `Locations` row names still belongs to the load the file put
66
+ * there. Only the three bounds set `truncated`, since only they mean the file
67
+ * holds more than this reader agreed to walk.
68
+ */
69
+ export function extractStructuralLoad(extractor, store, expressId) {
70
+ return readLoad(extractor, store, expressId, new Set(), { remaining: MAX_LOAD_NODES }, 0).value;
71
+ }
72
+ function readLoad(extractor, store, expressId, path, budget, depth) {
73
+ if (depth > MAX_LOAD_DEPTH)
74
+ return { dropped: 'depth', truncated: true };
75
+ if (path.has(expressId))
76
+ return { dropped: 'cycle', truncated: true };
77
+ if (budget.remaining <= 0)
78
+ return { dropped: 'budget', truncated: true };
79
+ const ref = store.entityIndex.byId.get(expressId);
80
+ if (!ref)
81
+ return { dropped: 'unresolved', truncated: false };
82
+ const entity = extractor.extractEntity(ref);
83
+ if (!entity)
84
+ return { dropped: 'unreadable', truncated: false };
85
+ budget.remaining--;
86
+ const type = normalizeIfcTypeName(entity.type);
87
+ const attrs = entity.attributes || [];
88
+ if (type.toUpperCase() === 'IFCSTRUCTURALLOADCONFIGURATION') {
89
+ const locations = readLocations(attrs[LOAD_CONFIGURATION_ATTR.Locations]);
90
+ const entries = [];
91
+ let truncated = false;
92
+ const values = attrs[LOAD_CONFIGURATION_ATTR.Values];
93
+ if (Array.isArray(values)) {
94
+ // On this node's path only — removed again below so a sibling that
95
+ // names the same load still reads it.
96
+ path.add(expressId);
97
+ for (let i = 0; i < values.length; i++) {
98
+ const v = values[i];
99
+ const row = locations?.[i];
100
+ const location = row && row.length > 0 ? row : undefined; // empty = placeholder for an unusable row
101
+ const slot = typeof v === 'number' && Number.isInteger(v) && v > 0
102
+ ? readLoad(extractor, store, v, path, budget, depth + 1)
103
+ : { dropped: 'invalid-reference', truncated: false };
104
+ if (slot.truncated)
105
+ truncated = true;
106
+ entries.push({ value: slot.value, dropped: slot.dropped, location });
107
+ }
108
+ path.delete(expressId);
109
+ }
110
+ return {
111
+ value: {
112
+ expressId,
113
+ type,
114
+ name: asString(attrs[LOAD_CONFIGURATION_ATTR.Name]),
115
+ components: {},
116
+ configuration: { entries, locations, truncated },
117
+ },
118
+ truncated,
119
+ };
120
+ }
121
+ return {
122
+ value: {
123
+ expressId,
124
+ type,
125
+ name: asString(attrs[0]),
126
+ components: readNumericComponents(type, attrs),
127
+ },
128
+ truncated: false,
129
+ };
130
+ }
131
+ /**
132
+ * Every attribute the registry names for `type`, except the inherited `Name`,
133
+ * that the record carries a finite number for.
134
+ */
135
+ function readNumericComponents(type, attrs) {
136
+ const components = {};
137
+ const names = getAttributeNames(type);
138
+ for (let i = 0; i < names.length; i++) {
139
+ const attrName = names[i];
140
+ if (attrName === NAME_ATTR)
141
+ continue;
142
+ const n = asNumber(attrs[i]);
143
+ if (n !== undefined)
144
+ components[attrName] = n;
145
+ }
146
+ return components;
147
+ }
148
+ /** Read one `IfcBoundaryCondition` entity by expressId. */
149
+ export function extractBoundaryCondition(extractor, store, expressId) {
150
+ const ref = store.entityIndex.byId.get(expressId);
151
+ if (!ref)
152
+ return undefined;
153
+ const entity = extractor.extractEntity(ref);
154
+ if (!entity)
155
+ return undefined;
156
+ const type = normalizeIfcTypeName(entity.type);
157
+ const attrs = entity.attributes || [];
158
+ const components = {};
159
+ const names = getAttributeNames(type);
160
+ for (let i = 0; i < names.length; i++) {
161
+ const attrName = names[i];
162
+ if (attrName === NAME_ATTR)
163
+ continue;
164
+ // The stiffness selects admit either a measure or IfcBoolean; read the
165
+ // boolean branch first, since a bare `.T.` would not survive the numeric
166
+ // test and a number is never a valid boolean token.
167
+ const b = asBoolean(attrs[i]);
168
+ if (b !== undefined) {
169
+ components[attrName] = b;
170
+ continue;
171
+ }
172
+ const n = asNumber(attrs[i]);
173
+ if (n !== undefined)
174
+ components[attrName] = n;
175
+ }
176
+ return { expressId, type, name: asString(attrs[0]), components };
177
+ }
178
+ //# sourceMappingURL=structural-load-extractor.js.map