@dabble/patches 0.6.0 → 0.7.1
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 +221 -208
- package/dist/BaseDoc-DkP3tUhT.d.ts +206 -0
- package/dist/algorithms/lww/consolidateOps.d.ts +40 -0
- package/dist/algorithms/lww/consolidateOps.js +103 -0
- package/dist/algorithms/lww/mergeServerWithLocal.d.ts +22 -0
- package/dist/algorithms/lww/mergeServerWithLocal.js +32 -0
- package/dist/algorithms/{client → ot/client}/applyCommittedChanges.d.ts +10 -3
- package/dist/algorithms/{client → ot/client}/applyCommittedChanges.js +7 -4
- package/dist/algorithms/{client → ot/client}/createStateFromSnapshot.d.ts +3 -3
- package/dist/algorithms/{client → ot/client}/createStateFromSnapshot.js +1 -1
- package/dist/algorithms/ot/server/commitChanges.d.ts +43 -0
- package/dist/algorithms/{server → ot/server}/commitChanges.js +22 -7
- package/dist/algorithms/{server → ot/server}/createVersion.d.ts +5 -5
- package/dist/algorithms/{server → ot/server}/createVersion.js +2 -2
- package/dist/algorithms/{server → ot/server}/getSnapshotAtRevision.d.ts +5 -5
- package/dist/algorithms/{server → ot/server}/getSnapshotAtRevision.js +1 -1
- package/dist/algorithms/{server → ot/server}/getStateAtRevision.d.ts +5 -5
- package/dist/algorithms/{server → ot/server}/getStateAtRevision.js +1 -1
- package/dist/algorithms/{server → ot/server}/handleOfflineSessionsAndBatches.d.ts +5 -5
- package/dist/algorithms/{server → ot/server}/handleOfflineSessionsAndBatches.js +3 -3
- package/dist/algorithms/{server → ot/server}/transformIncomingChanges.d.ts +3 -3
- package/dist/algorithms/{server → ot/server}/transformIncomingChanges.js +3 -3
- package/dist/algorithms/{shared → ot/shared}/applyChanges.d.ts +3 -3
- package/dist/algorithms/{shared → ot/shared}/applyChanges.js +2 -2
- package/dist/algorithms/{shared → ot/shared}/changeBatching.d.ts +3 -3
- package/dist/algorithms/{shared → ot/shared}/changeBatching.js +2 -2
- package/dist/algorithms/{shared → ot/shared}/rebaseChanges.d.ts +3 -3
- package/dist/algorithms/{shared → ot/shared}/rebaseChanges.js +2 -2
- package/dist/client/BaseDoc.d.ts +6 -0
- package/dist/client/BaseDoc.js +70 -0
- package/dist/client/ClientAlgorithm.d.ts +101 -0
- package/dist/client/ClientAlgorithm.js +0 -0
- package/dist/client/InMemoryStore.d.ts +5 -7
- package/dist/client/InMemoryStore.js +7 -36
- package/dist/client/IndexedDBStore.d.ts +39 -73
- package/dist/client/IndexedDBStore.js +17 -220
- package/dist/client/LWWAlgorithm.d.ts +43 -0
- package/dist/client/LWWAlgorithm.js +87 -0
- package/dist/client/LWWClientStore.d.ts +73 -0
- package/dist/client/LWWClientStore.js +0 -0
- package/dist/client/LWWDoc.d.ts +56 -0
- package/dist/client/LWWDoc.js +84 -0
- package/dist/client/LWWInMemoryStore.d.ts +88 -0
- package/dist/client/LWWInMemoryStore.js +208 -0
- package/dist/client/LWWIndexedDBStore.d.ts +91 -0
- package/dist/client/LWWIndexedDBStore.js +275 -0
- package/dist/client/OTAlgorithm.d.ts +42 -0
- package/dist/client/OTAlgorithm.js +113 -0
- package/dist/client/OTClientStore.d.ts +50 -0
- package/dist/client/OTClientStore.js +0 -0
- package/dist/client/OTDoc.d.ts +6 -0
- package/dist/client/OTDoc.js +97 -0
- package/dist/client/OTIndexedDBStore.d.ts +84 -0
- package/dist/client/OTIndexedDBStore.js +163 -0
- package/dist/client/Patches.d.ts +36 -16
- package/dist/client/Patches.js +60 -27
- package/dist/client/PatchesDoc.d.ts +4 -113
- package/dist/client/PatchesDoc.js +3 -153
- package/dist/client/PatchesHistoryClient.js +1 -1
- package/dist/client/PatchesStore.d.ts +8 -105
- package/dist/client/factories.d.ts +72 -0
- package/dist/client/factories.js +80 -0
- package/dist/client/index.d.ts +14 -5
- package/dist/client/index.js +9 -0
- package/dist/compression/index.d.ts +2 -2
- package/dist/compression/index.js +1 -1
- package/dist/{algorithms/shared → compression}/lz.js +1 -1
- package/dist/data/change.js +2 -0
- package/dist/fractionalIndex.d.ts +67 -0
- package/dist/fractionalIndex.js +241 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.js +1 -0
- package/dist/json-patch/types.d.ts +2 -0
- package/dist/net/PatchesClient.js +15 -15
- package/dist/net/PatchesSync.d.ts +20 -8
- package/dist/net/PatchesSync.js +57 -65
- package/dist/net/index.d.ts +7 -11
- package/dist/net/index.js +6 -1
- package/dist/net/protocol/JSONRPCClient.d.ts +4 -4
- package/dist/net/protocol/JSONRPCClient.js +6 -4
- package/dist/net/protocol/JSONRPCServer.d.ts +45 -9
- package/dist/net/protocol/JSONRPCServer.js +63 -8
- package/dist/net/serverContext.d.ts +38 -0
- package/dist/net/serverContext.js +20 -0
- package/dist/net/webrtc/WebRTCTransport.js +1 -1
- package/dist/net/websocket/AuthorizationProvider.d.ts +3 -3
- package/dist/net/websocket/WebSocketServer.d.ts +29 -20
- package/dist/net/websocket/WebSocketServer.js +23 -12
- package/dist/server/BranchManager.d.ts +50 -0
- package/dist/server/BranchManager.js +0 -0
- package/dist/server/CompressedStoreBackend.d.ts +10 -8
- package/dist/server/CompressedStoreBackend.js +7 -13
- package/dist/server/LWWBranchManager.d.ts +82 -0
- package/dist/server/LWWBranchManager.js +99 -0
- package/dist/server/LWWMemoryStoreBackend.d.ts +78 -0
- package/dist/server/LWWMemoryStoreBackend.js +182 -0
- package/dist/server/LWWServer.d.ts +130 -0
- package/dist/server/LWWServer.js +214 -0
- package/dist/server/{PatchesBranchManager.d.ts → OTBranchManager.d.ts} +32 -12
- package/dist/server/{PatchesBranchManager.js → OTBranchManager.js} +27 -42
- package/dist/server/OTServer.d.ts +108 -0
- package/dist/server/OTServer.js +141 -0
- package/dist/server/PatchesHistoryManager.d.ts +21 -16
- package/dist/server/PatchesHistoryManager.js +23 -11
- package/dist/server/PatchesServer.d.ts +70 -81
- package/dist/server/PatchesServer.js +0 -175
- package/dist/server/branchUtils.d.ts +82 -0
- package/dist/server/branchUtils.js +66 -0
- package/dist/server/index.d.ts +18 -7
- package/dist/server/index.js +33 -4
- package/dist/server/tombstone.d.ts +29 -0
- package/dist/server/tombstone.js +32 -0
- package/dist/server/types.d.ts +109 -27
- package/dist/server/utils.d.ts +12 -0
- package/dist/server/utils.js +23 -0
- package/dist/solid/context.d.ts +4 -3
- package/dist/solid/doc-manager.d.ts +3 -3
- package/dist/solid/index.d.ts +4 -3
- package/dist/solid/primitives.d.ts +2 -3
- package/dist/types.d.ts +4 -2
- package/dist/vue/composables.d.ts +2 -3
- package/dist/vue/doc-manager.d.ts +3 -3
- package/dist/vue/index.d.ts +4 -3
- package/dist/vue/provider.d.ts +4 -3
- package/package.json +1 -1
- package/dist/algorithms/client/collapsePendingChanges.d.ts +0 -30
- package/dist/algorithms/client/collapsePendingChanges.js +0 -78
- package/dist/algorithms/client/makeChange.d.ts +0 -9
- package/dist/algorithms/client/makeChange.js +0 -29
- package/dist/algorithms/server/commitChanges.d.ts +0 -19
- package/dist/net/websocket/RPCServer.d.ts +0 -141
- package/dist/net/websocket/RPCServer.js +0 -204
- /package/dist/{algorithms/shared → compression}/lz.d.ts +0 -0
package/dist/server/types.d.ts
CHANGED
|
@@ -1,41 +1,122 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONPatchOp } from '../json-patch/types.js';
|
|
2
|
+
import { DocumentTombstone, VersionMetadata, Change, ListVersionsOptions, EditableVersionMetadata, ListChangesOptions, Branch } from '../types.js';
|
|
2
3
|
import '../json-patch/JSONPatch.js';
|
|
3
4
|
import '@dabble/delta';
|
|
4
|
-
import '../json-patch/types.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Base interface for all server store backends.
|
|
8
|
+
* Provides the minimal deletion capability that all servers need.
|
|
9
9
|
*/
|
|
10
|
-
interface
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
interface ServerStoreBackend {
|
|
11
|
+
/** Deletes a document and all its associated data. */
|
|
12
|
+
deleteDoc(docId: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Interface for version storage, shared between OT and LWW.
|
|
16
|
+
* OT requires this, LWW can optionally implement it for user-visible versioning.
|
|
17
|
+
*/
|
|
18
|
+
interface VersioningStoreBackend {
|
|
19
19
|
/**
|
|
20
|
-
* Saves version metadata, its state snapshot, and the original changes
|
|
20
|
+
* Saves version metadata, its state snapshot, and optionally the original changes.
|
|
21
21
|
* State and changes are stored separately from the core metadata.
|
|
22
|
+
* @param changes - Optional for LWW (which doesn't store changes), required for OT.
|
|
22
23
|
*/
|
|
23
|
-
createVersion(docId: string, metadata: VersionMetadata, state: any, changes
|
|
24
|
+
createVersion(docId: string, metadata: VersionMetadata, state: any, changes?: Change[]): Promise<void>;
|
|
25
|
+
/** Lists version metadata based on filtering/sorting options. */
|
|
26
|
+
listVersions(docId: string, options: ListVersionsOptions): Promise<VersionMetadata[]>;
|
|
27
|
+
/** Loads the state snapshot for a specific version ID. */
|
|
28
|
+
loadVersionState(docId: string, versionId: string): Promise<any | undefined>;
|
|
24
29
|
/** Update a version's metadata. */
|
|
25
30
|
updateVersion(docId: string, versionId: string, metadata: EditableVersionMetadata): Promise<void>;
|
|
31
|
+
/** Loads the original Change objects associated with a specific version ID. */
|
|
32
|
+
loadVersionChanges?(docId: string, versionId: string): Promise<Change[]>;
|
|
26
33
|
/**
|
|
27
34
|
* Appends changes to an existing version, updating its state snapshot, endedAt, and endRev.
|
|
28
35
|
* Used when a session spans multiple batch submissions.
|
|
29
36
|
*/
|
|
30
|
-
appendVersionChanges(docId: string, versionId: string, changes: Change[], newEndedAt: number, newEndRev: number, newState: any): Promise<void>;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
appendVersionChanges?(docId: string, versionId: string, changes: Change[], newEndedAt: number, newEndRev: number, newState: any): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Interface for OT (Operational Transformation) storage backend.
|
|
41
|
+
* Extends ServerStoreBackend and VersioningStoreBackend because OT requires versioning
|
|
42
|
+
* for session tracking and state snapshots.
|
|
43
|
+
*/
|
|
44
|
+
interface OTStoreBackend extends ServerStoreBackend, VersioningStoreBackend {
|
|
45
|
+
/** Saves a batch of committed server changes. */
|
|
46
|
+
saveChanges(docId: string, changes: Change[]): Promise<void>;
|
|
47
|
+
/** Lists committed server changes based on revision numbers. */
|
|
48
|
+
listChanges(docId: string, options: ListChangesOptions): Promise<Change[]>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for listing fields. Use either sinceRev OR paths, not both.
|
|
52
|
+
*/
|
|
53
|
+
type ListFieldsOptions = {
|
|
54
|
+
sinceRev: number;
|
|
55
|
+
} | {
|
|
56
|
+
paths: string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Interface for LWW (Last-Write-Wins) storage backend.
|
|
60
|
+
* LWW stores fields (not changes) and reconstructs state from fields.
|
|
61
|
+
*/
|
|
62
|
+
interface LWWStoreBackend extends ServerStoreBackend {
|
|
63
|
+
/**
|
|
64
|
+
* Get the current revision number without reconstructing state.
|
|
65
|
+
* More efficient than getSnapshot() when only the revision is needed.
|
|
66
|
+
* @param docId - The document ID.
|
|
67
|
+
* @returns The current revision number, or 0 if document doesn't exist.
|
|
68
|
+
*/
|
|
69
|
+
getCurrentRev(docId: string): Promise<number>;
|
|
70
|
+
/**
|
|
71
|
+
* Get the latest snapshot of document state.
|
|
72
|
+
* @param docId - The document ID.
|
|
73
|
+
* @returns The snapshot state and revision, or null if no snapshot exists.
|
|
74
|
+
*/
|
|
75
|
+
getSnapshot(docId: string): Promise<{
|
|
76
|
+
state: any;
|
|
77
|
+
rev: number;
|
|
78
|
+
} | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Save a snapshot of document state (overwrites previous snapshot).
|
|
81
|
+
* @param docId - The document ID.
|
|
82
|
+
* @param state - The document state.
|
|
83
|
+
* @param rev - The revision number.
|
|
84
|
+
*/
|
|
85
|
+
saveSnapshot(docId: string, state: any, rev: number): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* List field metadata, optionally filtered by paths or revision.
|
|
88
|
+
*
|
|
89
|
+
* Options are mutually exclusive:
|
|
90
|
+
* - `{ sinceRev: number }` - Get fields changed since a revision
|
|
91
|
+
* - `{ paths: string[] }` - Get fields at specific paths
|
|
92
|
+
* - No options - Get all fields
|
|
93
|
+
*
|
|
94
|
+
* @param docId - The document ID.
|
|
95
|
+
* @param options - Optional filter options.
|
|
96
|
+
* @returns Array of field metadata matching the criteria.
|
|
97
|
+
*/
|
|
98
|
+
listOps(docId: string, options?: ListFieldsOptions): Promise<JSONPatchOp[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Save field metadata and atomically increment the revision.
|
|
101
|
+
*
|
|
102
|
+
* Implementation requirements:
|
|
103
|
+
* - Atomically increment the document revision
|
|
104
|
+
* - Set the rev on all saved fields to the new revision
|
|
105
|
+
* - Delete children atomically when saving a parent (e.g., saving /obj deletes /obj/name)
|
|
106
|
+
* - Delete paths in pathsToDelete atomically with saving ops
|
|
107
|
+
*
|
|
108
|
+
* @param docId - The document ID.
|
|
109
|
+
* @param ops - Array of ops to save.
|
|
110
|
+
* @param pathsToDelete - Optional paths to delete atomically.
|
|
111
|
+
* @returns The new revision number.
|
|
112
|
+
*/
|
|
113
|
+
saveOps(docId: string, ops: JSONPatchOp[], pathsToDelete?: string[]): Promise<number>;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Interface for tombstone storage, providing soft-delete capabilities.
|
|
117
|
+
* Optional add-on for servers that need to track deleted documents.
|
|
118
|
+
*/
|
|
119
|
+
interface TombstoneStoreBackend {
|
|
39
120
|
/** Creates a tombstone for a deleted document. Called before deleteDoc() to preserve deletion metadata. */
|
|
40
121
|
createTombstone(tombstone: DocumentTombstone): Promise<void>;
|
|
41
122
|
/** Retrieves a tombstone for a document if it exists. Returns undefined if the document was never deleted or tombstone has expired. */
|
|
@@ -44,9 +125,10 @@ interface PatchesStoreBackend {
|
|
|
44
125
|
removeTombstone(docId: string): Promise<void>;
|
|
45
126
|
}
|
|
46
127
|
/**
|
|
47
|
-
*
|
|
128
|
+
* Interface for branch storage. Standalone interface that can be composed
|
|
129
|
+
* with OTStoreBackend or LWWStoreBackend as needed.
|
|
48
130
|
*/
|
|
49
|
-
interface BranchingStoreBackend
|
|
131
|
+
interface BranchingStoreBackend {
|
|
50
132
|
/**
|
|
51
133
|
* Generates a unique ID for a new branch document.
|
|
52
134
|
* If not provided, a random 22-character ID is generated using createId().
|
|
@@ -68,4 +150,4 @@ interface BranchingStoreBackend extends PatchesStoreBackend {
|
|
|
68
150
|
closeBranch(branchId: string): Promise<void>;
|
|
69
151
|
}
|
|
70
152
|
|
|
71
|
-
export type { BranchingStoreBackend,
|
|
153
|
+
export type { BranchingStoreBackend, LWWStoreBackend, ListFieldsOptions, OTStoreBackend, ServerStoreBackend, TombstoneStoreBackend, VersioningStoreBackend };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EditableVersionMetadata } from '../types.js';
|
|
2
|
+
import '../json-patch/JSONPatch.js';
|
|
3
|
+
import '@dabble/delta';
|
|
4
|
+
import '../json-patch/types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Validates that version metadata does not contain non-modifiable fields.
|
|
8
|
+
* @throws Error if metadata contains any non-modifiable fields.
|
|
9
|
+
*/
|
|
10
|
+
declare function assertVersionMetadata(metadata?: EditableVersionMetadata): void;
|
|
11
|
+
|
|
12
|
+
export { assertVersionMetadata };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import "../chunk-IZ2YBCUP.js";
|
|
2
|
+
const nonModifiableVersionFields = /* @__PURE__ */ new Set([
|
|
3
|
+
"id",
|
|
4
|
+
"parentId",
|
|
5
|
+
"groupId",
|
|
6
|
+
"origin",
|
|
7
|
+
"branchName",
|
|
8
|
+
"startedAt",
|
|
9
|
+
"endedAt",
|
|
10
|
+
"rev",
|
|
11
|
+
"baseRev"
|
|
12
|
+
]);
|
|
13
|
+
function assertVersionMetadata(metadata) {
|
|
14
|
+
if (!metadata) return;
|
|
15
|
+
for (const key in metadata) {
|
|
16
|
+
if (nonModifiableVersionFields.has(key)) {
|
|
17
|
+
throw new Error(`Cannot modify version field ${key}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
assertVersionMetadata
|
|
23
|
+
};
|
package/dist/solid/context.d.ts
CHANGED
|
@@ -2,12 +2,12 @@ import { JSX } from 'solid-js';
|
|
|
2
2
|
import { Patches } from '../client/Patches.js';
|
|
3
3
|
import { PatchesSync } from '../net/PatchesSync.js';
|
|
4
4
|
import '../event-signal.js';
|
|
5
|
+
import '../json-patch/types.js';
|
|
5
6
|
import '../types.js';
|
|
6
7
|
import '../json-patch/JSONPatch.js';
|
|
7
8
|
import '@dabble/delta';
|
|
8
|
-
import '../
|
|
9
|
-
import '../
|
|
10
|
-
import '../algorithms/shared/changeBatching.js';
|
|
9
|
+
import '../client/ClientAlgorithm.js';
|
|
10
|
+
import '../BaseDoc-DkP3tUhT.js';
|
|
11
11
|
import '../client/PatchesStore.js';
|
|
12
12
|
import '../net/protocol/types.js';
|
|
13
13
|
import '../net/protocol/JSONRPCClient.js';
|
|
@@ -15,6 +15,7 @@ import '../net/websocket/PatchesWebSocket.js';
|
|
|
15
15
|
import '../net/PatchesClient.js';
|
|
16
16
|
import '../net/websocket/WebSocketTransport.js';
|
|
17
17
|
import '../utils/deferred.js';
|
|
18
|
+
import '../algorithms/ot/shared/changeBatching.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Context value containing Patches and optional PatchesSync instances.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Patches } from '../client/Patches.js';
|
|
2
|
-
import { PatchesDoc } from '../
|
|
2
|
+
import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
|
|
3
3
|
import '../event-signal.js';
|
|
4
|
+
import '../json-patch/types.js';
|
|
4
5
|
import '../types.js';
|
|
5
6
|
import '../json-patch/JSONPatch.js';
|
|
6
7
|
import '@dabble/delta';
|
|
7
|
-
import '../
|
|
8
|
+
import '../client/ClientAlgorithm.js';
|
|
8
9
|
import '../client/PatchesStore.js';
|
|
9
|
-
import '../algorithms/shared/changeBatching.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Reference counting manager for PatchesDoc instances.
|
package/dist/solid/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export { DocManager, getDocManager } from './doc-manager.js';
|
|
|
4
4
|
import 'solid-js';
|
|
5
5
|
import '../client/Patches.js';
|
|
6
6
|
import '../event-signal.js';
|
|
7
|
+
import '../json-patch/types.js';
|
|
7
8
|
import '../types.js';
|
|
8
9
|
import '../json-patch/JSONPatch.js';
|
|
9
10
|
import '@dabble/delta';
|
|
10
|
-
import '../
|
|
11
|
-
import '../
|
|
12
|
-
import '../algorithms/shared/changeBatching.js';
|
|
11
|
+
import '../client/ClientAlgorithm.js';
|
|
12
|
+
import '../BaseDoc-DkP3tUhT.js';
|
|
13
13
|
import '../client/PatchesStore.js';
|
|
14
14
|
import '../net/PatchesSync.js';
|
|
15
15
|
import '../net/protocol/types.js';
|
|
@@ -18,3 +18,4 @@ import '../net/websocket/PatchesWebSocket.js';
|
|
|
18
18
|
import '../net/PatchesClient.js';
|
|
19
19
|
import '../net/websocket/WebSocketTransport.js';
|
|
20
20
|
import '../utils/deferred.js';
|
|
21
|
+
import '../algorithms/ot/shared/changeBatching.js';
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Accessor } from 'solid-js';
|
|
2
|
-
import { PatchesDoc } from '../
|
|
2
|
+
import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
|
|
3
3
|
import { ChangeMutator } from '../types.js';
|
|
4
4
|
import '../event-signal.js';
|
|
5
|
-
import '../
|
|
5
|
+
import '../json-patch/types.js';
|
|
6
6
|
import '../json-patch/JSONPatch.js';
|
|
7
7
|
import '@dabble/delta';
|
|
8
|
-
import '../json-patch/types.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Options for usePatchesDoc primitive.
|
package/dist/types.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ interface ChangeInput {
|
|
|
17
17
|
baseRev?: number;
|
|
18
18
|
/** Optional revision number. If omitted, server assigns based on current state. */
|
|
19
19
|
rev?: number;
|
|
20
|
-
/** Unix timestamp in milliseconds when the change was created. */
|
|
21
|
-
createdAt
|
|
20
|
+
/** Unix timestamp in milliseconds when the change was created. If omitted, server sets to current time. */
|
|
21
|
+
createdAt?: number;
|
|
22
22
|
/** Optional batch identifier for grouping changes that belong to the same client batch (for multi-batch offline/large edits). */
|
|
23
23
|
batchId?: string;
|
|
24
24
|
/** Optional arbitrary metadata associated with the change. */
|
|
@@ -33,6 +33,8 @@ interface Change extends ChangeInput {
|
|
|
33
33
|
baseRev: number;
|
|
34
34
|
/** The revision number assigned by the server after commit. */
|
|
35
35
|
rev: number;
|
|
36
|
+
/** Unix timestamp in milliseconds when the change was created (always set by server if omitted from input). */
|
|
37
|
+
createdAt: number;
|
|
36
38
|
/** Unix timestamp in milliseconds when the change was committed. */
|
|
37
39
|
committedAt: number;
|
|
38
40
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { ShallowRef, Ref, MaybeRef } from 'vue';
|
|
2
|
-
import { PatchesDoc } from '../
|
|
2
|
+
import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
|
|
3
3
|
import { ChangeMutator } from '../types.js';
|
|
4
4
|
import '../event-signal.js';
|
|
5
|
-
import '../
|
|
5
|
+
import '../json-patch/types.js';
|
|
6
6
|
import '../json-patch/JSONPatch.js';
|
|
7
7
|
import '@dabble/delta';
|
|
8
|
-
import '../json-patch/types.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Options for usePatchesDoc composable.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Patches } from '../client/Patches.js';
|
|
2
|
-
import { PatchesDoc } from '../
|
|
2
|
+
import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
|
|
3
3
|
import '../event-signal.js';
|
|
4
|
+
import '../json-patch/types.js';
|
|
4
5
|
import '../types.js';
|
|
5
6
|
import '../json-patch/JSONPatch.js';
|
|
6
7
|
import '@dabble/delta';
|
|
7
|
-
import '../
|
|
8
|
+
import '../client/ClientAlgorithm.js';
|
|
8
9
|
import '../client/PatchesStore.js';
|
|
9
|
-
import '../algorithms/shared/changeBatching.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Reference counting manager for PatchesDoc instances.
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export { DocManager, getDocManager } from './doc-manager.js';
|
|
|
4
4
|
import 'vue';
|
|
5
5
|
import '../client/Patches.js';
|
|
6
6
|
import '../event-signal.js';
|
|
7
|
+
import '../json-patch/types.js';
|
|
7
8
|
import '../types.js';
|
|
8
9
|
import '../json-patch/JSONPatch.js';
|
|
9
10
|
import '@dabble/delta';
|
|
10
|
-
import '../
|
|
11
|
-
import '../
|
|
12
|
-
import '../algorithms/shared/changeBatching.js';
|
|
11
|
+
import '../client/ClientAlgorithm.js';
|
|
12
|
+
import '../BaseDoc-DkP3tUhT.js';
|
|
13
13
|
import '../client/PatchesStore.js';
|
|
14
14
|
import '../net/PatchesSync.js';
|
|
15
15
|
import '../net/protocol/types.js';
|
|
@@ -18,3 +18,4 @@ import '../net/websocket/PatchesWebSocket.js';
|
|
|
18
18
|
import '../net/PatchesClient.js';
|
|
19
19
|
import '../net/websocket/WebSocketTransport.js';
|
|
20
20
|
import '../utils/deferred.js';
|
|
21
|
+
import '../algorithms/ot/shared/changeBatching.js';
|
package/dist/vue/provider.d.ts
CHANGED
|
@@ -2,12 +2,12 @@ import { InjectionKey, App } from 'vue';
|
|
|
2
2
|
import { Patches } from '../client/Patches.js';
|
|
3
3
|
import { PatchesSync } from '../net/PatchesSync.js';
|
|
4
4
|
import '../event-signal.js';
|
|
5
|
+
import '../json-patch/types.js';
|
|
5
6
|
import '../types.js';
|
|
6
7
|
import '../json-patch/JSONPatch.js';
|
|
7
8
|
import '@dabble/delta';
|
|
8
|
-
import '../
|
|
9
|
-
import '../
|
|
10
|
-
import '../algorithms/shared/changeBatching.js';
|
|
9
|
+
import '../client/ClientAlgorithm.js';
|
|
10
|
+
import '../BaseDoc-DkP3tUhT.js';
|
|
11
11
|
import '../client/PatchesStore.js';
|
|
12
12
|
import '../net/protocol/types.js';
|
|
13
13
|
import '../net/protocol/JSONRPCClient.js';
|
|
@@ -15,6 +15,7 @@ import '../net/websocket/PatchesWebSocket.js';
|
|
|
15
15
|
import '../net/PatchesClient.js';
|
|
16
16
|
import '../net/websocket/WebSocketTransport.js';
|
|
17
17
|
import '../utils/deferred.js';
|
|
18
|
+
import '../algorithms/ot/shared/changeBatching.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Injection key for Patches instance.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dabble/patches",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
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": {
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Change } from '../../types.js';
|
|
2
|
-
import '../../json-patch/JSONPatch.js';
|
|
3
|
-
import '@dabble/delta';
|
|
4
|
-
import '../../json-patch/types.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Collapses redundant pending changes before sync to reduce network traffic.
|
|
8
|
-
*
|
|
9
|
-
* This optimization automatically detects and collapses multiple "replace" operations
|
|
10
|
-
* on the same JSON path with primitive values (boolean, number, string, null) into
|
|
11
|
-
* a single change containing only the final value.
|
|
12
|
-
*
|
|
13
|
-
* Example: If a user toggles a folder's open state 100 times while offline,
|
|
14
|
-
* this collapses those 100 changes into just 1 change with the final state.
|
|
15
|
-
*
|
|
16
|
-
* Safety guarantees:
|
|
17
|
-
* - Only collapses single-op changes (multi-op changes are atomic, preserve intent)
|
|
18
|
-
* - Only collapses "replace" operations (not add, remove, move)
|
|
19
|
-
* - Only collapses primitive values (not objects/arrays)
|
|
20
|
-
* - Detects path invalidation from structural changes (remove, array shifts, move)
|
|
21
|
-
* - Respects the submission bookmark to never collapse already-submitted changes
|
|
22
|
-
*
|
|
23
|
-
* @param changes Array of pending changes to potentially collapse
|
|
24
|
-
* @param afterRev Optional revision bookmark - changes at or before this rev are not collapsed
|
|
25
|
-
* (they may have been partially submitted to the server)
|
|
26
|
-
* @returns Collapsed array of changes, maintaining correct ordering
|
|
27
|
-
*/
|
|
28
|
-
declare function collapsePendingChanges(changes: Change[], afterRev?: number): Change[];
|
|
29
|
-
|
|
30
|
-
export { collapsePendingChanges };
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
-
function collapsePendingChanges(changes, afterRev) {
|
|
3
|
-
if (changes.length <= 1) {
|
|
4
|
-
return changes;
|
|
5
|
-
}
|
|
6
|
-
const pathState = /* @__PURE__ */ new Map();
|
|
7
|
-
const outputSlots = new Array(changes.length).fill(null);
|
|
8
|
-
for (let i = 0; i < changes.length; i++) {
|
|
9
|
-
const change = changes[i];
|
|
10
|
-
if (afterRev !== void 0 && change.rev !== void 0 && change.rev <= afterRev) {
|
|
11
|
-
outputSlots[i] = change;
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
updatePathInvalidations(change, pathState);
|
|
15
|
-
if (!isCollapsibleChange(change)) {
|
|
16
|
-
outputSlots[i] = change;
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
const path = change.ops[0].path;
|
|
20
|
-
const existing = pathState.get(path);
|
|
21
|
-
if (existing) {
|
|
22
|
-
outputSlots[existing.lastIndex] = null;
|
|
23
|
-
}
|
|
24
|
-
pathState.set(path, { lastChange: change, lastIndex: i });
|
|
25
|
-
outputSlots[i] = change;
|
|
26
|
-
}
|
|
27
|
-
return outputSlots.filter((c) => c !== null);
|
|
28
|
-
}
|
|
29
|
-
function isCollapsibleChange(change) {
|
|
30
|
-
if (change.ops.length !== 1) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
const op = change.ops[0];
|
|
34
|
-
if (op.op !== "replace") {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
return isPrimitiveValue(op.value);
|
|
38
|
-
}
|
|
39
|
-
function isPrimitiveValue(value) {
|
|
40
|
-
if (value === null) return true;
|
|
41
|
-
const type = typeof value;
|
|
42
|
-
return type === "boolean" || type === "number" || type === "string";
|
|
43
|
-
}
|
|
44
|
-
function updatePathInvalidations(change, pathState) {
|
|
45
|
-
for (const op of change.ops) {
|
|
46
|
-
if (op.op === "remove" || op.op === "move") {
|
|
47
|
-
invalidatePathAndChildren(op.path, pathState);
|
|
48
|
-
if (op.op === "move" && "from" in op) {
|
|
49
|
-
invalidatePathAndChildren(op.from, pathState);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (op.op === "add" || op.op === "remove") {
|
|
53
|
-
invalidateShiftedArrayPaths(op.path, pathState);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function invalidatePathAndChildren(opPath, pathState) {
|
|
58
|
-
for (const trackedPath of pathState.keys()) {
|
|
59
|
-
if (trackedPath === opPath || trackedPath.startsWith(opPath + "/")) {
|
|
60
|
-
pathState.delete(trackedPath);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function invalidateShiftedArrayPaths(opPath, pathState) {
|
|
65
|
-
const segments = opPath.split("/");
|
|
66
|
-
const lastSegment = segments[segments.length - 1];
|
|
67
|
-
if (/^\d+$/.test(lastSegment)) {
|
|
68
|
-
const arrayPath = segments.slice(0, -1).join("/");
|
|
69
|
-
for (const trackedPath of pathState.keys()) {
|
|
70
|
-
if (trackedPath.startsWith(arrayPath + "/")) {
|
|
71
|
-
pathState.delete(trackedPath);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export {
|
|
77
|
-
collapsePendingChanges
|
|
78
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { PatchesSnapshot, ChangeMutator, Change } from '../../types.js';
|
|
2
|
-
import { SizeCalculator } from '../shared/changeBatching.js';
|
|
3
|
-
import '../../json-patch/JSONPatch.js';
|
|
4
|
-
import '@dabble/delta';
|
|
5
|
-
import '../../json-patch/types.js';
|
|
6
|
-
|
|
7
|
-
declare function makeChange<T = any>(snapshot: PatchesSnapshot<T>, mutator: ChangeMutator<T>, changeMetadata?: Record<string, any>, maxStorageBytes?: number, sizeCalculator?: SizeCalculator): Change[];
|
|
8
|
-
|
|
9
|
-
export { makeChange };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
-
import { createChange } from "../../data/change.js";
|
|
3
|
-
import { createJSONPatch } from "../../json-patch/createJSONPatch.js";
|
|
4
|
-
import { breakChanges } from "../shared/changeBatching.js";
|
|
5
|
-
import { createStateFromSnapshot } from "./createStateFromSnapshot.js";
|
|
6
|
-
function makeChange(snapshot, mutator, changeMetadata, maxStorageBytes, sizeCalculator) {
|
|
7
|
-
const pendingChanges = snapshot.changes;
|
|
8
|
-
const pendingRev = pendingChanges[pendingChanges.length - 1]?.rev ?? snapshot.rev;
|
|
9
|
-
const state = createStateFromSnapshot(snapshot);
|
|
10
|
-
const patch = createJSONPatch(mutator);
|
|
11
|
-
if (patch.ops.length === 0) {
|
|
12
|
-
return [];
|
|
13
|
-
}
|
|
14
|
-
const rev = pendingRev + 1;
|
|
15
|
-
let newChangesArray = [createChange(snapshot.rev, rev, patch.ops, changeMetadata)];
|
|
16
|
-
try {
|
|
17
|
-
patch.apply(state);
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error("Failed to apply change to state during makeChange:", error);
|
|
20
|
-
throw new Error(`Failed to apply change to state during makeChange: ${error}`);
|
|
21
|
-
}
|
|
22
|
-
if (maxStorageBytes) {
|
|
23
|
-
newChangesArray = breakChanges(newChangesArray, maxStorageBytes, sizeCalculator);
|
|
24
|
-
}
|
|
25
|
-
return newChangesArray;
|
|
26
|
-
}
|
|
27
|
-
export {
|
|
28
|
-
makeChange
|
|
29
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { PatchesStoreBackend } from '../../server/types.js';
|
|
2
|
-
import { ChangeInput, CommitChangesOptions, Change } from '../../types.js';
|
|
3
|
-
import '../../json-patch/JSONPatch.js';
|
|
4
|
-
import '@dabble/delta';
|
|
5
|
-
import '../../json-patch/types.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Commits a set of changes to a document, applying operational transformation as needed.
|
|
9
|
-
* @param docId - The ID of the document.
|
|
10
|
-
* @param changes - The changes to commit.
|
|
11
|
-
* @param originClientId - The ID of the client that initiated the commit.
|
|
12
|
-
* @param options - Optional commit settings.
|
|
13
|
-
* @returns A tuple of [committedChanges, transformedChanges] where:
|
|
14
|
-
* - committedChanges: Changes that were already committed to the server after the client's base revision
|
|
15
|
-
* - transformedChanges: The client's changes after being transformed against concurrent changes
|
|
16
|
-
*/
|
|
17
|
-
declare function commitChanges(store: PatchesStoreBackend, docId: string, changes: ChangeInput[], sessionTimeoutMillis: number, options?: CommitChangesOptions, maxStorageBytes?: number): Promise<[Change[], Change[]]>;
|
|
18
|
-
|
|
19
|
-
export { CommitChangesOptions, commitChanges };
|