@editneo/sync 0.1.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/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/package.json +26 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
3
|
+
import { WebsocketProvider } from 'y-websocket';
|
|
4
|
+
import { NeoBlock } from '@editneo/core';
|
|
5
|
+
export declare class SyncManager {
|
|
6
|
+
doc: Y.Doc;
|
|
7
|
+
yBlocks: Y.Map<any>;
|
|
8
|
+
yRoot: Y.Array<string>;
|
|
9
|
+
provider: IndexeddbPersistence;
|
|
10
|
+
wsProvider?: WebsocketProvider;
|
|
11
|
+
constructor(docId?: string, syncConfig?: {
|
|
12
|
+
url: string;
|
|
13
|
+
room: string;
|
|
14
|
+
});
|
|
15
|
+
setupObservers(): void;
|
|
16
|
+
syncBlock(block: NeoBlock): void;
|
|
17
|
+
syncRoot(rootBlocks: string[]): void;
|
|
18
|
+
deleteBlock(id: string): void;
|
|
19
|
+
destroy(): void;
|
|
20
|
+
get awareness(): import("y-protocols/awareness").Awareness | undefined;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAkB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzD,qBAAa,WAAW;IACtB,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACX,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,UAAU,CAAC,EAAE,iBAAiB,CAAC;gBAEnB,KAAK,GAAE,MAAkB,EAAE,UAAU,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAoBjF,cAAc;IAmBP,SAAS,CAAC,KAAK,EAAE,QAAQ;IAczB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE;IAU7B,WAAW,CAAC,EAAE,EAAE,MAAM;IAM7B,OAAO;IAMP,IAAI,SAAS,0DAEZ;CACF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
3
|
+
import { WebsocketProvider } from 'y-websocket';
|
|
4
|
+
import { useEditorStore } from '@editneo/core';
|
|
5
|
+
export class SyncManager {
|
|
6
|
+
constructor(docId = 'default', syncConfig) {
|
|
7
|
+
this.doc = new Y.Doc();
|
|
8
|
+
this.yBlocks = this.doc.getMap('blocks');
|
|
9
|
+
this.yRoot = this.doc.getArray('rootBlocks');
|
|
10
|
+
// Offline persistence
|
|
11
|
+
this.provider = new IndexeddbPersistence(`editneo-document-${docId}`, this.doc);
|
|
12
|
+
// WebSocket Sync
|
|
13
|
+
if (syncConfig) {
|
|
14
|
+
this.wsProvider = new WebsocketProvider(syncConfig.url, syncConfig.room, this.doc);
|
|
15
|
+
this.wsProvider.on('status', (event) => {
|
|
16
|
+
console.log('Sync status:', event.status); // 'connected' or 'disconnected'
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
this.setupObservers();
|
|
20
|
+
}
|
|
21
|
+
setupObservers() {
|
|
22
|
+
// 1. Listen to Yjs changes and update Zustand
|
|
23
|
+
this.yBlocks.observe((event) => {
|
|
24
|
+
// Simplistic full sync for now (MVP optimization needed later)
|
|
25
|
+
const newBlocks = this.yBlocks.toJSON();
|
|
26
|
+
useEditorStore.setState({ blocks: newBlocks });
|
|
27
|
+
});
|
|
28
|
+
this.yRoot.observe((event) => {
|
|
29
|
+
const newRoot = this.yRoot.toJSON();
|
|
30
|
+
useEditorStore.setState({ rootBlocks: newRoot });
|
|
31
|
+
});
|
|
32
|
+
// Subscribe to store changes to push to Yjs?
|
|
33
|
+
// Doing it inside store via middleware is better to avoid loops.
|
|
34
|
+
// OR expose a method here that the store calls.
|
|
35
|
+
}
|
|
36
|
+
// These methods should be called by the store actions
|
|
37
|
+
syncBlock(block) {
|
|
38
|
+
// Only update if changed prevents some loops, but Yjs handles identical updates well.
|
|
39
|
+
// We should check if the update is coming from Yjs (remote) or local.
|
|
40
|
+
// Since we are calling this from store actions, it's local.
|
|
41
|
+
// However, store actions might be triggered by Yjs updates -> loop risk!
|
|
42
|
+
// We need a flag or compare content.
|
|
43
|
+
const currentYBlock = this.yBlocks.get(block.id);
|
|
44
|
+
if (JSON.stringify(currentYBlock) !== JSON.stringify(block)) {
|
|
45
|
+
// Improve: granular updates
|
|
46
|
+
this.yBlocks.set(block.id, block);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
syncRoot(rootBlocks) {
|
|
50
|
+
const currentYRoot = this.yRoot.toJSON();
|
|
51
|
+
if (JSON.stringify(currentYRoot) !== JSON.stringify(rootBlocks)) {
|
|
52
|
+
this.doc.transact(() => {
|
|
53
|
+
this.yRoot.delete(0, this.yRoot.length);
|
|
54
|
+
this.yRoot.push(rootBlocks);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
deleteBlock(id) {
|
|
59
|
+
if (this.yBlocks.has(id)) {
|
|
60
|
+
this.yBlocks.delete(id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
destroy() {
|
|
64
|
+
var _a;
|
|
65
|
+
this.provider.destroy();
|
|
66
|
+
(_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
67
|
+
this.doc.destroy();
|
|
68
|
+
}
|
|
69
|
+
get awareness() {
|
|
70
|
+
var _a;
|
|
71
|
+
return (_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a.awareness;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@editneo/sync",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Yjs-based CRDT sync manager for EditNeo with offline and WebSocket support",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"files": ["dist"],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"check-types": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"yjs": "^13.6.10",
|
|
17
|
+
"y-indexeddb": "^9.0.12",
|
|
18
|
+
"y-websocket": "^1.5.0",
|
|
19
|
+
"@editneo/core": "*"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.3.3",
|
|
23
|
+
"@types/node": "^20.11.24"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT"
|
|
26
|
+
}
|