@ifc-lite/collab 0.2.7 → 0.3.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/doc/entity.d.ts +14 -0
- package/dist/doc/entity.d.ts.map +1 -1
- package/dist/doc/entity.js +127 -5
- package/dist/doc/entity.js.map +1 -1
- package/dist/snapshot/from-ifcx.d.ts.map +1 -1
- package/dist/snapshot/from-ifcx.js +34 -2
- package/dist/snapshot/from-ifcx.js.map +1 -1
- package/dist/snapshot/index.d.ts +2 -0
- package/dist/snapshot/index.d.ts.map +1 -1
- package/dist/snapshot/index.js +2 -0
- package/dist/snapshot/index.js.map +1 -1
- package/dist/snapshot/minimal-layer.d.ts +20 -4
- package/dist/snapshot/minimal-layer.d.ts.map +1 -1
- package/dist/snapshot/minimal-layer.js +113 -70
- package/dist/snapshot/minimal-layer.js.map +1 -1
- package/dist/snapshot/publish-layer.d.ts +60 -0
- package/dist/snapshot/publish-layer.d.ts.map +1 -0
- package/dist/snapshot/publish-layer.js +43 -0
- package/dist/snapshot/publish-layer.js.map +1 -0
- package/dist/snapshot/structured-attrs.d.ts +107 -0
- package/dist/snapshot/structured-attrs.d.ts.map +1 -0
- package/dist/snapshot/structured-attrs.js +250 -0
- package/dist/snapshot/structured-attrs.js.map +1 -0
- package/dist/snapshot/to-ifcx.d.ts +4 -0
- package/dist/snapshot/to-ifcx.d.ts.map +1 -1
- package/dist/snapshot/to-ifcx.js +5 -2
- package/dist/snapshot/to-ifcx.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { IFCLITE_ATTR } from '@ifc-lite/ifcx';
|
|
4
5
|
import * as Y from 'yjs';
|
|
5
6
|
import { createCollabDoc, entitiesMap } from '../doc/schema.js';
|
|
6
7
|
import { entityToJSON } from '../doc/entity.js';
|
|
7
8
|
import { snapshotToIfcx } from './to-ifcx.js';
|
|
9
|
+
import { flattenStructuredBranches, geometryRecordLookup } from './structured-attrs.js';
|
|
8
10
|
/**
|
|
9
11
|
* Build a minimal IFCX layer expressing the diff between `baseline`
|
|
10
12
|
* and `doc`. `baseline` is whatever `Y.encodeStateAsUpdate(doc)`
|
|
@@ -12,85 +14,126 @@ import { snapshotToIfcx } from './to-ifcx.js';
|
|
|
12
14
|
*/
|
|
13
15
|
export function extractMinimalLayer(doc, baseline, options = {}) {
|
|
14
16
|
const includeUpdatedValues = options.includeUpdatedValues ?? true;
|
|
17
|
+
const includeDeletions = options.includeDeletions ?? true;
|
|
15
18
|
// Reconstruct the "before" state by replaying the baseline update on
|
|
16
19
|
// a fresh doc.
|
|
17
20
|
const before = createCollabDoc({ gc: false });
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
try {
|
|
22
|
+
if (baseline.byteLength > 0)
|
|
23
|
+
Y.applyUpdate(before, baseline);
|
|
24
|
+
// Snapshot the live doc through the standard writer so we get a
|
|
25
|
+
// header + imports + schemas template, then trim the data array down
|
|
26
|
+
// to the diff.
|
|
27
|
+
const live = snapshotToIfcx(doc, options.snapshot);
|
|
28
|
+
const beforeEnts = entitiesMap(before);
|
|
29
|
+
const liveEnts = entitiesMap(doc);
|
|
30
|
+
const liveGeometryFor = geometryRecordLookup(doc);
|
|
31
|
+
const beforeGeometryFor = geometryRecordLookup(before);
|
|
32
|
+
const diffNodes = [];
|
|
33
|
+
liveEnts.forEach((entUntyped, path) => {
|
|
34
|
+
const liveJson = entityToJSON(entUntyped);
|
|
35
|
+
// Diff over the flattened attribute view so structured-branch
|
|
36
|
+
// edits (psets / quantities / classifications / materials /
|
|
37
|
+
// geometryRef) surface exactly like the full writer emits them —
|
|
38
|
+
// the two writers stay in lockstep by construction (#1031).
|
|
39
|
+
const liveAttrs = flattenStructuredBranches(liveJson, { geometryRecordFor: liveGeometryFor });
|
|
40
|
+
const beforeUntyped = beforeEnts.get(path);
|
|
41
|
+
if (!beforeUntyped) {
|
|
42
|
+
// Entity is new — emit it whole (sans empty branches).
|
|
43
|
+
const node = { path };
|
|
44
|
+
if (Object.keys(liveAttrs).length > 0)
|
|
45
|
+
node.attributes = liveAttrs;
|
|
46
|
+
if (Object.keys(liveJson.children).length > 0)
|
|
47
|
+
node.children = { ...liveJson.children };
|
|
48
|
+
if (Object.keys(liveJson.inherits).length > 0)
|
|
49
|
+
node.inherits = { ...liveJson.inherits };
|
|
50
|
+
diffNodes.push(node);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const beforeJson = entityToJSON(beforeUntyped);
|
|
54
|
+
const beforeAttrs = flattenStructuredBranches(beforeJson, { geometryRecordFor: beforeGeometryFor });
|
|
32
55
|
const node = { path };
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// whose value changed.
|
|
47
|
-
const addedAttrs = {};
|
|
48
|
-
for (const [key, value] of Object.entries(liveJson.attributes)) {
|
|
49
|
-
const wasInBaseline = key in beforeJson.attributes;
|
|
50
|
-
if (!wasInBaseline) {
|
|
51
|
-
addedAttrs[key] = value;
|
|
52
|
-
continue;
|
|
56
|
+
let dirty = false;
|
|
57
|
+
// Attributes: include keys that are new OR (when configured)
|
|
58
|
+
// whose value changed; removed keys emit null.
|
|
59
|
+
const addedAttrs = {};
|
|
60
|
+
for (const [key, value] of Object.entries(liveAttrs)) {
|
|
61
|
+
const wasInBaseline = key in beforeAttrs;
|
|
62
|
+
if (!wasInBaseline) {
|
|
63
|
+
addedAttrs[key] = value;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (includeUpdatedValues && !deepEqual(value, beforeAttrs[key])) {
|
|
67
|
+
addedAttrs[key] = value;
|
|
68
|
+
}
|
|
53
69
|
}
|
|
54
|
-
if (
|
|
55
|
-
|
|
70
|
+
if (includeDeletions) {
|
|
71
|
+
for (const key of Object.keys(beforeAttrs)) {
|
|
72
|
+
if (!(key in liveAttrs))
|
|
73
|
+
addedAttrs[key] = null;
|
|
74
|
+
}
|
|
56
75
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
dirty = true;
|
|
61
|
-
}
|
|
62
|
-
// Children: same rule.
|
|
63
|
-
const addedChildren = {};
|
|
64
|
-
for (const [role, child] of Object.entries(liveJson.children)) {
|
|
65
|
-
const wasInBaseline = role in beforeJson.children;
|
|
66
|
-
if (!wasInBaseline || (includeUpdatedValues && beforeJson.children[role] !== child)) {
|
|
67
|
-
addedChildren[role] = child;
|
|
76
|
+
if (Object.keys(addedAttrs).length > 0) {
|
|
77
|
+
node.attributes = addedAttrs;
|
|
78
|
+
dirty = true;
|
|
68
79
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (const [role, inh] of Object.entries(liveJson.inherits)) {
|
|
77
|
-
const wasInBaseline = role in beforeJson.inherits;
|
|
78
|
-
if (!wasInBaseline || (includeUpdatedValues && beforeJson.inherits[role] !== inh)) {
|
|
79
|
-
addedInherits[role] = inh;
|
|
80
|
+
// Children: same rule; removed roles emit null (IFCX removal).
|
|
81
|
+
const addedChildren = {};
|
|
82
|
+
for (const [role, child] of Object.entries(liveJson.children)) {
|
|
83
|
+
const wasInBaseline = role in beforeJson.children;
|
|
84
|
+
if (!wasInBaseline || (includeUpdatedValues && beforeJson.children[role] !== child)) {
|
|
85
|
+
addedChildren[role] = child;
|
|
86
|
+
}
|
|
80
87
|
}
|
|
88
|
+
if (includeDeletions) {
|
|
89
|
+
for (const role of Object.keys(beforeJson.children)) {
|
|
90
|
+
if (!(role in liveJson.children))
|
|
91
|
+
addedChildren[role] = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (Object.keys(addedChildren).length > 0) {
|
|
95
|
+
node.children = addedChildren;
|
|
96
|
+
dirty = true;
|
|
97
|
+
}
|
|
98
|
+
// Inherits: same rule.
|
|
99
|
+
const addedInherits = {};
|
|
100
|
+
for (const [role, inh] of Object.entries(liveJson.inherits)) {
|
|
101
|
+
const wasInBaseline = role in beforeJson.inherits;
|
|
102
|
+
if (!wasInBaseline || (includeUpdatedValues && beforeJson.inherits[role] !== inh)) {
|
|
103
|
+
addedInherits[role] = inh;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (includeDeletions) {
|
|
107
|
+
for (const role of Object.keys(beforeJson.inherits)) {
|
|
108
|
+
if (!(role in liveJson.inherits))
|
|
109
|
+
addedInherits[role] = null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (Object.keys(addedInherits).length > 0) {
|
|
113
|
+
node.inherits = addedInherits;
|
|
114
|
+
dirty = true;
|
|
115
|
+
}
|
|
116
|
+
if (dirty)
|
|
117
|
+
diffNodes.push(node);
|
|
118
|
+
});
|
|
119
|
+
// Entities deleted since the baseline: tombstone opinions that shadow
|
|
120
|
+
// the entity (and its subtree) when the stack composes.
|
|
121
|
+
if (includeDeletions) {
|
|
122
|
+
beforeEnts.forEach((_entUntyped, path) => {
|
|
123
|
+
if (!liveEnts.has(path)) {
|
|
124
|
+
diffNodes.push({ path, attributes: { [IFCLITE_ATTR.DELETED]: true } });
|
|
125
|
+
}
|
|
126
|
+
});
|
|
81
127
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
...live,
|
|
92
|
-
data: diffNodes,
|
|
93
|
-
};
|
|
128
|
+
return {
|
|
129
|
+
...live,
|
|
130
|
+
data: diffNodes,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
// Deterministic cleanup even when extraction throws.
|
|
135
|
+
before.destroy();
|
|
136
|
+
}
|
|
94
137
|
}
|
|
95
138
|
/**
|
|
96
139
|
* Heuristic deep-equal: handles primitives, arrays, and plain objects.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"minimal-layer.js","sourceRoot":"","sources":["../../src/snapshot/minimal-layer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;
|
|
1
|
+
{"version":3,"file":"minimal-layer.js","sourceRoot":"","sources":["../../src/snapshot/minimal-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* publishLayer: freeze a draft into an immutable, content-addressed,
|
|
3
|
+
* provenance-stamped layer.
|
|
4
|
+
*
|
|
5
|
+
* The draft is a CRDT session (Y.Doc) bound to a base; freezing extracts
|
|
6
|
+
* the minimal layer (including deletion overlays), attaches the
|
|
7
|
+
* provenance manifest (intent, author, scope claims, base, checks), and
|
|
8
|
+
* content-addresses the result: `layerId = blake3(canonical_bytes)`.
|
|
9
|
+
*
|
|
10
|
+
* Check execution and scope-claim verification happen at the calling
|
|
11
|
+
* boundary (MCP/CLI/registry) — pass the results in; they are recorded
|
|
12
|
+
* in the manifest, and signatures never participate in the id.
|
|
13
|
+
*
|
|
14
|
+
* Spec: docs/architecture/layer-prs/02-layer-format.md §2.4,
|
|
15
|
+
* 03-provenance.md, 06-agents.md §6.2.
|
|
16
|
+
*/
|
|
17
|
+
import type { IfcxFile, ProvenanceAuthor, ProvenanceBase, ProvenanceCheck, ProvenanceManifest } from '@ifc-lite/ifcx';
|
|
18
|
+
import type * as Y from 'yjs';
|
|
19
|
+
import { type ExtractMinimalLayerOptions } from './minimal-layer.js';
|
|
20
|
+
export interface PublishLayerOptions {
|
|
21
|
+
/** Human-readable why. Mandatory — the `ifc layer log` line. */
|
|
22
|
+
intent: string;
|
|
23
|
+
/** Who authored the draft (human / agent / hybrid). */
|
|
24
|
+
author: ProvenanceAuthor;
|
|
25
|
+
/**
|
|
26
|
+
* Baseline the draft was forked from
|
|
27
|
+
* (`Y.encodeStateAsUpdate` / `captureBaseline` output).
|
|
28
|
+
*/
|
|
29
|
+
baseline: Uint8Array;
|
|
30
|
+
/** Identity of the base layer/stack the draft was authored against. */
|
|
31
|
+
base?: ProvenanceBase | null;
|
|
32
|
+
/** Capability-grammar scope claims declared for this layer. */
|
|
33
|
+
scope_claim?: string[];
|
|
34
|
+
/** Results of declared checks, run by the caller before publishing. */
|
|
35
|
+
checks?: ProvenanceCheck[];
|
|
36
|
+
/** blake3 digest of the prompt/task text that produced the layer. */
|
|
37
|
+
instructions_digest?: string;
|
|
38
|
+
/** Parent layer ids in the change DAG (defaults to the base id). */
|
|
39
|
+
parents?: string[];
|
|
40
|
+
/** Manifest timestamp override (defaults to now). */
|
|
41
|
+
created?: string;
|
|
42
|
+
/** Forwarded to the minimal-layer extractor. */
|
|
43
|
+
extract?: ExtractMinimalLayerOptions;
|
|
44
|
+
}
|
|
45
|
+
export interface PublishedLayer {
|
|
46
|
+
/** The immutable layer document, `header.id` set to the content address. */
|
|
47
|
+
file: IfcxFile;
|
|
48
|
+
/** `blake3:` content address over canonical bytes. */
|
|
49
|
+
layerId: string;
|
|
50
|
+
manifest: ProvenanceManifest;
|
|
51
|
+
/** Number of changed nodes the layer carries. */
|
|
52
|
+
opCount: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Freeze a draft doc into a published layer. Pure with respect to the
|
|
56
|
+
* draft: the Y.Doc is read, never mutated — publishing again after more
|
|
57
|
+
* edits produces a new layer with a new id.
|
|
58
|
+
*/
|
|
59
|
+
export declare function publishLayer(doc: Y.Doc, options: PublishLayerOptions): PublishedLayer;
|
|
60
|
+
//# sourceMappingURL=publish-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-layer.d.ts","sourceRoot":"","sources":["../../src/snapshot/publish-layer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,KAAK,CAAC,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAuB,KAAK,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;OAGG;IACH,QAAQ,EAAE,UAAU,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,uEAAuE;IACvE,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,CAAC,EAAE,0BAA0B,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,IAAI,EAAE,QAAQ,CAAC;IACf,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAkCrF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { computeLayerId, createProvenanceManifest, setProvenance } from '@ifc-lite/ifcx';
|
|
5
|
+
import { extractMinimalLayer } from './minimal-layer.js';
|
|
6
|
+
/**
|
|
7
|
+
* Freeze a draft doc into a published layer. Pure with respect to the
|
|
8
|
+
* draft: the Y.Doc is read, never mutated — publishing again after more
|
|
9
|
+
* edits produces a new layer with a new id.
|
|
10
|
+
*/
|
|
11
|
+
export function publishLayer(doc, options) {
|
|
12
|
+
const delta = extractMinimalLayer(doc, options.baseline, options.extract);
|
|
13
|
+
const manifest = createProvenanceManifest({
|
|
14
|
+
author: options.author,
|
|
15
|
+
intent: options.intent,
|
|
16
|
+
base: options.base ?? null,
|
|
17
|
+
created: options.created,
|
|
18
|
+
parents: options.parents ?? (options.base ? [options.base.id] : []),
|
|
19
|
+
scope_claim: options.scope_claim ?? [],
|
|
20
|
+
checks: options.checks ?? [],
|
|
21
|
+
instructions_digest: options.instructions_digest,
|
|
22
|
+
});
|
|
23
|
+
// Normalize the generated snapshot header to the publish event so the
|
|
24
|
+
// content address is a function of content + manifest, not of when the
|
|
25
|
+
// snapshot writer happened to run.
|
|
26
|
+
const normalized = {
|
|
27
|
+
...delta,
|
|
28
|
+
header: {
|
|
29
|
+
...delta.header,
|
|
30
|
+
author: options.author.principal,
|
|
31
|
+
timestamp: manifest.created,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const withManifest = setProvenance(normalized, manifest);
|
|
35
|
+
const layerId = computeLayerId(withManifest);
|
|
36
|
+
return {
|
|
37
|
+
file: { ...withManifest, header: { ...withManifest.header, id: layerId } },
|
|
38
|
+
layerId,
|
|
39
|
+
manifest,
|
|
40
|
+
opCount: delta.data.length,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=publish-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-layer.js","sourceRoot":"","sources":["../../src/snapshot/publish-layer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA0B/D,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEzF,OAAO,EAAE,mBAAmB,EAAmC,MAAM,oBAAoB,CAAC;AAsC1F;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAU,EAAE,OAA4B;IACnE,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;QACtC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;IAEH,sEAAsE;IACtE,uEAAuE;IACvE,mCAAmC;IACnC,MAAM,UAAU,GAAa;QAC3B,GAAG,KAAK;QACR,MAAM,EAAE;YACN,GAAG,KAAK,CAAC,MAAM;YACf,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS;YAChC,SAAS,EAAE,QAAQ,CAAC,OAAO;SAC5B;KACF,CAAC;IACF,MAAM,YAAY,GAAG,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;QAC1E,OAAO;QACP,QAAQ;QACR,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured-branch ↔ namespaced-attribute conversion (#1031).
|
|
3
|
+
*
|
|
4
|
+
* The Y.Doc keeps psets / quantities / classifications / materials /
|
|
5
|
+
* geometryRef as dedicated CRDT branches so concurrent edits to
|
|
6
|
+
* different branches never conflict, but the IFCX wire type only has
|
|
7
|
+
* `attributes` / `children` / `inherits`. At the snapshot boundary the
|
|
8
|
+
* structured branches fold into ordinary attributes; `seedFromIfcx`
|
|
9
|
+
* re-inflates them, so structured edits survive snapshot → seed
|
|
10
|
+
* round-trips.
|
|
11
|
+
*
|
|
12
|
+
* Representation (the convention the MCP draft tools, the merge
|
|
13
|
+
* engine's `pset:`/`qset:` component keys, scope verification, and the
|
|
14
|
+
* IFC4→5 migration already share):
|
|
15
|
+
* - pset property → `bsi::ifc::v5a::<Set>::<Prop>` with the full
|
|
16
|
+
* typed PropertyValue object as the attribute value;
|
|
17
|
+
* - quantity → `bsi::ifc::v5a::<Qto_Set>::<Name>` with the raw
|
|
18
|
+
* number as the attribute value;
|
|
19
|
+
* - classifications / materials / geometryRef → single attributes
|
|
20
|
+
* under the `ifclite::` extension namespace (whole-array values:
|
|
21
|
+
* the Y.Array is the unit users edit, and merge granularity at the
|
|
22
|
+
* array level matches that).
|
|
23
|
+
*
|
|
24
|
+
* Inflation is shape-gated so legacy flat attributes written by the
|
|
25
|
+
* IFC4→IFC5 migration (raw values under the same v5a keys) stay flat:
|
|
26
|
+
* only PropertyValue-shaped objects inflate into psets, and numbers
|
|
27
|
+
* inflate into quantities unless the set is `Pset_`-named — the
|
|
28
|
+
* migration only ever emits `Pset_*` set names, so that exclusion is
|
|
29
|
+
* exactly the legacy population, and custom quantity-set names still
|
|
30
|
+
* round-trip. Both directions are inverse to each other, so
|
|
31
|
+
* flatten(inflate(x)) == x and a doc holding the same key in both the
|
|
32
|
+
* flat and structured branch serializes deterministically (structured
|
|
33
|
+
* wins).
|
|
34
|
+
*/
|
|
35
|
+
import { V5A_ATTR_PREFIX } from '@ifc-lite/ifcx';
|
|
36
|
+
import * as Y from 'yjs';
|
|
37
|
+
import { type ClassificationRef, type GeometryRefRecord, type MaterialAssignment, type PropertyValue } from '../doc/schema.js';
|
|
38
|
+
export { V5A_ATTR_PREFIX };
|
|
39
|
+
/**
|
|
40
|
+
* Shape test for the typed PropertyValue record — the canonical wire
|
|
41
|
+
* shape every writer and reader shares (`isTypedPropertyValue` in
|
|
42
|
+
* `@ifc-lite/ifcx`). Strict on purpose: legacy migrated attributes
|
|
43
|
+
* carry raw scalars, never `{type, value}` objects, so this is what
|
|
44
|
+
* disambiguates pset inflation from "leave it as a flat attribute".
|
|
45
|
+
*/
|
|
46
|
+
export declare function isPropertyValueShaped(value: unknown): value is PropertyValue;
|
|
47
|
+
/** The structured branches `entityToJSON` exposes alongside attributes. */
|
|
48
|
+
export interface StructuredBranchesJSON {
|
|
49
|
+
psets: Record<string, Record<string, PropertyValue>>;
|
|
50
|
+
quantities: Record<string, Record<string, number>>;
|
|
51
|
+
classifications: ClassificationRef[];
|
|
52
|
+
materials: MaterialAssignment[];
|
|
53
|
+
geometryRefs: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Wire form of a geometry reference whose target record is known at
|
|
57
|
+
* snapshot time: carrying the record (sans CRDT version vector) keeps
|
|
58
|
+
* the round-trip self-contained — a seed can recreate the geometry map
|
|
59
|
+
* entry instead of restoring a dangling ref. A bare `geomId` string is
|
|
60
|
+
* still valid for refs whose geometry hydrates out-of-band (blob sync).
|
|
61
|
+
*/
|
|
62
|
+
export interface GeometryRefCarrier {
|
|
63
|
+
geomId: string;
|
|
64
|
+
type?: string;
|
|
65
|
+
source?: string;
|
|
66
|
+
blobHash?: string;
|
|
67
|
+
params?: Record<string, unknown>;
|
|
68
|
+
bbox?: number[];
|
|
69
|
+
}
|
|
70
|
+
export interface FlattenOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Resolve a geometry record for a geomId (typically from the doc's
|
|
73
|
+
* top-level geometry map). When it returns one, the carrier embeds it;
|
|
74
|
+
* otherwise only the id travels.
|
|
75
|
+
*/
|
|
76
|
+
geometryRecordFor?: (geomId: string) => Omit<GeometryRefCarrier, 'geomId'> | undefined;
|
|
77
|
+
}
|
|
78
|
+
/** Attribute key for one pset property / quantity. */
|
|
79
|
+
export declare function structuredAttributeKey(setName: string, name: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Fold an entity's structured branches into its flat attribute record.
|
|
82
|
+
* Structured values overwrite same-key flat attributes — the typed
|
|
83
|
+
* branch is the newer write path, so it wins deterministically.
|
|
84
|
+
*/
|
|
85
|
+
export declare function flattenStructuredBranches(json: {
|
|
86
|
+
attributes: Record<string, unknown>;
|
|
87
|
+
} & StructuredBranchesJSON, options?: FlattenOptions): Record<string, unknown>;
|
|
88
|
+
export interface InflatedAttributes extends StructuredBranchesJSON {
|
|
89
|
+
/** Whatever didn't inflate — stays in the flat attributes branch. */
|
|
90
|
+
attributes: Record<string, unknown>;
|
|
91
|
+
geometryRefRecord?: GeometryRefRecord;
|
|
92
|
+
/** Embedded geometry records to recreate in the doc's geometry map, if carried. */
|
|
93
|
+
geometryCarriers: GeometryRefCarrier[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Inverse of `flattenStructuredBranches`: split an IFCX attribute
|
|
97
|
+
* record into the flat remainder and the structured branches. Keys
|
|
98
|
+
* whose values don't pass the shape gates stay flat (legacy migrated
|
|
99
|
+
* raw values, foreign data under colliding namespaces).
|
|
100
|
+
*/
|
|
101
|
+
export declare function inflateStructuredAttributes(attributes: Record<string, unknown>): InflatedAttributes;
|
|
102
|
+
/**
|
|
103
|
+
* `FlattenOptions.geometryRecordFor` backed by `doc`'s geometry map.
|
|
104
|
+
* The CRDT version vector is replica bookkeeping and never travels.
|
|
105
|
+
*/
|
|
106
|
+
export declare function geometryRecordLookup(doc: Y.Doc): (geomId: string) => Omit<GeometryRefCarrier, 'geomId'> | undefined;
|
|
107
|
+
//# sourceMappingURL=structured-attrs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-attrs.d.ts","sourceRoot":"","sources":["../../src/snapshot/structured-attrs.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAgB,eAAe,EAAqC,MAAM,gBAAgB,CAAC;AAClG,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,eAAe,EAAE,CAAC;AAa3B;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAE5E;AAaD,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,eAAe,EAAE,iBAAiB,EAAE,CAAC;IACrC,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CACxF;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,sBAAsB,EACtE,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA+BzB;AAED,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,mFAAmF;IACnF,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,kBAAkB,CA+FpB;AAOD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,CAAC,CAAC,GAAG,GACT,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,SAAS,CAqBpE"}
|