@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.
- package/dist/commands/ask.d.ts +8 -0
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +10 -9
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/bsdd.d.ts.map +1 -1
- package/dist/commands/bsdd.js +49 -13
- package/dist/commands/bsdd.js.map +1 -1
- package/dist/commands/diff-classification-label.d.ts +12 -0
- package/dist/commands/diff-classification-label.d.ts.map +1 -0
- package/dist/commands/diff-classification-label.js +20 -0
- package/dist/commands/diff-classification-label.js.map +1 -0
- package/dist/commands/diff-engine.d.ts.map +1 -1
- package/dist/commands/diff-engine.js +33 -11
- package/dist/commands/diff-engine.js.map +1 -1
- package/dist/commands/diff-test-helpers.d.ts +12 -0
- package/dist/commands/diff-test-helpers.d.ts.map +1 -1
- package/dist/commands/diff-test-helpers.js +68 -0
- package/dist/commands/diff-test-helpers.js.map +1 -1
- package/dist/commands/diff-unit-scale-fixtures.d.ts +34 -0
- package/dist/commands/diff-unit-scale-fixtures.d.ts.map +1 -0
- package/dist/commands/diff-unit-scale-fixtures.js +94 -0
- package/dist/commands/diff-unit-scale-fixtures.js.map +1 -0
- package/dist/commands/export.d.ts +11 -0
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +9 -14
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/merge.d.ts.map +1 -1
- package/dist/commands/merge.js +8 -0
- package/dist/commands/merge.js.map +1 -1
- package/dist/commands/query-aggregation.d.ts +27 -4
- package/dist/commands/query-aggregation.d.ts.map +1 -1
- package/dist/commands/query-aggregation.js +67 -6
- package/dist/commands/query-aggregation.js.map +1 -1
- package/dist/commands/query-output.d.ts +7 -0
- package/dist/commands/query-output.d.ts.map +1 -1
- package/dist/commands/query-output.js +63 -27
- package/dist/commands/query-output.js.map +1 -1
- package/dist/commands/query-storey.d.ts +24 -0
- package/dist/commands/query-storey.d.ts.map +1 -0
- package/dist/commands/query-storey.js +71 -0
- package/dist/commands/query-storey.js.map +1 -0
- package/dist/commands/query.d.ts +2 -25
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +39 -158
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/schedule-aggregate.d.ts +51 -0
- package/dist/commands/schedule-aggregate.d.ts.map +1 -0
- package/dist/commands/schedule-aggregate.js +121 -0
- package/dist/commands/schedule-aggregate.js.map +1 -0
- package/dist/commands/schedule-columns.d.ts +15 -0
- package/dist/commands/schedule-columns.d.ts.map +1 -0
- package/dist/commands/schedule-columns.js +63 -0
- package/dist/commands/schedule-columns.js.map +1 -0
- package/dist/commands/schedule-group.d.ts +65 -0
- package/dist/commands/schedule-group.d.ts.map +1 -0
- package/dist/commands/schedule-group.js +0 -0
- package/dist/commands/schedule-group.js.map +1 -0
- package/dist/commands/schedule-presets.d.ts +21 -0
- package/dist/commands/schedule-presets.d.ts.map +1 -0
- package/dist/commands/schedule-presets.js +62 -0
- package/dist/commands/schedule-presets.js.map +1 -0
- package/dist/commands/schedule-render-html.d.ts +13 -0
- package/dist/commands/schedule-render-html.d.ts.map +1 -0
- package/dist/commands/schedule-render-html.js +100 -0
- package/dist/commands/schedule-render-html.js.map +1 -0
- package/dist/commands/schedule-render-md.d.ts +12 -0
- package/dist/commands/schedule-render-md.d.ts.map +1 -0
- package/dist/commands/schedule-render-md.js +77 -0
- package/dist/commands/schedule-render-md.js.map +1 -0
- package/dist/commands/schedule-render.d.ts +51 -0
- package/dist/commands/schedule-render.d.ts.map +1 -0
- package/dist/commands/schedule-render.js +205 -0
- package/dist/commands/schedule-render.js.map +1 -0
- package/dist/commands/schedule-spec.d.ts +29 -0
- package/dist/commands/schedule-spec.d.ts.map +1 -0
- package/dist/commands/schedule-spec.js +111 -0
- package/dist/commands/schedule-spec.js.map +1 -0
- package/dist/commands/schedule.d.ts +23 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +249 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +192 -17
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/stats-aggregation.d.ts +31 -6
- package/dist/commands/stats-aggregation.d.ts.map +1 -1
- package/dist/commands/stats-aggregation.js +79 -11
- package/dist/commands/stats-aggregation.js.map +1 -1
- package/dist/commands/stats.d.ts.map +1 -1
- package/dist/commands/stats.js +4 -4
- package/dist/commands/stats.js.map +1 -1
- package/dist/commands/validate.d.ts +7 -4
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +9 -6
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/where-filter.d.ts +42 -0
- package/dist/commands/where-filter.d.ts.map +1 -0
- package/dist/commands/where-filter.js +88 -0
- package/dist/commands/where-filter.js.map +1 -0
- package/dist/energy-export.d.ts.map +1 -1
- package/dist/energy-export.js +12 -2
- package/dist/energy-export.js.map +1 -1
- package/dist/geometry-report.d.ts.map +1 -1
- package/dist/geometry-report.js +15 -3
- package/dist/geometry-report.js.map +1 -1
- package/dist/headless-backend.d.ts +20 -5
- package/dist/headless-backend.d.ts.map +1 -1
- package/dist/headless-backend.js +131 -90
- package/dist/headless-backend.js.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +13 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +21 -0
- package/dist/output.js.map +1 -1
- package/dist/property-filter-match.d.ts +12 -0
- package/dist/property-filter-match.d.ts.map +1 -0
- package/dist/property-filter-match.js +17 -0
- package/dist/property-filter-match.js.map +1 -0
- package/dist/query-overlay-relations.d.ts +29 -0
- package/dist/query-overlay-relations.d.ts.map +1 -0
- package/dist/query-overlay-relations.js +88 -0
- package/dist/query-overlay-relations.js.map +1 -0
- package/dist/query-overlay.d.ts +44 -0
- package/dist/query-overlay.d.ts.map +1 -0
- package/dist/query-overlay.js +100 -0
- package/dist/query-overlay.js.map +1 -0
- 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":"
|
|
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"}
|
package/dist/commands/schema.js
CHANGED
|
@@ -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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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":"AAAA;;+DAE+D;AAE/D;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|