@voltro/local-first 0.52.0 → 0.53.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/CHANGELOG.md +229 -0
- package/THIRD-PARTY-NOTICES.md +29 -1
- package/dist/index.d.ts +329 -20
- package/dist/index.js +192 -27
- package/dist/react.d.ts +66 -7
- package/dist/react.js +20 -20
- package/dist/{room-wFNUwEgi.js → room-DZzqWoJq.js} +100 -38
- package/package.json +20 -3
|
@@ -25,7 +25,47 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
25
25
|
let n = r(e), i = n.getText(t).toString();
|
|
26
26
|
return n.destroy(), i;
|
|
27
27
|
},
|
|
28
|
-
emptyState: () => n(new e.Doc())
|
|
28
|
+
emptyState: () => n(new e.Doc()),
|
|
29
|
+
createDoc: (t) => {
|
|
30
|
+
let n = new e.Doc();
|
|
31
|
+
return t !== void 0 && t.length > 0 && e.applyUpdate(n, t), {
|
|
32
|
+
raw: n,
|
|
33
|
+
encodeState: () => e.encodeStateAsUpdate(n),
|
|
34
|
+
stateVector: () => e.encodeStateVector(n),
|
|
35
|
+
encodeUpdateSince: (t) => e.encodeStateAsUpdate(n, t),
|
|
36
|
+
applyState: (t) => {
|
|
37
|
+
t.length > 0 && e.applyUpdate(n, t);
|
|
38
|
+
},
|
|
39
|
+
onUpdate: (e) => {
|
|
40
|
+
let t = (t) => {
|
|
41
|
+
e(t);
|
|
42
|
+
};
|
|
43
|
+
return n.on("update", t), () => {
|
|
44
|
+
n.off("update", t);
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
encodeAnchor: (t, r) => {
|
|
48
|
+
let i = e.createRelativePositionFromTypeIndex(n.getText(t), r);
|
|
49
|
+
return e.encodeRelativePosition(i);
|
|
50
|
+
},
|
|
51
|
+
resolveAnchor: (t) => {
|
|
52
|
+
let r = e.createAbsolutePositionFromRelativePosition(e.decodeRelativePosition(t), n);
|
|
53
|
+
return r === null ? void 0 : r.index;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
compact: (t) => {
|
|
58
|
+
let n = r(t), i = e.encodeStateAsUpdate(n);
|
|
59
|
+
return n.destroy(), i;
|
|
60
|
+
},
|
|
61
|
+
rebaseText: (n) => {
|
|
62
|
+
let i = r(n), a = i.getText(t).toString();
|
|
63
|
+
i.destroy();
|
|
64
|
+
let o = new e.Doc();
|
|
65
|
+
a.length > 0 && o.getText(t).insert(0, a);
|
|
66
|
+
let s = e.encodeStateAsUpdate(o);
|
|
67
|
+
return o.destroy(), s;
|
|
68
|
+
}
|
|
29
69
|
}, o = a, s = (e, t = o) => {
|
|
30
70
|
let n = t.createText(e), r = {
|
|
31
71
|
backend: t.name,
|
|
@@ -36,15 +76,22 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
36
76
|
encode: () => n.encodeState()
|
|
37
77
|
};
|
|
38
78
|
return r;
|
|
39
|
-
}, c = (e, t, n
|
|
79
|
+
}, c = (e, t, n) => {
|
|
80
|
+
if (!(n instanceof Uint8Array) || !(t instanceof Uint8Array)) return n;
|
|
81
|
+
try {
|
|
82
|
+
return l(t, n);
|
|
83
|
+
} catch {
|
|
84
|
+
return n;
|
|
85
|
+
}
|
|
86
|
+
}, l = (e, t, n = o) => n.merge(e, t), u = (e, t = o) => t.decodeText(e), d = (e = o) => e.emptyState(), f = (e = !0) => ({
|
|
40
87
|
online: e,
|
|
41
88
|
pending: [],
|
|
42
89
|
inFlight: void 0,
|
|
43
90
|
lastError: void 0
|
|
44
|
-
}),
|
|
91
|
+
}), p = (e) => e.online && e.inFlight === void 0 && e.pending.length > 0, m = (e) => e.pending.length + (e.inFlight === void 0 ? 0 : 1), h = (e) => ({
|
|
45
92
|
...e,
|
|
46
93
|
attempts: e.attempts + 1
|
|
47
|
-
}),
|
|
94
|
+
}), g = (e, t) => {
|
|
48
95
|
switch (t.type) {
|
|
49
96
|
case "enqueue": return {
|
|
50
97
|
...e,
|
|
@@ -64,7 +111,7 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
64
111
|
inFlight: void 0
|
|
65
112
|
};
|
|
66
113
|
case "drain-start": {
|
|
67
|
-
if (!
|
|
114
|
+
if (!p(e)) return e;
|
|
68
115
|
let [t, ...n] = e.pending;
|
|
69
116
|
return t === void 0 ? e : {
|
|
70
117
|
...e,
|
|
@@ -80,15 +127,15 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
80
127
|
};
|
|
81
128
|
case "fail": return e.inFlight === void 0 || e.inFlight.id !== t.id ? e : {
|
|
82
129
|
...e,
|
|
83
|
-
pending: [
|
|
130
|
+
pending: [h(e.inFlight), ...e.pending],
|
|
84
131
|
inFlight: void 0,
|
|
85
132
|
lastError: t.error
|
|
86
133
|
};
|
|
87
134
|
}
|
|
88
|
-
},
|
|
135
|
+
}, _ = (e = "online") => ({
|
|
89
136
|
phase: e,
|
|
90
137
|
attempt: 0
|
|
91
|
-
}),
|
|
138
|
+
}), v = (e, t) => {
|
|
92
139
|
switch (t.type) {
|
|
93
140
|
case "network-down": return e.phase === "offline" ? e : {
|
|
94
141
|
phase: "offline",
|
|
@@ -107,87 +154,102 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
107
154
|
attempt: e.attempt + 1
|
|
108
155
|
} : e;
|
|
109
156
|
}
|
|
110
|
-
},
|
|
157
|
+
}, y = (e, t) => e === "offline" ? "offline" : e === "reconnecting" || t > 0 ? "syncing" : "synced", b = (e) => `${e.table}\u0000${e.id}\u0000${e.column}`, x = 0, S = () => {
|
|
111
158
|
let e = typeof crypto < "u" ? crypto : void 0;
|
|
112
|
-
return e && typeof e.randomUUID == "function" ? e.randomUUID() : `w_${Date.now().toString(36)}_${
|
|
113
|
-
},
|
|
114
|
-
let { transport: t, adapter: n } = e, r = e.backend ?? o, i = e.now ?? Date.now, a = e.maxAttempts ?? 5, s =
|
|
159
|
+
return e && typeof e.randomUUID == "function" ? e.randomUUID() : `w_${Date.now().toString(36)}_${x += 1}`;
|
|
160
|
+
}, C = (e) => {
|
|
161
|
+
let { transport: t, adapter: n } = e, r = e.backend ?? o, i = e.now ?? Date.now, a = e.maxAttempts ?? 5, s = f(e.online ?? !0), c = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Set(), d = () => {
|
|
115
162
|
for (let e of u) try {
|
|
116
163
|
e();
|
|
117
164
|
} catch {}
|
|
118
|
-
},
|
|
119
|
-
let i =
|
|
120
|
-
|
|
165
|
+
}, h = (e, t) => {
|
|
166
|
+
let i = b(e), a = c.get(i), o = a === void 0 ? t : l(a, t, r);
|
|
167
|
+
c.set(i, o), n?.saveCrdtState(e.table, e.id, o).catch(() => void 0);
|
|
121
168
|
}, _ = () => {
|
|
122
169
|
if (n === void 0) return;
|
|
123
170
|
let e = s.inFlight === void 0 ? s.pending : [s.inFlight, ...s.pending];
|
|
124
171
|
n.saveQueue(e).catch(() => void 0);
|
|
125
|
-
}, v = !1,
|
|
172
|
+
}, v = !1, y = async () => {
|
|
126
173
|
if (!v) {
|
|
127
174
|
v = !0;
|
|
128
175
|
try {
|
|
129
|
-
for (;
|
|
130
|
-
s =
|
|
176
|
+
for (; p(s);) {
|
|
177
|
+
s = g(s, { type: "drain-start" });
|
|
131
178
|
let e = s.inFlight;
|
|
132
179
|
if (e === void 0) break;
|
|
133
180
|
try {
|
|
134
|
-
await t.push(e), s =
|
|
181
|
+
await t.push(e), s = g(s, {
|
|
135
182
|
type: "ack",
|
|
136
183
|
id: e.id
|
|
137
|
-
}), _(),
|
|
184
|
+
}), _(), d();
|
|
138
185
|
} catch (t) {
|
|
139
|
-
if (s =
|
|
186
|
+
if (s = g(s, {
|
|
140
187
|
type: "fail",
|
|
141
188
|
id: e.id,
|
|
142
189
|
error: t instanceof Error ? t.message : String(t)
|
|
143
|
-
}), _(),
|
|
190
|
+
}), _(), d(), e.attempts + 1 >= a) break;
|
|
144
191
|
}
|
|
145
192
|
}
|
|
146
193
|
} finally {
|
|
147
194
|
v = !1;
|
|
148
195
|
}
|
|
149
196
|
}
|
|
150
|
-
},
|
|
151
|
-
|
|
197
|
+
}, x = t.onRemoteState((e) => {
|
|
198
|
+
h(e, e.state), d();
|
|
152
199
|
});
|
|
153
200
|
return {
|
|
154
201
|
enqueue: (e) => {
|
|
155
|
-
|
|
156
|
-
let t =
|
|
157
|
-
|
|
202
|
+
h(e, e.update);
|
|
203
|
+
let t = b(e), n = s.pending.findIndex((e) => b(e.payload) === t);
|
|
204
|
+
if (n !== -1) {
|
|
205
|
+
let t = s.pending[n], i = {
|
|
206
|
+
...t,
|
|
207
|
+
payload: {
|
|
208
|
+
...t.payload,
|
|
209
|
+
update: l(t.payload.update, e.update, r)
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
s = {
|
|
213
|
+
...s,
|
|
214
|
+
pending: s.pending.map((e, t) => t === n ? i : e)
|
|
215
|
+
}, _(), d(), y();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
let a = {
|
|
219
|
+
id: S(),
|
|
158
220
|
payload: e,
|
|
159
221
|
enqueuedAt: i(),
|
|
160
222
|
attempts: 0
|
|
161
223
|
};
|
|
162
|
-
s =
|
|
224
|
+
s = g(s, {
|
|
163
225
|
type: "enqueue",
|
|
164
|
-
write:
|
|
165
|
-
}), _(),
|
|
226
|
+
write: a
|
|
227
|
+
}), _(), d(), y();
|
|
166
228
|
},
|
|
167
229
|
setOnline: (e) => {
|
|
168
|
-
s =
|
|
230
|
+
s = g(s, e ? { type: "online" } : { type: "offline" }), _(), d(), e && y();
|
|
169
231
|
},
|
|
170
232
|
queueState: () => s,
|
|
171
|
-
outstanding: () =>
|
|
233
|
+
outstanding: () => m(s),
|
|
172
234
|
getState: (e) => {
|
|
173
|
-
let t =
|
|
235
|
+
let t = c.get(b(e));
|
|
174
236
|
return t === void 0 ? void 0 : t.slice();
|
|
175
237
|
},
|
|
176
238
|
getText: (e) => {
|
|
177
|
-
let t =
|
|
239
|
+
let t = c.get(b(e));
|
|
178
240
|
return t === void 0 ? "" : r.decodeText(t);
|
|
179
241
|
},
|
|
180
242
|
subscribe: (e) => (u.add(e), () => {
|
|
181
243
|
u.delete(e);
|
|
182
244
|
}),
|
|
183
245
|
flush: async () => {
|
|
184
|
-
await
|
|
246
|
+
await y();
|
|
185
247
|
},
|
|
186
248
|
close: () => {
|
|
187
|
-
|
|
249
|
+
x(), u.clear();
|
|
188
250
|
}
|
|
189
251
|
};
|
|
190
|
-
},
|
|
252
|
+
}, w = (e) => {
|
|
191
253
|
let { channel: t, roomId: n, peerId: r, initial: i } = e, a = e.ttlMs ?? 3e4, o = e.now ?? Date.now, s = i, c = 0, l = !1, u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), p = () => {
|
|
192
254
|
for (let e of f) try {
|
|
193
255
|
e();
|
|
@@ -248,4 +310,4 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
|
|
|
248
310
|
};
|
|
249
311
|
};
|
|
250
312
|
//#endregion
|
|
251
|
-
export {
|
|
313
|
+
export { _ as a, m as c, s as d, u as f, a as g, l as h, y as i, g as l, d as m, C as n, p as o, o as p, v as r, f as s, w as t, c as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/local-first",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Local-first / CRDT primitives (opt-in): a Yjs-backed crdtText() field and its deterministic merge, the bi-directional sync wire (createSyncClient + the useCrdtText React binding), durable IndexedDB persistence, presence rooms, connection-status state machine, and last-write-wins conflict policy. Remaining seams: the two app-level tags the sync wire is pointed at (the mutation that writes the column, the query that streams the row), the presence channel's broker binding, and an optional wa-sqlite/Turso adapter.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -38,14 +38,31 @@
|
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"yjs": "^13.6.32"
|
|
41
|
+
"yjs": "^13.6.32",
|
|
42
|
+
"y-protocols": "^1.0.6"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
|
-
"react": "^19.0.0"
|
|
45
|
+
"react": "^19.0.0",
|
|
46
|
+
"@tiptap/react": "^3.0.0",
|
|
47
|
+
"@tiptap/starter-kit": "^3.0.0",
|
|
48
|
+
"@tiptap/extension-collaboration": "^3.0.0",
|
|
49
|
+
"@tiptap/extension-collaboration-caret": "^3.0.0"
|
|
45
50
|
},
|
|
46
51
|
"peerDependenciesMeta": {
|
|
47
52
|
"react": {
|
|
48
53
|
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"@tiptap/react": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"@tiptap/starter-kit": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"@tiptap/extension-collaboration": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@tiptap/extension-collaboration-caret": {
|
|
65
|
+
"optional": true
|
|
49
66
|
}
|
|
50
67
|
},
|
|
51
68
|
"publishConfig": {
|