@ifc-lite/collab 0.2.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.
Files changed (219) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +92 -0
  3. package/dist/awareness/agent.d.ts +36 -0
  4. package/dist/awareness/agent.d.ts.map +1 -0
  5. package/dist/awareness/agent.js +39 -0
  6. package/dist/awareness/agent.js.map +1 -0
  7. package/dist/awareness/color.d.ts +31 -0
  8. package/dist/awareness/color.d.ts.map +1 -0
  9. package/dist/awareness/color.js +61 -0
  10. package/dist/awareness/color.js.map +1 -0
  11. package/dist/awareness/index.d.ts +6 -0
  12. package/dist/awareness/index.d.ts.map +1 -0
  13. package/dist/awareness/index.js +9 -0
  14. package/dist/awareness/index.js.map +1 -0
  15. package/dist/awareness/overlay.d.ts +59 -0
  16. package/dist/awareness/overlay.d.ts.map +1 -0
  17. package/dist/awareness/overlay.js +110 -0
  18. package/dist/awareness/overlay.js.map +1 -0
  19. package/dist/awareness/presence.d.ts +95 -0
  20. package/dist/awareness/presence.d.ts.map +1 -0
  21. package/dist/awareness/presence.js +114 -0
  22. package/dist/awareness/presence.js.map +1 -0
  23. package/dist/awareness/render.d.ts +58 -0
  24. package/dist/awareness/render.d.ts.map +1 -0
  25. package/dist/awareness/render.js +66 -0
  26. package/dist/awareness/render.js.map +1 -0
  27. package/dist/branch/branch-tree.d.ts +40 -0
  28. package/dist/branch/branch-tree.d.ts.map +1 -0
  29. package/dist/branch/branch-tree.js +66 -0
  30. package/dist/branch/branch-tree.js.map +1 -0
  31. package/dist/branch/branch.d.ts +44 -0
  32. package/dist/branch/branch.d.ts.map +1 -0
  33. package/dist/branch/branch.js +109 -0
  34. package/dist/branch/branch.js.map +1 -0
  35. package/dist/branch/history-automerge.d.ts +31 -0
  36. package/dist/branch/history-automerge.d.ts.map +1 -0
  37. package/dist/branch/history-automerge.js +237 -0
  38. package/dist/branch/history-automerge.js.map +1 -0
  39. package/dist/branch/history.d.ts +147 -0
  40. package/dist/branch/history.d.ts.map +1 -0
  41. package/dist/branch/history.js +223 -0
  42. package/dist/branch/history.js.map +1 -0
  43. package/dist/branch/index.d.ts +5 -0
  44. package/dist/branch/index.d.ts.map +1 -0
  45. package/dist/branch/index.js +8 -0
  46. package/dist/branch/index.js.map +1 -0
  47. package/dist/conflicts/detector.d.ts +52 -0
  48. package/dist/conflicts/detector.d.ts.map +1 -0
  49. package/dist/conflicts/detector.js +226 -0
  50. package/dist/conflicts/detector.js.map +1 -0
  51. package/dist/conflicts/index.d.ts +3 -0
  52. package/dist/conflicts/index.d.ts.map +1 -0
  53. package/dist/conflicts/index.js +6 -0
  54. package/dist/conflicts/index.js.map +1 -0
  55. package/dist/conflicts/ui-bridge.d.ts +80 -0
  56. package/dist/conflicts/ui-bridge.d.ts.map +1 -0
  57. package/dist/conflicts/ui-bridge.js +126 -0
  58. package/dist/conflicts/ui-bridge.js.map +1 -0
  59. package/dist/doc/entity.d.ts +84 -0
  60. package/dist/doc/entity.d.ts.map +1 -0
  61. package/dist/doc/entity.js +345 -0
  62. package/dist/doc/entity.js.map +1 -0
  63. package/dist/doc/geometry.d.ts +39 -0
  64. package/dist/doc/geometry.d.ts.map +1 -0
  65. package/dist/doc/geometry.js +99 -0
  66. package/dist/doc/geometry.js.map +1 -0
  67. package/dist/doc/index.d.ts +8 -0
  68. package/dist/doc/index.d.ts.map +1 -0
  69. package/dist/doc/index.js +11 -0
  70. package/dist/doc/index.js.map +1 -0
  71. package/dist/doc/migration-ifc4-to-ifc4x3.d.ts +21 -0
  72. package/dist/doc/migration-ifc4-to-ifc4x3.d.ts.map +1 -0
  73. package/dist/doc/migration-ifc4-to-ifc4x3.js +55 -0
  74. package/dist/doc/migration-ifc4-to-ifc4x3.js.map +1 -0
  75. package/dist/doc/relationship.d.ts +27 -0
  76. package/dist/doc/relationship.d.ts.map +1 -0
  77. package/dist/doc/relationship.js +110 -0
  78. package/dist/doc/relationship.js.map +1 -0
  79. package/dist/doc/schema-version.d.ts +47 -0
  80. package/dist/doc/schema-version.d.ts.map +1 -0
  81. package/dist/doc/schema-version.js +41 -0
  82. package/dist/doc/schema-version.js.map +1 -0
  83. package/dist/doc/schema.d.ts +131 -0
  84. package/dist/doc/schema.d.ts.map +1 -0
  85. package/dist/doc/schema.js +117 -0
  86. package/dist/doc/schema.js.map +1 -0
  87. package/dist/doc/units.d.ts +45 -0
  88. package/dist/doc/units.d.ts.map +1 -0
  89. package/dist/doc/units.js +120 -0
  90. package/dist/doc/units.js.map +1 -0
  91. package/dist/federation/bridge.d.ts +34 -0
  92. package/dist/federation/bridge.d.ts.map +1 -0
  93. package/dist/federation/bridge.js +52 -0
  94. package/dist/federation/bridge.js.map +1 -0
  95. package/dist/federation/index.d.ts +4 -0
  96. package/dist/federation/index.d.ts.map +1 -0
  97. package/dist/federation/index.js +7 -0
  98. package/dist/federation/index.js.map +1 -0
  99. package/dist/federation/resolver.d.ts +58 -0
  100. package/dist/federation/resolver.d.ts.map +1 -0
  101. package/dist/federation/resolver.js +43 -0
  102. package/dist/federation/resolver.js.map +1 -0
  103. package/dist/federation/session.d.ts +79 -0
  104. package/dist/federation/session.d.ts.map +1 -0
  105. package/dist/federation/session.js +126 -0
  106. package/dist/federation/session.js.map +1 -0
  107. package/dist/geometry/blob-store.d.ts +106 -0
  108. package/dist/geometry/blob-store.d.ts.map +1 -0
  109. package/dist/geometry/blob-store.js +266 -0
  110. package/dist/geometry/blob-store.js.map +1 -0
  111. package/dist/geometry/csg.d.ts +63 -0
  112. package/dist/geometry/csg.d.ts.map +1 -0
  113. package/dist/geometry/csg.js +101 -0
  114. package/dist/geometry/csg.js.map +1 -0
  115. package/dist/geometry/determinism.d.ts +45 -0
  116. package/dist/geometry/determinism.d.ts.map +1 -0
  117. package/dist/geometry/determinism.js +92 -0
  118. package/dist/geometry/determinism.js.map +1 -0
  119. package/dist/geometry/gc.d.ts +63 -0
  120. package/dist/geometry/gc.d.ts.map +1 -0
  121. package/dist/geometry/gc.js +109 -0
  122. package/dist/geometry/gc.js.map +1 -0
  123. package/dist/geometry/index.d.ts +6 -0
  124. package/dist/geometry/index.d.ts.map +1 -0
  125. package/dist/geometry/index.js +9 -0
  126. package/dist/geometry/index.js.map +1 -0
  127. package/dist/geometry/parametric.d.ts +92 -0
  128. package/dist/geometry/parametric.d.ts.map +1 -0
  129. package/dist/geometry/parametric.js +200 -0
  130. package/dist/geometry/parametric.js.map +1 -0
  131. package/dist/index.d.ts +27 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +46 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/mutations/bind.d.ts +56 -0
  136. package/dist/mutations/bind.d.ts.map +1 -0
  137. package/dist/mutations/bind.js +68 -0
  138. package/dist/mutations/bind.js.map +1 -0
  139. package/dist/mutations/index.d.ts +2 -0
  140. package/dist/mutations/index.d.ts.map +1 -0
  141. package/dist/mutations/index.js +5 -0
  142. package/dist/mutations/index.js.map +1 -0
  143. package/dist/perf/benchmark.d.ts +25 -0
  144. package/dist/perf/benchmark.d.ts.map +1 -0
  145. package/dist/perf/benchmark.js +97 -0
  146. package/dist/perf/benchmark.js.map +1 -0
  147. package/dist/perf/index.d.ts +3 -0
  148. package/dist/perf/index.d.ts.map +1 -0
  149. package/dist/perf/index.js +6 -0
  150. package/dist/perf/index.js.map +1 -0
  151. package/dist/perf/latency.d.ts +39 -0
  152. package/dist/perf/latency.d.ts.map +1 -0
  153. package/dist/perf/latency.js +79 -0
  154. package/dist/perf/latency.js.map +1 -0
  155. package/dist/privacy.d.ts +45 -0
  156. package/dist/privacy.d.ts.map +1 -0
  157. package/dist/privacy.js +66 -0
  158. package/dist/privacy.js.map +1 -0
  159. package/dist/providers/indexeddb.d.ts +37 -0
  160. package/dist/providers/indexeddb.d.ts.map +1 -0
  161. package/dist/providers/indexeddb.js +45 -0
  162. package/dist/providers/indexeddb.js.map +1 -0
  163. package/dist/providers/webrtc.d.ts +40 -0
  164. package/dist/providers/webrtc.d.ts.map +1 -0
  165. package/dist/providers/webrtc.js +81 -0
  166. package/dist/providers/webrtc.js.map +1 -0
  167. package/dist/providers/websocket.d.ts +45 -0
  168. package/dist/providers/websocket.d.ts.map +1 -0
  169. package/dist/providers/websocket.js +56 -0
  170. package/dist/providers/websocket.js.map +1 -0
  171. package/dist/security/e2e.d.ts +54 -0
  172. package/dist/security/e2e.d.ts.map +1 -0
  173. package/dist/security/e2e.js +147 -0
  174. package/dist/security/e2e.js.map +1 -0
  175. package/dist/security/index.d.ts +2 -0
  176. package/dist/security/index.d.ts.map +1 -0
  177. package/dist/security/index.js +5 -0
  178. package/dist/security/index.js.map +1 -0
  179. package/dist/session.d.ts +79 -0
  180. package/dist/session.d.ts.map +1 -0
  181. package/dist/session.js +112 -0
  182. package/dist/session.js.map +1 -0
  183. package/dist/snapshot/from-ifcx.d.ts +24 -0
  184. package/dist/snapshot/from-ifcx.d.ts.map +1 -0
  185. package/dist/snapshot/from-ifcx.js +93 -0
  186. package/dist/snapshot/from-ifcx.js.map +1 -0
  187. package/dist/snapshot/index.d.ts +6 -0
  188. package/dist/snapshot/index.d.ts.map +1 -0
  189. package/dist/snapshot/index.js +9 -0
  190. package/dist/snapshot/index.js.map +1 -0
  191. package/dist/snapshot/layers.d.ts +56 -0
  192. package/dist/snapshot/layers.d.ts.map +1 -0
  193. package/dist/snapshot/layers.js +82 -0
  194. package/dist/snapshot/layers.js.map +1 -0
  195. package/dist/snapshot/minimal-layer.d.ts +40 -0
  196. package/dist/snapshot/minimal-layer.d.ts.map +1 -0
  197. package/dist/snapshot/minimal-layer.js +123 -0
  198. package/dist/snapshot/minimal-layer.js.map +1 -0
  199. package/dist/snapshot/to-ifcx.d.ts +26 -0
  200. package/dist/snapshot/to-ifcx.d.ts.map +1 -0
  201. package/dist/snapshot/to-ifcx.js +54 -0
  202. package/dist/snapshot/to-ifcx.js.map +1 -0
  203. package/dist/snapshot/worker.d.ts +45 -0
  204. package/dist/snapshot/worker.d.ts.map +1 -0
  205. package/dist/snapshot/worker.js +73 -0
  206. package/dist/snapshot/worker.js.map +1 -0
  207. package/dist/sync/room.d.ts +15 -0
  208. package/dist/sync/room.d.ts.map +1 -0
  209. package/dist/sync/room.js +20 -0
  210. package/dist/sync/room.js.map +1 -0
  211. package/dist/undo.d.ts +25 -0
  212. package/dist/undo.d.ts.map +1 -0
  213. package/dist/undo.js +37 -0
  214. package/dist/undo.js.map +1 -0
  215. package/dist/viewer-bridge.d.ts +27 -0
  216. package/dist/viewer-bridge.d.ts.map +1 -0
  217. package/dist/viewer-bridge.js +82 -0
  218. package/dist/viewer-bridge.js.map +1 -0
  219. package/package.json +83 -0
@@ -0,0 +1,126 @@
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 { createCollabSession, } from '../session.js';
5
+ import { createPresence } from '../awareness/presence.js';
6
+ import { createCollabDoc } from '../doc/schema.js';
7
+ import { federationRoomId, roomIdFor } from '../sync/room.js';
8
+ const RECORDS_KEY = 'records';
9
+ /** Build a federation session and pre-load `models`. */
10
+ export async function createFederationSession(opts) {
11
+ // The federation Y.Doc holds cross-model state and acts as the host
12
+ // for project-scoped presence (§10.2).
13
+ const federationDoc = createCollabDoc({ gc: true });
14
+ const fedRoomId = federationRoomId(opts.projectId);
15
+ const presence = createPresence(federationDoc, opts.presence ?? {});
16
+ presence.setUser(opts.user);
17
+ presence.setStatus('active');
18
+ const recordsMap = federationDoc.getMap(RECORDS_KEY);
19
+ const models = new Map();
20
+ async function loadModel(modelId) {
21
+ const existing = models.get(modelId);
22
+ if (existing)
23
+ return existing;
24
+ const session = await createCollabSession({
25
+ roomId: roomIdFor({ projectId: opts.projectId, modelId }),
26
+ user: opts.user,
27
+ provider: opts.provider,
28
+ serverUrl: opts.serverUrl,
29
+ token: opts.token,
30
+ WebSocketPolyfill: opts.WebSocketPolyfill,
31
+ presence: opts.presence,
32
+ });
33
+ models.set(modelId, session);
34
+ return session;
35
+ }
36
+ // Bootstrap the federation room itself if a websocket provider was
37
+ // requested — share the same provider stack as model rooms.
38
+ let federationCarrier = null;
39
+ if (opts.provider && opts.provider !== 'memory') {
40
+ federationCarrier = await createCollabSession({
41
+ roomId: fedRoomId,
42
+ user: opts.user,
43
+ provider: opts.provider,
44
+ serverUrl: opts.serverUrl,
45
+ token: opts.token,
46
+ WebSocketPolyfill: opts.WebSocketPolyfill,
47
+ doc: federationDoc,
48
+ presence: opts.presence,
49
+ });
50
+ }
51
+ function listRecords() {
52
+ const out = [];
53
+ recordsMap.forEach((v) => out.push(cloneRecord(v)));
54
+ return out;
55
+ }
56
+ await Promise.all(opts.models.map(loadModel));
57
+ return {
58
+ projectId: opts.projectId,
59
+ federationDoc,
60
+ federationRoomId: fedRoomId,
61
+ presence,
62
+ user: opts.user,
63
+ models,
64
+ async addModel(modelId) {
65
+ return loadModel(modelId);
66
+ },
67
+ async removeModel(modelId) {
68
+ const session = models.get(modelId);
69
+ if (!session)
70
+ return;
71
+ session.dispose();
72
+ models.delete(modelId);
73
+ },
74
+ modelIds: () => Array.from(models.keys()),
75
+ upsertRecord(record) {
76
+ federationDoc.transact(() => {
77
+ recordsMap.set(record.recordId, sanitiseRecord(record));
78
+ });
79
+ },
80
+ getRecord(recordId) {
81
+ const v = recordsMap.get(recordId);
82
+ return v ? cloneRecord(v) : undefined;
83
+ },
84
+ removeRecord(recordId) {
85
+ if (!recordsMap.has(recordId))
86
+ return false;
87
+ recordsMap.delete(recordId);
88
+ return true;
89
+ },
90
+ listRecords: listRecords,
91
+ observeRecords(listener) {
92
+ const fn = () => listener(listRecords());
93
+ recordsMap.observeDeep(fn);
94
+ return () => recordsMap.unobserveDeep(fn);
95
+ },
96
+ async whenSynced() {
97
+ const synced = Array.from(models.values()).map((s) => s.whenSynced);
98
+ if (federationCarrier)
99
+ synced.push(federationCarrier.whenSynced);
100
+ await Promise.all(synced);
101
+ },
102
+ async dispose() {
103
+ for (const session of models.values())
104
+ session.dispose();
105
+ models.clear();
106
+ if (federationCarrier)
107
+ federationCarrier.dispose();
108
+ else
109
+ presence.dispose();
110
+ },
111
+ };
112
+ }
113
+ function sanitiseRecord(r) {
114
+ return {
115
+ recordId: r.recordId,
116
+ type: r.type,
117
+ refs: r.refs.map((ref) => ({ modelId: ref.modelId, globalId: ref.globalId })),
118
+ resolution: r.resolution,
119
+ bcfTopicId: r.bcfTopicId,
120
+ meta: r.meta ? { ...r.meta } : undefined,
121
+ };
122
+ }
123
+ function cloneRecord(r) {
124
+ return sanitiseRecord(r);
125
+ }
126
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/federation/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Content-addressed blob store (spec §11.1).
3
+ *
4
+ * Mesh / opaque blobs live OUTSIDE the Y.Doc — the Y.Doc only carries
5
+ * `blobHash` references (see `doc/geometry.ts`). The blob store is
6
+ * pluggable so apps can mix:
7
+ * - `MemoryBlobStore` — tests, ephemeral rooms
8
+ * - `IndexedDbBlobStore` — browsers, local-first
9
+ * - `HttpBlobStore` — `@ifc-lite/collab-server` blob route
10
+ * - composition: `LayeredBlobStore(local, remote)`
11
+ *
12
+ * Hashing is FNV-1a × 4 rounds → 32 hex chars. Cheap, dependency-free,
13
+ * collision properties good enough to identify ~10^9 blobs without
14
+ * coincidence in practice. For high-assurance deployments, swap to
15
+ * SHA-256 by registering a different `BlobHasher`.
16
+ */
17
+ export type BlobHash = string;
18
+ export interface BlobMeta {
19
+ hash: BlobHash;
20
+ byteLength: number;
21
+ contentType?: string;
22
+ uploadedAt?: string;
23
+ }
24
+ export interface BlobStore {
25
+ put(bytes: Uint8Array, contentType?: string): Promise<BlobMeta>;
26
+ get(hash: BlobHash): Promise<Uint8Array | null>;
27
+ has(hash: BlobHash): Promise<boolean>;
28
+ delete(hash: BlobHash): Promise<boolean>;
29
+ /** List currently-known blob hashes; ordering is implementation-defined. */
30
+ list(): Promise<BlobHash[]>;
31
+ /**
32
+ * Return the blob's metadata (size, contentType, uploadedAt) without
33
+ * downloading the bytes. Backends that can't cheaply compute this
34
+ * may return `null` and force callers to fall back to `get`.
35
+ */
36
+ stat?(hash: BlobHash): Promise<BlobMeta | null>;
37
+ }
38
+ export type BlobHasher = (bytes: Uint8Array) => BlobHash;
39
+ /**
40
+ * 128-bit hash (4 rounds of 32-bit FNV-1a with different seeds), encoded
41
+ * as 32 lowercase hex chars. Deterministic, dependency-free.
42
+ */
43
+ export declare const fnv128: BlobHasher;
44
+ export declare class MemoryBlobStore implements BlobStore {
45
+ private readonly hasher;
46
+ private readonly blobs;
47
+ constructor(hasher?: BlobHasher);
48
+ put(bytes: Uint8Array, contentType?: string): Promise<BlobMeta>;
49
+ get(hash: BlobHash): Promise<Uint8Array | null>;
50
+ has(hash: BlobHash): Promise<boolean>;
51
+ delete(hash: BlobHash): Promise<boolean>;
52
+ list(): Promise<BlobHash[]>;
53
+ stat(hash: BlobHash): Promise<BlobMeta | null>;
54
+ }
55
+ export interface IndexedDbBlobStoreOptions {
56
+ dbName?: string;
57
+ storeName?: string;
58
+ }
59
+ /**
60
+ * Browser-only IndexedDB-backed store. Loaded lazily so Node bundle
61
+ * paths don't trip on the missing global.
62
+ */
63
+ export declare function createIndexedDbBlobStore(opts?: IndexedDbBlobStoreOptions, hasher?: BlobHasher): Promise<BlobStore>;
64
+ export interface HttpBlobStoreOptions {
65
+ /** Base URL like `https://collab.ifclite.com`; we append `/blobs/<hash>`. */
66
+ baseUrl: string;
67
+ /** Bearer token forwarded as `Authorization: Bearer …`. */
68
+ token?: string;
69
+ /** Hasher used when deduping client-side before PUT. */
70
+ hasher?: BlobHasher;
71
+ /** Override fetch (mainly for tests). */
72
+ fetch?: typeof fetch;
73
+ }
74
+ export declare class HttpBlobStore implements BlobStore {
75
+ private readonly opts;
76
+ private readonly hasher;
77
+ private readonly fetchImpl;
78
+ constructor(opts: HttpBlobStoreOptions);
79
+ private url;
80
+ private headers;
81
+ put(bytes: Uint8Array, contentType?: string): Promise<BlobMeta>;
82
+ get(hash: BlobHash): Promise<Uint8Array | null>;
83
+ has(hash: BlobHash): Promise<boolean>;
84
+ delete(hash: BlobHash): Promise<boolean>;
85
+ list(): Promise<BlobHash[]>;
86
+ stat(hash: BlobHash): Promise<BlobMeta | null>;
87
+ }
88
+ /**
89
+ * Read-through / write-through layering: writes go to `local` and `remote`
90
+ * in parallel; reads check `local` first and fall back to `remote`,
91
+ * caching the result locally on hit.
92
+ *
93
+ * This is what we recommend for browser apps: instant local reads, durable
94
+ * remote storage, and offline-first semantics for already-fetched blobs.
95
+ */
96
+ export declare class LayeredBlobStore implements BlobStore {
97
+ private readonly local;
98
+ private readonly remote;
99
+ constructor(local: BlobStore, remote: BlobStore);
100
+ put(bytes: Uint8Array, contentType?: string): Promise<BlobMeta>;
101
+ get(hash: BlobHash): Promise<Uint8Array | null>;
102
+ has(hash: BlobHash): Promise<boolean>;
103
+ delete(hash: BlobHash): Promise<boolean>;
104
+ list(): Promise<BlobHash[]>;
105
+ }
106
+ //# sourceMappingURL=blob-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob-store.d.ts","sourceRoot":"","sources":["../../src/geometry/blob-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,266 @@
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
+ * 128-bit hash (4 rounds of 32-bit FNV-1a with different seeds), encoded
6
+ * as 32 lowercase hex chars. Deterministic, dependency-free.
7
+ */
8
+ export const fnv128 = (bytes) => {
9
+ const seeds = [0x811c9dc5, 0x84222325, 0xcbf29ce4, 0x100000001];
10
+ const out = [];
11
+ for (let s = 0; s < 4; s++) {
12
+ let h = seeds[s] >>> 0;
13
+ for (let i = 0; i < bytes.length; i++) {
14
+ h ^= bytes[i] ^ ((s + 1) << ((i & 3) * 8));
15
+ h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
16
+ }
17
+ out.push(h >>> 0);
18
+ }
19
+ return out.map((n) => n.toString(16).padStart(8, '0')).join('');
20
+ };
21
+ /* ------------------------------------------------------------------ */
22
+ /* Memory backend */
23
+ /* ------------------------------------------------------------------ */
24
+ export class MemoryBlobStore {
25
+ hasher;
26
+ blobs = new Map();
27
+ constructor(hasher = fnv128) {
28
+ this.hasher = hasher;
29
+ }
30
+ async put(bytes, contentType) {
31
+ const hash = this.hasher(bytes);
32
+ const meta = {
33
+ hash,
34
+ byteLength: bytes.byteLength,
35
+ contentType,
36
+ uploadedAt: new Date().toISOString(),
37
+ };
38
+ if (!this.blobs.has(hash)) {
39
+ // Defensive copy so callers can mutate `bytes` after put().
40
+ this.blobs.set(hash, { bytes: new Uint8Array(bytes), meta });
41
+ }
42
+ return meta;
43
+ }
44
+ async get(hash) {
45
+ const entry = this.blobs.get(hash);
46
+ return entry ? new Uint8Array(entry.bytes) : null;
47
+ }
48
+ async has(hash) {
49
+ return this.blobs.has(hash);
50
+ }
51
+ async delete(hash) {
52
+ return this.blobs.delete(hash);
53
+ }
54
+ async list() {
55
+ return Array.from(this.blobs.keys());
56
+ }
57
+ async stat(hash) {
58
+ const entry = this.blobs.get(hash);
59
+ return entry ? { ...entry.meta } : null;
60
+ }
61
+ }
62
+ /**
63
+ * Browser-only IndexedDB-backed store. Loaded lazily so Node bundle
64
+ * paths don't trip on the missing global.
65
+ */
66
+ export async function createIndexedDbBlobStore(opts = {}, hasher = fnv128) {
67
+ if (typeof indexedDB === 'undefined') {
68
+ throw new Error('@ifc-lite/collab: indexedDB is unavailable; createIndexedDbBlobStore requires a browser environment');
69
+ }
70
+ const dbName = opts.dbName ?? 'ifc-lite/collab/blobs';
71
+ const storeName = opts.storeName ?? 'blobs';
72
+ const db = await new Promise((resolve, reject) => {
73
+ const open = indexedDB.open(dbName, 1);
74
+ open.onupgradeneeded = () => {
75
+ open.result.createObjectStore(storeName, { keyPath: 'hash' });
76
+ };
77
+ open.onsuccess = () => resolve(open.result);
78
+ open.onerror = () => reject(open.error);
79
+ });
80
+ const tx = (mode) => db.transaction(storeName, mode).objectStore(storeName);
81
+ const promisify = (req) => new Promise((res, rej) => {
82
+ req.onsuccess = () => res(req.result);
83
+ req.onerror = () => rej(req.error);
84
+ });
85
+ return {
86
+ async put(bytes, contentType) {
87
+ const hash = hasher(bytes);
88
+ const meta = {
89
+ hash,
90
+ byteLength: bytes.byteLength,
91
+ contentType,
92
+ uploadedAt: new Date().toISOString(),
93
+ };
94
+ await promisify(tx('readwrite').put({ hash, bytes, meta }));
95
+ return meta;
96
+ },
97
+ async get(hash) {
98
+ const entry = await promisify(tx('readonly').get(hash));
99
+ if (!entry)
100
+ return null;
101
+ const bytes = entry.bytes;
102
+ return bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
103
+ },
104
+ async has(hash) {
105
+ const count = await promisify(tx('readonly').count(hash));
106
+ return count > 0;
107
+ },
108
+ async delete(hash) {
109
+ const had = await this.has(hash);
110
+ if (!had)
111
+ return false;
112
+ await promisify(tx('readwrite').delete(hash));
113
+ return true;
114
+ },
115
+ async list() {
116
+ const keys = await promisify(tx('readonly').getAllKeys());
117
+ return keys;
118
+ },
119
+ async stat(hash) {
120
+ const entry = await promisify(tx('readonly').get(hash));
121
+ if (!entry)
122
+ return null;
123
+ return (entry.meta) ?? null;
124
+ },
125
+ };
126
+ }
127
+ export class HttpBlobStore {
128
+ opts;
129
+ hasher;
130
+ fetchImpl;
131
+ constructor(opts) {
132
+ this.opts = opts;
133
+ this.hasher = opts.hasher ?? fnv128;
134
+ this.fetchImpl = opts.fetch ?? fetch;
135
+ }
136
+ url(hash) {
137
+ return `${this.opts.baseUrl.replace(/\/$/, '')}/blobs/${hash}`;
138
+ }
139
+ headers(extra) {
140
+ const h = { ...(extra ?? {}) };
141
+ if (this.opts.token)
142
+ h['authorization'] = `Bearer ${this.opts.token}`;
143
+ return h;
144
+ }
145
+ async put(bytes, contentType) {
146
+ const hash = this.hasher(bytes);
147
+ const res = await this.fetchImpl(this.url(hash), {
148
+ method: 'PUT',
149
+ headers: this.headers({ 'content-type': contentType ?? 'application/octet-stream' }),
150
+ // TS 5.7's tightened `Uint8Array<ArrayBufferLike>` typing doesn't
151
+ // satisfy `BodyInit` directly; the runtime accepts Uint8Array fine.
152
+ body: bytes,
153
+ });
154
+ if (!res.ok) {
155
+ throw new Error(`@ifc-lite/collab: blob PUT failed: ${res.status} ${res.statusText}`);
156
+ }
157
+ return {
158
+ hash,
159
+ byteLength: bytes.byteLength,
160
+ contentType,
161
+ uploadedAt: new Date().toISOString(),
162
+ };
163
+ }
164
+ async get(hash) {
165
+ const res = await this.fetchImpl(this.url(hash), { headers: this.headers() });
166
+ if (res.status === 404)
167
+ return null;
168
+ if (!res.ok)
169
+ throw new Error(`@ifc-lite/collab: blob GET failed: ${res.status}`);
170
+ const buf = await res.arrayBuffer();
171
+ return new Uint8Array(buf);
172
+ }
173
+ async has(hash) {
174
+ const res = await this.fetchImpl(this.url(hash), { method: 'HEAD', headers: this.headers() });
175
+ return res.ok;
176
+ }
177
+ async delete(hash) {
178
+ const res = await this.fetchImpl(this.url(hash), { method: 'DELETE', headers: this.headers() });
179
+ if (res.status === 404)
180
+ return false;
181
+ if (!res.ok)
182
+ throw new Error(`@ifc-lite/collab: blob DELETE failed: ${res.status}`);
183
+ return true;
184
+ }
185
+ async list() {
186
+ const res = await this.fetchImpl(`${this.opts.baseUrl.replace(/\/$/, '')}/blobs`, {
187
+ headers: this.headers({ accept: 'application/json' }),
188
+ });
189
+ if (!res.ok)
190
+ throw new Error(`@ifc-lite/collab: blob list failed: ${res.status}`);
191
+ const json = (await res.json());
192
+ if (Array.isArray(json))
193
+ return json;
194
+ return json.hashes ?? [];
195
+ }
196
+ async stat(hash) {
197
+ const res = await this.fetchImpl(this.url(hash), { method: 'HEAD', headers: this.headers() });
198
+ if (res.status === 404)
199
+ return null;
200
+ if (!res.ok)
201
+ throw new Error(`@ifc-lite/collab: blob HEAD failed: ${res.status}`);
202
+ const len = res.headers.get('content-length');
203
+ return {
204
+ hash,
205
+ byteLength: len ? Number(len) : 0,
206
+ contentType: res.headers.get('content-type') ?? undefined,
207
+ uploadedAt: res.headers.get('last-modified') ?? undefined,
208
+ };
209
+ }
210
+ }
211
+ /* ------------------------------------------------------------------ */
212
+ /* Layered (local-first) backend */
213
+ /* ------------------------------------------------------------------ */
214
+ /**
215
+ * Read-through / write-through layering: writes go to `local` and `remote`
216
+ * in parallel; reads check `local` first and fall back to `remote`,
217
+ * caching the result locally on hit.
218
+ *
219
+ * This is what we recommend for browser apps: instant local reads, durable
220
+ * remote storage, and offline-first semantics for already-fetched blobs.
221
+ */
222
+ export class LayeredBlobStore {
223
+ local;
224
+ remote;
225
+ constructor(local, remote) {
226
+ this.local = local;
227
+ this.remote = remote;
228
+ }
229
+ async put(bytes, contentType) {
230
+ const [meta] = await Promise.all([
231
+ this.local.put(bytes, contentType),
232
+ this.remote.put(bytes, contentType).catch(() => null),
233
+ ]);
234
+ return meta;
235
+ }
236
+ async get(hash) {
237
+ const local = await this.local.get(hash);
238
+ if (local)
239
+ return local;
240
+ const remote = await this.remote.get(hash);
241
+ if (remote) {
242
+ // Cache locally for next time. Best-effort.
243
+ this.local.put(remote).catch(() => {
244
+ /* writes to a full IDB store can fail; non-fatal */
245
+ });
246
+ }
247
+ return remote;
248
+ }
249
+ async has(hash) {
250
+ if (await this.local.has(hash))
251
+ return true;
252
+ return this.remote.has(hash);
253
+ }
254
+ async delete(hash) {
255
+ const [a, b] = await Promise.all([
256
+ this.local.delete(hash),
257
+ this.remote.delete(hash).catch(() => false),
258
+ ]);
259
+ return a || b;
260
+ }
261
+ async list() {
262
+ const [a, b] = await Promise.all([this.local.list(), this.remote.list().catch(() => [])]);
263
+ return Array.from(new Set([...a, ...b]));
264
+ }
265
+ }
266
+ //# sourceMappingURL=blob-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob-store.js","sourceRoot":"","sources":["../../src/geometry/blob-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * CSG (constructive solid geometry) operation tree as a Y.Array<CSGOp>.
3
+ *
4
+ * Spec §9.4 / §11 + open problem #4: full CRDT-tree merging of CSG ops is
5
+ * a v1.x topic. v0.1 stores ops as an ordered Y.Array — concurrent
6
+ * additions from two peers interleave preserving each peer's relative
7
+ * order, and a UI can drag-to-reorder via explicit moves. The CSG result
8
+ * is order-dependent; that's exposed honestly in the README.
9
+ *
10
+ * The geometry node referenced here is one of the Y.Doc's
11
+ * `geometry` top-level entries with `type: 'csg-tree'`. The tree's ops
12
+ * live as a Y.Array on `params.ops` so they ride the same CRDT machinery
13
+ * as parametric params.
14
+ */
15
+ import * as Y from 'yjs';
16
+ export type CSGBoolean = 'union' | 'difference' | 'intersection' | 'xor';
17
+ export interface CSGOp {
18
+ /** Stable per-op UUID. We push (op) records, not (op, payload) pairs. */
19
+ opId: string;
20
+ /** Boolean operator applied between the previous accumulator and `operandGeomId`. */
21
+ op: CSGBoolean;
22
+ /** geomId of the operand — points into the same Y.Doc geometry map. */
23
+ operandGeomId: string;
24
+ /** Optional transform applied to the operand before the boolean. */
25
+ transform?: number[];
26
+ /** Authoring metadata (which user added this op). */
27
+ author?: string;
28
+ /** Wall-clock authoring time. */
29
+ at?: string;
30
+ }
31
+ export interface CreateCSGTreeOptions {
32
+ /** Optional initial op list. */
33
+ ops?: CSGOp[];
34
+ /** Initial bounding box estimate. */
35
+ bbox?: [number, number, number, number, number, number];
36
+ }
37
+ /**
38
+ * Get-or-create a CSG-tree geometry node and return its `ops` Y.Array.
39
+ *
40
+ * Idempotent: if the geometry already exists with `type==='csg-tree'`,
41
+ * returns the existing ops Y.Array.
42
+ */
43
+ export declare function ensureCSGTree(doc: Y.Doc, geomId: string, options?: CreateCSGTreeOptions): Y.Array<CSGOp>;
44
+ export declare function getCSGOps(doc: Y.Doc, geomId: string): CSGOp[];
45
+ /** Append one CSG op. Concurrent appends interleave per Y.Array semantics. */
46
+ export declare function appendCSGOp(doc: Y.Doc, geomId: string, op: CSGOp): number;
47
+ /** Insert a CSG op at a specific index. */
48
+ export declare function insertCSGOp(doc: Y.Doc, geomId: string, index: number, op: CSGOp): void;
49
+ /**
50
+ * Remove a CSG op by `opId`. Returns true if found and removed.
51
+ *
52
+ * We search by opId rather than index so concurrent inserts elsewhere
53
+ * don't shift the target.
54
+ */
55
+ export declare function removeCSGOp(doc: Y.Doc, geomId: string, opId: string): boolean;
56
+ /**
57
+ * Reorder a CSG op (move by opId to a new index). Implemented as
58
+ * delete-then-insert; the underlying CRDT semantics keep concurrent
59
+ * reorder + reorder visible as the last-applied wins (ordering is what
60
+ * the user is *for sure* fighting over).
61
+ */
62
+ export declare function moveCSGOp(doc: Y.Doc, geomId: string, opId: string, toIndex: number): boolean;
63
+ //# sourceMappingURL=csg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csg.d.ts","sourceRoot":"","sources":["../../src/geometry/csg.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,cAAc,GAAG,KAAK,CAAC;AAEzE,MAAM,WAAW,KAAK;IACpB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,EAAE,EAAE,UAAU,CAAC;IACf,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;IACd,qCAAqC;IACrC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB,GACjC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAkBhB;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,CAK7D;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,MAAM,CAIzE;AAED,2CAA2C;AAC3C,wBAAgB,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,IAAI,CAGtF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAU7E;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAW5F"}