@ifc-lite/cli 0.26.0 → 0.27.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 (128) hide show
  1. package/dist/commands/ask.d.ts +8 -0
  2. package/dist/commands/ask.d.ts.map +1 -1
  3. package/dist/commands/ask.js +10 -9
  4. package/dist/commands/ask.js.map +1 -1
  5. package/dist/commands/bsdd.d.ts.map +1 -1
  6. package/dist/commands/bsdd.js +49 -13
  7. package/dist/commands/bsdd.js.map +1 -1
  8. package/dist/commands/diff-classification-label.d.ts +12 -0
  9. package/dist/commands/diff-classification-label.d.ts.map +1 -0
  10. package/dist/commands/diff-classification-label.js +20 -0
  11. package/dist/commands/diff-classification-label.js.map +1 -0
  12. package/dist/commands/diff-engine.d.ts.map +1 -1
  13. package/dist/commands/diff-engine.js +33 -11
  14. package/dist/commands/diff-engine.js.map +1 -1
  15. package/dist/commands/diff-test-helpers.d.ts +12 -0
  16. package/dist/commands/diff-test-helpers.d.ts.map +1 -1
  17. package/dist/commands/diff-test-helpers.js +68 -0
  18. package/dist/commands/diff-test-helpers.js.map +1 -1
  19. package/dist/commands/diff-unit-scale-fixtures.d.ts +34 -0
  20. package/dist/commands/diff-unit-scale-fixtures.d.ts.map +1 -0
  21. package/dist/commands/diff-unit-scale-fixtures.js +94 -0
  22. package/dist/commands/diff-unit-scale-fixtures.js.map +1 -0
  23. package/dist/commands/export.d.ts +11 -0
  24. package/dist/commands/export.d.ts.map +1 -1
  25. package/dist/commands/export.js +9 -14
  26. package/dist/commands/export.js.map +1 -1
  27. package/dist/commands/merge.d.ts.map +1 -1
  28. package/dist/commands/merge.js +8 -0
  29. package/dist/commands/merge.js.map +1 -1
  30. package/dist/commands/query-aggregation.d.ts +27 -4
  31. package/dist/commands/query-aggregation.d.ts.map +1 -1
  32. package/dist/commands/query-aggregation.js +67 -6
  33. package/dist/commands/query-aggregation.js.map +1 -1
  34. package/dist/commands/query-output.d.ts +7 -0
  35. package/dist/commands/query-output.d.ts.map +1 -1
  36. package/dist/commands/query-output.js +63 -27
  37. package/dist/commands/query-output.js.map +1 -1
  38. package/dist/commands/query-storey.d.ts +24 -0
  39. package/dist/commands/query-storey.d.ts.map +1 -0
  40. package/dist/commands/query-storey.js +71 -0
  41. package/dist/commands/query-storey.js.map +1 -0
  42. package/dist/commands/query.d.ts +2 -25
  43. package/dist/commands/query.d.ts.map +1 -1
  44. package/dist/commands/query.js +39 -158
  45. package/dist/commands/query.js.map +1 -1
  46. package/dist/commands/schedule-aggregate.d.ts +51 -0
  47. package/dist/commands/schedule-aggregate.d.ts.map +1 -0
  48. package/dist/commands/schedule-aggregate.js +121 -0
  49. package/dist/commands/schedule-aggregate.js.map +1 -0
  50. package/dist/commands/schedule-columns.d.ts +15 -0
  51. package/dist/commands/schedule-columns.d.ts.map +1 -0
  52. package/dist/commands/schedule-columns.js +63 -0
  53. package/dist/commands/schedule-columns.js.map +1 -0
  54. package/dist/commands/schedule-group.d.ts +65 -0
  55. package/dist/commands/schedule-group.d.ts.map +1 -0
  56. package/dist/commands/schedule-group.js +0 -0
  57. package/dist/commands/schedule-group.js.map +1 -0
  58. package/dist/commands/schedule-presets.d.ts +21 -0
  59. package/dist/commands/schedule-presets.d.ts.map +1 -0
  60. package/dist/commands/schedule-presets.js +62 -0
  61. package/dist/commands/schedule-presets.js.map +1 -0
  62. package/dist/commands/schedule-render-html.d.ts +13 -0
  63. package/dist/commands/schedule-render-html.d.ts.map +1 -0
  64. package/dist/commands/schedule-render-html.js +100 -0
  65. package/dist/commands/schedule-render-html.js.map +1 -0
  66. package/dist/commands/schedule-render-md.d.ts +12 -0
  67. package/dist/commands/schedule-render-md.d.ts.map +1 -0
  68. package/dist/commands/schedule-render-md.js +77 -0
  69. package/dist/commands/schedule-render-md.js.map +1 -0
  70. package/dist/commands/schedule-render.d.ts +51 -0
  71. package/dist/commands/schedule-render.d.ts.map +1 -0
  72. package/dist/commands/schedule-render.js +205 -0
  73. package/dist/commands/schedule-render.js.map +1 -0
  74. package/dist/commands/schedule-spec.d.ts +29 -0
  75. package/dist/commands/schedule-spec.d.ts.map +1 -0
  76. package/dist/commands/schedule-spec.js +111 -0
  77. package/dist/commands/schedule-spec.js.map +1 -0
  78. package/dist/commands/schedule.d.ts +23 -0
  79. package/dist/commands/schedule.d.ts.map +1 -0
  80. package/dist/commands/schedule.js +249 -0
  81. package/dist/commands/schedule.js.map +1 -0
  82. package/dist/commands/schema.d.ts.map +1 -1
  83. package/dist/commands/schema.js +192 -17
  84. package/dist/commands/schema.js.map +1 -1
  85. package/dist/commands/stats-aggregation.d.ts +31 -6
  86. package/dist/commands/stats-aggregation.d.ts.map +1 -1
  87. package/dist/commands/stats-aggregation.js +79 -11
  88. package/dist/commands/stats-aggregation.js.map +1 -1
  89. package/dist/commands/stats.d.ts.map +1 -1
  90. package/dist/commands/stats.js +4 -4
  91. package/dist/commands/stats.js.map +1 -1
  92. package/dist/commands/validate.d.ts +7 -4
  93. package/dist/commands/validate.d.ts.map +1 -1
  94. package/dist/commands/validate.js +9 -6
  95. package/dist/commands/validate.js.map +1 -1
  96. package/dist/commands/where-filter.d.ts +42 -0
  97. package/dist/commands/where-filter.d.ts.map +1 -0
  98. package/dist/commands/where-filter.js +88 -0
  99. package/dist/commands/where-filter.js.map +1 -0
  100. package/dist/energy-export.d.ts.map +1 -1
  101. package/dist/energy-export.js +12 -2
  102. package/dist/energy-export.js.map +1 -1
  103. package/dist/geometry-report.d.ts.map +1 -1
  104. package/dist/geometry-report.js +15 -3
  105. package/dist/geometry-report.js.map +1 -1
  106. package/dist/headless-backend.d.ts +20 -5
  107. package/dist/headless-backend.d.ts.map +1 -1
  108. package/dist/headless-backend.js +131 -90
  109. package/dist/headless-backend.js.map +1 -1
  110. package/dist/index.js +22 -0
  111. package/dist/index.js.map +1 -1
  112. package/dist/output.d.ts +13 -0
  113. package/dist/output.d.ts.map +1 -1
  114. package/dist/output.js +21 -0
  115. package/dist/output.js.map +1 -1
  116. package/dist/property-filter-match.d.ts +12 -0
  117. package/dist/property-filter-match.d.ts.map +1 -0
  118. package/dist/property-filter-match.js +17 -0
  119. package/dist/property-filter-match.js.map +1 -0
  120. package/dist/query-overlay-relations.d.ts +29 -0
  121. package/dist/query-overlay-relations.d.ts.map +1 -0
  122. package/dist/query-overlay-relations.js +88 -0
  123. package/dist/query-overlay-relations.js.map +1 -0
  124. package/dist/query-overlay.d.ts +44 -0
  125. package/dist/query-overlay.d.ts.map +1 -0
  126. package/dist/query-overlay.js +100 -0
  127. package/dist/query-overlay.js.map +1 -0
  128. package/package.json +21 -21
@@ -0,0 +1,23 @@
1
+ import { type ScheduleColumn } from './schedule-columns.js';
2
+ import { type ScheduleRow } from './schedule-render.js';
3
+ /**
4
+ * Resolve one column path against one entity.
5
+ *
6
+ * A `Set.Member` path (and the five native attributes) goes through the shared
7
+ * `resolveColumnValue` the `export` command uses, so schedule columns inherit
8
+ * its type-inheritance / same-named-pset / complex-property behaviour and agree
9
+ * with `--where`. A plain attribute name the shared resolver does not treat as
10
+ * native (e.g. `Tag`, `PredefinedType`) is then read from the canonical
11
+ * entity-attribute list — the same surface `query --attributes` exposes — so a
12
+ * missing value stays `null`.
13
+ */
14
+ export declare function resolveScheduleValue(entity: any, path: string, bim: any): unknown;
15
+ /**
16
+ * Build one row per entity, resolving every declared column. Reads
17
+ * properties/quantities/attributes/materials at most once per entity
18
+ * (see `memoizedColumnAccessors`) — measured 5.6x on FM_ARC_DigitalHub,
19
+ * 6 columns: 40.6ms -> 7.2ms per row build.
20
+ */
21
+ export declare function buildScheduleRows(entities: any[], columns: ScheduleColumn[], bim: any): ScheduleRow[];
22
+ export declare function scheduleCommand(args: string[]): Promise<void>;
23
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/commands/schedule.ts"],"names":[],"mappings":"AAmDA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAW9B;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CA2DjF;AAgCD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,GAAG,GAAG,WAAW,EAAE,CAGrG;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiHnE"}
@@ -0,0 +1,249 @@
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
+ * ifc-lite schedule <file.ifc> [--preset <name>] --type <IfcClass>
6
+ * --columns "<Header>=<path>[, ...]"
7
+ * [--where "<expr>"] [--sort "<Header>[:asc|desc][, ...]"]
8
+ * [--group-by "<Header>[, ...]"]
9
+ * [--subtotals "<agg>[, ...]"] [--format csv|json|md|html]
10
+ * [--spec <file.json>] [--save <file.json>]
11
+ *
12
+ * `--preset door|window|space|wall|material-takeoff` supplies a default
13
+ * `--type` and `--columns` (and, for some presets, a default group-by/sort/
14
+ * subtotals) so a common schedule runs with no other flags. An explicit flag of
15
+ * the same name overrides the preset's default; `--where`/`--format` apply as
16
+ * normal. See `schedule-presets.ts`.
17
+ *
18
+ * `--spec <file.json>` loads a saved schedule definition (see
19
+ * `schedule-spec.ts`) supplying the same defaults a preset would (lower
20
+ * priority than an explicit flag, higher priority than `--preset`); `--save
21
+ * <file.json>` writes the definition this invocation resolved to — after any
22
+ * `--preset`/`--spec` defaults are folded in — so it can be re-run later with
23
+ * `--spec` alone. A spec that names an unresolvable preset, isn't valid JSON,
24
+ * or is missing both `type` and `preset` is a `fatal(...)`, never a silent
25
+ * empty schedule.
26
+ *
27
+ * Produce a tabular schedule of one IFC class: pick the entities of `--type`,
28
+ * (optionally) narrow them with the same `--where` filter `query` uses, and
29
+ * emit one row per entity with the requested columns. A column path is a plain
30
+ * attribute name, a `PsetName.PropName`, or a `QtoName.QtyName`, resolved
31
+ * through the SAME resolver the `export` command uses so schedule columns and
32
+ * query filters agree on type-inheritance / same-named-pset / complex-property
33
+ * behaviour. `--format md` emits a GFM table; `--format html` emits a
34
+ * standalone HTML document — both lay out `--group-by`/`--subtotals` rows
35
+ * identically to CSV/JSON (see `schedule-render-md.ts`/`schedule-render-html.ts`)
36
+ * and escape cell text for their format (`|`/newline for Markdown;
37
+ * `&`/`<`/`>`/quotes for HTML — model text is untrusted).
38
+ *
39
+ * `--sort`, `--group-by` and `--subtotals` all name column HEADERS (never
40
+ * paths); a header that is not among `--columns` is a `fatal(...)`. Rows are
41
+ * ordered by group first (so each group is contiguous) then by the remaining
42
+ * sort keys, with the original entity order as the stable tiebreaker.
43
+ * `--subtotals` emits a subtotal row after each group and a grand-total row;
44
+ * without `--group-by` it emits only the grand total.
45
+ */
46
+ import { createHeadlessContext } from '../loader.js';
47
+ import { getFlag, fatal, printJson, firstNonBlank, isBlank } from '../output.js';
48
+ import { normalizeTypeName, parseWhereFilter, applyWhereFilter } from './query.js';
49
+ import { resolveColumnValue } from './export.js';
50
+ import { parseColumnSpec } from './schedule-columns.js';
51
+ import { renderScheduleCsv, renderScheduleJson, renderScheduleCsvWithSubtotals, renderScheduleJsonWithSubtotals, } from './schedule-render.js';
52
+ import { renderScheduleMarkdown, renderScheduleMarkdownWithSubtotals } from './schedule-render-md.js';
53
+ import { renderScheduleHtml, renderScheduleHtmlWithSubtotals } from './schedule-render-html.js';
54
+ import { parseSortSpec, parseGroupBySpec, orderRows } from './schedule-group.js';
55
+ import { parseSubtotalsSpec, buildSubtotalPlan } from './schedule-aggregate.js';
56
+ import { resolvePreset } from './schedule-presets.js';
57
+ import { loadScheduleSpec, saveScheduleSpec } from './schedule-spec.js';
58
+ const FORMATS = ['csv', 'json', 'md', 'html'];
59
+ /**
60
+ * Resolve one column path against one entity.
61
+ *
62
+ * A `Set.Member` path (and the five native attributes) goes through the shared
63
+ * `resolveColumnValue` the `export` command uses, so schedule columns inherit
64
+ * its type-inheritance / same-named-pset / complex-property behaviour and agree
65
+ * with `--where`. A plain attribute name the shared resolver does not treat as
66
+ * native (e.g. `Tag`, `PredefinedType`) is then read from the canonical
67
+ * entity-attribute list — the same surface `query --attributes` exposes — so a
68
+ * missing value stays `null`.
69
+ */
70
+ export function resolveScheduleValue(entity, path, bim) {
71
+ // `Material` is a pseudo-column: resolve the element's associated material
72
+ // name through the same fallback chain `packages/mcp/src/material-naming.ts`
73
+ // `materialFallbackName` applies (duplicated locally the same way
74
+ // `firstNonBlank`/`isBlank` already are in `output.ts` — a cross-package
75
+ // import would widen `@ifc-lite/mcp`'s public surface for one helper). A
76
+ // plain `.name`/`.materials[0]` pair (the pre-fix behaviour) only covers a
77
+ // bare `IfcMaterial` or `IfcMaterialList`: the normal `IfcWall` shape is a
78
+ // `MaterialLayerSet` with no top-level `LayerSetName`, whose real name
79
+ // lives on `layers[]`/`profiles[]`/`constituents[]` — reading only
80
+ // `.name`/`.materials[0]` returns `null` for every such wall, and
81
+ // `--preset material-takeoff`'s default `--group-by Material` collapses
82
+ // them into one unlabelled group instead of one group per real material.
83
+ // A whitespace-only leaf name falls through the same way (#3714's family),
84
+ // and a fully blank result renders `(no material)` — the same placeholder
85
+ // `query --group-by material` uses — rather than a silent empty cell, so a
86
+ // group-by/subtotal on `Material` buckets blank elements together under a
87
+ // readable label instead of splitting on `null` vs `''` vs whitespace.
88
+ if (path === 'Material') {
89
+ const mat = bim.materials(entity.ref);
90
+ if (!mat)
91
+ return '(no material)';
92
+ return (firstNonBlank(mat.name, mat.materials?.[0]?.name, mat.layers?.find(l => !isBlank(l.materialName))?.materialName, mat.profiles?.find(p => !isBlank(p.materialName))?.materialName, mat.constituents?.find(c => !isBlank(c.materialName))?.materialName) ?? '(no material)');
93
+ }
94
+ // A dot-free path checks the canonical entity-attribute list FIRST.
95
+ // resolveColumnValue's own bare-name fallback (below) sweeps EVERY property
96
+ // and quantity set for a member with that literal name — a user-authored
97
+ // pset property that happens to share a schema attribute's name (e.g. a
98
+ // "Tag" property in some custom Pset) would otherwise shadow the real
99
+ // IfcDoor.Tag attribute that a column like --preset door's `Mark=Tag`
100
+ // means. A dotted `Pset.Prop`/`Qto.Qty` path is unambiguous and always
101
+ // goes straight through resolveColumnValue.
102
+ if (!path.includes('.')) {
103
+ const attrs = bim.attributes(entity.ref);
104
+ const hit = attrs.find(a => a.name === path);
105
+ if (hit && hit.value != null)
106
+ return hit.value;
107
+ }
108
+ const viaColumn = resolveColumnValue(entity, path, bim);
109
+ if (viaColumn != null)
110
+ return viaColumn;
111
+ return null;
112
+ }
113
+ /** Wrap a single-argument function so a repeated call with the SAME argument (by `===`) is served from cache instead of re-invoked. */
114
+ function memoize(fn) {
115
+ const cache = new Map();
116
+ return (arg) => {
117
+ const hit = cache.get(arg);
118
+ if (hit !== undefined || cache.has(arg))
119
+ return hit;
120
+ const result = fn(arg);
121
+ cache.set(arg, result);
122
+ return result;
123
+ };
124
+ }
125
+ /**
126
+ * Wrap `bim` so `properties`/`quantities`/`attributes`/`materials` — the only
127
+ * four methods `resolveScheduleValue` (and the `resolveColumnValue` it
128
+ * delegates to) ever call — are read at most ONCE per entity ref for the
129
+ * whole schedule, however many `--columns` request them. Resolving each
130
+ * column independently means an N-column row calls e.g. `bim.properties(ref)`
131
+ * N times for the identical entity, re-walking the same property-set list
132
+ * from scratch each time.
133
+ */
134
+ function memoizedColumnAccessors(bim) {
135
+ return {
136
+ properties: memoize((ref) => bim.properties(ref)),
137
+ quantities: memoize((ref) => bim.quantities(ref)),
138
+ attributes: memoize((ref) => bim.attributes(ref)),
139
+ materials: memoize((ref) => bim.materials(ref)),
140
+ };
141
+ }
142
+ /**
143
+ * Build one row per entity, resolving every declared column. Reads
144
+ * properties/quantities/attributes/materials at most once per entity
145
+ * (see `memoizedColumnAccessors`) — measured 5.6x on FM_ARC_DigitalHub,
146
+ * 6 columns: 40.6ms -> 7.2ms per row build.
147
+ */
148
+ export function buildScheduleRows(entities, columns, bim) {
149
+ const cached = memoizedColumnAccessors(bim);
150
+ return entities.map((e) => columns.map(col => resolveScheduleValue(e, col.path, cached)));
151
+ }
152
+ export async function scheduleCommand(args) {
153
+ const filePath = args.find(a => !a.startsWith('-'));
154
+ if (!filePath) {
155
+ fatal('Usage: ifc-lite schedule <file.ifc> --type IfcDoor --columns "Name=Name, Mark=Pset_DoorCommon.Reference" [--where PsetName.Prop=Value] [--format csv|json]');
156
+ }
157
+ // --spec loads a saved definition (see schedule-spec.ts); its fields sit
158
+ // between an explicit flag (wins) and a --preset default (loses) in
159
+ // precedence, whether the preset comes from --preset or the spec's own
160
+ // "preset" field.
161
+ const specPath = getFlag(args, '--spec');
162
+ const spec = specPath ? await loadScheduleSpec(specPath) : undefined;
163
+ // --preset supplies default type/columns (and optionally group-by/sort/
164
+ // subtotals); an explicit flag of the same name overrides the preset default.
165
+ const presetName = getFlag(args, '--preset') ?? spec?.preset;
166
+ const preset = presetName ? resolvePreset(presetName) : undefined;
167
+ const typeRaw = getFlag(args, '--type') ?? spec?.type ?? preset?.type;
168
+ if (!typeRaw) {
169
+ fatal('--type is required (or pass --preset/--spec), e.g. --type IfcDoor or --preset door');
170
+ }
171
+ const type = normalizeTypeName(typeRaw);
172
+ const columnsSpec = getFlag(args, '--columns') ?? spec?.columns ?? preset?.columns;
173
+ const columns = parseColumnSpec(columnsSpec);
174
+ const format = (getFlag(args, '--format') ?? spec?.format ?? 'csv').toLowerCase();
175
+ if (!FORMATS.includes(format)) {
176
+ fatal(`Unknown --format "${format}". Expected ${FORMATS.join(', ')}.`);
177
+ }
178
+ const whereFilter = getFlag(args, '--where') ?? spec?.where;
179
+ // --sort / --group-by / --subtotals name declared column HEADERS; an unknown
180
+ // header is a fatal(...) with the valid headers listed (raised during parse).
181
+ const sortSpec = getFlag(args, '--sort') ?? spec?.sort ?? preset?.sort;
182
+ const groupBySpec = getFlag(args, '--group-by') ?? spec?.groupBy ?? preset?.groupBy;
183
+ const subtotalsSpec = getFlag(args, '--subtotals') ?? spec?.subtotals ?? preset?.subtotals;
184
+ const sortKeys = parseSortSpec(sortSpec, columns);
185
+ const groupKeys = parseGroupBySpec(groupBySpec, columns);
186
+ const subtotalAggs = parseSubtotalsSpec(subtotalsSpec, columns);
187
+ // --save's target path is captured here (so --save itself is validated up
188
+ // front, same as every other flag) but the file is written only once this
189
+ // run has actually succeeded — see below.
190
+ const savePath = getFlag(args, '--save');
191
+ const { bim } = await createHeadlessContext(filePath);
192
+ let entities = bim.query().byType(...type.split(',')).toArray();
193
+ // --where reuses the exact query filter (property sets + quantity fallback).
194
+ if (whereFilter) {
195
+ const parsed = parseWhereFilter(whereFilter);
196
+ entities = applyWhereFilter(entities, parsed, bim);
197
+ }
198
+ // One row per entity, in entity order — the stable tiebreaker for ordering.
199
+ let rows = buildScheduleRows(entities, columns, bim);
200
+ // Order once, after row assembly: groups contiguous, then remaining sort keys.
201
+ if (sortKeys.length > 0 || groupKeys.length > 0) {
202
+ rows = orderRows(rows, sortKeys, groupKeys);
203
+ }
204
+ // --save persists the definition this invocation actually resolved to
205
+ // (after --preset/--spec defaults are folded in), so the written file is
206
+ // self-contained and reloadable with --spec alone. Written only here, once
207
+ // --type/--where/--sort/--group-by/--subtotals have all parsed AND the
208
+ // input file has loaded successfully — writing it any earlier (its
209
+ // original position, before --where was even parsed and before the input
210
+ // file was opened) could persist a broken spec despite the run's own
211
+ // non-zero exit.
212
+ if (savePath) {
213
+ await saveScheduleSpec(savePath, {
214
+ type, columns: columnsSpec, where: whereFilter,
215
+ sort: sortSpec, groupBy: groupBySpec, subtotals: subtotalsSpec, format,
216
+ });
217
+ }
218
+ if (subtotalAggs.length > 0) {
219
+ const plan = buildSubtotalPlan(rows, groupKeys, subtotalAggs);
220
+ if (format === 'json') {
221
+ printJson(renderScheduleJsonWithSubtotals(columns, plan));
222
+ return;
223
+ }
224
+ if (format === 'md') {
225
+ process.stdout.write(renderScheduleMarkdownWithSubtotals(columns, plan) + '\n');
226
+ return;
227
+ }
228
+ if (format === 'html') {
229
+ process.stdout.write(renderScheduleHtmlWithSubtotals(columns, plan));
230
+ return;
231
+ }
232
+ process.stdout.write(renderScheduleCsvWithSubtotals(columns, plan) + '\n');
233
+ return;
234
+ }
235
+ if (format === 'json') {
236
+ printJson(renderScheduleJson(columns, rows));
237
+ return;
238
+ }
239
+ if (format === 'md') {
240
+ process.stdout.write(renderScheduleMarkdown(columns, rows) + '\n');
241
+ return;
242
+ }
243
+ if (format === 'html') {
244
+ process.stdout.write(renderScheduleHtml(columns, rows));
245
+ return;
246
+ }
247
+ process.stdout.write(renderScheduleCsv(columns, rows) + '\n');
248
+ }
249
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/commands/schedule.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAaA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDjE"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAmNA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDjE"}
@@ -7,7 +7,194 @@
7
7
  * Dump the complete SDK API schema as JSON.
8
8
  * Useful for LLM tools to discover available commands and methods.
9
9
  */
10
+ import { BimContext, QueryBuilder } from '@ifc-lite/sdk';
10
11
  import { printJson, hasFlag } from '../output.js';
12
+ /**
13
+ * Doc strings for the `BimContext` / `QueryBuilder` methods that
14
+ * `NAMESPACE_SCHEMAS` does not name (#3763). Only prose lives here — the
15
+ * method LIST itself is reflected off the runtime classes below, so a method
16
+ * added or removed upstream changes the dump without an edit here, and
17
+ * `schema.runtime-shape.test.ts` fails if the two ever disagree.
18
+ *
19
+ * Keyed per class, like `RUNTIME_METHOD_SIGNATURES` below (#3763 follow-up):
20
+ * `bim` and `query` are reflected off two different prototypes, so a bare
21
+ * name shared between them (there is none today, but nothing prevented it)
22
+ * would otherwise read whichever entry came first.
23
+ */
24
+ const RUNTIME_METHOD_DOCS = {
25
+ bim: {
26
+ query: 'Start a query chain: bim.query().byType(...).toArray()',
27
+ on: 'Subscribe to an event, e.g. bim.on("selection:changed", handler)',
28
+ },
29
+ query: {
30
+ model: 'Restrict the chain to one model',
31
+ byType: "Filter by IFC type e.g. 'IfcWall'",
32
+ where: 'Filter by a property-set value',
33
+ limit: 'Cap the number of results',
34
+ offset: 'Skip the first n results',
35
+ toArray: 'Run the chain and return the entities',
36
+ first: 'Run the chain and return the first entity, or null',
37
+ count: 'Run the chain and return the number of matches',
38
+ refs: 'Run the chain and return entity refs only',
39
+ },
40
+ };
41
+ /**
42
+ * Parameter names and return types for `BimContext` / `QueryBuilder` methods,
43
+ * transcribed from their own signatures in `packages/sdk/src/context.ts` and
44
+ * `packages/sdk/src/namespaces/query.ts` (#3763 follow-up).
45
+ *
46
+ * Keyed per class, not by bare method name: `BimContext` and `QueryBuilder`
47
+ * are reflected separately in `withRuntimeQueryShape`, and a future method
48
+ * that shares a name across both classes (their param/return shapes need not
49
+ * match) would otherwise read the wrong entry silently.
50
+ *
51
+ * `describe()` used to spread the sandbox bridge's own `paramNames`/`tsReturn`
52
+ * onto these methods, with the bridge as a fallback when a method had no
53
+ * entry here. The bridge runs a whole query synchronously and returns plain
54
+ * data (`bim.query.byType(...): BimEntity[]`, `entity(modelId, expressId)`),
55
+ * which is not the shape the CLI's raw `BimContext`/`QueryBuilder` have
56
+ * (`byType(...types): this`, `entity(ref: EntityRef)`) — falling back to it
57
+ * produced a schema entry an agent could follow into a TypeError or a chain
58
+ * that stops one link early. `describe()` now throws instead of falling back,
59
+ * so a new runtime method with no entry here fails the dump loudly (and
60
+ * `schema.runtime-shape.test.ts` with it) rather than shipping mislabelled.
61
+ */
62
+ const RUNTIME_METHOD_SIGNATURES = {
63
+ bim: {
64
+ query: { tsReturn: 'QueryBuilder' },
65
+ matchingActiveFilter: { tsReturn: 'EntityData[] | null' },
66
+ entity: { paramNames: ['ref'], tsReturn: 'EntityData | null' },
67
+ attributes: { paramNames: ['ref'], tsReturn: 'EntityAttributeData[]' },
68
+ properties: { paramNames: ['ref'], tsReturn: 'PropertySetData[]' },
69
+ quantities: { paramNames: ['ref'], tsReturn: 'QuantitySetData[]' },
70
+ classifications: { paramNames: ['ref'], tsReturn: 'ClassificationData[]' },
71
+ materials: { paramNames: ['ref'], tsReturn: 'MaterialData | null' },
72
+ typeProperties: { paramNames: ['ref'], tsReturn: 'TypePropertiesData | null' },
73
+ documents: { paramNames: ['ref'], tsReturn: 'DocumentData[]' },
74
+ relationships: { paramNames: ['ref'], tsReturn: 'EntityRelationshipsData' },
75
+ property: { paramNames: ['ref', 'psetName', 'propName'], tsReturn: 'string | number | boolean | null' },
76
+ quantity: { paramNames: ['ref', 'qsetNameOrQuantityName', 'quantityName?'], tsReturn: 'number | null' },
77
+ related: { paramNames: ['ref', 'relType', 'direction'], tsReturn: 'EntityData[]' },
78
+ containedIn: { paramNames: ['ref'], tsReturn: 'EntityData | null' },
79
+ contains: { paramNames: ['ref'], tsReturn: 'EntityData[]' },
80
+ decomposedBy: { paramNames: ['ref'], tsReturn: 'EntityData | null' },
81
+ decomposes: { paramNames: ['ref'], tsReturn: 'EntityData[]' },
82
+ storey: { paramNames: ['ref'], tsReturn: 'EntityData | null' },
83
+ path: { paramNames: ['ref'], tsReturn: 'EntityData[]' },
84
+ storeys: { tsReturn: 'EntityData[]' },
85
+ on: { paramNames: ['event', 'handler'], tsReturn: 'void' },
86
+ },
87
+ query: {
88
+ model: { paramNames: ['modelId'], tsReturn: 'this' },
89
+ byType: { paramNames: ['...types'], tsReturn: 'this' },
90
+ where: { paramNames: ['psetName', 'propName', 'operator?', 'value?'], tsReturn: 'this' },
91
+ limit: { paramNames: ['n'], tsReturn: 'this' },
92
+ offset: { paramNames: ['n'], tsReturn: 'this' },
93
+ toArray: { tsReturn: 'EntityData[]' },
94
+ first: { tsReturn: 'EntityData | null' },
95
+ count: { tsReturn: 'number' },
96
+ refs: { tsReturn: 'EntityRef[]' },
97
+ },
98
+ };
99
+ /**
100
+ * Own value-function property names on a prototype, minus the constructor,
101
+ * plus getters whose value is itself callable (e.g. `BimContext.prototype.on`,
102
+ * a getter returning a bound subscription function) — the CLI exposes those
103
+ * the same way as a method, so a filter that only checked `.value` silently
104
+ * dropped them from the dump (#3763 follow-up).
105
+ *
106
+ * A getter can't be classified from the prototype alone — invoking it there
107
+ * runs the getter with `this` bound to the bare prototype, not an instance,
108
+ * which is exactly the state `on`'s getter needs (`this._boundOn`, set in
109
+ * the constructor) to return the function rather than `undefined`. `instance`
110
+ * lets a caller supply a real object to invoke the getter against; without
111
+ * one, getters are skipped rather than guessed at.
112
+ */
113
+ function prototypeMethods(proto, instance) {
114
+ return Object.getOwnPropertyNames(proto).filter((name) => {
115
+ if (name === 'constructor')
116
+ return false;
117
+ const desc = Object.getOwnPropertyDescriptor(proto, name);
118
+ if (typeof desc?.value === 'function')
119
+ return true;
120
+ if (typeof desc?.get === 'function' && instance) {
121
+ return typeof instance[name] === 'function';
122
+ }
123
+ return false;
124
+ });
125
+ }
126
+ /**
127
+ * Replace the sandbox bridge's flat `query` namespace with the two shapes the
128
+ * CLI's `bim` object actually has.
129
+ *
130
+ * `NAMESPACE_SCHEMAS` describes the browser sandbox bridge, where
131
+ * `bim.query.properties(ref)` is a real method. `ifc-lite run` / `ifc-lite eval`
132
+ * hand scripts a raw `BimContext` instead: `query()` starts a builder and
133
+ * `properties`, `quantities`, `relationships` and ~19 siblings sit at the top
134
+ * level of `bim`. Emitting the bridge shape here made every `bim.query.X(...)`
135
+ * call an agent copied out of `ifc-lite schema` throw a TypeError (#3763).
136
+ *
137
+ * Method lists are reflected off `BimContext.prototype` and
138
+ * `QueryBuilder.prototype` — the objects `run`/`eval` construct — rather than
139
+ * transcribed, so this cannot drift from the runtime. Params and return types
140
+ * come from `RUNTIME_METHOD_SIGNATURES`, not the bridge schema: the bridge
141
+ * describes its own (different) call shape, and copying its `paramNames` /
142
+ * `tsReturn` here just relabelled the wrong signature (#3763 follow-up).
143
+ *
144
+ * The bridge's `query` namespace (`bridgeQuery` below) is a flat list of the
145
+ * same ~20 entity-lookup methods that sit at the top level of `bim`
146
+ * (`entity`, `properties`, `quantities`, ...). That is the namespace those
147
+ * methods belong to on the bridge, and it is only ever used as a `doc` /
148
+ * `llmSemantics` fallback for the `bim` prototype. It is never consulted for
149
+ * the `query` builder-chain prototype: `QueryBuilder`'s `byType`/`where`/
150
+ * `limit`/… have no counterpart there (the bridge runs a whole chain
151
+ * synchronously instead of building one), so reading `bridgeMethods` by bare
152
+ * name for that prototype could silently attach an unrelated bridge method's
153
+ * doc to a same-named builder method. `RUNTIME_METHOD_DOCS.query` documents
154
+ * every builder method already, so restricting the fallback to `bim` needs
155
+ * no "no entry" carve-out.
156
+ */
157
+ function withRuntimeQueryShape(schemas) {
158
+ const bridgeQuery = schemas.find((ns) => ns?.name === 'query');
159
+ const bridgeMethods = new Map((bridgeQuery?.methods ?? []).map((m) => [m.name, m]));
160
+ const describe = (proto) => (name) => {
161
+ const fromBridge = proto === 'bim' ? bridgeMethods.get(name) : undefined;
162
+ const signature = RUNTIME_METHOD_SIGNATURES[proto][name];
163
+ if (!signature) {
164
+ // A method exists on the runtime prototype but nobody transcribed its
165
+ // signature into RUNTIME_METHOD_SIGNATURES — fail loudly rather than
166
+ // fall back to the bridge's (differently shaped) entry, so a new
167
+ // BimContext/QueryBuilder method cannot ship mislabelled (#3763 follow-up).
168
+ throw new Error(`RUNTIME_METHOD_SIGNATURES.${proto} has no entry for '${name}' — add its ` +
169
+ `paramNames/tsReturn, transcribed from packages/sdk/src/context.ts or ` +
170
+ `packages/sdk/src/namespaces/query.ts.`);
171
+ }
172
+ return {
173
+ doc: RUNTIME_METHOD_DOCS[proto][name] ?? fromBridge?.doc ?? name,
174
+ name,
175
+ paramNames: signature.paramNames,
176
+ tsReturn: signature.tsReturn,
177
+ llmSemantics: fromBridge?.llmSemantics,
178
+ };
179
+ };
180
+ // Constructed only to invoke the `on` getter against real instance state
181
+ // (see `prototypeMethods`) — no backend method is called during
182
+ // construction or by this dump.
183
+ const bimInstance = new BimContext({ backend: {} });
184
+ return [
185
+ {
186
+ name: 'bim',
187
+ doc: 'Top-level methods on the `bim` object (call as bim.<method>(...))',
188
+ methods: prototypeMethods(BimContext.prototype, bimInstance).map(describe('bim')),
189
+ },
190
+ {
191
+ name: 'query',
192
+ doc: 'Query builder chain — start it with bim.query()',
193
+ methods: prototypeMethods(QueryBuilder.prototype).map(describe('query')),
194
+ },
195
+ ...schemas.filter((ns) => ns?.name !== 'query'),
196
+ ];
197
+ }
11
198
  export async function schemaCommand(args) {
12
199
  const compact = hasFlag(args, '--compact');
13
200
  // Dynamically import the bridge schema to get tool definitions
@@ -41,7 +228,7 @@ export async function schemaCommand(args) {
41
228
  // opting out of error handling altogether. stdout stays pure JSON.
42
229
  process.exitCode = 1;
43
230
  }
44
- const output = schemas.map(ns => ({
231
+ const output = withRuntimeQueryShape(schemas).map(ns => ({
45
232
  namespace: ns.name,
46
233
  description: ns.doc,
47
234
  methods: ns.methods.map((m) => {
@@ -74,22 +261,10 @@ function getStaticSchema() {
74
261
  { name: 'activeId', doc: 'Get active model ID' },
75
262
  ],
76
263
  },
77
- {
78
- name: 'query', doc: 'Query entities',
79
- methods: [
80
- { name: 'all', doc: 'Get all entities' },
81
- { name: 'byType', doc: 'Filter by IFC type', paramNames: ['...types'] },
82
- { name: 'entity', doc: 'Get single entity', paramNames: ['modelId', 'expressId'] },
83
- { name: 'attributes', doc: 'Entity IFC attributes', paramNames: ['entity'] },
84
- { name: 'properties', doc: 'Property sets', paramNames: ['entity'] },
85
- { name: 'quantities', doc: 'Quantity sets', paramNames: ['entity'] },
86
- { name: 'classifications', doc: 'Classification references', paramNames: ['entity'] },
87
- { name: 'materials', doc: 'Material assignments', paramNames: ['entity'] },
88
- { name: 'typeProperties', doc: 'Type-level properties', paramNames: ['entity'] },
89
- { name: 'documents', doc: 'Linked documents', paramNames: ['entity'] },
90
- { name: 'relationships', doc: 'Structural relationships', paramNames: ['entity'] },
91
- ],
92
- },
264
+ // No `query` entry: `withRuntimeQueryShape` reflects the `bim` root and
265
+ // the query-builder chain off the SDK classes, on the fallback path too,
266
+ // so a hand-written copy here could only rot (and the one that used to
267
+ // live here documented the sandbox bridge's `bim.query.*`, #3763).
93
268
  {
94
269
  name: 'export', doc: 'Multi-format export',
95
270
  methods: [
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,mBAAmB,GAAmE;IAC1F,GAAG,EAAE;QACH,KAAK,EAAE,wDAAwD;QAC/D,EAAE,EAAE,kEAAkE;KACvE;IACD,KAAK,EAAE;QACL,KAAK,EAAE,iCAAiC;QACxC,MAAM,EAAE,mCAAmC;QAC3C,KAAK,EAAE,gCAAgC;QACvC,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,0BAA0B;QAClC,OAAO,EAAE,uCAAuC;QAChD,KAAK,EAAE,oDAAoD;QAC3D,KAAK,EAAE,gDAAgD;QACvD,IAAI,EAAE,2CAA2C;KAClD;CACF,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,yBAAyB,GAAqF;IAClH,GAAG,EAAE;QACH,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE;QACnC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,qBAAqB,EAAE;QACzD,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QAC9D,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,uBAAuB,EAAE;QACtE,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QAClE,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QAClE,eAAe,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE;QAC1E,SAAS,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,qBAAqB,EAAE;QACnE,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,2BAA2B,EAAE;QAC9E,SAAS,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE;QAC9D,aAAa,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,yBAAyB,EAAE;QAC3E,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,kCAAkC,EAAE;QACvG,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,wBAAwB,EAAE,eAAe,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE;QACvG,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE;QAClF,WAAW,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QACnE,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE;QAC3D,YAAY,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QACpE,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE;QAC7D,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QAC9D,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE;QACvD,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE;QACrC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;KAC3D;IACD,KAAK,EAAE;QACL,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;QACpD,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;QACtD,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;QACxF,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;QAC9C,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE;QAC/C,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE;QACrC,KAAK,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QACxC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAC7B,IAAI,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE;KAClC;CACF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,SAAS,gBAAgB,CAAC,KAAa,EAAE,QAAiB;IACxD,OAAO,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QACvD,IAAI,IAAI,KAAK,aAAa;YAAE,OAAO,KAAK,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1D,IAAI,OAAO,IAAI,EAAE,KAAK,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;QACnD,IAAI,OAAO,IAAI,EAAE,GAAG,KAAK,UAAU,IAAI,QAAQ,EAAE,CAAC;YAChD,OAAO,OAAQ,QAAoC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;QAC3E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAS,qBAAqB,CAAC,OAAc;IAC3C,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAC/D,MAAM,aAAa,GAAG,IAAI,GAAG,CAC3B,CAAC,WAAW,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAC1D,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,CAAC,IAAY,EAAE,EAAE;QAC5D,MAAM,UAAU,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,sEAAsE;YACtE,qEAAqE;YACrE,iEAAiE;YACjE,4EAA4E;YAC5E,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,sBAAsB,IAAI,cAAc;gBACxE,uEAAuE;gBACvE,uCAAuC,CAC1C,CAAC;QACJ,CAAC;QACD,OAAO;YACL,GAAG,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,GAAG,IAAI,IAAI;YAChE,IAAI;YACJ,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,YAAY,EAAE,UAAU,EAAE,YAAY;SACvC,CAAC;IACJ,CAAC,CAAC;IAEF,yEAAyE;IACzE,gEAAgE;IAChE,gCAAgC;IAChC,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,EAAW,EAAE,CAAC,CAAC;IAE7D,OAAO;QACL;YACE,IAAI,EAAE,KAAK;YACX,GAAG,EAAE,mEAAmE;YACxE,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAClF;QACD;YACE,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,iDAAiD;YACtD,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SACzE;QACD,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,KAAK,OAAO,CAAC;KAChD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE3C,+DAA+D;IAC/D,IAAI,OAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACrD,yEAAyE;QACzE,wEAAwE;QACxE,0EAA0E;QAC1E,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,SAAS,CACjB,wBAAwB,GAAG,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,EAAE,CAC3F,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,GAAG,CAAC,iBAAiB,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,uEAAuE;QACvE,yEAAyE;QACzE,sEAAsE;QACtE,qEAAqE;QACrE,cAAc;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4EAA4E;YAC1E,IAAI,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK;YACzD,yEAAyE,CAC5E,CAAC;QACF,OAAO,GAAG,eAAe,EAAE,CAAC;QAC5B,yEAAyE;QACzE,mEAAmE;QACnE,mEAAmE;QACnE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACvD,SAAS,EAAE,EAAE,CAAC,IAAI;QAClB,WAAW,EAAE,EAAE,CAAC,GAAG;QACnB,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE;YACjC,MAAM,KAAK,GAA4B;gBACrC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,WAAW,EAAE,CAAC,CAAC,GAAG;aACnB,CAAC;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,UAAU;oBAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC;gBAC9C,IAAI,CAAC,CAAC,QAAQ;oBAAE,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC;gBAC3C,IAAI,CAAC,CAAC,YAAY,EAAE,OAAO;oBAAE,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC;gBACpE,IAAI,CAAC,CAAC,YAAY,EAAE,QAAQ;oBAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;YACzE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;KACH,CAAC,CAAC,CAAC;IAEJ,SAAS,CAAC,MAAM,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,eAAe;IACtB,OAAO;QACL;YACE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB;YACtC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,oBAAoB,EAAE;gBAC3C,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,kBAAkB,EAAE;gBAC3C,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,qBAAqB,EAAE;aACjD;SACF;QACD,wEAAwE;QACxE,yEAAyE;QACzE,uEAAuE;QACvE,mEAAmE;QACnE;YACE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,qBAAqB;YAC1C,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;gBAC1E,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;gBAC5E,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;aAChF;SACF;QACD;YACE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB;YAClC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE;gBAC5E,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,4BAA4B,EAAE,UAAU,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE;gBAC/F,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,6BAA6B,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;aAClF;SACF;QACD;YACE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,mBAAmB;YACrC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;gBAC7E,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,oBAAoB,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;gBAC3E,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;gBACzE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE;gBAC5D,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;aAClE;SACF;QACD;YACE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc;YACnC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,wBAAwB,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;gBAC1E,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,gCAAgC,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;aACpF;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -1,9 +1,3 @@
1
- /**
2
- * Pure aggregation helpers for `ifc-lite stats` — extracted so the KPI /
3
- * WWR / GFA math can be unit tested against a fake `bim` surface instead of
4
- * only through a real parsed IFC file. `statsCommand` in stats.ts wires
5
- * these to the SDK's `BimContext`.
6
- */
7
1
  export interface QuantitySet {
8
2
  name: string;
9
3
  quantities: Array<{
@@ -72,6 +66,22 @@ export declare function computeWindowWallRatio(totalWindowArea: number, exterior
72
66
  export declare function computeGrossFloorArea<R>(bim: QuantityBim<R>, storeys: Array<{
73
67
  ref: R;
74
68
  }>, fallbackTotalFloorArea: number): number;
69
+ /**
70
+ * Distinct, display-ready storey names: blank/whitespace-only Names
71
+ * (`IFCBUILDINGSTOREY('...','',...)`) are dropped, same as a genuinely
72
+ * absent one, rather than surfacing as a blank entry in the storey list.
73
+ */
74
+ export declare function computeStoreyNames(storeys: Array<{
75
+ name?: string | null;
76
+ }>): string[];
77
+ /**
78
+ * The first `IfcBuilding`'s display name, or `'(unnamed)'` when absent OR
79
+ * blank/whitespace-only — `?? '(unnamed)'` alone only falls through on
80
+ * null/undefined, so a present-but-blank `Name` was returned verbatim.
81
+ */
82
+ export declare function computeBuildingName(buildings: Array<{
83
+ name?: string | null;
84
+ }>): string;
75
85
  export interface MaterialSummaryEntry {
76
86
  name: string;
77
87
  count: number;
@@ -92,6 +102,21 @@ export interface MaterialsBim<R = unknown> extends QuantityBim<R> {
92
102
  export declare function computeMaterialSummary<R>(bim: MaterialsBim<R>, elements: Array<{
93
103
  ref: R;
94
104
  }>, round: (n: number) => number): MaterialSummaryEntry[];
105
+ /**
106
+ * Scope an unfiltered `bim.query().toArray()` result down to physical building
107
+ * elements, for the material summary and validation stats. `bim.query()` with
108
+ * no type filter answers with every `IfcObjectDefinition` occurrence, so
109
+ * spatial containers, groupings and drafting annotations would otherwise inflate
110
+ * the material summary and the `unnamedElements`/`duplicateGlobalIds` counts (an
111
+ * `IfcAnnotation` dimension line never carries a Name and is not a defect).
112
+ *
113
+ * Excluding rather than testing for `IfcElement` is deliberate: a positive test
114
+ * would also drop `IfcGrid`, `IfcPort` and the structural-analysis items, which
115
+ * this fix has no opinion about — they stay counted exactly as before.
116
+ */
117
+ export declare function filterBuildingElements<T extends {
118
+ type: string;
119
+ }>(entities: T[]): T[];
95
120
  export interface ValidationSummary {
96
121
  duplicateGlobalIds: number;
97
122
  unnamedElements: number;