@ifc-lite/cli 0.33.1 → 0.34.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/README.md +8 -1
- package/dist/commands/diff-content-io.d.ts +50 -0
- package/dist/commands/diff-content-io.d.ts.map +1 -0
- package/dist/commands/diff-content-io.js +104 -0
- package/dist/commands/diff-content-io.js.map +1 -0
- package/dist/commands/diff-content-report.d.ts +23 -0
- package/dist/commands/diff-content-report.d.ts.map +1 -0
- package/dist/commands/diff-content-report.js +67 -0
- package/dist/commands/diff-content-report.js.map +1 -0
- package/dist/commands/diff-content.d.ts +19 -0
- package/dist/commands/diff-content.d.ts.map +1 -1
- package/dist/commands/diff-content.js +120 -129
- package/dist/commands/diff-content.js.map +1 -1
- package/dist/commands/diff-engine.d.ts +32 -1
- package/dist/commands/diff-engine.d.ts.map +1 -1
- package/dist/commands/diff-engine.js +75 -15
- package/dist/commands/diff-engine.js.map +1 -1
- package/dist/commands/diff-geometry.d.ts +107 -0
- package/dist/commands/diff-geometry.d.ts.map +1 -0
- package/dist/commands/diff-geometry.js +262 -0
- package/dist/commands/diff-geometry.js.map +1 -0
- package/dist/commands/diff-lineage-io.d.ts +23 -0
- package/dist/commands/diff-lineage-io.d.ts.map +1 -0
- package/dist/commands/diff-lineage-io.js +119 -0
- package/dist/commands/diff-lineage-io.js.map +1 -0
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +34 -3
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/rekey.d.ts +27 -0
- package/dist/commands/rekey.d.ts.map +1 -0
- package/dist/commands/rekey.js +192 -0
- package/dist/commands/rekey.js.map +1 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +2 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/headless-backend.d.ts.map +1 -1
- package/dist/headless-backend.js +31 -23
- package/dist/headless-backend.js.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/query-overlay-relations.d.ts +8 -28
- package/dist/query-overlay-relations.d.ts.map +1 -1
- package/dist/query-overlay-relations.js +68 -78
- package/dist/query-overlay-relations.js.map +1 -1
- package/dist/query-overlay.d.ts +6 -2
- package/dist/query-overlay.d.ts.map +1 -1
- package/dist/query-overlay.js +61 -5
- package/dist/query-overlay.js.map +1 -1
- package/package.json +18 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-content.js","sourceRoot":"","sources":["../../src/commands/diff-content.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D
|
|
1
|
+
{"version":3,"file":"diff-content.js","sourceRoot":"","sources":["../../src/commands/diff-content.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,5 +19,36 @@ export declare function modelIdentityOf(path: string, bytes: Uint8Array): ModelI
|
|
|
19
19
|
* check is inert unless both sides supply them (see the "Hash collisions"
|
|
20
20
|
* section of `docs/guide/model-diff.md`).
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
/** Adapter options shared by the CLI and MCP fingerprint builders (issue #4955). */
|
|
23
|
+
export interface FingerprintAdapterOptions {
|
|
24
|
+
/**
|
|
25
|
+
* An authored key to use as the cross-revision identity instead of GlobalId:
|
|
26
|
+
* `Tag`, or `<PsetName>.<PropertyName>`. An entity carrying a non-empty value
|
|
27
|
+
* is keyed `prop:<value>`; one without falls back to its GlobalId. Two
|
|
28
|
+
* entities sharing one authored value collapse under the diff's first-wins
|
|
29
|
+
* key index, so they are reported on `duplicateAuthoredKeys` and fall back
|
|
30
|
+
* to GlobalId too — a key that names two things is not a key.
|
|
31
|
+
*/
|
|
32
|
+
keyProperty?: string;
|
|
33
|
+
/** Receives every authored value more than one entity carried. */
|
|
34
|
+
duplicateAuthoredKeys?: Map<string, number[]>;
|
|
35
|
+
}
|
|
36
|
+
/** Prefix on a fingerprint key taken from an authored property rather than a GlobalId. */
|
|
37
|
+
export declare const AUTHORED_KEY_PREFIX = "prop:";
|
|
38
|
+
/**
|
|
39
|
+
* Resolve every entity's key under an authored-key spec: `prop:<value>` where
|
|
40
|
+
* the value is present and unique, GlobalId otherwise. Duplicates are reported
|
|
41
|
+
* to the caller rather than silently collapsed by `indexByKey`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveAuthoredKeys(store: IfcDataStore, entities: readonly {
|
|
44
|
+
expressId: number;
|
|
45
|
+
globalId: string;
|
|
46
|
+
}[], options: FingerprintAdapterOptions): Map<number, string>;
|
|
47
|
+
export declare function buildFileFingerprints(store: IfcDataStore, options?: FingerprintAdapterOptions): EntityFingerprint<DiffRef>[];
|
|
48
|
+
/** A collision discovered in either file invalidates that authored value in
|
|
49
|
+
* both files, including fingerprints already built for the first side. */
|
|
50
|
+
export declare function fallbackPairDuplicateAuthoredKeys(sides: readonly {
|
|
51
|
+
fingerprints: EntityFingerprint<DiffRef>[];
|
|
52
|
+
store: IfcDataStore;
|
|
53
|
+
}[], duplicates: ReadonlyMap<string, number[]>): void;
|
|
23
54
|
//# sourceMappingURL=diff-engine.d.ts.map
|
|
@@ -1 +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,
|
|
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,EAcL,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAI1B,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,oFAAoF;AACpF,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC/C;AAED,0FAA0F;AAC1F,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,EAC5D,OAAO,EAAE,yBAAyB,GACjC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBrB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,yBAA8B,GACtC,iBAAiB,CAAC,OAAO,CAAC,EAAE,CA8B9B;AAED;0EAC0E;AAC1E,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,SAAS;IACd,YAAY,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3C,KAAK,EAAE,YAAY,CAAC;CACrB,EAAE,EACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACxC,IAAI,CAiBN"}
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { createHash } from 'node:crypto';
|
|
29
29
|
import { buildComponentFingerprints, buildDataFingerprint, } from '@ifc-lite/diff';
|
|
30
|
-
import { RelationshipType } from '@ifc-lite/data';
|
|
31
|
-
import { EntityExtractor, extractAllEntityAttributes, extractClassificationsOnDemand, extractProjectUnits, extractPropertiesOnDemand, extractQuantitiesOnDemand, getAttributeNamesAcrossSchemas, quantitySiScale, roundToScale, scaledPropertyValue, } from '@ifc-lite/parser';
|
|
30
|
+
import { RelationshipType, resolvedTypeName } from '@ifc-lite/data';
|
|
31
|
+
import { EntityExtractor, extractAllEntityAttributes, extractClassificationsOnDemand, extractProjectUnits, extractPropertiesOnDemand, extractQuantitiesOnDemand, authoredKeyValue, getAttributeNamesAcrossSchemas, parseAuthoredKeySpec, spatialContainerPath, quantitySiScale, roundToScale, scaledPropertyValue, } from '@ifc-lite/parser';
|
|
32
32
|
import { classificationLabel } from './diff-classification-label.js';
|
|
33
33
|
import { comparableEntities } from './diff-scope.js';
|
|
34
34
|
/**
|
|
@@ -42,16 +42,46 @@ export function modelIdentityOf(path, bytes) {
|
|
|
42
42
|
const digest = createHash('sha256').update(bytes).digest('hex');
|
|
43
43
|
return { hash: `sha256:${digest}`, path };
|
|
44
44
|
}
|
|
45
|
+
/** Prefix on a fingerprint key taken from an authored property rather than a GlobalId. */
|
|
46
|
+
export const AUTHORED_KEY_PREFIX = 'prop:';
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* defence against a `dataHash` collision retiring an unrelated add/delete pair
|
|
50
|
-
* is agreement on `ifcType` and on every component sub-hash, and the second
|
|
51
|
-
* check is inert unless both sides supply them (see the "Hash collisions"
|
|
52
|
-
* section of `docs/guide/model-diff.md`).
|
|
48
|
+
* Resolve every entity's key under an authored-key spec: `prop:<value>` where
|
|
49
|
+
* the value is present and unique, GlobalId otherwise. Duplicates are reported
|
|
50
|
+
* to the caller rather than silently collapsed by `indexByKey`.
|
|
53
51
|
*/
|
|
54
|
-
export function
|
|
52
|
+
export function resolveAuthoredKeys(store, entities, options) {
|
|
53
|
+
const keys = new Map();
|
|
54
|
+
const spec = options.keyProperty ? parseAuthoredKeySpec(options.keyProperty) : undefined;
|
|
55
|
+
if (!spec) {
|
|
56
|
+
for (const { expressId, globalId } of entities)
|
|
57
|
+
keys.set(expressId, globalId);
|
|
58
|
+
return keys;
|
|
59
|
+
}
|
|
60
|
+
const extractor = new EntityExtractor(store.source);
|
|
61
|
+
const owners = new Map();
|
|
62
|
+
for (const { expressId } of entities) {
|
|
63
|
+
const value = authoredKeyValue(store, expressId, spec, extractor);
|
|
64
|
+
if (value === undefined)
|
|
65
|
+
continue;
|
|
66
|
+
const list = owners.get(value);
|
|
67
|
+
if (list)
|
|
68
|
+
list.push(expressId);
|
|
69
|
+
else
|
|
70
|
+
owners.set(value, [expressId]);
|
|
71
|
+
}
|
|
72
|
+
for (const { expressId, globalId } of entities)
|
|
73
|
+
keys.set(expressId, globalId);
|
|
74
|
+
for (const [value, ids] of owners) {
|
|
75
|
+
if (ids.length === 1) {
|
|
76
|
+
keys.set(ids[0], `${AUTHORED_KEY_PREFIX}${value}`);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
options.duplicateAuthoredKeys?.set(value, ids);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return keys;
|
|
83
|
+
}
|
|
84
|
+
export function buildFileFingerprints(store, options = {}) {
|
|
55
85
|
// Resolved once per store, not per entity: the same `IFCUNITASSIGNMENT` walk
|
|
56
86
|
// every property in the file would otherwise repeat, and both `quantitySiScale`
|
|
57
87
|
// and `scaleMeasureValue` are pure over it. An IfcQuantityLength/Area/Volume
|
|
@@ -61,19 +91,49 @@ export function buildFileFingerprints(store) {
|
|
|
61
91
|
// physical quantity actually changed, reports every quantified/measured
|
|
62
92
|
// entity as `modified` (see `buildDataInput`'s scaling comment).
|
|
63
93
|
const units = extractProjectUnits(store.source, store.entityIndex);
|
|
94
|
+
const entities = [...comparableEntities(store)];
|
|
95
|
+
const keys = resolveAuthoredKeys(store, entities, options);
|
|
64
96
|
const fingerprints = [];
|
|
65
|
-
for (const { expressId, globalId, ifcType, source, isTypeObject } of
|
|
97
|
+
for (const { expressId, globalId, ifcType, source, isTypeObject } of entities) {
|
|
66
98
|
const input = buildDataInput(store, expressId, ifcType, source, isTypeObject, units);
|
|
67
|
-
|
|
68
|
-
key: globalId,
|
|
99
|
+
const fingerprint = {
|
|
100
|
+
key: keys.get(expressId) ?? globalId,
|
|
69
101
|
ifcType,
|
|
70
102
|
dataHash: buildDataFingerprint(input),
|
|
71
103
|
components: buildComponentFingerprints(input),
|
|
72
104
|
ref: expressId,
|
|
73
|
-
}
|
|
105
|
+
};
|
|
106
|
+
// Where the element sits, as a name path (issue #4955). Read for every
|
|
107
|
+
// entity even though only the successor stage consumes it: the adapter
|
|
108
|
+
// does not know which stages the caller will run.
|
|
109
|
+
const container = spatialContainerPath(store, expressId);
|
|
110
|
+
if (container !== undefined)
|
|
111
|
+
fingerprint.container = container;
|
|
112
|
+
fingerprints.push(fingerprint);
|
|
74
113
|
}
|
|
75
114
|
return fingerprints;
|
|
76
115
|
}
|
|
116
|
+
/** A collision discovered in either file invalidates that authored value in
|
|
117
|
+
* both files, including fingerprints already built for the first side. */
|
|
118
|
+
export function fallbackPairDuplicateAuthoredKeys(sides, duplicates) {
|
|
119
|
+
if (duplicates.size === 0)
|
|
120
|
+
return;
|
|
121
|
+
for (const { fingerprints, store } of sides) {
|
|
122
|
+
const globalIds = new Map([...comparableEntities(store)].map((entity) => [entity.expressId, entity.globalId]));
|
|
123
|
+
for (const fingerprint of fingerprints) {
|
|
124
|
+
if (!fingerprint.key.startsWith(AUTHORED_KEY_PREFIX))
|
|
125
|
+
continue;
|
|
126
|
+
const value = fingerprint.key.slice(AUTHORED_KEY_PREFIX.length);
|
|
127
|
+
if (!duplicates.has(value))
|
|
128
|
+
continue;
|
|
129
|
+
const globalId = globalIds.get(fingerprint.ref);
|
|
130
|
+
if (!globalId) {
|
|
131
|
+
throw new Error(`Cannot restore GlobalId for authored-key collision on #${fingerprint.ref}`);
|
|
132
|
+
}
|
|
133
|
+
fingerprint.key = globalId;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
77
137
|
/**
|
|
78
138
|
* Assemble the canonical {@link DataFingerprintInput} for one entity.
|
|
79
139
|
*
|
|
@@ -125,7 +185,7 @@ units) {
|
|
|
125
185
|
.map((typeId) => ({
|
|
126
186
|
globalId: store.entities.getGlobalId(typeId) || undefined,
|
|
127
187
|
name: store.entities.getName(typeId) || undefined,
|
|
128
|
-
type: store.entities
|
|
188
|
+
type: resolvedTypeName(store.entities, typeId),
|
|
129
189
|
}));
|
|
130
190
|
// Resolved classification references (never entity references — see
|
|
131
191
|
// `DataFingerprintInput.classifications`): an `IfcRelAssociatesClassification`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-engine.js","sourceRoot":"","sources":["../../src/commands/diff-engine.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GAIrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"diff-engine.js","sourceRoot":"","sources":["../../src/commands/diff-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { DiffScope, EntityFingerprint } from '@ifc-lite/diff';
|
|
2
|
+
import type { IfcAPI as WasmIfcAPI } from '@ifc-lite/wasm';
|
|
3
|
+
import type { DiffRef } from './diff-engine.js';
|
|
4
|
+
/** Quantization grid for the geometry hash, in metres — the wasm default
|
|
5
|
+
* (`DEFAULT_GEOM_HASH_TOLERANCE` in `@ifc-lite/geometry`), restated here so
|
|
6
|
+
* this module has no runtime dependency on that package. */
|
|
7
|
+
export declare const GEOMETRY_HASH_TOLERANCE = 0.001;
|
|
8
|
+
/** Printed (CLI) or returned (adapters) when `--geometry` cannot run because
|
|
9
|
+
* the wasm runtime is not built on this host — the `.wasm` binary is
|
|
10
|
+
* gitignored and only present after a Rust-capable build. */
|
|
11
|
+
export declare const WASM_RUNTIME_ABSENT_MESSAGE: string;
|
|
12
|
+
export interface WasmRuntime {
|
|
13
|
+
api: WasmIfcAPI;
|
|
14
|
+
}
|
|
15
|
+
export type WasmRuntimeResult = {
|
|
16
|
+
ok: true;
|
|
17
|
+
runtime: WasmRuntime;
|
|
18
|
+
} | {
|
|
19
|
+
ok: false;
|
|
20
|
+
message: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Lazily load and initialize `@ifc-lite/wasm`, returning a ready `IfcAPI` with
|
|
24
|
+
* geometry hashing switched on.
|
|
25
|
+
*
|
|
26
|
+
* Never throws: a missing `.wasm` binary, a missing package resolution, or an
|
|
27
|
+
* init failure all come back as `{ ok: false, message }` so the caller can
|
|
28
|
+
* report a clear, actionable message instead of a raw stack trace. Not
|
|
29
|
+
* memoised — the caller owns the returned `IfcAPI` and must `.free()` it
|
|
30
|
+
* (issue #4956, AGENTS.md "Geometry & WASM").
|
|
31
|
+
*/
|
|
32
|
+
export declare function loadWasmRuntime(): Promise<WasmRuntimeResult>;
|
|
33
|
+
export interface GeometryAabb {
|
|
34
|
+
readonly min: readonly [number, number, number];
|
|
35
|
+
readonly max: readonly [number, number, number];
|
|
36
|
+
}
|
|
37
|
+
/** Per-entity world geometry hashes, boxes and volumes from one wasm mesh
|
|
38
|
+
* pass, keyed by express id. */
|
|
39
|
+
export interface GeometryPassResult {
|
|
40
|
+
hashes: Map<DiffRef, bigint>;
|
|
41
|
+
aabbs: Map<DiffRef, GeometryAabb>;
|
|
42
|
+
volumes: Map<DiffRef, number>;
|
|
43
|
+
unitScale: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Run the wasm geometry pass over one file's bytes and collect per-entity
|
|
47
|
+
* world hashes, boxes and volumes (issue #4956).
|
|
48
|
+
*
|
|
49
|
+
* Ported from `scripts/xmatch/fingerprints.mjs`'s `geometryPass` — see that
|
|
50
|
+
* file's history for why each guard exists: a box with a non-finite
|
|
51
|
+
* coordinate is dropped rather than passed on (a present box must be usable,
|
|
52
|
+
* never a NaN the engine would classify as garbage), and a volume is kept
|
|
53
|
+
* only when finite and positive (`NaN` is the wasm's "not proved closed"
|
|
54
|
+
* sentinel).
|
|
55
|
+
*
|
|
56
|
+
* **Chunked, not one `processGeometryBatch` call over every job.** The naive
|
|
57
|
+
* one-shot version materializes every mesh of the whole file into a single
|
|
58
|
+
* `MeshCollection` before any hash is read, which OOMs on a large model
|
|
59
|
+
* (issue #4956 review) — the same reason the browser worker path never does
|
|
60
|
+
* this either (`@ifc-lite/geometry`'s `processStreamingBytes`, `batch-sizing.ts`).
|
|
61
|
+
* Each `JOBS_PER_BATCH`-sized slice gets its own `MeshCollection`, is read and
|
|
62
|
+
* freed, and only its extracted (hash, aabb, volume) triples survive into the
|
|
63
|
+
* next iteration.
|
|
64
|
+
*
|
|
65
|
+
* The pre-pass call is inside the same `try` the cache-clear `finally`
|
|
66
|
+
* guards: `buildPrePassOnce` can itself throw (a malformed file), and a throw
|
|
67
|
+
* before the `try` would skip `clearPrePassCache()`, carrying whatever partial
|
|
68
|
+
* state it left behind into the next file processed through this `api`.
|
|
69
|
+
*
|
|
70
|
+
* **Installs the source once, rather than passing `bytes` to every chunk's
|
|
71
|
+
* `processGeometryBatch` call.** The legacy call takes `data` positionally and
|
|
72
|
+
* copies it into wasm linear memory on every invocation — fine for one call,
|
|
73
|
+
* but `JOBS_PER_BATCH`-chunking turns that into hundreds of copies of the
|
|
74
|
+
* whole file for a large model (issue #4956 review). `setSourceBytes` +
|
|
75
|
+
* `processGeometryBatchFromSource` is the same lever the browser worker's
|
|
76
|
+
* cold-load path uses (`geometry.worker.ts`'s `applySourceBytesToApi` /
|
|
77
|
+
* `batchFromSourceFn`): install the file ONCE, then every chunk reads it off
|
|
78
|
+
* the wasm heap. Feature-detected — a wasm build that predates the `*FromSource`
|
|
79
|
+
* pair falls back to the legacy per-call `bytes` argument.
|
|
80
|
+
*/
|
|
81
|
+
export declare function runGeometryPass(api: WasmIfcAPI, bytes: Uint8Array): GeometryPassResult;
|
|
82
|
+
/**
|
|
83
|
+
* Attach one file's geometry pass onto the fingerprints already built for it
|
|
84
|
+
* (mutates in place — the fingerprints are freshly built per file, never
|
|
85
|
+
* shared, so this is not a hazard).
|
|
86
|
+
*/
|
|
87
|
+
export declare function attachGeometryFingerprints(fingerprints: readonly EntityFingerprint<DiffRef>[], geometry: GeometryPassResult): void;
|
|
88
|
+
/**
|
|
89
|
+
* The whole `--geometry` opt-in, as one call for `diff-content.ts`: lazily
|
|
90
|
+
* load the runtime, run the pass over both files, attach it to both sets of
|
|
91
|
+
* fingerprints, and report the resulting {@link DiffScope}. A missing runtime
|
|
92
|
+
* is reported through `warn` (a stderr line, not a thrown error) and the
|
|
93
|
+
* scope falls back to `'data'` — the rest of `--by-content` works fine
|
|
94
|
+
* without geometry, exactly as it always has.
|
|
95
|
+
*
|
|
96
|
+
* Frees the `IfcAPI` handle in `finally`, even if a pass throws (AGENTS.md
|
|
97
|
+
* "Geometry & WASM"). A pass that throws — a malformed or truncated model,
|
|
98
|
+
* or an internal wasm panic surfaced as a JS error — degrades to `'data'`
|
|
99
|
+
* scope with a warning rather than aborting the whole `--by-content` command
|
|
100
|
+
* (issue #4956 review): `--geometry` is opt-in extra evidence, and the
|
|
101
|
+
* data-only comparison underneath it is still a useful answer. Any
|
|
102
|
+
* `geometryHash`/`aabb`/`volume` a partial pass DID manage to attach before
|
|
103
|
+
* throwing is harmless left attached — `scope: 'data'` takes geometry out of
|
|
104
|
+
* the comparison regardless of what individual fingerprints carry.
|
|
105
|
+
*/
|
|
106
|
+
export declare function resolveGeometryScope(enabled: boolean, baseBytes: Uint8Array, headBytes: Uint8Array, baseFingerprints: readonly EntityFingerprint<DiffRef>[], headFingerprints: readonly EntityFingerprint<DiffRef>[], warn: (message: string) => void): Promise<DiffScope>;
|
|
107
|
+
//# sourceMappingURL=diff-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-geometry.d.ts","sourceRoot":"","sources":["../../src/commands/diff-geometry.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;6DAE6D;AAC7D,eAAO,MAAM,uBAAuB,QAAO,CAAC;AAE5C;;8DAE8D;AAC9D,eAAO,MAAM,2BAA2B,QAGsC,CAAC;AAE/E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;;;;;;GASG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAmClE;AAuBD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACjD;AAED;iCACiC;AACjC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAClC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAuGtF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE,EACnD,QAAQ,EAAE,kBAAkB,GAC3B,IAAI,CASN;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,UAAU,EACrB,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE,EACvD,gBAAgB,EAAE,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE,EACvD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC9B,OAAO,CAAC,SAAS,CAAC,CAiBpB"}
|
|
@@ -0,0 +1,262 @@
|
|
|
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
|
+
* The `--geometry` half of `ifc-lite diff --by-content` (issue #4956).
|
|
6
|
+
*
|
|
7
|
+
* `diff-engine.ts` builds DATA-scope fingerprints only — the Node CLI has no
|
|
8
|
+
* geometry pipeline of its own, so every geometry-backed tier of
|
|
9
|
+
* `@ifc-lite/diff` (`renamed` on world geometry hash, `moved`/`reshaped`,
|
|
10
|
+
* split/merge, successors) abstains under `scope: 'data'`. This module is the
|
|
11
|
+
* missing pipeline: it loads `@ifc-lite/wasm` LAZILY (only when `--geometry` is
|
|
12
|
+
* passed — most invocations of this command never touch wasm at all), runs the
|
|
13
|
+
* same mesh pass the viewer's compare uses (`setComputeGeometryHashes` +
|
|
14
|
+
* `buildPrePassOnce` + `processGeometryBatch`), and attaches `geometryHash`,
|
|
15
|
+
* `aabb` and `volume` to fingerprints the caller already built.
|
|
16
|
+
*
|
|
17
|
+
* `scripts/xmatch/fingerprints.mjs` imports this module's compiled output
|
|
18
|
+
* rather than re-implementing the pass — see that file's header.
|
|
19
|
+
*/
|
|
20
|
+
import { createRequire } from 'node:module';
|
|
21
|
+
import { readFile } from 'node:fs/promises';
|
|
22
|
+
/** Quantization grid for the geometry hash, in metres — the wasm default
|
|
23
|
+
* (`DEFAULT_GEOM_HASH_TOLERANCE` in `@ifc-lite/geometry`), restated here so
|
|
24
|
+
* this module has no runtime dependency on that package. */
|
|
25
|
+
export const GEOMETRY_HASH_TOLERANCE = 1e-3;
|
|
26
|
+
/** Printed (CLI) or returned (adapters) when `--geometry` cannot run because
|
|
27
|
+
* the wasm runtime is not built on this host — the `.wasm` binary is
|
|
28
|
+
* gitignored and only present after a Rust-capable build. */
|
|
29
|
+
export const WASM_RUNTIME_ABSENT_MESSAGE = '--geometry requires the @ifc-lite/wasm runtime, which is not built on this host ' +
|
|
30
|
+
'(packages/wasm/pkg/ifc-lite_bg.wasm is missing). Run `pnpm build:wasm:fetch` to fetch ' +
|
|
31
|
+
'a prebuilt binary, or `pnpm build:wasm` with the Rust toolchain installed.';
|
|
32
|
+
/**
|
|
33
|
+
* Lazily load and initialize `@ifc-lite/wasm`, returning a ready `IfcAPI` with
|
|
34
|
+
* geometry hashing switched on.
|
|
35
|
+
*
|
|
36
|
+
* Never throws: a missing `.wasm` binary, a missing package resolution, or an
|
|
37
|
+
* init failure all come back as `{ ok: false, message }` so the caller can
|
|
38
|
+
* report a clear, actionable message instead of a raw stack trace. Not
|
|
39
|
+
* memoised — the caller owns the returned `IfcAPI` and must `.free()` it
|
|
40
|
+
* (issue #4956, AGENTS.md "Geometry & WASM").
|
|
41
|
+
*/
|
|
42
|
+
export async function loadWasmRuntime() {
|
|
43
|
+
let wasmPath;
|
|
44
|
+
try {
|
|
45
|
+
wasmPath = createRequire(import.meta.url).resolve('@ifc-lite/wasm/ifc-lite_bg.wasm');
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return { ok: false, message: WASM_RUNTIME_ABSENT_MESSAGE };
|
|
49
|
+
}
|
|
50
|
+
let bytes;
|
|
51
|
+
try {
|
|
52
|
+
bytes = await readFile(wasmPath);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return { ok: false, message: WASM_RUNTIME_ABSENT_MESSAGE };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const wasmModule = await import('@ifc-lite/wasm');
|
|
59
|
+
wasmModule.initSync({ module: bytes });
|
|
60
|
+
// Constructed before the next call that can throw, so a failure past this
|
|
61
|
+
// point has a handle to free rather than leaking it (AGENTS.md "Geometry
|
|
62
|
+
// & WASM").
|
|
63
|
+
const api = new wasmModule.IfcAPI();
|
|
64
|
+
try {
|
|
65
|
+
api.setComputeGeometryHashes(GEOMETRY_HASH_TOLERANCE);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
api.free();
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return { ok: true, runtime: { api } };
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
message: `${WASM_RUNTIME_ABSENT_MESSAGE} (init failed: ${error.message})`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Number of jobs sent to one `processGeometryBatch` call.
|
|
82
|
+
*
|
|
83
|
+
* Matches `DEFAULT_BATCH_SIZING.maxJobs` in `@ifc-lite/geometry`'s
|
|
84
|
+
* `batch-sizing.ts` — the cap the browser worker's adaptive sizer clamps every
|
|
85
|
+
* call to, tuned on the largest real models so one call's meshes stay a
|
|
86
|
+
* bounded slice of the file rather than the whole thing. Restated here
|
|
87
|
+
* (rather than imported) because that module is internal to the geometry
|
|
88
|
+
* worker's streaming path and not part of `@ifc-lite/geometry`'s public
|
|
89
|
+
* surface; kept in sync by citing the source. This path has no adaptive
|
|
90
|
+
* timing to resize it (a one-shot CLI pass, not a watchdog-bounded worker), so
|
|
91
|
+
* it is a fixed cap rather than the worker's targetMs-driven adaptive size.
|
|
92
|
+
*/
|
|
93
|
+
const JOBS_PER_BATCH = 512;
|
|
94
|
+
/** Uint32 slots per job in `PrePassResult.jobs` — see `prePass.jobs.slice(startJob
|
|
95
|
+
* * JOB_STRIDE, endJob * JOB_STRIDE)` in `@ifc-lite/geometry`'s `processStreamingBytes`. */
|
|
96
|
+
const JOB_STRIDE = 3;
|
|
97
|
+
/**
|
|
98
|
+
* Run the wasm geometry pass over one file's bytes and collect per-entity
|
|
99
|
+
* world hashes, boxes and volumes (issue #4956).
|
|
100
|
+
*
|
|
101
|
+
* Ported from `scripts/xmatch/fingerprints.mjs`'s `geometryPass` — see that
|
|
102
|
+
* file's history for why each guard exists: a box with a non-finite
|
|
103
|
+
* coordinate is dropped rather than passed on (a present box must be usable,
|
|
104
|
+
* never a NaN the engine would classify as garbage), and a volume is kept
|
|
105
|
+
* only when finite and positive (`NaN` is the wasm's "not proved closed"
|
|
106
|
+
* sentinel).
|
|
107
|
+
*
|
|
108
|
+
* **Chunked, not one `processGeometryBatch` call over every job.** The naive
|
|
109
|
+
* one-shot version materializes every mesh of the whole file into a single
|
|
110
|
+
* `MeshCollection` before any hash is read, which OOMs on a large model
|
|
111
|
+
* (issue #4956 review) — the same reason the browser worker path never does
|
|
112
|
+
* this either (`@ifc-lite/geometry`'s `processStreamingBytes`, `batch-sizing.ts`).
|
|
113
|
+
* Each `JOBS_PER_BATCH`-sized slice gets its own `MeshCollection`, is read and
|
|
114
|
+
* freed, and only its extracted (hash, aabb, volume) triples survive into the
|
|
115
|
+
* next iteration.
|
|
116
|
+
*
|
|
117
|
+
* The pre-pass call is inside the same `try` the cache-clear `finally`
|
|
118
|
+
* guards: `buildPrePassOnce` can itself throw (a malformed file), and a throw
|
|
119
|
+
* before the `try` would skip `clearPrePassCache()`, carrying whatever partial
|
|
120
|
+
* state it left behind into the next file processed through this `api`.
|
|
121
|
+
*
|
|
122
|
+
* **Installs the source once, rather than passing `bytes` to every chunk's
|
|
123
|
+
* `processGeometryBatch` call.** The legacy call takes `data` positionally and
|
|
124
|
+
* copies it into wasm linear memory on every invocation — fine for one call,
|
|
125
|
+
* but `JOBS_PER_BATCH`-chunking turns that into hundreds of copies of the
|
|
126
|
+
* whole file for a large model (issue #4956 review). `setSourceBytes` +
|
|
127
|
+
* `processGeometryBatchFromSource` is the same lever the browser worker's
|
|
128
|
+
* cold-load path uses (`geometry.worker.ts`'s `applySourceBytesToApi` /
|
|
129
|
+
* `batchFromSourceFn`): install the file ONCE, then every chunk reads it off
|
|
130
|
+
* the wasm heap. Feature-detected — a wasm build that predates the `*FromSource`
|
|
131
|
+
* pair falls back to the legacy per-call `bytes` argument.
|
|
132
|
+
*/
|
|
133
|
+
export function runGeometryPass(api, bytes) {
|
|
134
|
+
const hashes = new Map();
|
|
135
|
+
const aabbs = new Map();
|
|
136
|
+
const volumes = new Map();
|
|
137
|
+
let unitScale = 1;
|
|
138
|
+
const useSource = typeof api.setSourceBytes === 'function' &&
|
|
139
|
+
typeof api.processGeometryBatchFromSource === 'function';
|
|
140
|
+
if (useSource)
|
|
141
|
+
api.setSourceBytes(bytes);
|
|
142
|
+
try {
|
|
143
|
+
const pre = api.buildPrePassOnce(bytes);
|
|
144
|
+
unitScale = pre?.unitScale ?? 1;
|
|
145
|
+
const total = pre?.totalJobs ?? 0;
|
|
146
|
+
if (!pre || !pre.jobs || total === 0)
|
|
147
|
+
return { hashes, aabbs, volumes, unitScale };
|
|
148
|
+
const rtcOffset = pre.rtcOffset ? Array.from(pre.rtcOffset) : [0, 0, 0];
|
|
149
|
+
const [rtcX, rtcY, rtcZ] = rtcOffset;
|
|
150
|
+
const voidKeys = pre.voidKeys ?? new Uint32Array(0);
|
|
151
|
+
const voidCounts = pre.voidCounts ?? new Uint32Array(0);
|
|
152
|
+
const voidValues = pre.voidValues ?? new Uint32Array(0);
|
|
153
|
+
const styleIds = pre.styleIds ?? new Uint32Array(0);
|
|
154
|
+
const styleColors = pre.styleColors ?? new Uint8Array(0);
|
|
155
|
+
for (let startJob = 0; startJob < total; startJob += JOBS_PER_BATCH) {
|
|
156
|
+
const endJob = Math.min(startJob + JOBS_PER_BATCH, total);
|
|
157
|
+
const jobSlice = pre.jobs.slice(startJob * JOB_STRIDE, endJob * JOB_STRIDE);
|
|
158
|
+
const collection = useSource
|
|
159
|
+
? api.processGeometryBatchFromSource(jobSlice, pre.unitScale ?? 1, rtcX, rtcY, rtcZ, pre.needsShift ?? false, voidKeys, voidCounts, voidValues, styleIds, styleColors, pre.planeAngleToRadians, pre.materialElementIds, pre.materialColorCounts, pre.materialColors)
|
|
160
|
+
: api.processGeometryBatch(bytes, jobSlice, pre.unitScale ?? 1, rtcX, rtcY, rtcZ, pre.needsShift ?? false, voidKeys, voidCounts, voidValues, styleIds, styleColors, pre.planeAngleToRadians, pre.materialElementIds, pre.materialColorCounts, pre.materialColors);
|
|
161
|
+
try {
|
|
162
|
+
const ids = collection.geometryHashIds;
|
|
163
|
+
const values = collection.geometryHashValues;
|
|
164
|
+
const boxes = collection.geometryAabbValues;
|
|
165
|
+
// Optional getter (issue #4955): a wasm build that predates it
|
|
166
|
+
// answers `undefined`, and volumes simply stay empty rather than
|
|
167
|
+
// throwing.
|
|
168
|
+
const volumeValues = collection.geometryVolumeValues;
|
|
169
|
+
for (let i = 0; i < ids.length; i++) {
|
|
170
|
+
hashes.set(ids[i], values[i]);
|
|
171
|
+
const volume = volumeValues?.[i];
|
|
172
|
+
if (volume !== undefined && Number.isFinite(volume) && volume > 0) {
|
|
173
|
+
volumes.set(ids[i], volume);
|
|
174
|
+
}
|
|
175
|
+
// Same optional-getter rule as volumes: no boxes, keep the hashes.
|
|
176
|
+
const box = boxes ? Array.from(boxes.slice(6 * i, 6 * i + 6)) : [];
|
|
177
|
+
if (box.length === 6 && box.every((value) => Number.isFinite(value))) {
|
|
178
|
+
aabbs.set(ids[i], {
|
|
179
|
+
min: [box[0], box[1], box[2]],
|
|
180
|
+
max: [box[3], box[4], box[5]],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
// Freed before the next chunk's call, not batched up with the rest —
|
|
187
|
+
// this is the whole point of chunking: at most one batch's meshes
|
|
188
|
+
// are live in wasm memory at a time.
|
|
189
|
+
collection.free();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
if (api.clearPrePassCache)
|
|
195
|
+
api.clearPrePassCache();
|
|
196
|
+
// `setSourceBytes` "REPLACES the previous file wholesale" (its own doc
|
|
197
|
+
// comment) — there is no dedicated release call, so installing an empty
|
|
198
|
+
// buffer is how this drops its reference to a possibly large file instead
|
|
199
|
+
// of leaving it resident on the wasm heap for the rest of the process.
|
|
200
|
+
if (useSource)
|
|
201
|
+
api.setSourceBytes(new Uint8Array(0));
|
|
202
|
+
}
|
|
203
|
+
return { hashes, aabbs, volumes, unitScale };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Attach one file's geometry pass onto the fingerprints already built for it
|
|
207
|
+
* (mutates in place — the fingerprints are freshly built per file, never
|
|
208
|
+
* shared, so this is not a hazard).
|
|
209
|
+
*/
|
|
210
|
+
export function attachGeometryFingerprints(fingerprints, geometry) {
|
|
211
|
+
for (const fingerprint of fingerprints) {
|
|
212
|
+
const hash = geometry.hashes.get(fingerprint.ref);
|
|
213
|
+
if (hash !== undefined)
|
|
214
|
+
fingerprint.geometryHash = hash;
|
|
215
|
+
const aabb = geometry.aabbs.get(fingerprint.ref);
|
|
216
|
+
if (aabb !== undefined)
|
|
217
|
+
fingerprint.aabb = aabb;
|
|
218
|
+
const volume = geometry.volumes.get(fingerprint.ref);
|
|
219
|
+
if (volume !== undefined)
|
|
220
|
+
fingerprint.volume = volume;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The whole `--geometry` opt-in, as one call for `diff-content.ts`: lazily
|
|
225
|
+
* load the runtime, run the pass over both files, attach it to both sets of
|
|
226
|
+
* fingerprints, and report the resulting {@link DiffScope}. A missing runtime
|
|
227
|
+
* is reported through `warn` (a stderr line, not a thrown error) and the
|
|
228
|
+
* scope falls back to `'data'` — the rest of `--by-content` works fine
|
|
229
|
+
* without geometry, exactly as it always has.
|
|
230
|
+
*
|
|
231
|
+
* Frees the `IfcAPI` handle in `finally`, even if a pass throws (AGENTS.md
|
|
232
|
+
* "Geometry & WASM"). A pass that throws — a malformed or truncated model,
|
|
233
|
+
* or an internal wasm panic surfaced as a JS error — degrades to `'data'`
|
|
234
|
+
* scope with a warning rather than aborting the whole `--by-content` command
|
|
235
|
+
* (issue #4956 review): `--geometry` is opt-in extra evidence, and the
|
|
236
|
+
* data-only comparison underneath it is still a useful answer. Any
|
|
237
|
+
* `geometryHash`/`aabb`/`volume` a partial pass DID manage to attach before
|
|
238
|
+
* throwing is harmless left attached — `scope: 'data'` takes geometry out of
|
|
239
|
+
* the comparison regardless of what individual fingerprints carry.
|
|
240
|
+
*/
|
|
241
|
+
export async function resolveGeometryScope(enabled, baseBytes, headBytes, baseFingerprints, headFingerprints, warn) {
|
|
242
|
+
if (!enabled)
|
|
243
|
+
return 'data';
|
|
244
|
+
const runtime = await loadWasmRuntime();
|
|
245
|
+
if (!runtime.ok) {
|
|
246
|
+
warn(runtime.message);
|
|
247
|
+
return 'data';
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
attachGeometryFingerprints(baseFingerprints, runGeometryPass(runtime.runtime.api, baseBytes));
|
|
251
|
+
attachGeometryFingerprints(headFingerprints, runGeometryPass(runtime.runtime.api, headBytes));
|
|
252
|
+
return 'both';
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
warn(`--geometry failed (${error.message}); continuing with data scope.`);
|
|
256
|
+
return 'data';
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
runtime.runtime.api.free();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=diff-geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-geometry.js","sourceRoot":"","sources":["../../src/commands/diff-geometry.ts"],"names":[],"mappings":"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"}
|