@ifc-lite/collab 0.2.7 → 0.4.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/session.d.ts +7 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +4 -0
- package/dist/session.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
|
@@ -0,0 +1,250 @@
|
|
|
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
|
+
* Structured-branch ↔ namespaced-attribute conversion (#1031).
|
|
6
|
+
*
|
|
7
|
+
* The Y.Doc keeps psets / quantities / classifications / materials /
|
|
8
|
+
* geometryRef as dedicated CRDT branches so concurrent edits to
|
|
9
|
+
* different branches never conflict, but the IFCX wire type only has
|
|
10
|
+
* `attributes` / `children` / `inherits`. At the snapshot boundary the
|
|
11
|
+
* structured branches fold into ordinary attributes; `seedFromIfcx`
|
|
12
|
+
* re-inflates them, so structured edits survive snapshot → seed
|
|
13
|
+
* round-trips.
|
|
14
|
+
*
|
|
15
|
+
* Representation (the convention the MCP draft tools, the merge
|
|
16
|
+
* engine's `pset:`/`qset:` component keys, scope verification, and the
|
|
17
|
+
* IFC4→5 migration already share):
|
|
18
|
+
* - pset property → `bsi::ifc::v5a::<Set>::<Prop>` with the full
|
|
19
|
+
* typed PropertyValue object as the attribute value;
|
|
20
|
+
* - quantity → `bsi::ifc::v5a::<Qto_Set>::<Name>` with the raw
|
|
21
|
+
* number as the attribute value;
|
|
22
|
+
* - classifications / materials / geometryRef → single attributes
|
|
23
|
+
* under the `ifclite::` extension namespace (whole-array values:
|
|
24
|
+
* the Y.Array is the unit users edit, and merge granularity at the
|
|
25
|
+
* array level matches that).
|
|
26
|
+
*
|
|
27
|
+
* Inflation is shape-gated so legacy flat attributes written by the
|
|
28
|
+
* IFC4→IFC5 migration (raw values under the same v5a keys) stay flat:
|
|
29
|
+
* only PropertyValue-shaped objects inflate into psets, and numbers
|
|
30
|
+
* inflate into quantities unless the set is `Pset_`-named — the
|
|
31
|
+
* migration only ever emits `Pset_*` set names, so that exclusion is
|
|
32
|
+
* exactly the legacy population, and custom quantity-set names still
|
|
33
|
+
* round-trip. Both directions are inverse to each other, so
|
|
34
|
+
* flatten(inflate(x)) == x and a doc holding the same key in both the
|
|
35
|
+
* flat and structured branch serializes deterministically (structured
|
|
36
|
+
* wins).
|
|
37
|
+
*/
|
|
38
|
+
import { IFCLITE_ATTR, V5A_ATTR_PREFIX, isTypedPropertyValue, parseV5aKey } from '@ifc-lite/ifcx';
|
|
39
|
+
import * as Y from 'yjs';
|
|
40
|
+
import { GEOMETRY_KEY, geometryMap, } from '../doc/schema.js';
|
|
41
|
+
// Re-exported for existing consumers; the canonical definition lives in
|
|
42
|
+
// @ifc-lite/ifcx next to the routing rule that shares the dialect.
|
|
43
|
+
export { V5A_ATTR_PREFIX };
|
|
44
|
+
/**
|
|
45
|
+
* Numbers under `Pset_*` sets never inflate into quantities: the
|
|
46
|
+
* IFC4→IFC5 migration writes raw scalars under `Pset_*` keys only, so
|
|
47
|
+
* this exclusion keeps exactly that legacy population flat while any
|
|
48
|
+
* other set name (Qto_* or custom) round-trips as a quantity.
|
|
49
|
+
*/
|
|
50
|
+
const PSET_SET_RE = /^Pset_/;
|
|
51
|
+
/** `Qto_*` members route to quantities even when wrapped in a typed record. */
|
|
52
|
+
const QTO_SET_RE = /^Qto_/;
|
|
53
|
+
/**
|
|
54
|
+
* Shape test for the typed PropertyValue record — the canonical wire
|
|
55
|
+
* shape every writer and reader shares (`isTypedPropertyValue` in
|
|
56
|
+
* `@ifc-lite/ifcx`). Strict on purpose: legacy migrated attributes
|
|
57
|
+
* carry raw scalars, never `{type, value}` objects, so this is what
|
|
58
|
+
* disambiguates pset inflation from "leave it as a flat attribute".
|
|
59
|
+
*/
|
|
60
|
+
export function isPropertyValueShaped(value) {
|
|
61
|
+
return isTypedPropertyValue(value);
|
|
62
|
+
}
|
|
63
|
+
function isClassificationRefShaped(value) {
|
|
64
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
65
|
+
return false;
|
|
66
|
+
const record = value;
|
|
67
|
+
return typeof record.system === 'string' && typeof record.code === 'string';
|
|
68
|
+
}
|
|
69
|
+
function isMaterialAssignmentShaped(value) {
|
|
70
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
71
|
+
return false;
|
|
72
|
+
return typeof value.materialId === 'string';
|
|
73
|
+
}
|
|
74
|
+
/** Attribute key for one pset property / quantity. */
|
|
75
|
+
export function structuredAttributeKey(setName, name) {
|
|
76
|
+
return `${V5A_ATTR_PREFIX}${setName}::${name}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fold an entity's structured branches into its flat attribute record.
|
|
80
|
+
* Structured values overwrite same-key flat attributes — the typed
|
|
81
|
+
* branch is the newer write path, so it wins deterministically.
|
|
82
|
+
*/
|
|
83
|
+
export function flattenStructuredBranches(json, options = {}) {
|
|
84
|
+
const out = { ...json.attributes };
|
|
85
|
+
for (const [setName, props] of Object.entries(json.psets)) {
|
|
86
|
+
for (const [propName, value] of Object.entries(props)) {
|
|
87
|
+
out[structuredAttributeKey(setName, propName)] = { ...value };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [setName, qtys] of Object.entries(json.quantities)) {
|
|
91
|
+
for (const [qtyName, value] of Object.entries(qtys)) {
|
|
92
|
+
out[structuredAttributeKey(setName, qtyName)] = value;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (json.classifications.length > 0) {
|
|
96
|
+
out[IFCLITE_ATTR.CLASSIFICATIONS] = json.classifications.map((ref) => ({ ...ref }));
|
|
97
|
+
}
|
|
98
|
+
if (json.materials.length > 0) {
|
|
99
|
+
out[IFCLITE_ATTR.MATERIALS] = json.materials.map((mat) => ({ ...mat }));
|
|
100
|
+
}
|
|
101
|
+
if (json.geometryRefs.length > 0) {
|
|
102
|
+
// One ref keeps the legacy scalar wire shape (string or carrier) so
|
|
103
|
+
// single-geometry snapshots stay byte-identical; several refs ride as
|
|
104
|
+
// an ordered list of the same per-ref shapes.
|
|
105
|
+
const entries = json.geometryRefs.map((geomId) => {
|
|
106
|
+
const record = options.geometryRecordFor?.(geomId);
|
|
107
|
+
return record ? { geomId, ...record } : geomId;
|
|
108
|
+
});
|
|
109
|
+
out[IFCLITE_ATTR.GEOMETRY_REF] = entries.length === 1 ? entries[0] : entries;
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Inverse of `flattenStructuredBranches`: split an IFCX attribute
|
|
115
|
+
* record into the flat remainder and the structured branches. Keys
|
|
116
|
+
* whose values don't pass the shape gates stay flat (legacy migrated
|
|
117
|
+
* raw values, foreign data under colliding namespaces).
|
|
118
|
+
*/
|
|
119
|
+
export function inflateStructuredAttributes(attributes) {
|
|
120
|
+
const flat = {};
|
|
121
|
+
const psets = {};
|
|
122
|
+
const quantities = {};
|
|
123
|
+
let classifications = [];
|
|
124
|
+
let materials = [];
|
|
125
|
+
let geometryRefs = [];
|
|
126
|
+
const geometryCarriers = [];
|
|
127
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
128
|
+
if (key === IFCLITE_ATTR.CLASSIFICATIONS) {
|
|
129
|
+
if (Array.isArray(value) && value.every(isClassificationRefShaped)) {
|
|
130
|
+
classifications = value.map((ref) => ({ ...ref }));
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
flat[key] = value;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (key === IFCLITE_ATTR.MATERIALS) {
|
|
137
|
+
if (Array.isArray(value) && value.every(isMaterialAssignmentShaped)) {
|
|
138
|
+
materials = value.map((mat) => ({ ...mat }));
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
flat[key] = value;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (key === IFCLITE_ATTR.GEOMETRY_REF) {
|
|
145
|
+
// Scalar (string or carrier) is the single-ref wire shape; a list of
|
|
146
|
+
// the same per-ref shapes carries multi-geometry entities. Anything
|
|
147
|
+
// else stays flat.
|
|
148
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
149
|
+
const ids = [];
|
|
150
|
+
const carriers = [];
|
|
151
|
+
let recognized = entries.length > 0;
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (typeof entry === 'string') {
|
|
154
|
+
ids.push(entry);
|
|
155
|
+
}
|
|
156
|
+
else if (isGeometryRefCarrierShaped(entry)) {
|
|
157
|
+
ids.push(entry.geomId);
|
|
158
|
+
carriers.push({ ...entry });
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
recognized = false;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (recognized) {
|
|
166
|
+
geometryRefs = ids;
|
|
167
|
+
geometryCarriers.push(...carriers);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
flat[key] = value;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
{
|
|
174
|
+
const v5a = parseV5aKey(key);
|
|
175
|
+
if (v5a) {
|
|
176
|
+
const { setName, name } = v5a;
|
|
177
|
+
// Qto_* members are quantities before anything else: a typed
|
|
178
|
+
// record under a quantity set (e.g. written by a draft
|
|
179
|
+
// set_property op) unwraps to its number — otherwise the value
|
|
180
|
+
// would land in psets and compete with later quantity edits on
|
|
181
|
+
// the same wire key. The quantities branch stores plain numbers,
|
|
182
|
+
// so the raw number is the canonical re-flattened shape.
|
|
183
|
+
if (QTO_SET_RE.test(setName)) {
|
|
184
|
+
const candidate = isPropertyValueShaped(value) ? value.value : value;
|
|
185
|
+
if (typeof candidate === 'number' && Number.isFinite(candidate)) {
|
|
186
|
+
(quantities[setName] ??= {})[name] = candidate;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (isPropertyValueShaped(value)) {
|
|
191
|
+
(psets[setName] ??= {})[name] = { ...value };
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (typeof value === 'number' && Number.isFinite(value) && !PSET_SET_RE.test(setName)) {
|
|
195
|
+
(quantities[setName] ??= {})[name] = value;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
flat[key] = value;
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
attributes: flat,
|
|
204
|
+
psets,
|
|
205
|
+
quantities,
|
|
206
|
+
classifications,
|
|
207
|
+
materials,
|
|
208
|
+
geometryRefs,
|
|
209
|
+
geometryRefRecord: geometryRefs.length > 0 ? { geomIds: geometryRefs } : undefined,
|
|
210
|
+
geometryCarriers,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function isGeometryRefCarrierShaped(value) {
|
|
214
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
215
|
+
return false;
|
|
216
|
+
return typeof value.geomId === 'string';
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* `FlattenOptions.geometryRecordFor` backed by `doc`'s geometry map.
|
|
220
|
+
* The CRDT version vector is replica bookkeeping and never travels.
|
|
221
|
+
*/
|
|
222
|
+
export function geometryRecordLookup(doc) {
|
|
223
|
+
return (geomId) => {
|
|
224
|
+
const entry = geometryMap(doc).get(geomId);
|
|
225
|
+
if (!entry)
|
|
226
|
+
return undefined;
|
|
227
|
+
const record = {};
|
|
228
|
+
const type = entry.get(GEOMETRY_KEY.TYPE);
|
|
229
|
+
if (typeof type === 'string')
|
|
230
|
+
record.type = type;
|
|
231
|
+
const source = entry.get(GEOMETRY_KEY.SOURCE);
|
|
232
|
+
if (typeof source === 'string')
|
|
233
|
+
record.source = source;
|
|
234
|
+
const blobHash = entry.get(GEOMETRY_KEY.BLOB_HASH);
|
|
235
|
+
if (typeof blobHash === 'string')
|
|
236
|
+
record.blobHash = blobHash;
|
|
237
|
+
const params = entry.get(GEOMETRY_KEY.PARAMS);
|
|
238
|
+
if (params instanceof Y.Map && params.size > 0) {
|
|
239
|
+
const plain = {};
|
|
240
|
+
for (const [k, v] of params.entries())
|
|
241
|
+
plain[k] = v;
|
|
242
|
+
record.params = plain;
|
|
243
|
+
}
|
|
244
|
+
const bbox = entry.get(GEOMETRY_KEY.BBOX);
|
|
245
|
+
if (Array.isArray(bbox))
|
|
246
|
+
record.bbox = bbox;
|
|
247
|
+
return record;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=structured-attrs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-attrs.js","sourceRoot":"","sources":["../../src/snapshot/structured-attrs.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* Round-trips with `seedFromIfcx`: seeding a doc, snapshotting, then
|
|
5
5
|
* seeding a fresh doc from the snapshot must produce structurally equal
|
|
6
6
|
* Y states (verified by tests).
|
|
7
|
+
*
|
|
8
|
+
* Structured branches (psets / quantities / classifications / materials
|
|
9
|
+
* / geometryRef) fold into namespaced attributes on the wire — see
|
|
10
|
+
* `structured-attrs.ts` for the representation contract (#1031).
|
|
7
11
|
*/
|
|
8
12
|
import type { IfcxFile } from '@ifc-lite/ifcx';
|
|
9
13
|
import * as Y from 'yjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-ifcx.d.ts","sourceRoot":"","sources":["../../src/snapshot/to-ifcx.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"to-ifcx.d.ts","sourceRoot":"","sources":["../../src/snapshot/to-ifcx.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAoC,MAAM,gBAAgB,CAAC;AACjF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAmDlF;AAED,yCAAyC;AACzC,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,UAAO,GAAG,MAAM,CAEnE"}
|
package/dist/snapshot/to-ifcx.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
import { entityToJSON, iterEntities } from '../doc/entity.js';
|
|
5
5
|
import { metaMap } from '../doc/schema.js';
|
|
6
|
+
import { flattenStructuredBranches, geometryRecordLookup } from './structured-attrs.js';
|
|
6
7
|
export function snapshotToIfcx(doc, options = {}) {
|
|
7
8
|
const meta = metaMap(doc);
|
|
8
9
|
const seededHeader = meta.get('header') ?? undefined;
|
|
@@ -16,6 +17,7 @@ export function snapshotToIfcx(doc, options = {}) {
|
|
|
16
17
|
timestamp: options.timestamp ?? new Date().toISOString(),
|
|
17
18
|
};
|
|
18
19
|
const data = [];
|
|
20
|
+
const geometryRecordFor = geometryRecordLookup(doc);
|
|
19
21
|
for (const [path, entity] of iterEntities(doc)) {
|
|
20
22
|
const json = entityToJSON(entity);
|
|
21
23
|
const node = { path };
|
|
@@ -35,8 +37,9 @@ export function snapshotToIfcx(doc, options = {}) {
|
|
|
35
37
|
for (const k of inheritsKeys)
|
|
36
38
|
node.inherits[k] = json.inherits[k];
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
const attributes = flattenStructuredBranches(json, { geometryRecordFor });
|
|
41
|
+
if (Object.keys(attributes).length > 0) {
|
|
42
|
+
node.attributes = attributes;
|
|
40
43
|
}
|
|
41
44
|
data.push(node);
|
|
42
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-ifcx.js","sourceRoot":"","sources":["../../src/snapshot/to-ifcx.ts"],"names":[],"mappings":"AAAA;;+DAE+D;
|
|
1
|
+
{"version":3,"file":"to-ifcx.js","sourceRoot":"","sources":["../../src/snapshot/to-ifcx.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAgB/D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAgBxF,MAAM,UAAU,cAAc,CAAC,GAAU,EAAE,UAA2B,EAAE;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,YAAY,GAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAA4B,IAAI,SAAS,CAAC;IACjF,MAAM,aAAa,GAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAA8B,IAAI,EAAE,CAAC;IAC9E,MAAM,aAAa,GAChB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAyC,IAAI,EAAE,CAAC;IAErE,MAAM,MAAM,GAAe;QACzB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,YAAY,EAAE,EAAE,IAAI,0BAA0B;QAChE,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,YAAY,EAAE,WAAW,IAAI,YAAY;QAC7E,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,YAAY,EAAE,WAAW,IAAI,OAAO;QACxE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,YAAY,EAAE,MAAM,IAAI,iBAAiB;QACnE,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACzD,CAAC;IAEF,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,IAAI,GAAa,EAAE,IAAI,EAAE,CAAC;QAEhC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY;YACvC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE;YACnC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,IAAI,YAAY;gBAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY;YACvC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE;YACnC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,IAAI,YAAY;gBAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,UAAU,GAAG,yBAAyB,CAAC,IAAI,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC1E,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO,EAAE,aAAoC;QAC7C,OAAO,EAAE,aAAoC;QAC7C,IAAI;KACL,CAAC;AACJ,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,MAAM,GAAG,IAAI;IACzD,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ifc-lite/collab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Real-time collaborative BIM via CRDT on IFCX",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"y-protocols": "^1.0.6",
|
|
40
40
|
"y-websocket": "^3.0.0",
|
|
41
41
|
"yjs": "^13.6.31",
|
|
42
|
-
"@ifc-lite/data": "^2.5.
|
|
43
|
-
"@ifc-lite/ifcx": "^2.
|
|
44
|
-
"@ifc-lite/mutations": "^1.
|
|
42
|
+
"@ifc-lite/data": "^2.5.3",
|
|
43
|
+
"@ifc-lite/ifcx": "^2.3.0",
|
|
44
|
+
"@ifc-lite/mutations": "^1.20.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"typescript": "^6.0.3",
|