@framers/sql-storage-adapter 0.4.2 → 0.5.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 +94 -2
- package/dist/adapters/electron/electronMainAdapter.d.ts +241 -0
- package/dist/adapters/electron/electronMainAdapter.d.ts.map +1 -0
- package/dist/adapters/electron/electronMainAdapter.js +442 -0
- package/dist/adapters/electron/electronMainAdapter.js.map +1 -0
- package/dist/adapters/electron/electronRendererAdapter.d.ts +177 -0
- package/dist/adapters/electron/electronRendererAdapter.d.ts.map +1 -0
- package/dist/adapters/electron/electronRendererAdapter.js +339 -0
- package/dist/adapters/electron/electronRendererAdapter.js.map +1 -0
- package/dist/adapters/electron/index.d.ts +74 -0
- package/dist/adapters/electron/index.d.ts.map +1 -0
- package/dist/adapters/electron/index.js +96 -0
- package/dist/adapters/electron/index.js.map +1 -0
- package/dist/adapters/electron/ipc/channels.d.ts +196 -0
- package/dist/adapters/electron/ipc/channels.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/channels.js +121 -0
- package/dist/adapters/electron/ipc/channels.js.map +1 -0
- package/dist/adapters/electron/ipc/index.d.ts +11 -0
- package/dist/adapters/electron/ipc/index.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/index.js +11 -0
- package/dist/adapters/electron/ipc/index.js.map +1 -0
- package/dist/adapters/electron/ipc/protocol.d.ts +78 -0
- package/dist/adapters/electron/ipc/protocol.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/protocol.js +347 -0
- package/dist/adapters/electron/ipc/protocol.js.map +1 -0
- package/dist/adapters/electron/ipc/types.d.ts +248 -0
- package/dist/adapters/electron/ipc/types.d.ts.map +1 -0
- package/dist/adapters/electron/ipc/types.js +8 -0
- package/dist/adapters/electron/ipc/types.js.map +1 -0
- package/dist/adapters/electron/migration/autoMigrator.d.ts +184 -0
- package/dist/adapters/electron/migration/autoMigrator.d.ts.map +1 -0
- package/dist/adapters/electron/migration/autoMigrator.js +478 -0
- package/dist/adapters/electron/migration/autoMigrator.js.map +1 -0
- package/dist/adapters/electron/migration/index.d.ts +9 -0
- package/dist/adapters/electron/migration/index.d.ts.map +1 -0
- package/dist/adapters/electron/migration/index.js +9 -0
- package/dist/adapters/electron/migration/index.js.map +1 -0
- package/dist/adapters/electron/preload.d.ts +126 -0
- package/dist/adapters/electron/preload.d.ts.map +1 -0
- package/dist/adapters/electron/preload.js +254 -0
- package/dist/adapters/electron/preload.js.map +1 -0
- package/dist/adapters/electron/recovery/corruptionDetector.d.ts +214 -0
- package/dist/adapters/electron/recovery/corruptionDetector.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/corruptionDetector.js +410 -0
- package/dist/adapters/electron/recovery/corruptionDetector.js.map +1 -0
- package/dist/adapters/electron/recovery/index.d.ts +11 -0
- package/dist/adapters/electron/recovery/index.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/index.js +11 -0
- package/dist/adapters/electron/recovery/index.js.map +1 -0
- package/dist/adapters/electron/recovery/walCheckpoint.d.ts +186 -0
- package/dist/adapters/electron/recovery/walCheckpoint.d.ts.map +1 -0
- package/dist/adapters/electron/recovery/walCheckpoint.js +302 -0
- package/dist/adapters/electron/recovery/walCheckpoint.js.map +1 -0
- package/dist/adapters/electron/window/index.d.ts +9 -0
- package/dist/adapters/electron/window/index.d.ts.map +1 -0
- package/dist/adapters/electron/window/index.js +9 -0
- package/dist/adapters/electron/window/index.js.map +1 -0
- package/dist/adapters/electron/window/windowManager.d.ts +190 -0
- package/dist/adapters/electron/window/windowManager.d.ts.map +1 -0
- package/dist/adapters/electron/window/windowManager.js +358 -0
- package/dist/adapters/electron/window/windowManager.js.map +1 -0
- package/dist/core/contracts/context.d.ts +2 -2
- package/dist/core/contracts/context.d.ts.map +1 -1
- package/dist/core/database.d.ts +19 -0
- package/dist/core/database.d.ts.map +1 -1
- package/dist/core/database.js +4 -0
- package/dist/core/database.js.map +1 -1
- package/dist/core/resolver.d.ts +3 -0
- package/dist/core/resolver.d.ts.map +1 -1
- package/dist/core/resolver.js +39 -3
- package/dist/core/resolver.js.map +1 -1
- package/dist/features/sync/conflicts/conflictResolver.d.ts +222 -0
- package/dist/features/sync/conflicts/conflictResolver.d.ts.map +1 -0
- package/dist/features/sync/conflicts/conflictResolver.js +396 -0
- package/dist/features/sync/conflicts/conflictResolver.js.map +1 -0
- package/dist/features/sync/conflicts/index.d.ts +9 -0
- package/dist/features/sync/conflicts/index.d.ts.map +1 -0
- package/dist/features/sync/conflicts/index.js +9 -0
- package/dist/features/sync/conflicts/index.js.map +1 -0
- package/dist/features/sync/crossPlatformSync.d.ts +281 -0
- package/dist/features/sync/crossPlatformSync.d.ts.map +1 -0
- package/dist/features/sync/crossPlatformSync.js +623 -0
- package/dist/features/sync/crossPlatformSync.js.map +1 -0
- package/dist/features/sync/devices/deviceManager.d.ts +243 -0
- package/dist/features/sync/devices/deviceManager.d.ts.map +1 -0
- package/dist/features/sync/devices/deviceManager.js +494 -0
- package/dist/features/sync/devices/deviceManager.js.map +1 -0
- package/dist/features/sync/devices/index.d.ts +10 -0
- package/dist/features/sync/devices/index.d.ts.map +1 -0
- package/dist/features/sync/devices/index.js +10 -0
- package/dist/features/sync/devices/index.js.map +1 -0
- package/dist/features/sync/index.d.ts +37 -0
- package/dist/features/sync/index.d.ts.map +1 -0
- package/dist/features/sync/index.js +47 -0
- package/dist/features/sync/index.js.map +1 -0
- package/dist/features/sync/protocol/index.d.ts +11 -0
- package/dist/features/sync/protocol/index.d.ts.map +1 -0
- package/dist/features/sync/protocol/index.js +11 -0
- package/dist/features/sync/protocol/index.js.map +1 -0
- package/dist/features/sync/protocol/messages.d.ts +348 -0
- package/dist/features/sync/protocol/messages.d.ts.map +1 -0
- package/dist/features/sync/protocol/messages.js +216 -0
- package/dist/features/sync/protocol/messages.js.map +1 -0
- package/dist/features/sync/protocol/vectorClock.d.ts +164 -0
- package/dist/features/sync/protocol/vectorClock.d.ts.map +1 -0
- package/dist/features/sync/protocol/vectorClock.js +286 -0
- package/dist/features/sync/protocol/vectorClock.js.map +1 -0
- package/dist/features/sync/tables/index.d.ts +10 -0
- package/dist/features/sync/tables/index.d.ts.map +1 -0
- package/dist/features/sync/tables/index.js +10 -0
- package/dist/features/sync/tables/index.js.map +1 -0
- package/dist/features/sync/tables/syncLogManager.d.ts +216 -0
- package/dist/features/sync/tables/syncLogManager.d.ts.map +1 -0
- package/dist/features/sync/tables/syncLogManager.js +456 -0
- package/dist/features/sync/tables/syncLogManager.js.map +1 -0
- package/dist/features/sync/transport/httpTransport.d.ts +123 -0
- package/dist/features/sync/transport/httpTransport.d.ts.map +1 -0
- package/dist/features/sync/transport/httpTransport.js +380 -0
- package/dist/features/sync/transport/httpTransport.js.map +1 -0
- package/dist/features/sync/transport/index.d.ts +12 -0
- package/dist/features/sync/transport/index.d.ts.map +1 -0
- package/dist/features/sync/transport/index.js +12 -0
- package/dist/features/sync/transport/index.js.map +1 -0
- package/dist/features/sync/transport/transport.d.ts +259 -0
- package/dist/features/sync/transport/transport.d.ts.map +1 -0
- package/dist/features/sync/transport/transport.js +153 -0
- package/dist/features/sync/transport/transport.js.map +1 -0
- package/dist/features/sync/transport/websocketTransport.d.ts +126 -0
- package/dist/features/sync/transport/websocketTransport.d.ts.map +1 -0
- package/dist/features/sync/transport/websocketTransport.js +374 -0
- package/dist/features/sync/transport/websocketTransport.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +21 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict Detection and Resolution.
|
|
3
|
+
*
|
|
4
|
+
* Provides conflict detection using vector clocks and
|
|
5
|
+
* configurable resolution strategies with UI hooks.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import type { VectorClockData } from '../protocol/vectorClock';
|
|
10
|
+
/**
|
|
11
|
+
* Conflict resolution strategy.
|
|
12
|
+
*/
|
|
13
|
+
export type ConflictStrategy = 'last-write-wins' | 'local-wins' | 'remote-wins' | 'merge' | 'manual';
|
|
14
|
+
/**
|
|
15
|
+
* Resolution decision for a conflict.
|
|
16
|
+
*/
|
|
17
|
+
export type ResolutionDecision = 'use_local' | 'use_remote' | 'use_merged' | 'keep_both' | 'defer';
|
|
18
|
+
/**
|
|
19
|
+
* Represents a sync conflict between local and remote data.
|
|
20
|
+
*/
|
|
21
|
+
export interface SyncConflict {
|
|
22
|
+
/** Unique conflict identifier */
|
|
23
|
+
conflictId: string;
|
|
24
|
+
/** Table where conflict occurred */
|
|
25
|
+
tableName: string;
|
|
26
|
+
/** Primary key of the conflicting record */
|
|
27
|
+
recordId: string;
|
|
28
|
+
/** Local version of the data */
|
|
29
|
+
localData: Record<string, unknown>;
|
|
30
|
+
/** Remote version of the data */
|
|
31
|
+
remoteData: Record<string, unknown>;
|
|
32
|
+
/** Local vector clock */
|
|
33
|
+
localClock: VectorClockData;
|
|
34
|
+
/** Remote vector clock */
|
|
35
|
+
remoteClock: VectorClockData;
|
|
36
|
+
/** Local device ID */
|
|
37
|
+
localDeviceId: string;
|
|
38
|
+
/** Remote device ID */
|
|
39
|
+
remoteDeviceId: string;
|
|
40
|
+
/** When the conflict was detected */
|
|
41
|
+
detectedAt: number;
|
|
42
|
+
/** Fields that differ between versions */
|
|
43
|
+
conflictingFields: string[];
|
|
44
|
+
/** Conflict status */
|
|
45
|
+
status: 'pending' | 'resolved' | 'deferred';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolution result after conflict is resolved.
|
|
49
|
+
*/
|
|
50
|
+
export interface ConflictResolution {
|
|
51
|
+
/** How the conflict was resolved */
|
|
52
|
+
decision: ResolutionDecision;
|
|
53
|
+
/** Merged data if decision is 'use_merged' */
|
|
54
|
+
mergedData?: Record<string, unknown>;
|
|
55
|
+
/** Merged vector clock */
|
|
56
|
+
mergedClock: VectorClockData;
|
|
57
|
+
/** Who/what resolved the conflict */
|
|
58
|
+
resolvedBy: 'auto' | 'user' | 'strategy';
|
|
59
|
+
/** Resolution timestamp */
|
|
60
|
+
resolvedAt: number;
|
|
61
|
+
/** Optional reason for the resolution */
|
|
62
|
+
reason?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* UI hooks for conflict resolution.
|
|
66
|
+
*/
|
|
67
|
+
export interface ConflictUIHooks {
|
|
68
|
+
/**
|
|
69
|
+
* Called when a conflict requires manual resolution.
|
|
70
|
+
* Return the resolution decision from the UI.
|
|
71
|
+
*/
|
|
72
|
+
onConflictNeedsResolution?: (conflict: SyncConflict) => Promise<ConflictResolution>;
|
|
73
|
+
/**
|
|
74
|
+
* Called when a conflict is detected (before auto-resolution).
|
|
75
|
+
*/
|
|
76
|
+
onConflictDetected?: (conflict: SyncConflict) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Called after a conflict is resolved.
|
|
79
|
+
*/
|
|
80
|
+
onConflictResolved?: (conflict: SyncConflict, resolution: ConflictResolution) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Called when auto-merge fails and manual intervention is needed.
|
|
83
|
+
*/
|
|
84
|
+
onMergeFailed?: (conflict: SyncConflict, error: Error) => void;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Configuration for the conflict resolver.
|
|
88
|
+
*/
|
|
89
|
+
export interface ConflictResolverOptions {
|
|
90
|
+
/** Default resolution strategy */
|
|
91
|
+
defaultStrategy: ConflictStrategy;
|
|
92
|
+
/** Per-table strategy overrides */
|
|
93
|
+
tableStrategies?: Record<string, ConflictStrategy>;
|
|
94
|
+
/** Per-field merge functions for 'merge' strategy */
|
|
95
|
+
fieldMergers?: Record<string, FieldMerger>;
|
|
96
|
+
/** UI hooks for manual resolution */
|
|
97
|
+
hooks?: ConflictUIHooks;
|
|
98
|
+
/** Maximum time to wait for manual resolution (ms) */
|
|
99
|
+
manualResolutionTimeout?: number;
|
|
100
|
+
/** Auto-resolve conflicts older than this (ms) */
|
|
101
|
+
autoResolveAfter?: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Function to merge a single field.
|
|
105
|
+
*/
|
|
106
|
+
export type FieldMerger = (fieldName: string, localValue: unknown, remoteValue: unknown, localTimestamp: number, remoteTimestamp: number) => unknown;
|
|
107
|
+
/**
|
|
108
|
+
* Built-in field mergers.
|
|
109
|
+
*/
|
|
110
|
+
export declare const FieldMergers: {
|
|
111
|
+
/**
|
|
112
|
+
* Use the most recent value based on timestamp.
|
|
113
|
+
*/
|
|
114
|
+
lastWriteWins: FieldMerger;
|
|
115
|
+
/**
|
|
116
|
+
* For numeric fields, take the maximum value.
|
|
117
|
+
*/
|
|
118
|
+
max: FieldMerger;
|
|
119
|
+
/**
|
|
120
|
+
* For numeric fields, sum the values.
|
|
121
|
+
*/
|
|
122
|
+
sum: FieldMerger;
|
|
123
|
+
/**
|
|
124
|
+
* For arrays, union the values.
|
|
125
|
+
*/
|
|
126
|
+
union: FieldMerger;
|
|
127
|
+
/**
|
|
128
|
+
* For strings, concatenate with separator.
|
|
129
|
+
*/
|
|
130
|
+
concat: FieldMerger;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Conflict resolver for cross-platform sync.
|
|
134
|
+
*
|
|
135
|
+
* Detects conflicts using vector clock comparison and resolves
|
|
136
|
+
* them using configurable strategies or UI hooks.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const resolver = new ConflictResolver({
|
|
141
|
+
* defaultStrategy: 'last-write-wins',
|
|
142
|
+
* tableStrategies: {
|
|
143
|
+
* notes: 'merge',
|
|
144
|
+
* settings: 'local-wins',
|
|
145
|
+
* },
|
|
146
|
+
* hooks: {
|
|
147
|
+
* onConflictNeedsResolution: async (conflict) => {
|
|
148
|
+
* return showConflictDialog(conflict);
|
|
149
|
+
* },
|
|
150
|
+
* },
|
|
151
|
+
* });
|
|
152
|
+
*
|
|
153
|
+
* const resolution = await resolver.resolve(conflict);
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export declare class ConflictResolver {
|
|
157
|
+
private _options;
|
|
158
|
+
private _pendingConflicts;
|
|
159
|
+
private _resolvedConflicts;
|
|
160
|
+
constructor(options: ConflictResolverOptions);
|
|
161
|
+
/**
|
|
162
|
+
* Detect if there is a conflict between local and remote data.
|
|
163
|
+
*/
|
|
164
|
+
detectConflict(tableName: string, recordId: string, localData: Record<string, unknown>, remoteData: Record<string, unknown>, localClock: VectorClockData, remoteClock: VectorClockData, localDeviceId: string, remoteDeviceId: string): SyncConflict | null;
|
|
165
|
+
/**
|
|
166
|
+
* Resolve a conflict using the configured strategy.
|
|
167
|
+
*/
|
|
168
|
+
resolve(conflict: SyncConflict): Promise<ConflictResolution>;
|
|
169
|
+
/**
|
|
170
|
+
* Get pending conflicts.
|
|
171
|
+
*/
|
|
172
|
+
getPendingConflicts(): SyncConflict[];
|
|
173
|
+
/**
|
|
174
|
+
* Get a specific pending conflict.
|
|
175
|
+
*/
|
|
176
|
+
getConflict(conflictId: string): SyncConflict | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Manually resolve a conflict with a user decision.
|
|
179
|
+
*/
|
|
180
|
+
resolveManually(conflictId: string, decision: ResolutionDecision, mergedData?: Record<string, unknown>): Promise<ConflictResolution>;
|
|
181
|
+
/**
|
|
182
|
+
* Auto-resolve old conflicts that have been pending too long.
|
|
183
|
+
*/
|
|
184
|
+
autoResolveStale(): ConflictResolution[];
|
|
185
|
+
/**
|
|
186
|
+
* Get the resolution strategy for a table.
|
|
187
|
+
*/
|
|
188
|
+
private _getStrategy;
|
|
189
|
+
/**
|
|
190
|
+
* Find fields that differ between local and remote data.
|
|
191
|
+
*/
|
|
192
|
+
private _findConflictingFields;
|
|
193
|
+
/**
|
|
194
|
+
* Check if two values are equal (deep comparison for objects/arrays).
|
|
195
|
+
*/
|
|
196
|
+
private _valuesEqual;
|
|
197
|
+
/**
|
|
198
|
+
* Resolve using last-write-wins strategy.
|
|
199
|
+
*/
|
|
200
|
+
private _resolveLastWriteWins;
|
|
201
|
+
/**
|
|
202
|
+
* Resolve using local-wins strategy.
|
|
203
|
+
*/
|
|
204
|
+
private _resolveLocalWins;
|
|
205
|
+
/**
|
|
206
|
+
* Resolve using remote-wins strategy.
|
|
207
|
+
*/
|
|
208
|
+
private _resolveRemoteWins;
|
|
209
|
+
/**
|
|
210
|
+
* Resolve using field-level merge strategy.
|
|
211
|
+
*/
|
|
212
|
+
private _resolveMerge;
|
|
213
|
+
/**
|
|
214
|
+
* Resolve using manual/UI strategy.
|
|
215
|
+
*/
|
|
216
|
+
private _resolveManual;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create a conflict resolver instance.
|
|
220
|
+
*/
|
|
221
|
+
export declare const createConflictResolver: (options: ConflictResolverOptions) => ConflictResolver;
|
|
222
|
+
//# sourceMappingURL=conflictResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflictResolver.d.ts","sourceRoot":"","sources":["../../../../src/features/sync/conflicts/conflictResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict Detection and Resolution.
|
|
3
|
+
*
|
|
4
|
+
* Provides conflict detection using vector clocks and
|
|
5
|
+
* configurable resolution strategies with UI hooks.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { compareClocks } from '../protocol/vectorClock.js';
|
|
10
|
+
/**
|
|
11
|
+
* Built-in field mergers.
|
|
12
|
+
*/
|
|
13
|
+
export const FieldMergers = {
|
|
14
|
+
/**
|
|
15
|
+
* Use the most recent value based on timestamp.
|
|
16
|
+
*/
|
|
17
|
+
lastWriteWins: ((_fieldName, localValue, remoteValue, localTimestamp, remoteTimestamp) => {
|
|
18
|
+
return localTimestamp >= remoteTimestamp ? localValue : remoteValue;
|
|
19
|
+
}),
|
|
20
|
+
/**
|
|
21
|
+
* For numeric fields, take the maximum value.
|
|
22
|
+
*/
|
|
23
|
+
max: ((_fieldName, localValue, remoteValue) => {
|
|
24
|
+
const local = Number(localValue) || 0;
|
|
25
|
+
const remote = Number(remoteValue) || 0;
|
|
26
|
+
return Math.max(local, remote);
|
|
27
|
+
}),
|
|
28
|
+
/**
|
|
29
|
+
* For numeric fields, sum the values.
|
|
30
|
+
*/
|
|
31
|
+
sum: ((_fieldName, localValue, remoteValue) => {
|
|
32
|
+
const local = Number(localValue) || 0;
|
|
33
|
+
const remote = Number(remoteValue) || 0;
|
|
34
|
+
return local + remote;
|
|
35
|
+
}),
|
|
36
|
+
/**
|
|
37
|
+
* For arrays, union the values.
|
|
38
|
+
*/
|
|
39
|
+
union: ((_fieldName, localValue, remoteValue) => {
|
|
40
|
+
const local = Array.isArray(localValue) ? localValue : [];
|
|
41
|
+
const remote = Array.isArray(remoteValue) ? remoteValue : [];
|
|
42
|
+
return [...new Set([...local, ...remote])];
|
|
43
|
+
}),
|
|
44
|
+
/**
|
|
45
|
+
* For strings, concatenate with separator.
|
|
46
|
+
*/
|
|
47
|
+
concat: ((_fieldName, localValue, remoteValue) => {
|
|
48
|
+
const local = String(localValue ?? '');
|
|
49
|
+
const remote = String(remoteValue ?? '');
|
|
50
|
+
if (!local)
|
|
51
|
+
return remote;
|
|
52
|
+
if (!remote)
|
|
53
|
+
return local;
|
|
54
|
+
if (local === remote)
|
|
55
|
+
return local;
|
|
56
|
+
return `${local}\n---\n${remote}`;
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Merge two vector clocks by taking max of each device's counter.
|
|
61
|
+
*/
|
|
62
|
+
function mergeVectorClocks(a, b) {
|
|
63
|
+
const merged = { ...a };
|
|
64
|
+
for (const [deviceId, value] of Object.entries(b)) {
|
|
65
|
+
merged[deviceId] = Math.max(merged[deviceId] ?? 0, value);
|
|
66
|
+
}
|
|
67
|
+
return merged;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get total tick count from a vector clock.
|
|
71
|
+
*/
|
|
72
|
+
function getTotalTicks(clock) {
|
|
73
|
+
return Object.values(clock).reduce((sum, val) => sum + val, 0);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Conflict resolver for cross-platform sync.
|
|
77
|
+
*
|
|
78
|
+
* Detects conflicts using vector clock comparison and resolves
|
|
79
|
+
* them using configurable strategies or UI hooks.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const resolver = new ConflictResolver({
|
|
84
|
+
* defaultStrategy: 'last-write-wins',
|
|
85
|
+
* tableStrategies: {
|
|
86
|
+
* notes: 'merge',
|
|
87
|
+
* settings: 'local-wins',
|
|
88
|
+
* },
|
|
89
|
+
* hooks: {
|
|
90
|
+
* onConflictNeedsResolution: async (conflict) => {
|
|
91
|
+
* return showConflictDialog(conflict);
|
|
92
|
+
* },
|
|
93
|
+
* },
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* const resolution = await resolver.resolve(conflict);
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export class ConflictResolver {
|
|
100
|
+
constructor(options) {
|
|
101
|
+
this._pendingConflicts = new Map();
|
|
102
|
+
this._resolvedConflicts = new Map();
|
|
103
|
+
this._options = {
|
|
104
|
+
defaultStrategy: options.defaultStrategy,
|
|
105
|
+
tableStrategies: options.tableStrategies ?? {},
|
|
106
|
+
fieldMergers: options.fieldMergers ?? {},
|
|
107
|
+
hooks: options.hooks ?? {},
|
|
108
|
+
manualResolutionTimeout: options.manualResolutionTimeout ?? 300000, // 5 minutes
|
|
109
|
+
autoResolveAfter: options.autoResolveAfter ?? 0, // Disabled by default
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Detect if there is a conflict between local and remote data.
|
|
114
|
+
*/
|
|
115
|
+
detectConflict(tableName, recordId, localData, remoteData, localClock, remoteClock, localDeviceId, remoteDeviceId) {
|
|
116
|
+
// Compare vector clocks
|
|
117
|
+
const comparison = compareClocks(localClock, remoteClock);
|
|
118
|
+
// No conflict if one is clearly before the other
|
|
119
|
+
if (comparison === 'before' || comparison === 'after') {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
// Concurrent changes - potential conflict
|
|
123
|
+
// Check if data actually differs
|
|
124
|
+
const conflictingFields = this._findConflictingFields(localData, remoteData);
|
|
125
|
+
if (conflictingFields.length === 0) {
|
|
126
|
+
// Same data, no conflict
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const conflict = {
|
|
130
|
+
conflictId: `${tableName}:${recordId}:${Date.now()}`,
|
|
131
|
+
tableName,
|
|
132
|
+
recordId,
|
|
133
|
+
localData,
|
|
134
|
+
remoteData,
|
|
135
|
+
localClock,
|
|
136
|
+
remoteClock,
|
|
137
|
+
localDeviceId,
|
|
138
|
+
remoteDeviceId,
|
|
139
|
+
detectedAt: Date.now(),
|
|
140
|
+
conflictingFields,
|
|
141
|
+
status: 'pending',
|
|
142
|
+
};
|
|
143
|
+
this._pendingConflicts.set(conflict.conflictId, conflict);
|
|
144
|
+
this._options.hooks.onConflictDetected?.(conflict);
|
|
145
|
+
return conflict;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Resolve a conflict using the configured strategy.
|
|
149
|
+
*/
|
|
150
|
+
async resolve(conflict) {
|
|
151
|
+
const strategy = this._getStrategy(conflict.tableName);
|
|
152
|
+
let resolution;
|
|
153
|
+
switch (strategy) {
|
|
154
|
+
case 'last-write-wins':
|
|
155
|
+
resolution = this._resolveLastWriteWins(conflict);
|
|
156
|
+
break;
|
|
157
|
+
case 'local-wins':
|
|
158
|
+
resolution = this._resolveLocalWins(conflict);
|
|
159
|
+
break;
|
|
160
|
+
case 'remote-wins':
|
|
161
|
+
resolution = this._resolveRemoteWins(conflict);
|
|
162
|
+
break;
|
|
163
|
+
case 'merge':
|
|
164
|
+
resolution = this._resolveMerge(conflict);
|
|
165
|
+
break;
|
|
166
|
+
case 'manual':
|
|
167
|
+
resolution = await this._resolveManual(conflict);
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
resolution = this._resolveLastWriteWins(conflict);
|
|
171
|
+
}
|
|
172
|
+
// Update conflict status
|
|
173
|
+
conflict.status = resolution.decision === 'defer' ? 'deferred' : 'resolved';
|
|
174
|
+
// Store resolution
|
|
175
|
+
this._resolvedConflicts.set(conflict.conflictId, resolution);
|
|
176
|
+
this._pendingConflicts.delete(conflict.conflictId);
|
|
177
|
+
// Notify hooks
|
|
178
|
+
this._options.hooks.onConflictResolved?.(conflict, resolution);
|
|
179
|
+
return resolution;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get pending conflicts.
|
|
183
|
+
*/
|
|
184
|
+
getPendingConflicts() {
|
|
185
|
+
return Array.from(this._pendingConflicts.values());
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get a specific pending conflict.
|
|
189
|
+
*/
|
|
190
|
+
getConflict(conflictId) {
|
|
191
|
+
return this._pendingConflicts.get(conflictId);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Manually resolve a conflict with a user decision.
|
|
195
|
+
*/
|
|
196
|
+
async resolveManually(conflictId, decision, mergedData) {
|
|
197
|
+
const conflict = this._pendingConflicts.get(conflictId);
|
|
198
|
+
if (!conflict) {
|
|
199
|
+
throw new Error(`Conflict not found: ${conflictId}`);
|
|
200
|
+
}
|
|
201
|
+
const resolution = {
|
|
202
|
+
decision,
|
|
203
|
+
mergedData,
|
|
204
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
205
|
+
resolvedBy: 'user',
|
|
206
|
+
resolvedAt: Date.now(),
|
|
207
|
+
};
|
|
208
|
+
conflict.status = 'resolved';
|
|
209
|
+
this._resolvedConflicts.set(conflictId, resolution);
|
|
210
|
+
this._pendingConflicts.delete(conflictId);
|
|
211
|
+
this._options.hooks.onConflictResolved?.(conflict, resolution);
|
|
212
|
+
return resolution;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Auto-resolve old conflicts that have been pending too long.
|
|
216
|
+
*/
|
|
217
|
+
autoResolveStale() {
|
|
218
|
+
if (this._options.autoResolveAfter <= 0) {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
const now = Date.now();
|
|
222
|
+
const staleThreshold = now - this._options.autoResolveAfter;
|
|
223
|
+
const resolutions = [];
|
|
224
|
+
for (const conflict of this._pendingConflicts.values()) {
|
|
225
|
+
if (conflict.detectedAt < staleThreshold) {
|
|
226
|
+
// Auto-resolve with last-write-wins
|
|
227
|
+
const resolution = this._resolveLastWriteWins(conflict);
|
|
228
|
+
resolution.reason = 'Auto-resolved due to timeout';
|
|
229
|
+
conflict.status = 'resolved';
|
|
230
|
+
this._resolvedConflicts.set(conflict.conflictId, resolution);
|
|
231
|
+
this._pendingConflicts.delete(conflict.conflictId);
|
|
232
|
+
resolutions.push(resolution);
|
|
233
|
+
this._options.hooks.onConflictResolved?.(conflict, resolution);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return resolutions;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get the resolution strategy for a table.
|
|
240
|
+
*/
|
|
241
|
+
_getStrategy(tableName) {
|
|
242
|
+
return this._options.tableStrategies[tableName] ?? this._options.defaultStrategy;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Find fields that differ between local and remote data.
|
|
246
|
+
*/
|
|
247
|
+
_findConflictingFields(localData, remoteData) {
|
|
248
|
+
const allKeys = new Set([
|
|
249
|
+
...Object.keys(localData),
|
|
250
|
+
...Object.keys(remoteData),
|
|
251
|
+
]);
|
|
252
|
+
const conflicting = [];
|
|
253
|
+
for (const key of allKeys) {
|
|
254
|
+
// Skip metadata fields
|
|
255
|
+
if (key.startsWith('_'))
|
|
256
|
+
continue;
|
|
257
|
+
const localValue = localData[key];
|
|
258
|
+
const remoteValue = remoteData[key];
|
|
259
|
+
if (!this._valuesEqual(localValue, remoteValue)) {
|
|
260
|
+
conflicting.push(key);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return conflicting;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Check if two values are equal (deep comparison for objects/arrays).
|
|
267
|
+
*/
|
|
268
|
+
_valuesEqual(a, b) {
|
|
269
|
+
if (a === b)
|
|
270
|
+
return true;
|
|
271
|
+
if (a === null || b === null)
|
|
272
|
+
return false;
|
|
273
|
+
if (typeof a !== typeof b)
|
|
274
|
+
return false;
|
|
275
|
+
if (typeof a === 'object') {
|
|
276
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Resolve using last-write-wins strategy.
|
|
282
|
+
*/
|
|
283
|
+
_resolveLastWriteWins(conflict) {
|
|
284
|
+
// Use the clock's total ticks as a proxy for recency
|
|
285
|
+
const localTicks = getTotalTicks(conflict.localClock);
|
|
286
|
+
const remoteTicks = getTotalTicks(conflict.remoteClock);
|
|
287
|
+
// If clocks are equal, prefer remote (server-side typically more authoritative)
|
|
288
|
+
const useLocal = localTicks > remoteTicks;
|
|
289
|
+
return {
|
|
290
|
+
decision: useLocal ? 'use_local' : 'use_remote',
|
|
291
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
292
|
+
resolvedBy: 'strategy',
|
|
293
|
+
resolvedAt: Date.now(),
|
|
294
|
+
reason: `Last-write-wins: ${useLocal ? 'local' : 'remote'} had higher clock (${useLocal ? localTicks : remoteTicks} ticks)`,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Resolve using local-wins strategy.
|
|
299
|
+
*/
|
|
300
|
+
_resolveLocalWins(conflict) {
|
|
301
|
+
return {
|
|
302
|
+
decision: 'use_local',
|
|
303
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
304
|
+
resolvedBy: 'strategy',
|
|
305
|
+
resolvedAt: Date.now(),
|
|
306
|
+
reason: 'Local-wins strategy',
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Resolve using remote-wins strategy.
|
|
311
|
+
*/
|
|
312
|
+
_resolveRemoteWins(conflict) {
|
|
313
|
+
return {
|
|
314
|
+
decision: 'use_remote',
|
|
315
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
316
|
+
resolvedBy: 'strategy',
|
|
317
|
+
resolvedAt: Date.now(),
|
|
318
|
+
reason: 'Remote-wins strategy',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Resolve using field-level merge strategy.
|
|
323
|
+
*/
|
|
324
|
+
_resolveMerge(conflict) {
|
|
325
|
+
try {
|
|
326
|
+
const mergedData = { ...conflict.localData };
|
|
327
|
+
// Use current timestamp for LWW fallback
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
for (const field of conflict.conflictingFields) {
|
|
330
|
+
const merger = this._options.fieldMergers[field] ?? FieldMergers.lastWriteWins;
|
|
331
|
+
mergedData[field] = merger(field, conflict.localData[field], conflict.remoteData[field], now, now);
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
decision: 'use_merged',
|
|
335
|
+
mergedData,
|
|
336
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
337
|
+
resolvedBy: 'strategy',
|
|
338
|
+
resolvedAt: Date.now(),
|
|
339
|
+
reason: `Merged ${conflict.conflictingFields.length} conflicting fields`,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
this._options.hooks.onMergeFailed?.(conflict, error);
|
|
344
|
+
// Fallback to last-write-wins
|
|
345
|
+
return this._resolveLastWriteWins(conflict);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Resolve using manual/UI strategy.
|
|
350
|
+
*/
|
|
351
|
+
async _resolveManual(conflict) {
|
|
352
|
+
const hook = this._options.hooks.onConflictNeedsResolution;
|
|
353
|
+
if (!hook) {
|
|
354
|
+
// No UI hook, fall back to last-write-wins
|
|
355
|
+
console.warn('[ConflictResolver] No UI hook for manual resolution, falling back to LWW');
|
|
356
|
+
return this._resolveLastWriteWins(conflict);
|
|
357
|
+
}
|
|
358
|
+
// Create a timeout promise
|
|
359
|
+
const timeout = new Promise((_, reject) => {
|
|
360
|
+
setTimeout(() => {
|
|
361
|
+
reject(new Error('Manual resolution timed out'));
|
|
362
|
+
}, this._options.manualResolutionTimeout);
|
|
363
|
+
});
|
|
364
|
+
try {
|
|
365
|
+
// Race between user resolution and timeout
|
|
366
|
+
const resolution = await Promise.race([
|
|
367
|
+
hook(conflict),
|
|
368
|
+
timeout,
|
|
369
|
+
]);
|
|
370
|
+
return {
|
|
371
|
+
...resolution,
|
|
372
|
+
mergedClock: mergeVectorClocks(conflict.localClock, conflict.remoteClock),
|
|
373
|
+
resolvedBy: 'user',
|
|
374
|
+
resolvedAt: Date.now(),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
console.warn('[ConflictResolver] Manual resolution failed:', error);
|
|
379
|
+
// Defer the conflict for later
|
|
380
|
+
return {
|
|
381
|
+
decision: 'defer',
|
|
382
|
+
mergedClock: conflict.localClock, // Keep local for now
|
|
383
|
+
resolvedBy: 'auto',
|
|
384
|
+
resolvedAt: Date.now(),
|
|
385
|
+
reason: `Manual resolution failed: ${error.message}`,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Create a conflict resolver instance.
|
|
392
|
+
*/
|
|
393
|
+
export const createConflictResolver = (options) => {
|
|
394
|
+
return new ConflictResolver(options);
|
|
395
|
+
};
|
|
396
|
+
//# sourceMappingURL=conflictResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflictResolver.js","sourceRoot":"","sources":["../../../../src/features/sync/conflicts/conflictResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/features/sync/conflicts/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/features/sync/conflicts/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,oBAAoB,CAAC"}
|