@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.
Files changed (133) hide show
  1. package/README.md +221 -208
  2. package/dist/BaseDoc-DkP3tUhT.d.ts +206 -0
  3. package/dist/algorithms/lww/consolidateOps.d.ts +40 -0
  4. package/dist/algorithms/lww/consolidateOps.js +103 -0
  5. package/dist/algorithms/lww/mergeServerWithLocal.d.ts +22 -0
  6. package/dist/algorithms/lww/mergeServerWithLocal.js +32 -0
  7. package/dist/algorithms/{client → ot/client}/applyCommittedChanges.d.ts +10 -3
  8. package/dist/algorithms/{client → ot/client}/applyCommittedChanges.js +7 -4
  9. package/dist/algorithms/{client → ot/client}/createStateFromSnapshot.d.ts +3 -3
  10. package/dist/algorithms/{client → ot/client}/createStateFromSnapshot.js +1 -1
  11. package/dist/algorithms/ot/server/commitChanges.d.ts +43 -0
  12. package/dist/algorithms/{server → ot/server}/commitChanges.js +22 -7
  13. package/dist/algorithms/{server → ot/server}/createVersion.d.ts +5 -5
  14. package/dist/algorithms/{server → ot/server}/createVersion.js +2 -2
  15. package/dist/algorithms/{server → ot/server}/getSnapshotAtRevision.d.ts +5 -5
  16. package/dist/algorithms/{server → ot/server}/getSnapshotAtRevision.js +1 -1
  17. package/dist/algorithms/{server → ot/server}/getStateAtRevision.d.ts +5 -5
  18. package/dist/algorithms/{server → ot/server}/getStateAtRevision.js +1 -1
  19. package/dist/algorithms/{server → ot/server}/handleOfflineSessionsAndBatches.d.ts +5 -5
  20. package/dist/algorithms/{server → ot/server}/handleOfflineSessionsAndBatches.js +3 -3
  21. package/dist/algorithms/{server → ot/server}/transformIncomingChanges.d.ts +3 -3
  22. package/dist/algorithms/{server → ot/server}/transformIncomingChanges.js +3 -3
  23. package/dist/algorithms/{shared → ot/shared}/applyChanges.d.ts +3 -3
  24. package/dist/algorithms/{shared → ot/shared}/applyChanges.js +2 -2
  25. package/dist/algorithms/{shared → ot/shared}/changeBatching.d.ts +3 -3
  26. package/dist/algorithms/{shared → ot/shared}/changeBatching.js +2 -2
  27. package/dist/algorithms/{shared → ot/shared}/rebaseChanges.d.ts +3 -3
  28. package/dist/algorithms/{shared → ot/shared}/rebaseChanges.js +2 -2
  29. package/dist/client/BaseDoc.d.ts +6 -0
  30. package/dist/client/BaseDoc.js +70 -0
  31. package/dist/client/ClientAlgorithm.d.ts +101 -0
  32. package/dist/client/ClientAlgorithm.js +0 -0
  33. package/dist/client/InMemoryStore.d.ts +5 -7
  34. package/dist/client/InMemoryStore.js +7 -36
  35. package/dist/client/IndexedDBStore.d.ts +39 -73
  36. package/dist/client/IndexedDBStore.js +17 -220
  37. package/dist/client/LWWAlgorithm.d.ts +43 -0
  38. package/dist/client/LWWAlgorithm.js +87 -0
  39. package/dist/client/LWWClientStore.d.ts +73 -0
  40. package/dist/client/LWWClientStore.js +0 -0
  41. package/dist/client/LWWDoc.d.ts +56 -0
  42. package/dist/client/LWWDoc.js +84 -0
  43. package/dist/client/LWWInMemoryStore.d.ts +88 -0
  44. package/dist/client/LWWInMemoryStore.js +208 -0
  45. package/dist/client/LWWIndexedDBStore.d.ts +91 -0
  46. package/dist/client/LWWIndexedDBStore.js +275 -0
  47. package/dist/client/OTAlgorithm.d.ts +42 -0
  48. package/dist/client/OTAlgorithm.js +113 -0
  49. package/dist/client/OTClientStore.d.ts +50 -0
  50. package/dist/client/OTClientStore.js +0 -0
  51. package/dist/client/OTDoc.d.ts +6 -0
  52. package/dist/client/OTDoc.js +97 -0
  53. package/dist/client/OTIndexedDBStore.d.ts +84 -0
  54. package/dist/client/OTIndexedDBStore.js +163 -0
  55. package/dist/client/Patches.d.ts +36 -16
  56. package/dist/client/Patches.js +60 -27
  57. package/dist/client/PatchesDoc.d.ts +4 -113
  58. package/dist/client/PatchesDoc.js +3 -153
  59. package/dist/client/PatchesHistoryClient.js +1 -1
  60. package/dist/client/PatchesStore.d.ts +8 -105
  61. package/dist/client/factories.d.ts +72 -0
  62. package/dist/client/factories.js +80 -0
  63. package/dist/client/index.d.ts +14 -5
  64. package/dist/client/index.js +9 -0
  65. package/dist/compression/index.d.ts +2 -2
  66. package/dist/compression/index.js +1 -1
  67. package/dist/{algorithms/shared → compression}/lz.js +1 -1
  68. package/dist/data/change.js +2 -0
  69. package/dist/fractionalIndex.d.ts +67 -0
  70. package/dist/fractionalIndex.js +241 -0
  71. package/dist/index.d.ts +13 -3
  72. package/dist/index.js +1 -0
  73. package/dist/json-patch/types.d.ts +2 -0
  74. package/dist/net/PatchesClient.js +15 -15
  75. package/dist/net/PatchesSync.d.ts +20 -8
  76. package/dist/net/PatchesSync.js +57 -65
  77. package/dist/net/index.d.ts +7 -11
  78. package/dist/net/index.js +6 -1
  79. package/dist/net/protocol/JSONRPCClient.d.ts +4 -4
  80. package/dist/net/protocol/JSONRPCClient.js +6 -4
  81. package/dist/net/protocol/JSONRPCServer.d.ts +45 -9
  82. package/dist/net/protocol/JSONRPCServer.js +63 -8
  83. package/dist/net/serverContext.d.ts +38 -0
  84. package/dist/net/serverContext.js +20 -0
  85. package/dist/net/webrtc/WebRTCTransport.js +1 -1
  86. package/dist/net/websocket/AuthorizationProvider.d.ts +3 -3
  87. package/dist/net/websocket/WebSocketServer.d.ts +29 -20
  88. package/dist/net/websocket/WebSocketServer.js +23 -12
  89. package/dist/server/BranchManager.d.ts +50 -0
  90. package/dist/server/BranchManager.js +0 -0
  91. package/dist/server/CompressedStoreBackend.d.ts +10 -8
  92. package/dist/server/CompressedStoreBackend.js +7 -13
  93. package/dist/server/LWWBranchManager.d.ts +82 -0
  94. package/dist/server/LWWBranchManager.js +99 -0
  95. package/dist/server/LWWMemoryStoreBackend.d.ts +78 -0
  96. package/dist/server/LWWMemoryStoreBackend.js +182 -0
  97. package/dist/server/LWWServer.d.ts +130 -0
  98. package/dist/server/LWWServer.js +214 -0
  99. package/dist/server/{PatchesBranchManager.d.ts → OTBranchManager.d.ts} +32 -12
  100. package/dist/server/{PatchesBranchManager.js → OTBranchManager.js} +27 -42
  101. package/dist/server/OTServer.d.ts +108 -0
  102. package/dist/server/OTServer.js +141 -0
  103. package/dist/server/PatchesHistoryManager.d.ts +21 -16
  104. package/dist/server/PatchesHistoryManager.js +23 -11
  105. package/dist/server/PatchesServer.d.ts +70 -81
  106. package/dist/server/PatchesServer.js +0 -175
  107. package/dist/server/branchUtils.d.ts +82 -0
  108. package/dist/server/branchUtils.js +66 -0
  109. package/dist/server/index.d.ts +18 -7
  110. package/dist/server/index.js +33 -4
  111. package/dist/server/tombstone.d.ts +29 -0
  112. package/dist/server/tombstone.js +32 -0
  113. package/dist/server/types.d.ts +109 -27
  114. package/dist/server/utils.d.ts +12 -0
  115. package/dist/server/utils.js +23 -0
  116. package/dist/solid/context.d.ts +4 -3
  117. package/dist/solid/doc-manager.d.ts +3 -3
  118. package/dist/solid/index.d.ts +4 -3
  119. package/dist/solid/primitives.d.ts +2 -3
  120. package/dist/types.d.ts +4 -2
  121. package/dist/vue/composables.d.ts +2 -3
  122. package/dist/vue/doc-manager.d.ts +3 -3
  123. package/dist/vue/index.d.ts +4 -3
  124. package/dist/vue/provider.d.ts +4 -3
  125. package/package.json +1 -1
  126. package/dist/algorithms/client/collapsePendingChanges.d.ts +0 -30
  127. package/dist/algorithms/client/collapsePendingChanges.js +0 -78
  128. package/dist/algorithms/client/makeChange.d.ts +0 -9
  129. package/dist/algorithms/client/makeChange.js +0 -29
  130. package/dist/algorithms/server/commitChanges.d.ts +0 -19
  131. package/dist/net/websocket/RPCServer.d.ts +0 -141
  132. package/dist/net/websocket/RPCServer.js +0 -204
  133. /package/dist/{algorithms/shared → compression}/lz.d.ts +0 -0
@@ -1,41 +1,122 @@
1
- import { Change, ListChangesOptions, PatchesState, VersionMetadata, EditableVersionMetadata, ListVersionsOptions, DocumentTombstone, Branch } from '../types.js';
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
- * Interface for a backend storage system for patch synchronization.
8
- * Defines methods needed by PatchesServer, PatchesHistoryManager, etc.
7
+ * Base interface for all server store backends.
8
+ * Provides the minimal deletion capability that all servers need.
9
9
  */
10
- interface PatchesStoreBackend {
11
- /** Saves a batch of committed server changes. */
12
- saveChanges(docId: string, changes: Change[]): Promise<void>;
13
- /** Lists committed server changes based on revision numbers. */
14
- listChanges(docId: string, options: ListChangesOptions): Promise<Change[]>;
15
- /** Loads the last version state for a document. Optional method for performance. */
16
- loadLastVersionState?: (docId: string) => Promise<PatchesState | undefined>;
17
- /** Saves the last version state for a document. Optional method for performance. */
18
- saveLastVersionState?: (docId: string, rev: number, state: any) => Promise<void>;
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 that constitute it.
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: Change[]): Promise<void>;
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
- /** Lists version metadata based on filtering/sorting options. */
32
- listVersions(docId: string, options: ListVersionsOptions): Promise<VersionMetadata[]>;
33
- /** Loads the state snapshot for a specific version ID. */
34
- loadVersionState(docId: string, versionId: string): Promise<any | undefined>;
35
- /** Loads the original Change objects associated with a specific version ID. */
36
- loadVersionChanges(docId: string, versionId: string): Promise<Change[]>;
37
- /** Deletes a document. */
38
- deleteDoc(docId: string): Promise<void>;
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
- * Extends PatchesStoreBackend with methods specifically for managing branches.
128
+ * Interface for branch storage. Standalone interface that can be composed
129
+ * with OTStoreBackend or LWWStoreBackend as needed.
48
130
  */
49
- interface BranchingStoreBackend extends PatchesStoreBackend {
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, PatchesStoreBackend };
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
+ };
@@ -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 '../json-patch/types.js';
9
- import '../client/PatchesDoc.js';
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 '../client/PatchesDoc.js';
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 '../json-patch/types.js';
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.
@@ -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 '../json-patch/types.js';
11
- import '../client/PatchesDoc.js';
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 '../client/PatchesDoc.js';
2
+ import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
3
3
  import { ChangeMutator } from '../types.js';
4
4
  import '../event-signal.js';
5
- import '../algorithms/shared/changeBatching.js';
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: number;
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 '../client/PatchesDoc.js';
2
+ import { a as PatchesDoc } from '../BaseDoc-DkP3tUhT.js';
3
3
  import { ChangeMutator } from '../types.js';
4
4
  import '../event-signal.js';
5
- import '../algorithms/shared/changeBatching.js';
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 '../client/PatchesDoc.js';
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 '../json-patch/types.js';
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.
@@ -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 '../json-patch/types.js';
11
- import '../client/PatchesDoc.js';
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';
@@ -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 '../json-patch/types.js';
9
- import '../client/PatchesDoc.js';
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.6.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 };