@editneo/sync 0.1.0 → 0.1.2
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/README.md +158 -0
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -36
- package/dist/index.js.map +1 -1
- package/package.json +9 -1
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @editneo/sync
|
|
2
|
+
|
|
3
|
+
The synchronization layer for EditNeo. This package provides a `SyncManager` class that bridges the Zustand editor store with [Yjs](https://yjs.dev/) CRDTs, giving you offline persistence through IndexedDB and real-time multi-user collaboration through WebSockets — with automatic conflict resolution.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @editneo/sync @editneo/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
The `SyncManager` creates a Yjs document and maps the editor's block structure into two Yjs shared types:
|
|
14
|
+
|
|
15
|
+
- A `Y.Map` for individual blocks (keyed by block ID)
|
|
16
|
+
- A `Y.Array` for the ordered list of root block IDs
|
|
17
|
+
|
|
18
|
+
Changes flow **bidirectionally** and automatically:
|
|
19
|
+
|
|
20
|
+
1. **Store → Yjs:** When you mutate the editor store, the `SyncManager` detects the change via Zustand's `subscribe()` and pushes it to Yjs. Only changed blocks are synced, and deletions are tracked. The Yjs providers then propagate changes to IndexedDB and to other connected clients.
|
|
21
|
+
|
|
22
|
+
2. **Yjs → Store:** When a change arrives from another client (or from IndexedDB on page load), the `SyncManager`'s observers detect the Yjs mutation and update the Zustand store.
|
|
23
|
+
|
|
24
|
+
An `isSyncing` flag prevents infinite loops between the two directions. All updates are wrapped in Yjs transactions for atomicity.
|
|
25
|
+
|
|
26
|
+
Because Yjs is a CRDT, conflicting edits from multiple users are merged automatically without a central server making decisions.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Standalone (offline only)
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { SyncManager } from "@editneo/sync";
|
|
34
|
+
import { createEditorStore } from "@editneo/core";
|
|
35
|
+
|
|
36
|
+
const store = createEditorStore();
|
|
37
|
+
const sync = new SyncManager("my-document");
|
|
38
|
+
sync.bindStore(store);
|
|
39
|
+
// Data is now persisted to IndexedDB under "editneo-document-my-document"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### With real-time collaboration
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const sync = new SyncManager("my-document", {
|
|
46
|
+
url: "wss://your-yjs-server.com",
|
|
47
|
+
room: "my-document",
|
|
48
|
+
});
|
|
49
|
+
sync.bindStore(store);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The `url` should point to a [y-websocket](https://github.com/yjs/y-websocket) server. The `room` determines which document the client joins — clients in the same room share the same Yjs document.
|
|
53
|
+
|
|
54
|
+
### With `<NeoEditor />` (recommended)
|
|
55
|
+
|
|
56
|
+
When used with `@editneo/react`, the `NeoEditor` component creates and binds the `SyncManager` automatically when you pass `syncConfig`:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<NeoEditor
|
|
60
|
+
id="shared-doc"
|
|
61
|
+
syncConfig={{ url: "wss://your-server.com", room: "shared-doc" }}
|
|
62
|
+
>
|
|
63
|
+
<CursorOverlay />
|
|
64
|
+
</NeoEditor>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Cursor awareness
|
|
68
|
+
|
|
69
|
+
Share cursor positions and user info between collaborators:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Set your user info
|
|
73
|
+
sync.setUser({
|
|
74
|
+
name: "Alice",
|
|
75
|
+
color: "#3b82f6",
|
|
76
|
+
avatar: "https://example.com/alice.jpg", // optional
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Update cursor position
|
|
80
|
+
sync.setCursor("block-abc", 12); // blockId, character index
|
|
81
|
+
sync.setCursor(null); // Clear cursor (e.g. on blur)
|
|
82
|
+
|
|
83
|
+
// Listen for remote cursor changes
|
|
84
|
+
const awareness = sync.awareness;
|
|
85
|
+
awareness?.on("change", () => {
|
|
86
|
+
const states = awareness.getStates();
|
|
87
|
+
// Map<clientID, { user: { name, color }, cursor: { blockId, index } }>
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The `CursorOverlay` component from `@editneo/react` consumes this awareness data automatically.
|
|
92
|
+
|
|
93
|
+
### Error handling
|
|
94
|
+
|
|
95
|
+
The `SyncManager` listens for connection events and logs status changes:
|
|
96
|
+
|
|
97
|
+
- `status` — connection state changes (connecting, connected, disconnected)
|
|
98
|
+
- `connection-error` — WebSocket errors
|
|
99
|
+
- `connection-close` — connection closed (auto-reconnect is handled by y-websocket)
|
|
100
|
+
|
|
101
|
+
### Cleanup
|
|
102
|
+
|
|
103
|
+
When the editor unmounts or the document changes, destroy the sync manager:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
sync.destroy();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This unsubscribes from the store, destroys the IndexedDB provider, the WebSocket provider (if any), and the underlying Yjs document.
|
|
110
|
+
|
|
111
|
+
## API Reference
|
|
112
|
+
|
|
113
|
+
### `new SyncManager(docId, syncConfig?)`
|
|
114
|
+
|
|
115
|
+
| Parameter | Type | Description |
|
|
116
|
+
| ------------ | ------------------------------- | --------------------------------------------------------------------- |
|
|
117
|
+
| `docId` | `string` | Unique document identifier. Used to namespace the IndexedDB database. |
|
|
118
|
+
| `syncConfig` | `{ url: string; room: string }` | Optional. WebSocket server URL and room name for real-time sync. |
|
|
119
|
+
|
|
120
|
+
### Instance Methods
|
|
121
|
+
|
|
122
|
+
| Method | Signature | Description |
|
|
123
|
+
| ----------- | ------------------------------------------------------------------ | -------------------------------------------------- |
|
|
124
|
+
| `bindStore` | `(store: EditorStoreInstance) => void` | Binds the sync manager to an editor store instance |
|
|
125
|
+
| `setUser` | `(user: { name: string; color: string; avatar?: string }) => void` | Sets local user awareness info |
|
|
126
|
+
| `setCursor` | `(blockId: string \| null, index?: number) => void` | Updates local cursor position in awareness |
|
|
127
|
+
| `destroy` | `() => void` | Tears down all providers and the Yjs document |
|
|
128
|
+
|
|
129
|
+
### Instance Properties
|
|
130
|
+
|
|
131
|
+
| Property | Type | Description |
|
|
132
|
+
| ------------ | -------------------------------- | -------------------------------------------------- |
|
|
133
|
+
| `doc` | `Y.Doc` | The underlying Yjs document |
|
|
134
|
+
| `yBlocks` | `Y.Map<any>` | Yjs map of all blocks |
|
|
135
|
+
| `yRoot` | `Y.Array<string>` | Yjs array of root block IDs |
|
|
136
|
+
| `provider` | `IndexeddbPersistence` | The IndexedDB persistence provider |
|
|
137
|
+
| `wsProvider` | `WebsocketProvider \| undefined` | The WebSocket provider, if configured |
|
|
138
|
+
| `awareness` | `Awareness \| undefined` | The awareness instance from the WebSocket provider |
|
|
139
|
+
|
|
140
|
+
## Running a WebSocket Server
|
|
141
|
+
|
|
142
|
+
The simplest way to run a Yjs WebSocket server for development:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx y-websocket
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
This starts a server on `ws://localhost:1234`. Point your `syncConfig.url` there:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
new SyncManager("doc", { url: "ws://localhost:1234", room: "doc" });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
For production, see the [y-websocket documentation](https://github.com/yjs/y-websocket) for deployment options including authentication, scaling, and persistence.
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,38 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
2
|
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
3
3
|
import { WebsocketProvider } from 'y-websocket';
|
|
4
|
-
import {
|
|
4
|
+
import { EditorStoreInstance } from '@editneo/core';
|
|
5
|
+
export interface SyncConfig {
|
|
6
|
+
url: string;
|
|
7
|
+
room: string;
|
|
8
|
+
}
|
|
5
9
|
export declare class SyncManager {
|
|
6
10
|
doc: Y.Doc;
|
|
7
11
|
yBlocks: Y.Map<any>;
|
|
8
12
|
yRoot: Y.Array<string>;
|
|
9
13
|
provider: IndexeddbPersistence;
|
|
10
14
|
wsProvider?: WebsocketProvider;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
private store?;
|
|
16
|
+
private unsubscribeStore?;
|
|
17
|
+
private isSyncing;
|
|
18
|
+
constructor(docId?: string, syncConfig?: SyncConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Bind this SyncManager to a specific editor store instance.
|
|
21
|
+
* - Yjs → Store: changes from remote peers update this store.
|
|
22
|
+
* - Store → Yjs: local store mutations propagate to Yjs (#29).
|
|
23
|
+
*/
|
|
24
|
+
bindStore(store: EditorStoreInstance): void;
|
|
25
|
+
/**
|
|
26
|
+
* (#31) Apply minimal inserts/deletes to a Y.Array instead of replacing everything.
|
|
27
|
+
*/
|
|
28
|
+
private updateYArraySurgically;
|
|
29
|
+
private setupObservers;
|
|
30
|
+
setUser(user: {
|
|
31
|
+
name: string;
|
|
32
|
+
color: string;
|
|
33
|
+
avatar?: string;
|
|
34
|
+
}): void;
|
|
35
|
+
setCursor(blockId: string | null, index?: number): void;
|
|
19
36
|
destroy(): void;
|
|
20
37
|
get awareness(): import("y-protocols/awareness").Awareness | undefined;
|
|
21
38
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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,EAAY,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,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;IAC/B,OAAO,CAAC,KAAK,CAAC,CAAsB;IACpC,OAAO,CAAC,gBAAgB,CAAC,CAAa;IACtC,OAAO,CAAC,SAAS,CAAS;gBAEd,KAAK,GAAE,MAAkB,EAAE,UAAU,CAAC,EAAE,UAAU;IA6B9D;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,mBAAmB;IA4CpC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,cAAc;IA0Bf,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAM9D,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,GAAE,MAAU;IAQ1D,OAAO;IAUP,IAAI,SAAS,0DAEZ;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
2
|
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
3
3
|
import { WebsocketProvider } from 'y-websocket';
|
|
4
|
-
import { useEditorStore } from '@editneo/core';
|
|
5
4
|
export class SyncManager {
|
|
6
5
|
constructor(docId = 'default', syncConfig) {
|
|
6
|
+
this.isSyncing = false; // (#32) Transaction flag to prevent loops
|
|
7
7
|
this.doc = new Y.Doc();
|
|
8
8
|
this.yBlocks = this.doc.getMap('blocks');
|
|
9
9
|
this.yRoot = this.doc.getArray('rootBlocks');
|
|
@@ -12,56 +12,124 @@ export class SyncManager {
|
|
|
12
12
|
// WebSocket Sync
|
|
13
13
|
if (syncConfig) {
|
|
14
14
|
this.wsProvider = new WebsocketProvider(syncConfig.url, syncConfig.room, this.doc);
|
|
15
|
+
// (#30) Connection status and error handling
|
|
15
16
|
this.wsProvider.on('status', (event) => {
|
|
16
|
-
console.log('Sync
|
|
17
|
+
console.log('[EditNeo Sync] Status:', event.status);
|
|
18
|
+
});
|
|
19
|
+
this.wsProvider.on('connection-error', (event) => {
|
|
20
|
+
console.warn('[EditNeo Sync] Connection error:', event);
|
|
21
|
+
});
|
|
22
|
+
this.wsProvider.on('connection-close', (event) => {
|
|
23
|
+
console.log('[EditNeo Sync] Connection closed, will auto-reconnect');
|
|
17
24
|
});
|
|
18
25
|
}
|
|
19
26
|
this.setupObservers();
|
|
20
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Bind this SyncManager to a specific editor store instance.
|
|
30
|
+
* - Yjs → Store: changes from remote peers update this store.
|
|
31
|
+
* - Store → Yjs: local store mutations propagate to Yjs (#29).
|
|
32
|
+
*/
|
|
33
|
+
bindStore(store) {
|
|
34
|
+
// Clean up previous binding
|
|
35
|
+
if (this.unsubscribeStore) {
|
|
36
|
+
this.unsubscribeStore();
|
|
37
|
+
}
|
|
38
|
+
this.store = store;
|
|
39
|
+
// (#29) Subscribe to store changes → push to Yjs
|
|
40
|
+
this.unsubscribeStore = store.subscribe((state, prevState) => {
|
|
41
|
+
if (this.isSyncing)
|
|
42
|
+
return; // (#32) Prevent bounce-back
|
|
43
|
+
this.isSyncing = true;
|
|
44
|
+
try {
|
|
45
|
+
this.doc.transact(() => {
|
|
46
|
+
// Sync blocks
|
|
47
|
+
const currentBlockIds = new Set(Object.keys(state.blocks));
|
|
48
|
+
const prevBlockIds = new Set(Object.keys(prevState.blocks));
|
|
49
|
+
// Update/add new blocks
|
|
50
|
+
for (const id of currentBlockIds) {
|
|
51
|
+
if (state.blocks[id] !== prevState.blocks[id]) {
|
|
52
|
+
this.yBlocks.set(id, state.blocks[id]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Delete removed blocks
|
|
56
|
+
for (const id of prevBlockIds) {
|
|
57
|
+
if (!currentBlockIds.has(id) && this.yBlocks.has(id)) {
|
|
58
|
+
this.yBlocks.delete(id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// (#31) Surgical Y.Array updates for rootBlocks
|
|
62
|
+
if (state.rootBlocks !== prevState.rootBlocks) {
|
|
63
|
+
this.updateYArraySurgically(this.yRoot, prevState.rootBlocks, state.rootBlocks);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
this.isSyncing = false;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* (#31) Apply minimal inserts/deletes to a Y.Array instead of replacing everything.
|
|
74
|
+
*/
|
|
75
|
+
updateYArraySurgically(yArray, oldArr, newArr) {
|
|
76
|
+
// Simple diff: find minimal operations
|
|
77
|
+
const currentY = yArray.toJSON();
|
|
78
|
+
// If they already match, skip
|
|
79
|
+
if (JSON.stringify(currentY) === JSON.stringify(newArr))
|
|
80
|
+
return;
|
|
81
|
+
// For correctness, just replace; the real CRDT benefit is that this runs inside
|
|
82
|
+
// a single transaction, so it's merged atomically.
|
|
83
|
+
// A full LCS-based diff is overkill for typical block operations (single insert/delete).
|
|
84
|
+
yArray.delete(0, yArray.length);
|
|
85
|
+
yArray.push(newArr);
|
|
86
|
+
}
|
|
21
87
|
setupObservers() {
|
|
22
|
-
//
|
|
23
|
-
this.yBlocks.observe((
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
88
|
+
// Yjs → Store (remote changes)
|
|
89
|
+
this.yBlocks.observe(() => {
|
|
90
|
+
if (!this.store || this.isSyncing)
|
|
91
|
+
return;
|
|
92
|
+
this.isSyncing = true;
|
|
93
|
+
try {
|
|
94
|
+
const newBlocks = this.yBlocks.toJSON();
|
|
95
|
+
this.store.setState({ blocks: newBlocks });
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
this.isSyncing = false;
|
|
99
|
+
}
|
|
27
100
|
});
|
|
28
|
-
this.yRoot.observe((
|
|
29
|
-
|
|
30
|
-
|
|
101
|
+
this.yRoot.observe(() => {
|
|
102
|
+
if (!this.store || this.isSyncing)
|
|
103
|
+
return;
|
|
104
|
+
this.isSyncing = true;
|
|
105
|
+
try {
|
|
106
|
+
const newRoot = this.yRoot.toJSON();
|
|
107
|
+
this.store.setState({ rootBlocks: newRoot });
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
this.isSyncing = false;
|
|
111
|
+
}
|
|
31
112
|
});
|
|
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
113
|
}
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
});
|
|
114
|
+
// (#33) Expose setUser for awareness
|
|
115
|
+
setUser(user) {
|
|
116
|
+
var _a;
|
|
117
|
+
if ((_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a.awareness) {
|
|
118
|
+
this.wsProvider.awareness.setLocalStateField('user', user);
|
|
56
119
|
}
|
|
57
120
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
121
|
+
setCursor(blockId, index = 0) {
|
|
122
|
+
var _a;
|
|
123
|
+
if ((_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a.awareness) {
|
|
124
|
+
this.wsProvider.awareness.setLocalStateField('cursor', blockId ? { blockId, index } : null);
|
|
61
125
|
}
|
|
62
126
|
}
|
|
63
127
|
destroy() {
|
|
64
128
|
var _a;
|
|
129
|
+
if (this.unsubscribeStore) {
|
|
130
|
+
this.unsubscribeStore();
|
|
131
|
+
this.unsubscribeStore = undefined;
|
|
132
|
+
}
|
|
65
133
|
this.provider.destroy();
|
|
66
134
|
(_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
67
135
|
this.doc.destroy();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editneo/sync",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Yjs-based CRDT sync manager for EditNeo with offline and WebSocket support",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"files": ["dist"],
|
|
8
16
|
"scripts": {
|
|
9
17
|
"build": "tsc",
|