@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.
@@ -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
+ }