@dabble/patches 0.7.6 → 0.7.8

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.
Files changed (49) hide show
  1. package/dist/{BaseDoc-DkP3tUhT.d.ts → BaseDoc-_Rsau70J.d.ts} +9 -9
  2. package/dist/algorithms/lww/consolidateOps.d.ts +1 -1
  3. package/dist/algorithms/lww/consolidateOps.js +42 -0
  4. package/dist/client/BaseDoc.d.ts +1 -1
  5. package/dist/client/BaseDoc.js +2 -2
  6. package/dist/client/ClientAlgorithm.d.ts +1 -1
  7. package/dist/client/IndexedDBStore.d.ts +11 -11
  8. package/dist/client/IndexedDBStore.js +14 -14
  9. package/dist/client/LWWAlgorithm.d.ts +1 -1
  10. package/dist/client/LWWDoc.d.ts +3 -3
  11. package/dist/client/LWWIndexedDBStore.d.ts +1 -1
  12. package/dist/client/OTAlgorithm.d.ts +1 -1
  13. package/dist/client/OTDoc.d.ts +1 -1
  14. package/dist/client/OTIndexedDBStore.d.ts +1 -1
  15. package/dist/client/Patches.d.ts +12 -6
  16. package/dist/client/PatchesDoc.d.ts +1 -1
  17. package/dist/client/factories.d.ts +1 -1
  18. package/dist/client/index.d.ts +2 -2
  19. package/dist/index.d.ts +2 -2
  20. package/dist/net/PatchesClient.d.ts +1 -1
  21. package/dist/net/PatchesClient.js +2 -2
  22. package/dist/net/PatchesSync.d.ts +1 -1
  23. package/dist/net/index.d.ts +1 -1
  24. package/dist/net/protocol/JSONRPCClient.js +2 -0
  25. package/dist/net/protocol/JSONRPCServer.js +7 -1
  26. package/dist/net/protocol/types.d.ts +1 -1
  27. package/dist/net/websocket/WebSocketServer.d.ts +4 -10
  28. package/dist/net/websocket/WebSocketServer.js +5 -9
  29. package/dist/server/LWWBranchManager.d.ts +2 -2
  30. package/dist/server/LWWBranchManager.js +3 -3
  31. package/dist/server/OTBranchManager.d.ts +1 -1
  32. package/dist/server/OTBranchManager.js +2 -2
  33. package/dist/server/branchUtils.d.ts +1 -1
  34. package/dist/server/branchUtils.js +2 -2
  35. package/dist/shared/doc-manager.d.ts +3 -3
  36. package/dist/shared/doc-manager.js +2 -2
  37. package/dist/solid/context.d.ts +1 -1
  38. package/dist/solid/doc-manager.d.ts +1 -1
  39. package/dist/solid/index.d.ts +1 -1
  40. package/dist/solid/primitives.d.ts +10 -5
  41. package/dist/solid/primitives.js +80 -132
  42. package/dist/vue/composables.d.ts +9 -4
  43. package/dist/vue/composables.js +93 -148
  44. package/dist/vue/doc-manager.d.ts +1 -1
  45. package/dist/vue/index.d.ts +1 -1
  46. package/dist/vue/managed-docs.d.ts +10 -1
  47. package/dist/vue/managed-docs.js +3 -2
  48. package/dist/vue/provider.d.ts +1 -1
  49. package/package.json +1 -1
@@ -11,48 +11,86 @@ import {
11
11
  import { JSONPatch } from "../json-patch/JSONPatch.js";
12
12
  import { usePatchesContext } from "./provider.js";
13
13
  import { getDocManager } from "./doc-manager.js";
14
- function usePatchesDoc(docIdOrOptions, options) {
15
- if (typeof docIdOrOptions === "string") {
16
- return _usePatchesDocEager(docIdOrOptions, options ?? {});
17
- }
18
- return _usePatchesDocLazy(docIdOrOptions ?? {});
19
- }
20
- function _usePatchesDocEager(docId, options) {
21
- const { patches } = usePatchesContext();
22
- const { autoClose = false } = options;
23
- const shouldUntrack = autoClose === "untrack";
14
+ function createDocReactiveState(options) {
15
+ const { initialLoading = true, transformState, changeBehavior } = options;
24
16
  const doc = ref(void 0);
25
17
  const data = shallowRef(void 0);
26
- const loading = ref(true);
18
+ const loading = ref(initialLoading);
27
19
  const error = ref(null);
28
20
  const rev = ref(0);
29
21
  const hasPending = ref(false);
30
- const unsubscribers = [];
31
- const manager = getDocManager(patches);
32
22
  function setupDoc(patchesDoc) {
33
23
  doc.value = patchesDoc;
34
24
  const unsubState = patchesDoc.subscribe((state) => {
25
+ if (transformState && state) {
26
+ state = transformState(state, patchesDoc);
27
+ }
35
28
  data.value = state;
36
29
  rev.value = patchesDoc.committedRev;
37
30
  hasPending.value = patchesDoc.hasPending;
38
31
  });
39
- unsubscribers.push(unsubState);
40
32
  const unsubSync = patchesDoc.onSyncing((syncState) => {
41
33
  loading.value = syncState === "initial" || syncState === "updating";
42
34
  error.value = syncState instanceof Error ? syncState : null;
43
35
  });
44
- unsubscribers.push(unsubSync);
45
36
  loading.value = patchesDoc.syncing !== null;
37
+ return () => {
38
+ unsubState();
39
+ unsubSync();
40
+ };
41
+ }
42
+ function resetRefs() {
43
+ doc.value = void 0;
44
+ data.value = void 0;
45
+ loading.value = false;
46
+ error.value = null;
47
+ rev.value = 0;
48
+ hasPending.value = false;
49
+ }
50
+ function change(mutator) {
51
+ if (changeBehavior === "throw") {
52
+ if (!doc.value) {
53
+ throw new Error("Cannot make changes: document not loaded yet");
54
+ }
55
+ doc.value.change(mutator);
56
+ } else {
57
+ doc.value?.change(mutator);
58
+ }
59
+ }
60
+ const baseReturn = {
61
+ data,
62
+ loading,
63
+ error,
64
+ rev,
65
+ hasPending,
66
+ change,
67
+ doc
68
+ };
69
+ return { doc, data, loading, error, rev, hasPending, setupDoc, resetRefs, change, baseReturn };
70
+ }
71
+ function usePatchesDoc(docIdOrOptions, options) {
72
+ if (typeof docIdOrOptions === "string") {
73
+ return _usePatchesDocEager(docIdOrOptions, options ?? {});
46
74
  }
75
+ return _usePatchesDocLazy(docIdOrOptions ?? {});
76
+ }
77
+ function _usePatchesDocEager(docId, options) {
78
+ const { patches } = usePatchesContext();
79
+ const { autoClose = false, algorithm, metadata } = options;
80
+ const shouldUntrack = autoClose === "untrack";
81
+ const openDocOpts = { algorithm, metadata };
82
+ const manager = getDocManager(patches);
83
+ const { setupDoc, baseReturn } = createDocReactiveState({ changeBehavior: "throw" });
84
+ let unsubscribe = null;
47
85
  if (autoClose) {
48
- manager.openDoc(patches, docId).then((patchesDoc) => {
49
- setupDoc(patchesDoc);
86
+ manager.openDoc(patches, docId, openDocOpts).then((patchesDoc) => {
87
+ unsubscribe = setupDoc(patchesDoc);
50
88
  }).catch((err) => {
51
- error.value = err;
52
- loading.value = false;
89
+ baseReturn.error.value = err;
90
+ baseReturn.loading.value = false;
53
91
  });
54
92
  onBeforeUnmount(() => {
55
- unsubscribers.forEach((unsub) => unsub());
93
+ unsubscribe?.();
56
94
  manager.closeDoc(patches, docId, shouldUntrack);
57
95
  });
58
96
  } else {
@@ -63,74 +101,30 @@ function _usePatchesDocEager(docId, options) {
63
101
  );
64
102
  }
65
103
  manager.incrementRefCount(docId);
66
- setupDoc(patchesDoc);
104
+ unsubscribe = setupDoc(patchesDoc);
67
105
  onBeforeUnmount(() => {
68
- unsubscribers.forEach((unsub) => unsub());
106
+ unsubscribe?.();
69
107
  manager.decrementRefCount(docId);
70
108
  });
71
109
  }
72
- function change(mutator) {
73
- if (!doc.value) {
74
- throw new Error("Cannot make changes: document not loaded yet");
75
- }
76
- doc.value.change(mutator);
77
- }
78
- return {
79
- data,
80
- loading,
81
- error,
82
- rev,
83
- hasPending,
84
- change,
85
- doc
86
- };
110
+ return baseReturn;
87
111
  }
88
112
  function _usePatchesDocLazy(options) {
89
113
  const { patches } = usePatchesContext();
90
114
  const { idProp } = options;
91
- let currentDoc = null;
115
+ const { setupDoc, resetRefs, baseReturn } = createDocReactiveState({
116
+ initialLoading: false,
117
+ changeBehavior: "noop",
118
+ transformState: idProp ? (state, patchesDoc) => ({ ...state, [idProp]: patchesDoc.id }) : void 0
119
+ });
92
120
  let unsubscribe = null;
93
121
  const path = ref(null);
94
- const doc = ref(void 0);
95
- const data = shallowRef(void 0);
96
- const loading = ref(false);
97
- const error = ref(null);
98
- const rev = ref(0);
99
- const hasPending = ref(false);
100
- function setupDoc(patchesDoc) {
101
- currentDoc = patchesDoc;
102
- doc.value = patchesDoc;
103
- unsubscribe = patchesDoc.subscribe((state) => {
104
- if (state && idProp && currentDoc) {
105
- state = { ...state, [idProp]: currentDoc.id };
106
- }
107
- data.value = state;
108
- rev.value = patchesDoc.committedRev;
109
- hasPending.value = patchesDoc.hasPending;
110
- });
111
- const unsubSync = patchesDoc.onSyncing((syncState) => {
112
- loading.value = syncState === "initial" || syncState === "updating";
113
- error.value = syncState instanceof Error ? syncState : null;
114
- });
115
- const origUnsub = unsubscribe;
116
- unsubscribe = () => {
117
- origUnsub();
118
- unsubSync();
119
- };
120
- loading.value = patchesDoc.syncing !== null;
121
- }
122
122
  function teardown() {
123
123
  unsubscribe?.();
124
124
  unsubscribe = null;
125
- currentDoc = null;
126
- doc.value = void 0;
127
- data.value = void 0;
128
- loading.value = false;
129
- error.value = null;
130
- rev.value = 0;
131
- hasPending.value = false;
125
+ resetRefs();
132
126
  }
133
- async function load(docPath) {
127
+ async function load(docPath, options2) {
134
128
  if (path.value) {
135
129
  const prevPath = path.value;
136
130
  teardown();
@@ -138,11 +132,11 @@ function _usePatchesDocLazy(options) {
138
132
  }
139
133
  path.value = docPath;
140
134
  try {
141
- const patchesDoc = await patches.openDoc(docPath);
142
- setupDoc(patchesDoc);
135
+ const patchesDoc = await patches.openDoc(docPath, options2);
136
+ unsubscribe = setupDoc(patchesDoc);
143
137
  } catch (err) {
144
- error.value = err;
145
- loading.value = false;
138
+ baseReturn.error.value = err;
139
+ baseReturn.loading.value = false;
146
140
  }
147
141
  }
148
142
  async function close() {
@@ -153,8 +147,8 @@ function _usePatchesDocLazy(options) {
153
147
  await patches.closeDoc(prevPath);
154
148
  }
155
149
  }
156
- async function create(docPath, initialState) {
157
- const newDoc = await patches.openDoc(docPath);
150
+ async function create(docPath, initialState, options2) {
151
+ const newDoc = await patches.openDoc(docPath, options2);
158
152
  newDoc.change((patch, root) => {
159
153
  if (initialState instanceof JSONPatch) {
160
154
  patch.ops = initialState.ops;
@@ -166,22 +160,7 @@ function _usePatchesDocLazy(options) {
166
160
  });
167
161
  await patches.closeDoc(docPath);
168
162
  }
169
- function change(mutator) {
170
- currentDoc?.change(mutator);
171
- }
172
- return {
173
- data,
174
- loading,
175
- error,
176
- rev,
177
- hasPending,
178
- change,
179
- doc,
180
- path,
181
- load,
182
- close,
183
- create
184
- };
163
+ return { ...baseReturn, path, load, close, create };
185
164
  }
186
165
  function usePatchesSync() {
187
166
  const { sync } = usePatchesContext();
@@ -210,43 +189,24 @@ function createDocInjectionKey(name) {
210
189
  }
211
190
  function providePatchesDoc(name, docId, options = {}) {
212
191
  const { patches } = usePatchesContext();
213
- const { autoClose = false } = options;
192
+ const { autoClose = false, algorithm, metadata } = options;
214
193
  const shouldUntrack = autoClose === "untrack";
194
+ const openDocOpts = { algorithm, metadata };
215
195
  const manager = getDocManager(patches);
216
- const doc = ref(void 0);
217
- const data = shallowRef(void 0);
218
- const loading = ref(true);
219
- const error = ref(null);
220
- const rev = ref(0);
221
- const hasPending = ref(false);
196
+ const { setupDoc, baseReturn } = createDocReactiveState({ changeBehavior: "throw" });
222
197
  const currentDocId = ref(unref(docId));
223
- const unsubscribers = [];
224
- function setupDoc(patchesDoc) {
225
- unsubscribers.forEach((unsub) => unsub());
226
- unsubscribers.length = 0;
227
- doc.value = patchesDoc;
228
- const unsubState = patchesDoc.subscribe((state) => {
229
- data.value = state;
230
- rev.value = patchesDoc.committedRev;
231
- hasPending.value = patchesDoc.hasPending;
232
- });
233
- unsubscribers.push(unsubState);
234
- const unsubSync = patchesDoc.onSyncing((syncState) => {
235
- loading.value = syncState === "initial" || syncState === "updating";
236
- error.value = syncState instanceof Error ? syncState : null;
237
- });
238
- unsubscribers.push(unsubSync);
239
- loading.value = patchesDoc.syncing !== null;
240
- }
198
+ let unsubscribe = null;
241
199
  async function initDoc(id) {
242
200
  currentDocId.value = id;
201
+ unsubscribe?.();
202
+ unsubscribe = null;
243
203
  if (autoClose) {
244
204
  try {
245
- const patchesDoc = await manager.openDoc(patches, id);
246
- setupDoc(patchesDoc);
205
+ const patchesDoc = await manager.openDoc(patches, id, openDocOpts);
206
+ unsubscribe = setupDoc(patchesDoc);
247
207
  } catch (err) {
248
- error.value = err;
249
- loading.value = false;
208
+ baseReturn.error.value = err;
209
+ baseReturn.loading.value = false;
250
210
  }
251
211
  } else {
252
212
  try {
@@ -257,36 +217,21 @@ function providePatchesDoc(name, docId, options = {}) {
257
217
  );
258
218
  }
259
219
  manager.incrementRefCount(id);
260
- setupDoc(patchesDoc);
220
+ unsubscribe = setupDoc(patchesDoc);
261
221
  } catch (err) {
262
- error.value = err;
263
- loading.value = false;
222
+ baseReturn.error.value = err;
223
+ baseReturn.loading.value = false;
264
224
  }
265
225
  }
266
226
  }
267
- function change(mutator) {
268
- if (!doc.value) {
269
- throw new Error("Cannot make changes: document not loaded yet");
270
- }
271
- doc.value.change(mutator);
272
- }
273
- const docReturn = {
274
- data,
275
- loading,
276
- error,
277
- rev,
278
- hasPending,
279
- change,
280
- doc
281
- };
282
227
  const key = createDocInjectionKey(name);
283
- provide(key, docReturn);
228
+ provide(key, baseReturn);
284
229
  initDoc(unref(docId));
285
230
  if (typeof docId !== "string") {
286
231
  watch(docId, async (newDocId, oldDocId) => {
287
232
  if (newDocId === oldDocId) return;
288
- unsubscribers.forEach((unsub) => unsub());
289
- unsubscribers.length = 0;
233
+ unsubscribe?.();
234
+ unsubscribe = null;
290
235
  if (autoClose) {
291
236
  await manager.closeDoc(patches, oldDocId, shouldUntrack);
292
237
  } else {
@@ -296,14 +241,14 @@ function providePatchesDoc(name, docId, options = {}) {
296
241
  });
297
242
  }
298
243
  onBeforeUnmount(async () => {
299
- unsubscribers.forEach((unsub) => unsub());
244
+ unsubscribe?.();
300
245
  if (autoClose) {
301
246
  await manager.closeDoc(patches, currentDocId.value, shouldUntrack);
302
247
  } else {
303
248
  manager.decrementRefCount(currentDocId.value);
304
249
  }
305
250
  });
306
- return docReturn;
251
+ return baseReturn;
307
252
  }
308
253
  function useCurrentDoc(name) {
309
254
  const key = createDocInjectionKey(name);
@@ -6,5 +6,5 @@ import '../types.js';
6
6
  import '../json-patch/JSONPatch.js';
7
7
  import '@dabble/delta';
8
8
  import '../client/ClientAlgorithm.js';
9
- import '../BaseDoc-DkP3tUhT.js';
9
+ import '../BaseDoc-_Rsau70J.js';
10
10
  import '../client/PatchesStore.js';
@@ -11,7 +11,7 @@ import '../types.js';
11
11
  import '../json-patch/JSONPatch.js';
12
12
  import '@dabble/delta';
13
13
  import '../client/ClientAlgorithm.js';
14
- import '../BaseDoc-DkP3tUhT.js';
14
+ import '../BaseDoc-_Rsau70J.js';
15
15
  import '../client/PatchesStore.js';
16
16
  import '../net/PatchesSync.js';
17
17
  import '../net/protocol/types.js';
@@ -1,9 +1,18 @@
1
1
  import { Ref, ShallowRef } from 'vue';
2
+ import { OpenDocOptions } from '../client/Patches.js';
3
+ import '../event-signal.js';
4
+ import '../json-patch/types.js';
5
+ import '../types.js';
6
+ import '../json-patch/JSONPatch.js';
7
+ import '@dabble/delta';
8
+ import '../client/ClientAlgorithm.js';
9
+ import '../BaseDoc-_Rsau70J.js';
10
+ import '../client/PatchesStore.js';
2
11
 
3
12
  /**
4
13
  * Options for useManagedDocs composable.
5
14
  */
6
- interface UseManagedDocsOptions {
15
+ interface UseManagedDocsOptions extends OpenDocOptions {
7
16
  /**
8
17
  * Inject doc.id into state under this key on every state update.
9
18
  * Useful when the document ID is derived from the path but needed in the data.
@@ -5,7 +5,8 @@ import { areSetsEqual } from "./utils.js";
5
5
  const emptyPaths = /* @__PURE__ */ new Set();
6
6
  function useManagedDocs(pathsRef, initialData, reducer, options) {
7
7
  const { patches } = usePatchesContext();
8
- const { idProp } = options ?? {};
8
+ const { idProp, algorithm, metadata } = options ?? {};
9
+ const openDocOpts = { algorithm, metadata };
9
10
  const data = shallowRef(initialData);
10
11
  const docs = /* @__PURE__ */ new Map();
11
12
  const unsubscribes = /* @__PURE__ */ new Map();
@@ -28,7 +29,7 @@ function useManagedDocs(pathsRef, initialData, reducer, options) {
28
29
  });
29
30
  async function openPath(path) {
30
31
  try {
31
- const doc = await patches.openDoc(path);
32
+ const doc = await patches.openDoc(path, openDocOpts);
32
33
  if (currentPaths.has(path)) {
33
34
  docs.set(path, doc);
34
35
  let initialState = doc.state;
@@ -7,7 +7,7 @@ import '../types.js';
7
7
  import '../json-patch/JSONPatch.js';
8
8
  import '@dabble/delta';
9
9
  import '../client/ClientAlgorithm.js';
10
- import '../BaseDoc-DkP3tUhT.js';
10
+ import '../BaseDoc-_Rsau70J.js';
11
11
  import '../client/PatchesStore.js';
12
12
  import '../net/protocol/types.js';
13
13
  import '../net/protocol/JSONRPCClient.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dabble/patches",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
4
4
  "description": "Immutable JSON Patch implementation based on RFC 6902 supporting operational transformation and last-writer-wins",
5
5
  "author": "Jacob Wright <jacwright@gmail.com>",
6
6
  "bugs": {