@homeostate/core 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aliaksandr Mialeshka
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @homeostate/core
2
+
3
+ > **Draft / placeholder release.** `0.0.0` reserves the name while the API is still
4
+ > being designed. Nothing here is stable — do not depend on it yet.
5
+
6
+ State-manager agnostic sync engine between a store adapter and a [Yjs](https://github.com/yjs/yjs) document.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @homeostate/core yjs
12
+ ```
13
+
14
+ `yjs` is a peer dependency.
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import { createSyncEngine } from '@homeostate/core';
20
+ ```
21
+
22
+ See the [repository](https://github.com/mixedrays/homeostate) for the full workspace,
23
+ store adapters, and a runnable playground.
24
+
25
+ ## License
26
+
27
+ MIT — see [LICENSE](./LICENSE). Includes code derived from
28
+ [zustand-middleware-yjs](https://github.com/joebobmiles/zustand-middleware-yjs);
29
+ see [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,33 @@
1
+ # Third-Party Notices
2
+
3
+ ## zustand-middleware-yjs
4
+
5
+ `@homeostate/core` includes code derived from
6
+ [zustand-middleware-yjs](https://github.com/joebobmiles/zustand-middleware-yjs).
7
+
8
+ Copyright (c) 2021 Joseph R Miles
9
+
10
+ The upstream project is licensed under the MIT License:
11
+
12
+ ```text
13
+ The MIT License (MIT)
14
+
15
+ Copyright (c) 2021 Joseph R Miles
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
18
+ this software and associated documentation files (the "Software"), to deal in
19
+ the Software without restriction, including without limitation the rights to
20
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
21
+ the Software, and to permit persons to whom the Software is furnished to do so,
22
+ subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
29
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
30
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
31
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
+ ```
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Describes the change that needs to be made.
3
+ */
4
+ export declare enum ChangeType {
5
+ /** No change. */
6
+ NONE = "none",
7
+ /** A value was inserted. */
8
+ INSERT = "insert",
9
+ /** A value was replaced. */
10
+ UPDATE = "update",
11
+ /** A value was deleted. */
12
+ DELETE = "delete",
13
+ /** The value requires a recursive diff to identify further changes. */
14
+ PENDING = "pending"
15
+ }
16
+ /**
17
+ * A record that documents a change to an entry in an array or object.
18
+ */
19
+ export type Change = [ChangeType, string | number, unknown];
20
+ //# sourceMappingURL=change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,UAAU;IACpB,iBAAiB;IACjB,IAAI,SAAS;IACb,4BAA4B;IAC5B,MAAM,WAAW;IACjB,4BAA4B;IAC5B,MAAM,WAAW;IACjB,2BAA2B;IAC3B,MAAM,WAAW;IACjB,uEAAuE;IACvE,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC"}
package/dist/change.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Describes the change that needs to be made.
3
+ */
4
+ export var ChangeType;
5
+ (function (ChangeType) {
6
+ /** No change. */
7
+ ChangeType["NONE"] = "none";
8
+ /** A value was inserted. */
9
+ ChangeType["INSERT"] = "insert";
10
+ /** A value was replaced. */
11
+ ChangeType["UPDATE"] = "update";
12
+ /** A value was deleted. */
13
+ ChangeType["DELETE"] = "delete";
14
+ /** The value requires a recursive diff to identify further changes. */
15
+ ChangeType["PENDING"] = "pending";
16
+ })(ChangeType || (ChangeType = {}));
17
+ //# sourceMappingURL=change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change.js","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,UAWX;AAXD,WAAY,UAAU;IACpB,iBAAiB;IACjB,2BAAa,CAAA;IACb,4BAA4B;IAC5B,+BAAiB,CAAA;IACjB,4BAA4B;IAC5B,+BAAiB,CAAA;IACjB,2BAA2B;IAC3B,+BAAiB,CAAA;IACjB,uEAAuE;IACvE,iCAAmB,CAAA;AACrB,CAAC,EAXW,UAAU,KAAV,UAAU,QAWrB"}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { type Change } from './change.js';
2
+ type Diffable = Record<string, unknown> | Array<unknown> | string;
3
+ export declare const getChanges: (a: Diffable, b: Diffable) => Change[];
4
+ export {};
5
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEtD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;AAYlE,eAAO,MAAM,UAAU,GAAI,GAAG,QAAQ,EAAE,GAAG,QAAQ,KAAG,MAAM,EAK3D,CAAC"}
package/dist/diff.js ADDED
@@ -0,0 +1,202 @@
1
+ import { ChangeType } from './change.js';
2
+ const isDiffable = (v) => isArray(v) || isString(v) || (v !== null && typeof v === 'object');
3
+ const isArray = (d) => d instanceof Array;
4
+ const isString = (d) => typeof d === 'string';
5
+ const isRecord = (d) => !isArray(d) && !isString(d);
6
+ export const getChanges = (a, b) => {
7
+ if (isString(a) && isString(b))
8
+ return getStringChanges(a, b);
9
+ else if (isArray(a) && isArray(b))
10
+ return getArrayChanges(a, b);
11
+ else if (isRecord(a) && isRecord(b))
12
+ return getRecordChanges(a, b);
13
+ else
14
+ return [];
15
+ };
16
+ const getStringChanges = (a, b) => {
17
+ if (a === b)
18
+ return [];
19
+ else if (a.length === 0) {
20
+ return b
21
+ .split('')
22
+ .map((character, index) => [ChangeType.INSERT, index, character]);
23
+ }
24
+ else if (b.length === 0) {
25
+ return a.split('').map(() => [ChangeType.DELETE, 0, undefined]);
26
+ }
27
+ else if (!hasCommonSubsequence(a, b)) {
28
+ const deletes = a
29
+ .split('')
30
+ .map(() => [ChangeType.DELETE, 0, undefined]);
31
+ const inserts = b
32
+ .split('')
33
+ .map((character, index) => [ChangeType.INSERT, index, character]);
34
+ return deletes.concat(inserts);
35
+ }
36
+ else {
37
+ const m = a.length, n = b.length;
38
+ const reverse = m >= n;
39
+ return reverse ? _diffText(b, a, reverse) : _diffText(a, b, reverse);
40
+ }
41
+ };
42
+ const getArrayChanges = (a, b) => {
43
+ const changeList = [];
44
+ let finalIndices = 0;
45
+ let bOffset = 0;
46
+ for (let index = 0; index < a.length; index++) {
47
+ const value = a[index];
48
+ const bIndex = index + bOffset;
49
+ if (b[bIndex] === undefined)
50
+ changeList.push([ChangeType.DELETE, index, undefined]);
51
+ else if (isDiffable(value) && isDiffable(b[bIndex])) {
52
+ const currentDiff = getChanges(value, b[bIndex]);
53
+ const nextDiff = typeof b[bIndex + 1] === 'undefined'
54
+ ? []
55
+ : getChanges(value, b[bIndex + 1]);
56
+ if (typeof b[bIndex + 1] !== 'undefined' && nextDiff.length === 0) {
57
+ changeList.push([ChangeType.INSERT, index, b[bIndex]]);
58
+ finalIndices += 2;
59
+ bOffset++;
60
+ }
61
+ else if (currentDiff.length !== 0) {
62
+ changeList.push([ChangeType.PENDING, index, currentDiff]);
63
+ finalIndices++;
64
+ }
65
+ else
66
+ finalIndices++;
67
+ }
68
+ else if (value !== b[bIndex] && value === b[bIndex + 1]) {
69
+ changeList.push([ChangeType.INSERT, bIndex, b[bIndex]]);
70
+ finalIndices += 2;
71
+ bOffset++;
72
+ }
73
+ else if (value !== b[bIndex] && value !== b[bIndex + 1]) {
74
+ changeList.push([ChangeType.UPDATE, bIndex, b[bIndex]]);
75
+ finalIndices++;
76
+ }
77
+ else
78
+ finalIndices++;
79
+ }
80
+ if (finalIndices < b.length) {
81
+ b.slice(a.length).forEach((value, index) => changeList.push([ChangeType.INSERT, finalIndices + index, value]));
82
+ }
83
+ return changeList;
84
+ };
85
+ const getRecordChanges = (a, b) => {
86
+ const changeList = [];
87
+ Object.entries(a).forEach(([property, value]) => {
88
+ if (!(property in b) && !(value instanceof Function))
89
+ changeList.push([ChangeType.DELETE, property, undefined]);
90
+ });
91
+ Object.entries(b).forEach(([property, value]) => {
92
+ if (!(property in a))
93
+ changeList.push([ChangeType.INSERT, property, value]);
94
+ else if (isDiffable(a[property]) && isDiffable(value)) {
95
+ const d = getChanges(a[property], value);
96
+ if (d.length !== 0)
97
+ changeList.push([ChangeType.PENDING, property, d]);
98
+ }
99
+ else if (a[property] !== value)
100
+ changeList.push([ChangeType.UPDATE, property, value]);
101
+ });
102
+ return changeList;
103
+ };
104
+ const hasCommonSubsequence = (a, b) => {
105
+ const alphabetOfA = a.split('');
106
+ const alphabetOfB = b.split('');
107
+ let hasCommonSubsequence = false;
108
+ for (const c of alphabetOfA)
109
+ hasCommonSubsequence = hasCommonSubsequence || alphabetOfB.includes(c);
110
+ return hasCommonSubsequence;
111
+ };
112
+ /**
113
+ * An adaptation of Wu et al. O(NP) text diff. (See docs/text-diff)
114
+ *
115
+ * Credit to [this JavaScript implementation](https://github.com/cubicdaiya/onp/blob/master/javascript/onp.js).
116
+ *
117
+ * @param a The old string to transform.
118
+ * @param b The new string to transform to.
119
+ * @param isReversed Whether or not a or b have been swapped.
120
+ * @returns A list of changes that that turn a into b.
121
+ */
122
+ const _diffText = (a, b, isReversed) => {
123
+ const m = a.length, n = b.length;
124
+ const offset = m;
125
+ const delta = n - m;
126
+ const size = m + n + 1;
127
+ const frontierPoints = [];
128
+ for (let i = 0; i < size; i++)
129
+ frontierPoints[i] = -1;
130
+ const path = [];
131
+ for (let i = 0; i < size; i++)
132
+ path[i] = -1;
133
+ const pathPositions = [];
134
+ const snake = (k, p, q) => {
135
+ let y = Math.max(p, q);
136
+ let x = y - k;
137
+ while (x < m && y < n && a[x] === b[y]) {
138
+ x++;
139
+ y++;
140
+ }
141
+ path[k + offset] = pathPositions.length;
142
+ pathPositions[pathPositions.length] = {
143
+ x: x,
144
+ y: y,
145
+ k: p > q ? path[k + offset - 1] : path[k + offset + 1],
146
+ };
147
+ return y;
148
+ };
149
+ let p = -1;
150
+ do {
151
+ p++;
152
+ for (let k = -p; k < delta; k++) {
153
+ frontierPoints[k + offset] = snake(k, frontierPoints[k + offset - 1] + 1, frontierPoints[k + offset + 1]);
154
+ }
155
+ for (let k = delta + p; k > delta; k--) {
156
+ frontierPoints[k + offset] = snake(k, frontierPoints[k + offset - 1] + 1, frontierPoints[k + offset + 1]);
157
+ }
158
+ frontierPoints[delta + offset] = snake(delta, frontierPoints[delta + offset - 1] + 1, frontierPoints[delta + offset + 1]);
159
+ } while (frontierPoints[delta + offset] !== n);
160
+ let k = path[delta + offset];
161
+ const editPath = [];
162
+ while (k !== -1) {
163
+ editPath[editPath.length] = {
164
+ x: pathPositions[k].x,
165
+ y: pathPositions[k].y,
166
+ };
167
+ k = pathPositions[k].k;
168
+ }
169
+ const changeList = [];
170
+ let x = 0, y = 0, index = -1;
171
+ for (let i = editPath.length - 1; i >= 0; i--) {
172
+ while (x <= editPath[i].x || y <= editPath[i].y) {
173
+ if (editPath[i].y - editPath[i].x > y - x) {
174
+ if (isReversed) {
175
+ changeList[changeList.length] = [ChangeType.DELETE, index, undefined];
176
+ }
177
+ else {
178
+ changeList[changeList.length] = [ChangeType.INSERT, index, b[y - 1]];
179
+ index++;
180
+ }
181
+ y++;
182
+ }
183
+ else if (editPath[i].y - editPath[i].x < y - x) {
184
+ if (isReversed) {
185
+ changeList[changeList.length] = [ChangeType.INSERT, index, a[x - 1]];
186
+ index++;
187
+ }
188
+ else {
189
+ changeList[changeList.length] = [ChangeType.DELETE, index, undefined];
190
+ }
191
+ x++;
192
+ }
193
+ else {
194
+ x++;
195
+ y++;
196
+ index++;
197
+ }
198
+ }
199
+ }
200
+ return changeList;
201
+ };
202
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { createSyncEngine } from './sync-engine.js';
2
+ export { defaultSyncFilter } from './types.js';
3
+ export type { StoreAdapter, SyncEngine, SyncEngineConfig, Unsubscribe, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { createSyncEngine } from './sync-engine.js';
2
+ export { defaultSyncFilter } from './types.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,19 @@
1
+ import * as Y from 'yjs';
2
+ /**
3
+ * Converts a normal JavaScript array to a YArray shared type. Any nested
4
+ * objects or arrays are turned into YMaps and YArrays, respectively.
5
+ *
6
+ * @param array The array to transform into a YArray
7
+ * @returns A YArray.
8
+ */
9
+ export declare const arrayToYArray: (array: unknown[]) => Y.Array<unknown>;
10
+ /**
11
+ * Converts a normal JavaScript object into a YMap shared type. Any nested
12
+ * objects or arrays are turned into YMaps or YArrays, respectively.
13
+ *
14
+ * @param object The object to turn into a YMap shared type.
15
+ * @returns A YMap.
16
+ */
17
+ export declare const objectToYMap: (object: Record<string, unknown>) => Y.Map<unknown>;
18
+ export declare const stringToYText: (string: string) => Y.Text;
19
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,EAAE,KAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAW/D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAW3E,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,CAAC,CAAC,IAA0B,CAAC"}
@@ -0,0 +1,45 @@
1
+ import * as Y from 'yjs';
2
+ /**
3
+ * Converts a normal JavaScript array to a YArray shared type. Any nested
4
+ * objects or arrays are turned into YMaps and YArrays, respectively.
5
+ *
6
+ * @param array The array to transform into a YArray
7
+ * @returns A YArray.
8
+ */
9
+ export const arrayToYArray = (array) => {
10
+ const yarray = new Y.Array();
11
+ array.forEach((value) => {
12
+ if (value instanceof Array)
13
+ yarray.push([arrayToYArray(value)]);
14
+ else if (value !== null && typeof value === 'object')
15
+ yarray.push([objectToYMap(value)]);
16
+ else if (typeof value === 'string')
17
+ yarray.push([stringToYText(value)]);
18
+ else
19
+ yarray.push([value]);
20
+ });
21
+ return yarray;
22
+ };
23
+ /**
24
+ * Converts a normal JavaScript object into a YMap shared type. Any nested
25
+ * objects or arrays are turned into YMaps or YArrays, respectively.
26
+ *
27
+ * @param object The object to turn into a YMap shared type.
28
+ * @returns A YMap.
29
+ */
30
+ export const objectToYMap = (object) => {
31
+ const ymap = new Y.Map();
32
+ Object.entries(object).forEach(([property, value]) => {
33
+ if (value instanceof Array)
34
+ ymap.set(property, arrayToYArray(value));
35
+ else if (value !== null && typeof value === 'object')
36
+ ymap.set(property, objectToYMap(value));
37
+ else if (typeof value === 'string')
38
+ ymap.set(property, stringToYText(value));
39
+ else
40
+ ymap.set(property, value);
41
+ });
42
+ return ymap;
43
+ };
44
+ export const stringToYText = (string) => new Y.Text(string);
45
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAgB,EAAoB,EAAE;IAClE,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAE7B,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACtB,IAAI,KAAK,YAAY,KAAK;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;aAC3D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,KAAgC,CAAC,CAAC,CAAC,CAAC;aAC/G,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;;YACnE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAA+B,EAAkB,EAAE;IAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;IAEzB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;QACnD,IAAI,KAAK,YAAY,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;aAChE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAgC,CAAC,CAAC,CAAC;aACpH,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;;YACxE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import * as Y from 'yjs';
2
+ /**
3
+ * Diffs sharedType and newState to create a list of changes for transforming
4
+ * the contents of sharedType into that of newState. For every nested, 'pending'
5
+ * change detected, this function recurses, as a nested object or array is
6
+ * represented as a Y.Map or Y.Array.
7
+ *
8
+ * @param sharedType The Yjs shared type to patch.
9
+ * @param newState The new state to patch the shared type into.
10
+ */
11
+ export declare const patchSharedType: (sharedType: Y.Map<unknown> | Y.Array<unknown> | Y.Text, newState: unknown) => void;
12
+ /**
13
+ * Patches oldState to be identical to newState. This function recurses when
14
+ * an array or object is encountered. If oldState and newState are already
15
+ * identical (indicated by an empty diff), then oldState is returned.
16
+ *
17
+ * @param oldState The state we want to patch.
18
+ * @param newState The state we want oldState to match after patching.
19
+ *
20
+ * @returns The patched oldState, identical to newState.
21
+ */
22
+ export declare const patchState: <T>(oldState: T, newState: T) => T;
23
+ //# sourceMappingURL=patching.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patching.d.ts","sourceRoot":"","sources":["../src/patching.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAC1B,YAAY,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EACtD,UAAU,OAAO,KAChB,IAmEF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,UAAU,CAAC,EAAE,UAAU,CAAC,KAAG,CA+GxD,CAAC"}
@@ -0,0 +1,159 @@
1
+ import * as Y from 'yjs';
2
+ import { ChangeType } from './change.js';
3
+ import { getChanges } from './diff.js';
4
+ import { arrayToYArray, objectToYMap, stringToYText } from './mapping.js';
5
+ /**
6
+ * Diffs sharedType and newState to create a list of changes for transforming
7
+ * the contents of sharedType into that of newState. For every nested, 'pending'
8
+ * change detected, this function recurses, as a nested object or array is
9
+ * represented as a Y.Map or Y.Array.
10
+ *
11
+ * @param sharedType The Yjs shared type to patch.
12
+ * @param newState The new state to patch the shared type into.
13
+ */
14
+ export const patchSharedType = (sharedType, newState) => {
15
+ const changes = getChanges(sharedType.toJSON(), newState);
16
+ changes.forEach(([type, property, value]) => {
17
+ switch (type) {
18
+ case ChangeType.INSERT:
19
+ case ChangeType.UPDATE:
20
+ if (value instanceof Function === false) {
21
+ if (sharedType instanceof Y.Map) {
22
+ if (typeof value === 'string')
23
+ sharedType.set(property, stringToYText(value));
24
+ else if (value instanceof Array)
25
+ sharedType.set(property, arrayToYArray(value));
26
+ else if (value instanceof Object)
27
+ sharedType.set(property, objectToYMap(value));
28
+ else
29
+ sharedType.set(property, value);
30
+ }
31
+ else if (sharedType instanceof Y.Array) {
32
+ const index = property;
33
+ if (type === ChangeType.UPDATE)
34
+ sharedType.delete(index);
35
+ if (typeof value === 'string')
36
+ sharedType.insert(index, [stringToYText(value)]);
37
+ else if (value instanceof Array)
38
+ sharedType.insert(index, [arrayToYArray(value)]);
39
+ else if (value instanceof Object)
40
+ sharedType.insert(index, [objectToYMap(value)]);
41
+ else
42
+ sharedType.insert(index, [value]);
43
+ }
44
+ else if (sharedType instanceof Y.Text)
45
+ sharedType.insert(property, value);
46
+ }
47
+ break;
48
+ case ChangeType.DELETE:
49
+ if (sharedType instanceof Y.Map)
50
+ sharedType.delete(property);
51
+ else if (sharedType instanceof Y.Array) {
52
+ const index = property;
53
+ sharedType.delete(sharedType.length <= index ? sharedType.length - 1 : index);
54
+ }
55
+ else if (sharedType instanceof Y.Text)
56
+ // A delete operation for text is only ever for a single character.
57
+ sharedType.delete(property, 1);
58
+ break;
59
+ case ChangeType.PENDING:
60
+ if (sharedType instanceof Y.Map) {
61
+ patchSharedType(sharedType.get(property), newState[property]);
62
+ }
63
+ else if (sharedType instanceof Y.Array) {
64
+ patchSharedType(sharedType.get(property), newState[property]);
65
+ }
66
+ break;
67
+ default:
68
+ break;
69
+ }
70
+ });
71
+ };
72
+ /**
73
+ * Patches oldState to be identical to newState. This function recurses when
74
+ * an array or object is encountered. If oldState and newState are already
75
+ * identical (indicated by an empty diff), then oldState is returned.
76
+ *
77
+ * @param oldState The state we want to patch.
78
+ * @param newState The state we want oldState to match after patching.
79
+ *
80
+ * @returns The patched oldState, identical to newState.
81
+ */
82
+ export const patchState = (oldState, newState) => {
83
+ const changes = getChanges(oldState, newState);
84
+ const applyChanges = (state, changes) => {
85
+ if (typeof state === 'string')
86
+ return applyChangesToString(state, changes);
87
+ else if (state instanceof Array)
88
+ return applyChangesToArray(state, changes);
89
+ else if (state instanceof Object)
90
+ return applyChangesToObject(state, changes);
91
+ };
92
+ const applyChangesToArray = (array, changes) => changes
93
+ .sort(([, indexA], [, indexB]) => Math.sign(indexA - indexB))
94
+ .reduce((revisedArray, [type, index, value]) => {
95
+ switch (type) {
96
+ case ChangeType.INSERT: {
97
+ revisedArray.splice(index, 0, value);
98
+ return revisedArray;
99
+ }
100
+ case ChangeType.UPDATE: {
101
+ revisedArray[index] = value;
102
+ return revisedArray;
103
+ }
104
+ case ChangeType.PENDING: {
105
+ revisedArray[index] = applyChanges(array[index], value);
106
+ return revisedArray;
107
+ }
108
+ case ChangeType.DELETE: {
109
+ revisedArray.splice(index, 1);
110
+ return revisedArray;
111
+ }
112
+ case ChangeType.NONE:
113
+ default:
114
+ return revisedArray;
115
+ }
116
+ }, array);
117
+ const applyChangesToObject = (object, changes) => changes.reduce((revisedObject, [type, property, value]) => {
118
+ switch (type) {
119
+ case ChangeType.INSERT:
120
+ case ChangeType.UPDATE: {
121
+ revisedObject[property] = value;
122
+ return revisedObject;
123
+ }
124
+ case ChangeType.PENDING: {
125
+ revisedObject[property] = applyChanges(object[property], value);
126
+ return revisedObject;
127
+ }
128
+ case ChangeType.DELETE: {
129
+ delete revisedObject[property];
130
+ return revisedObject;
131
+ }
132
+ case ChangeType.NONE:
133
+ default:
134
+ return revisedObject;
135
+ }
136
+ }, object);
137
+ const applyChangesToString = (string, changes) => changes.reduce((revisedString, [type, index, value]) => {
138
+ switch (type) {
139
+ case ChangeType.INSERT: {
140
+ const left = revisedString.slice(0, index);
141
+ const right = revisedString.slice(index);
142
+ return left + value + right;
143
+ }
144
+ case ChangeType.DELETE: {
145
+ const left = revisedString.slice(0, index);
146
+ const right = revisedString.slice(index + 1);
147
+ return left + right;
148
+ }
149
+ default: {
150
+ return revisedString;
151
+ }
152
+ }
153
+ }, string);
154
+ if (changes.length === 0)
155
+ return oldState;
156
+ else
157
+ return applyChanges(oldState, changes);
158
+ };
159
+ //# sourceMappingURL=patching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patching.js","sourceRoot":"","sources":["../src/patching.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import * as Y from 'yjs';
2
+ import type { StoreAdapter, SyncEngine, SyncEngineConfig } from './types.js';
3
+ /**
4
+ * Creates a sync engine that manages bidirectional synchronization
5
+ * between any store (via adapter) and a Yjs document.
6
+ *
7
+ * This is the core abstraction that makes the sync logic state-manager agnostic.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const doc = new Y.Doc();
12
+ * const adapter = new ZustandAdapter(store);
13
+ * const engine = createSyncEngine(doc, adapter, { name: 'shared' });
14
+ * engine.connect();
15
+ * ```
16
+ */
17
+ export declare function createSyncEngine<S>(doc: Y.Doc, adapter: StoreAdapter<S>, config: SyncEngineConfig): SyncEngine;
18
+ //# sourceMappingURL=sync-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../src/sync-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EACxB,MAAM,EAAE,gBAAgB,GACvB,UAAU,CAiJZ"}
@@ -0,0 +1,137 @@
1
+ import { defaultSyncFilter } from './types.js';
2
+ import { patchSharedType, patchState } from './patching.js';
3
+ /**
4
+ * Creates a sync engine that manages bidirectional synchronization
5
+ * between any store (via adapter) and a Yjs document.
6
+ *
7
+ * This is the core abstraction that makes the sync logic state-manager agnostic.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const doc = new Y.Doc();
12
+ * const adapter = new ZustandAdapter(store);
13
+ * const engine = createSyncEngine(doc, adapter, { name: 'shared' });
14
+ * engine.connect();
15
+ * ```
16
+ */
17
+ export function createSyncEngine(doc, adapter, config) {
18
+ const { name, filter = defaultSyncFilter } = config;
19
+ // The root Y.Map that the store is written and read from
20
+ const yMap = doc.getMap(name);
21
+ let connected = false;
22
+ let storeUnsubscribe = null;
23
+ let isUpdatingFromYjs = false;
24
+ let isUpdatingFromStore = false;
25
+ /**
26
+ * Filter state to only include syncable properties
27
+ */
28
+ const filterState = (state) => {
29
+ if (typeof state !== 'object' || state === null) {
30
+ return state;
31
+ }
32
+ const filtered = {};
33
+ for (const [key, value] of Object.entries(state)) {
34
+ if (filter(key, value)) {
35
+ filtered[key] = value;
36
+ }
37
+ }
38
+ return filtered;
39
+ };
40
+ /**
41
+ * Sync store state to Yjs
42
+ */
43
+ const syncToYjs = () => {
44
+ if (isUpdatingFromYjs)
45
+ return;
46
+ isUpdatingFromStore = true;
47
+ try {
48
+ const state = adapter.getState();
49
+ const filteredState = filterState(state);
50
+ doc.transact(() => {
51
+ patchSharedType(yMap, filteredState);
52
+ });
53
+ }
54
+ finally {
55
+ isUpdatingFromStore = false;
56
+ }
57
+ };
58
+ /**
59
+ * Sync Yjs state to store
60
+ */
61
+ const syncToStore = () => {
62
+ if (isUpdatingFromStore)
63
+ return;
64
+ isUpdatingFromYjs = true;
65
+ try {
66
+ const yjsState = yMap.toJSON();
67
+ const currentState = adapter.getState();
68
+ // Merge Yjs state with current state (preserving functions and non-synced props)
69
+ const mergedState = mergeStates(currentState, yjsState);
70
+ adapter.setState(mergedState, true);
71
+ }
72
+ finally {
73
+ isUpdatingFromYjs = false;
74
+ }
75
+ };
76
+ /**
77
+ * Merge Yjs state with current store state, preserving non-syncable properties
78
+ */
79
+ const mergeStates = (current, fromYjs) => {
80
+ if (typeof current !== 'object' || current === null) {
81
+ return fromYjs;
82
+ }
83
+ const currentObj = current;
84
+ const yjsObj = fromYjs;
85
+ // Start with current state (preserves functions, etc.)
86
+ const merged = { ...currentObj };
87
+ // Apply Yjs state using patching for proper deep merging
88
+ const patchedData = patchState({ ...merged }, yjsObj);
89
+ // Restore non-syncable properties (like functions)
90
+ for (const [key, value] of Object.entries(currentObj)) {
91
+ if (!filter(key, value)) {
92
+ patchedData[key] = value;
93
+ }
94
+ }
95
+ return patchedData;
96
+ };
97
+ /**
98
+ * Handler for Yjs changes
99
+ */
100
+ const handleYjsChange = () => {
101
+ syncToStore();
102
+ };
103
+ return {
104
+ connect: () => {
105
+ if (connected)
106
+ return;
107
+ // Initialize Yjs with current store state
108
+ const initialState = adapter.getInitialState();
109
+ const filteredInitial = filterState(initialState);
110
+ doc.transact(() => {
111
+ patchSharedType(yMap, filteredInitial);
112
+ });
113
+ // Subscribe to Yjs changes
114
+ yMap.observeDeep(handleYjsChange);
115
+ // Subscribe to store changes
116
+ storeUnsubscribe = adapter.subscribe(() => {
117
+ syncToYjs();
118
+ });
119
+ connected = true;
120
+ },
121
+ disconnect: () => {
122
+ if (!connected)
123
+ return;
124
+ // Unsubscribe from Yjs
125
+ yMap.unobserveDeep(handleYjsChange);
126
+ // Unsubscribe from store
127
+ if (storeUnsubscribe) {
128
+ storeUnsubscribe();
129
+ storeUnsubscribe = null;
130
+ }
131
+ connected = false;
132
+ },
133
+ getYMap: () => yMap,
134
+ isConnected: () => connected,
135
+ };
136
+ }
137
+ //# sourceMappingURL=sync-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../src/sync-engine.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAU,EACV,OAAwB,EACxB,MAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,MAAM,CAAC;IAEpD,yDAAyD;IACzD,MAAM,IAAI,GAAmB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE9C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,gBAAgB,GAAuB,IAAI,CAAC;IAChD,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAEhC;;OAEG;IACH,MAAM,WAAW,GAAG,CAAC,KAAQ,EAAc,EAAE;QAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC5E,IAAI,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;gBACvB,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACxB,CAAC;QACH,CAAC;QACD,OAAO,QAAsB,CAAC;IAChC,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,SAAS,GAAG,GAAS,EAAE;QAC3B,IAAI,iBAAiB;YAAE,OAAO;QAE9B,mBAAmB,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAEzC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;gBAChB,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YACvC,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,mBAAmB,GAAG,KAAK,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,WAAW,GAAG,GAAS,EAAE;QAC7B,IAAI,mBAAmB;YAAE,OAAO;QAEhC,iBAAiB,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAO,CAAC;YACpC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YAExC,iFAAiF;YACjF,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;gBAAS,CAAC;YACT,iBAAiB,GAAG,KAAK,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,WAAW,GAAG,CAAC,OAAU,EAAE,OAAmB,EAAK,EAAE;QACzD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACpD,OAAO,OAAY,CAAC;QACtB,CAAC;QAED,MAAM,UAAU,GAAG,OAAkC,CAAC;QACtD,MAAM,MAAM,GAAG,OAAkC,CAAC;QAElD,uDAAuD;QACvD,MAAM,MAAM,GAA4B,EAAE,GAAG,UAAU,EAAE,CAAC;QAE1D,yDAAyD;QACzD,MAAM,WAAW,GAAG,UAAU,CAC5B,EAAE,GAAG,MAAM,EAAE,EACb,MAAM,CACP,CAAC;QAEF,mDAAmD;QACnD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;gBACxB,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,OAAO,WAAgB,CAAC;IAC1B,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,eAAe,GAAG,GAAS,EAAE;QACjC,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,GAAS,EAAE;YAClB,IAAI,SAAS;gBAAE,OAAO;YAEtB,0CAA0C;YAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;YAC/C,MAAM,eAAe,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;YAElD,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;gBAChB,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;YAEH,2BAA2B;YAC3B,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;YAElC,6BAA6B;YAC7B,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;gBACxC,SAAS,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,UAAU,EAAE,GAAS,EAAE;YACrB,IAAI,CAAC,SAAS;gBAAE,OAAO;YAEvB,uBAAuB;YACvB,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC;YAEpC,yBAAyB;YACzB,IAAI,gBAAgB,EAAE,CAAC;gBACrB,gBAAgB,EAAE,CAAC;gBACnB,gBAAgB,GAAG,IAAI,CAAC;YAC1B,CAAC;YAED,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QAED,OAAO,EAAE,GAAmB,EAAE,CAAC,IAAI;QAEnC,WAAW,EAAE,GAAY,EAAE,CAAC,SAAS;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Core types for the state-manager agnostic Yjs sync engine.
3
+ * These interfaces allow any store manager to be connected to Yjs for P2P sync.
4
+ */
5
+ /**
6
+ * Unsubscribe function returned by subscribe
7
+ */
8
+ export type Unsubscribe = () => void;
9
+ /**
10
+ * Adapter interface that bridges a specific state manager with the sync engine.
11
+ * Implement this interface to add support for any state manager (Zustand, Redux, MobX, etc.)
12
+ */
13
+ export interface StoreAdapter<S> {
14
+ /** Get the current state from the store */
15
+ getState: () => S;
16
+ /**
17
+ * Set state in the store.
18
+ * @param state - New state to set
19
+ * @param fromSync - If true, this update came from Yjs sync and should not trigger sync back
20
+ */
21
+ setState: (state: S, fromSync?: boolean) => void;
22
+ /**
23
+ * Subscribe to store changes that should trigger Yjs sync.
24
+ * @returns Unsubscribe function
25
+ */
26
+ subscribe: (onStoreChange: () => void) => Unsubscribe;
27
+ /** Get the initial state of the store */
28
+ getInitialState: () => S;
29
+ }
30
+ /**
31
+ * Configuration options for the sync engine
32
+ */
33
+ export interface SyncEngineConfig {
34
+ /** Name of the Y.Map in the Y.Doc to store the state */
35
+ name: string;
36
+ /**
37
+ * Filter function to determine which state keys should be synced.
38
+ * Return true to sync the key, false to exclude it.
39
+ * By default, functions are excluded from sync.
40
+ */
41
+ filter?: (key: string, value: unknown) => boolean;
42
+ }
43
+ /**
44
+ * The sync engine interface - manages bidirectional sync between store and Yjs
45
+ */
46
+ export interface SyncEngine {
47
+ /** Start synchronization */
48
+ connect: () => void;
49
+ /** Stop synchronization and cleanup */
50
+ disconnect: () => void;
51
+ /** Get the underlying Y.Map */
52
+ getYMap: () => unknown;
53
+ /** Check if engine is connected */
54
+ isConnected: () => boolean;
55
+ }
56
+ /**
57
+ * Default filter that excludes functions from sync
58
+ */
59
+ export declare const defaultSyncFilter: (_key: string, value: unknown) => boolean;
60
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC,CAAC;IAElB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAEjD;;;OAGG;IACH,SAAS,EAAE,CAAC,aAAa,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;IAEtD,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,uCAAuC;IACvC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,mCAAmC;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,OAAO,OAAO,KAAG,OAEhE,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Core types for the state-manager agnostic Yjs sync engine.
3
+ * These interfaces allow any store manager to be connected to Yjs for P2P sync.
4
+ */
5
+ /**
6
+ * Default filter that excludes functions from sync
7
+ */
8
+ export const defaultSyncFilter = (_key, value) => {
9
+ return typeof value !== 'function';
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4DH;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,KAAc,EAAW,EAAE;IACzE,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@homeostate/core",
3
+ "version": "0.0.0",
4
+ "description": "State-manager agnostic sync engine between a store adapter and a Yjs document",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/mixedrays/homeostate.git",
10
+ "directory": "packages/core"
11
+ },
12
+ "homepage": "https://github.com/mixedrays/homeostate#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/mixedrays/homeostate/issues"
15
+ },
16
+ "keywords": [
17
+ "yjs",
18
+ "crdt",
19
+ "sync",
20
+ "state-management",
21
+ "collaborative"
22
+ ],
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE",
35
+ "THIRD_PARTY_NOTICES.md"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "peerDependencies": {
41
+ "yjs": "^13.6.0"
42
+ },
43
+ "devDependencies": {
44
+ "yjs": "^13.6.23"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -b"
48
+ }
49
+ }