@ifc-lite/cli 0.21.1 → 0.23.1
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/clash.d.ts.map +1 -1
- package/dist/commands/clash.js +88 -46
- package/dist/commands/clash.js.map +1 -1
- package/dist/commands/diagnose-geometry.d.ts.map +1 -1
- package/dist/commands/diagnose-geometry.js +28 -22
- package/dist/commands/diagnose-geometry.js.map +1 -1
- package/dist/commands/diff-content.d.ts +11 -0
- package/dist/commands/diff-content.d.ts.map +1 -0
- package/dist/commands/diff-content.js +270 -0
- package/dist/commands/diff-content.js.map +1 -0
- package/dist/commands/diff-engine.d.ts +23 -0
- package/dist/commands/diff-engine.d.ts.map +1 -0
- package/dist/commands/diff-engine.js +159 -0
- package/dist/commands/diff-engine.js.map +1 -0
- package/dist/commands/diff-scope.d.ts +77 -0
- package/dist/commands/diff-scope.d.ts.map +1 -0
- package/dist/commands/diff-scope.js +160 -0
- package/dist/commands/diff-scope.js.map +1 -0
- package/dist/commands/diff-test-helpers.d.ts +70 -0
- package/dist/commands/diff-test-helpers.d.ts.map +1 -0
- package/dist/commands/diff-test-helpers.js +203 -0
- package/dist/commands/diff-test-helpers.js.map +1 -0
- package/dist/commands/diff.d.ts +1 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +71 -25
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +7 -3
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +45 -16
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/extract-entities.d.ts.map +1 -1
- package/dist/commands/extract-entities.js +8 -2
- package/dist/commands/extract-entities.js.map +1 -1
- package/dist/commands/gym/channels.d.ts.map +1 -1
- package/dist/commands/gym/channels.js +4 -3
- package/dist/commands/gym/channels.js.map +1 -1
- package/dist/commands/gym.d.ts.map +1 -1
- package/dist/commands/gym.js +77 -62
- package/dist/commands/gym.js.map +1 -1
- package/dist/commands/layer-push.d.ts.map +1 -1
- package/dist/commands/layer-push.js +2 -0
- package/dist/commands/layer-push.js.map +1 -1
- package/dist/commands/query.d.ts +30 -0
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +32 -17
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +23 -2
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +36 -5
- package/dist/commands/validate.js.map +1 -1
- package/dist/hbjson-export.d.ts.map +1 -1
- package/dist/hbjson-export.js +27 -24
- package/dist/hbjson-export.js.map +1 -1
- package/dist/headless-backend.d.ts.map +1 -1
- package/dist/headless-backend.js +44 -4
- package/dist/headless-backend.js.map +1 -1
- package/dist/index.js +6 -13
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +8 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +21 -0
- package/dist/output.js.map +1 -1
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +38 -0
- package/dist/version.js.map +1 -0
- package/package.json +20 -19
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clash.d.ts","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"clash.d.ts","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"AAmKA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGhE"}
|
package/dist/commands/clash.js
CHANGED
|
@@ -45,15 +45,24 @@ async function meshModel(store, modelId, filePath) {
|
|
|
45
45
|
const cached = meshCache.get(modelId);
|
|
46
46
|
if (cached)
|
|
47
47
|
return cached;
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const mesh = async (bytes) => {
|
|
49
|
+
const processor = await getProcessor();
|
|
50
|
+
const result = await processor.process(bytes);
|
|
51
|
+
return result.meshes;
|
|
52
|
+
};
|
|
53
|
+
// The wasm mesher is a genuine whole-file consumer, so the source is
|
|
54
|
+
// materialised — but scoped, so the buffer cannot outlive the mesh pass
|
|
55
|
+
// (only the meshes are cached).
|
|
56
|
+
let meshes;
|
|
57
|
+
if (store.source.byteLength > 0) {
|
|
58
|
+
meshes = await store.source.withMaterializedAsync(mesh);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
50
61
|
const buffer = await readFile(filePath);
|
|
51
|
-
|
|
62
|
+
meshes = await mesh(new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength));
|
|
52
63
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
meshCache.set(modelId, result.meshes);
|
|
56
|
-
return result.meshes;
|
|
64
|
+
meshCache.set(modelId, meshes);
|
|
65
|
+
return meshes;
|
|
57
66
|
}
|
|
58
67
|
function parseMode(raw) {
|
|
59
68
|
const mode = raw ?? 'hard';
|
|
@@ -149,47 +158,80 @@ export async function clashCommand(args) {
|
|
|
149
158
|
const bcfStatus = getFlag(args, '--bcf-status');
|
|
150
159
|
const maxTopics = parseNumberFlag(getFlag(args, '--max-topics'), '--max-topics');
|
|
151
160
|
const { store } = await createHeadlessContext(filePath);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
projectName: 'Clash report',
|
|
175
|
-
// Headless: no snapshots (no renderer) — viewer export embeds those.
|
|
176
|
-
...(bcfStatus ? { status: bcfStatus } : {}),
|
|
177
|
-
...(maxTopics != null ? { maxTopics } : {}),
|
|
161
|
+
// `getProcessor()` (called from `meshModel` below) lazily creates and caches
|
|
162
|
+
// `sharedProcessor` at module scope, session-scoped for this one `clash`
|
|
163
|
+
// invocation — a fresh CLI process per run, so it was never freed on any
|
|
164
|
+
// path out of this function (#1959 P2). Wrap the whole run in try/finally
|
|
165
|
+
// so the WASM handle is freed on success, on a thrown clash/BCF error, and
|
|
166
|
+
// is a no-op (nothing to dispose) when meshing itself never ran.
|
|
167
|
+
try {
|
|
168
|
+
const modelId = basename(filePath);
|
|
169
|
+
if (!jsonOutput)
|
|
170
|
+
process.stderr.write(` Meshing ${modelId} ...\n`);
|
|
171
|
+
const meshes = await meshModel(store, modelId, filePath);
|
|
172
|
+
const { elements, exclusions } = elementsFromStep({ store, meshes, modelId });
|
|
173
|
+
const rules = buildRules(args, mode, tolerance, clearance);
|
|
174
|
+
const engine = createClashEngine({ backend: 'ts' });
|
|
175
|
+
const result = await engine.run(elements, rules, {
|
|
176
|
+
exclusions,
|
|
177
|
+
tolerance,
|
|
178
|
+
onProgress: (p) => {
|
|
179
|
+
if (!jsonOutput) {
|
|
180
|
+
process.stderr.write(`\r Clashing: ${p.phase} ${p.rule} (${p.done}/${p.total})`);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
178
183
|
});
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
if (!jsonOutput)
|
|
185
|
+
process.stderr.write('\n');
|
|
186
|
+
if (bcfPath) {
|
|
187
|
+
const groups = groupClashes(result, { by: bcfGroupBy });
|
|
188
|
+
const project = await createBCFFromClashResult(result, groups, {
|
|
189
|
+
author: 'ifc-lite clash',
|
|
190
|
+
projectName: 'Clash report',
|
|
191
|
+
// Headless: no snapshots (no renderer) — viewer export embeds those.
|
|
192
|
+
...(bcfStatus ? { status: bcfStatus } : {}),
|
|
193
|
+
...(maxTopics != null ? { maxTopics } : {}),
|
|
194
|
+
});
|
|
195
|
+
const blob = await writeBCF(project);
|
|
196
|
+
const buffer = Buffer.from(await blob.arrayBuffer());
|
|
197
|
+
await writeFile(bcfPath, buffer);
|
|
198
|
+
process.stderr.write(` BCF report written to ${bcfPath} (${groups.length} topic group(s), grouped by ${bcfGroupBy})\n`);
|
|
199
|
+
}
|
|
200
|
+
if (jsonOutput) {
|
|
201
|
+
const total = result.clashes.length;
|
|
202
|
+
const clashes = result.clashes.slice(0, JSON_CLASH_CAP);
|
|
203
|
+
const truncated = total > clashes.length
|
|
204
|
+
? { reason: `capped at ${JSON_CLASH_CAP} clashes for display`, dropped: total - clashes.length }
|
|
205
|
+
: null;
|
|
206
|
+
printJson({ summary: result.summary, truncated, clashes });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
printHumanSummary(result);
|
|
183
210
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
211
|
+
finally {
|
|
212
|
+
// Reset BEFORE disposing, and never let a cleanup failure escape.
|
|
213
|
+
//
|
|
214
|
+
// Ordering: if `dispose()` throws, an assignment placed after it is
|
|
215
|
+
// skipped, leaving `sharedProcessor` pointing at a processor whose handle
|
|
216
|
+
// may be half-freed — the next `clashCommand` in the same host would then
|
|
217
|
+
// reuse it. That is the dangling-reference case the reset exists to
|
|
218
|
+
// prevent, reintroduced on the failure path. Clearing first cannot be
|
|
219
|
+
// skipped. (#2128 review)
|
|
220
|
+
//
|
|
221
|
+
// Not hypothetical: #1922 is an OOM inside a drained job aborting the
|
|
222
|
+
// WASM module at dispose time — precisely a throwing `dispose()`.
|
|
223
|
+
//
|
|
224
|
+
// Swallowed: a cleanup failure must not replace the clash/BCF error the
|
|
225
|
+
// caller was about to see. Warned, not silent, per the no-silent-catch
|
|
226
|
+
// rule.
|
|
227
|
+
const processor = sharedProcessor;
|
|
228
|
+
sharedProcessor = undefined;
|
|
229
|
+
try {
|
|
230
|
+
processor?.dispose();
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
console.warn('[clash] geometry processor dispose failed; continuing', err);
|
|
234
|
+
}
|
|
192
235
|
}
|
|
193
|
-
printHumanSummary(result);
|
|
194
236
|
}
|
|
195
237
|
//# sourceMappingURL=clash.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clash.js","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAiB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,GAKb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,6EAA6E;AAC7E,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,+DAA+D;AAC/D,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;GAGG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEhD,IAAI,eAA8C,CAAC;AAEnD,KAAK,UAAU,YAAY;IACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAC1C,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,SAAS,CAAC,KAAmB,EAAE,OAAe,EAAE,QAAgB;IAC7E,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"clash.js","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose-geometry.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose-geometry.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAMjF,KAAK,SAAS,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,SAAS,EAAE,CAMb;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"diagnose-geometry.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose-geometry.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAMjF,KAAK,SAAS,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAAE,EAClB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,SAAS,EAAE,CAMb;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkF3E"}
|
|
@@ -52,31 +52,37 @@ export async function diagnoseGeometryCommand(args) {
|
|
|
52
52
|
const buf = await readFile(filePath);
|
|
53
53
|
const bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
54
54
|
const gp = new GeometryProcessor();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (productArg !== undefined) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
let diag;
|
|
56
|
+
try {
|
|
57
|
+
await gp.init();
|
|
58
|
+
diag = gp.diagnoseGeometry(bytes);
|
|
59
|
+
if (diag && (productArg !== undefined || typeArg !== undefined)) {
|
|
60
|
+
let productId;
|
|
61
|
+
if (productArg !== undefined) {
|
|
62
|
+
if (isExpressId(productArg)) {
|
|
63
|
+
productId = parseInt(productArg, 10);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// GlobalId: resolve via the columnar parser's entity table (the wasm
|
|
67
|
+
// diagnostics pass never surfaces GlobalIds, only express IDs). Parse
|
|
68
|
+
// the bytes ALREADY in memory rather than re-reading the file from disk
|
|
69
|
+
// — the geometry pass above already loaded them, so this avoids a
|
|
70
|
+
// redundant disk read (the wasm IfcAPI exposes no GlobalId lookup, so a
|
|
71
|
+
// columnar parse is still required to map GlobalId → expressId).
|
|
72
|
+
const store = await loadIfcBytes(bytes, filePath);
|
|
73
|
+
const resolved = store.entities.getExpressIdByGlobalId(productArg);
|
|
74
|
+
if (resolved === -1) {
|
|
75
|
+
fatal(`--product: no entity found with GlobalId "${productArg}"`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
productId = resolved;
|
|
75
79
|
}
|
|
76
|
-
productId = resolved;
|
|
77
80
|
}
|
|
81
|
+
diag = { ...diag, worstHosts: filterWorstHosts(diag.worstHosts, { productId, ifcType: typeArg }) };
|
|
78
82
|
}
|
|
79
|
-
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
gp.dispose();
|
|
80
86
|
}
|
|
81
87
|
if (asJson || outPath) {
|
|
82
88
|
const json = JSON.stringify(diag ?? null, null, 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose-geometry.js","sourceRoot":"","sources":["../../src/commands/diagnose-geometry.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,sEAAsE;AACtE,4DAA4D;AAE5D;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAA4B,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAIlF,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAkB,EAClB,IAA8C;IAE9C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACxB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QACjF,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAAc;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,KAAK,CACH,0EAA0E;YACxE,qDAAqD,CACxD,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAEzE,MAAM,EAAE,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACnC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnose-geometry.js","sourceRoot":"","sources":["../../src/commands/diagnose-geometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ContentDiffOptions {
|
|
2
|
+
basePath: string;
|
|
3
|
+
headPath: string;
|
|
4
|
+
/** `--identity-in`: a sidecar to replay as key aliases. */
|
|
5
|
+
identityIn?: string;
|
|
6
|
+
/** `--identity-out`: where to write the sidecar this run establishes. */
|
|
7
|
+
identityOut?: string;
|
|
8
|
+
json: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function contentDiffCommand(options: ContentDiffOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=diff-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-content.d.ts","sourceRoot":"","sources":["../../src/commands/diff-content.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFnF"}
|
|
@@ -0,0 +1,270 @@
|
|
|
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 diff --by-content` — the engine-backed half of the diff command
|
|
6
|
+
* (issue #1891), plus the identity-map sidecar it can emit and consume.
|
|
7
|
+
*
|
|
8
|
+
* The loop this closes: run it once, review the `renamed` matches, keep the
|
|
9
|
+
* sidecar. On the next run the accepted claims come back in as key aliases, the
|
|
10
|
+
* re-GUIDed elements are matched by key, and they never show up as churn again.
|
|
11
|
+
* See `diff-engine.ts` for why this path is data-scope only.
|
|
12
|
+
*/
|
|
13
|
+
import { readFile, stat, writeFile } from 'node:fs/promises';
|
|
14
|
+
import { resolve } from 'node:path';
|
|
15
|
+
import { createIdentityMapSidecar, diffModels, identityMapFromContentMatches, identityMapSidecarMismatches, keyAliasesFromSidecar, parseIdentityMapSidecar, serializeIdentityMapSidecar, } from '@ifc-lite/diff';
|
|
16
|
+
import { loadIfcBytes } from '../loader.js';
|
|
17
|
+
import { fatal, printJson } from '../output.js';
|
|
18
|
+
import { buildFileFingerprints, modelIdentityOf } from './diff-engine.js';
|
|
19
|
+
export async function contentDiffCommand(options) {
|
|
20
|
+
const { basePath, headPath } = options;
|
|
21
|
+
// Before anything is read, and long before anything is written.
|
|
22
|
+
await refuseOverwritingAnInput(options);
|
|
23
|
+
const baseBytes = await readModel(basePath);
|
|
24
|
+
const headBytes = await readModel(headPath);
|
|
25
|
+
const baseIdentity = modelIdentityOf(basePath, baseBytes);
|
|
26
|
+
const headIdentity = modelIdentityOf(headPath, headBytes);
|
|
27
|
+
const incoming = options.identityIn
|
|
28
|
+
? await readVerifiedSidecar(options.identityIn, baseIdentity, headIdentity)
|
|
29
|
+
: undefined;
|
|
30
|
+
process.stderr.write('Loading files...\n');
|
|
31
|
+
const baseStore = await loadIfcBytes(baseBytes, basePath);
|
|
32
|
+
const headStore = await loadIfcBytes(headBytes, headPath);
|
|
33
|
+
const diff = diffModels(buildFileFingerprints(baseStore), buildFileFingerprints(headStore), {
|
|
34
|
+
// No meshes in Node: `data` is the honest description of what this path can
|
|
35
|
+
// compare. See diff-engine.ts.
|
|
36
|
+
scope: 'data',
|
|
37
|
+
matchUnpairedByContent: true,
|
|
38
|
+
keyAliases: incoming ? keyAliasesFromSidecar(incoming) : undefined,
|
|
39
|
+
});
|
|
40
|
+
const applied = diff.appliedKeyAliases ?? new Map();
|
|
41
|
+
const ignored = incoming ? countClaims(incoming) - applied.size : 0;
|
|
42
|
+
let written;
|
|
43
|
+
if (options.identityOut) {
|
|
44
|
+
const entries = mergeIdentityClaims(incoming, applied, diff.contentMatches);
|
|
45
|
+
const sidecar = createIdentityMapSidecar({
|
|
46
|
+
base: baseIdentity,
|
|
47
|
+
head: headIdentity,
|
|
48
|
+
entries,
|
|
49
|
+
// Reproducible by construction: identical inputs write identical bytes.
|
|
50
|
+
// The builder sorts and de-duplicates so a checked-in sidecar produces an
|
|
51
|
+
// empty git diff when nothing changed, and stamping `Date.now()` here
|
|
52
|
+
// would throw that away — every rerun, including the
|
|
53
|
+
// `--identity-in x --identity-out x` carry-forward, would show a one-line
|
|
54
|
+
// diff that says nothing about the claims. An incoming `created` is
|
|
55
|
+
// preserved instead of refreshed: it dates the claims, not the rewrite,
|
|
56
|
+
// and the sidecar is addressed by the two model digests either way. There
|
|
57
|
+
// is deliberately no flag to request a fresh stamp — it would add CLI
|
|
58
|
+
// surface for a field the format already documents as informational and
|
|
59
|
+
// optional, and `git log` dates a reviewed, committed artifact better
|
|
60
|
+
// than a self-reported timestamp does.
|
|
61
|
+
created: incoming?.created,
|
|
62
|
+
});
|
|
63
|
+
await writeFile(options.identityOut, serializeIdentityMapSidecar(sidecar), 'utf-8');
|
|
64
|
+
written = { path: options.identityOut, entries: sidecar.entries };
|
|
65
|
+
}
|
|
66
|
+
if (options.json) {
|
|
67
|
+
printJson({
|
|
68
|
+
base: { path: basePath, hash: baseIdentity.hash, schema: baseStore.schemaVersion },
|
|
69
|
+
head: { path: headPath, hash: headIdentity.hash, schema: headStore.schemaVersion },
|
|
70
|
+
scope: diff.scope,
|
|
71
|
+
counts: diff.counts,
|
|
72
|
+
contentMatches: (diff.contentMatches ?? []).map((match) => ({
|
|
73
|
+
kind: match.kind,
|
|
74
|
+
base: match.base.map((entity) => entity.key),
|
|
75
|
+
head: match.head.map((entity) => entity.key),
|
|
76
|
+
})),
|
|
77
|
+
identityMap: {
|
|
78
|
+
in: options.identityIn
|
|
79
|
+
? { path: options.identityIn, applied: applied.size, ignored }
|
|
80
|
+
: undefined,
|
|
81
|
+
out: written ? { path: written.path, entries: written.entries.length } : undefined,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
printReport({
|
|
87
|
+
basePath,
|
|
88
|
+
headPath,
|
|
89
|
+
diff,
|
|
90
|
+
appliedCount: applied.size,
|
|
91
|
+
ignoredCount: ignored,
|
|
92
|
+
identityIn: options.identityIn,
|
|
93
|
+
written,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Refuse to run at all if `--identity-out` names one of the two input models.
|
|
98
|
+
*
|
|
99
|
+
* The sidecar is a JSON document. Writing it over an IFC file destroys the
|
|
100
|
+
* user's model, and a mistyped or shell-completed path is all it takes — the
|
|
101
|
+
* two arguments right before it are IFC paths. So this is checked first, and
|
|
102
|
+
* the command exits without reading, comparing, or writing anything.
|
|
103
|
+
*
|
|
104
|
+
* Two independent tests, because a path string is not a file:
|
|
105
|
+
*
|
|
106
|
+
* 1. Resolved paths are equal. Catches `./v1.ifc` vs `v1.ifc` vs `sub/../v1.ifc`
|
|
107
|
+
* with no filesystem access, and is the whole answer on a platform where
|
|
108
|
+
* `stat` reports no usable inode.
|
|
109
|
+
* 2. The output already exists AND is the same file as an input, by device +
|
|
110
|
+
* inode. This is the exhaustive test: it catches a symlink, a hard link, a
|
|
111
|
+
* bind mount, and `V1.IFC` on a case-insensitive filesystem — every way two
|
|
112
|
+
* different strings can name one file. It is also sufficient on its own for
|
|
113
|
+
* the destructive case, because a path that does not resolve to an existing
|
|
114
|
+
* file cannot be overwriting an input: the inputs must exist to be read.
|
|
115
|
+
*
|
|
116
|
+
* `--identity-in` and `--identity-out` naming the SAME sidecar is not checked
|
|
117
|
+
* here, because that is the carry-forward workflow this feature is built around
|
|
118
|
+
* (read the accepted claims, write back the ones that still held).
|
|
119
|
+
*/
|
|
120
|
+
async function refuseOverwritingAnInput(options) {
|
|
121
|
+
const { identityOut } = options;
|
|
122
|
+
if (identityOut === undefined)
|
|
123
|
+
return;
|
|
124
|
+
const out = resolve(identityOut);
|
|
125
|
+
const outStat = await statOrUndefined(identityOut);
|
|
126
|
+
for (const [label, input] of [
|
|
127
|
+
['base model', options.basePath],
|
|
128
|
+
['head model', options.headPath],
|
|
129
|
+
]) {
|
|
130
|
+
if (resolve(input) !== out && !isSameFile(outStat, await statOrUndefined(input)))
|
|
131
|
+
continue;
|
|
132
|
+
fatal(`--identity-out ${identityOut} is the ${label} (${input}). ` +
|
|
133
|
+
'Writing the identity map there would overwrite the input file.');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function statOrUndefined(path) {
|
|
137
|
+
// A missing or unreadable path cannot be an input file being overwritten;
|
|
138
|
+
// reading the models is what reports it, with its own message.
|
|
139
|
+
try {
|
|
140
|
+
return await stat(path);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function isSameFile(a, b) {
|
|
147
|
+
return a !== undefined && b !== undefined && a.dev === b.dev && a.ino === b.ino;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Read one of the two input models, reporting a missing or unreadable path the
|
|
151
|
+
* way the rest of the command reports problems rather than throwing a raw
|
|
152
|
+
* `ENOENT` stack at the user — the same treatment `readVerifiedSidecar` already
|
|
153
|
+
* gives the sidecar.
|
|
154
|
+
*/
|
|
155
|
+
async function readModel(path) {
|
|
156
|
+
try {
|
|
157
|
+
return await readFile(path);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return fatal(`Cannot read ${path}: ${error.message}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Read a sidecar and refuse it unless it was verified against exactly these two
|
|
165
|
+
* files.
|
|
166
|
+
*
|
|
167
|
+
* This is the whole reason the sidecar pins both content digests. A rename list
|
|
168
|
+
* with no idea which revisions a human looked at when accepting it is not a
|
|
169
|
+
* claim, it is a guess with a filename; replayed against the wrong pair it
|
|
170
|
+
* either silently does nothing or asserts an identity nobody reviewed. There is
|
|
171
|
+
* deliberately no override flag: the fix for a mismatch is to re-run the
|
|
172
|
+
* comparison that produced the claims, which is one command.
|
|
173
|
+
*/
|
|
174
|
+
async function readVerifiedSidecar(path, base, head) {
|
|
175
|
+
let text;
|
|
176
|
+
try {
|
|
177
|
+
text = await readFile(path, 'utf-8');
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
return fatal(`Cannot read identity map ${path}: ${error.message}`);
|
|
181
|
+
}
|
|
182
|
+
let sidecar;
|
|
183
|
+
try {
|
|
184
|
+
sidecar = parseIdentityMapSidecar(text);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return fatal(error.message);
|
|
188
|
+
}
|
|
189
|
+
const problems = identityMapSidecarMismatches(sidecar, { base, head });
|
|
190
|
+
if (problems.length > 0) {
|
|
191
|
+
return fatal(`Identity map ${path} was not verified against these files:\n ${problems.join('\n ')}`);
|
|
192
|
+
}
|
|
193
|
+
return sidecar;
|
|
194
|
+
}
|
|
195
|
+
/** Distinct head keys a sidecar actually claims (self-claims and repeats are
|
|
196
|
+
* no-ops the consumer drops, so counting raw entries would overstate what
|
|
197
|
+
* could have applied). */
|
|
198
|
+
function countClaims(sidecar) {
|
|
199
|
+
return keyAliasesFromSidecar(sidecar).size;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The claims the output sidecar should carry: the incoming ones that still
|
|
203
|
+
* applied, plus the ones this run's content matching established.
|
|
204
|
+
*
|
|
205
|
+
* Carrying the incoming claims forward is not bookkeeping, it is the point.
|
|
206
|
+
* An applied alias matches its pair by key, so that pair is no longer in
|
|
207
|
+
* `contentMatches` — deriving the output from the matches alone would drop
|
|
208
|
+
* exactly the claims that worked, and `--identity-in x --identity-out x` would
|
|
209
|
+
* erase the map a little more on every run. Their original `reason` is
|
|
210
|
+
* preserved so a hand-written claim does not silently become an engine-derived
|
|
211
|
+
* one. Incoming claims that did NOT apply (stale, or colliding) are dropped:
|
|
212
|
+
* the sidecar records what held against these two files, not what someone once
|
|
213
|
+
* hoped.
|
|
214
|
+
*/
|
|
215
|
+
function mergeIdentityClaims(incoming, applied, matches) {
|
|
216
|
+
const entries = [];
|
|
217
|
+
if (incoming) {
|
|
218
|
+
const reasons = new Map();
|
|
219
|
+
for (const entry of incoming.entries) {
|
|
220
|
+
if (!reasons.has(entry.here))
|
|
221
|
+
reasons.set(entry.here, entry.reason);
|
|
222
|
+
}
|
|
223
|
+
for (const [here, base] of applied) {
|
|
224
|
+
entries.push({ base, here, reason: reasons.get(here) ?? 'carried forward' });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
entries.push(...identityMapFromContentMatches(matches));
|
|
228
|
+
return entries;
|
|
229
|
+
}
|
|
230
|
+
function printReport(report) {
|
|
231
|
+
const { diff } = report;
|
|
232
|
+
const out = (line) => {
|
|
233
|
+
process.stdout.write(`${line}\n`);
|
|
234
|
+
};
|
|
235
|
+
out('');
|
|
236
|
+
out(` Base: ${report.basePath}`);
|
|
237
|
+
out(` Head: ${report.headPath}`);
|
|
238
|
+
out(` Scope: data (the CLI has no geometry pipeline)`);
|
|
239
|
+
out('');
|
|
240
|
+
out(` Unchanged: ${diff.counts.unchanged}`);
|
|
241
|
+
out(` Modified: ${diff.counts.modified}`);
|
|
242
|
+
out(` Added: ${diff.counts.added}`);
|
|
243
|
+
out(` Deleted: ${diff.counts.deleted}`);
|
|
244
|
+
const byKind = new Map();
|
|
245
|
+
for (const match of diff.contentMatches ?? []) {
|
|
246
|
+
byKind.set(match.kind, (byKind.get(match.kind) ?? 0) + 1);
|
|
247
|
+
}
|
|
248
|
+
out('');
|
|
249
|
+
if (byKind.size === 0) {
|
|
250
|
+
out(' Content matches: none');
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
out(' Content matches:');
|
|
254
|
+
for (const [kind, count] of [...byKind].sort()) {
|
|
255
|
+
out(` ${kind.padEnd(13)} ${count}`);
|
|
256
|
+
}
|
|
257
|
+
out(' (renamed / moved / reshaped are resolved; the rest need a human)');
|
|
258
|
+
}
|
|
259
|
+
if (report.identityIn) {
|
|
260
|
+
out('');
|
|
261
|
+
out(` Identity map in: ${report.identityIn}`);
|
|
262
|
+
out(` applied: ${report.appliedCount}, ignored: ${report.ignoredCount}`);
|
|
263
|
+
}
|
|
264
|
+
if (report.written) {
|
|
265
|
+
out('');
|
|
266
|
+
out(` Identity map out: ${report.written.path} (${report.written.entries.length} claims)`);
|
|
267
|
+
}
|
|
268
|
+
out('');
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=diff-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-content.js","sourceRoot":"","sources":["../../src/commands/diff-content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type EntityFingerprint, type ModelIdentity } from '@ifc-lite/diff';
|
|
2
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
3
|
+
/** Adapter handle threaded through the diff: the entity's express id. */
|
|
4
|
+
export type DiffRef = number;
|
|
5
|
+
/**
|
|
6
|
+
* Content digest of a model's bytes, as written into the sidecar.
|
|
7
|
+
*
|
|
8
|
+
* The digest is over the file **as it sits on disk**, before any `.ifcZIP`
|
|
9
|
+
* unwrapping — that is the thing a user can reproduce with `shasum`, and the
|
|
10
|
+
* thing that changes when someone re-exports.
|
|
11
|
+
*/
|
|
12
|
+
export declare function modelIdentityOf(path: string, bytes: Uint8Array): ModelIdentity;
|
|
13
|
+
/**
|
|
14
|
+
* Build one {@link EntityFingerprint} per `IfcObjectDefinition` in a store.
|
|
15
|
+
*
|
|
16
|
+
* `components` is populated as well as `dataHash`: the content pass's only
|
|
17
|
+
* defence against a `dataHash` collision retiring an unrelated add/delete pair
|
|
18
|
+
* is agreement on `ifcType` and on every component sub-hash, and the second
|
|
19
|
+
* check is inert unless both sides supply them (see the "Hash collisions"
|
|
20
|
+
* section of `docs/guide/model-diff.md`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildFileFingerprints(store: IfcDataStore): EntityFingerprint<DiffRef>[];
|
|
23
|
+
//# sourceMappingURL=diff-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-engine.d.ts","sourceRoot":"","sources":["../../src/commands/diff-engine.ts"],"names":[],"mappings":"AA8BA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,yEAAyE;AACzE,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,aAAa,CAG9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAavF"}
|