@fatagnus/dink-sync 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +312 -0
- package/dist/client/attachment.d.ts +225 -0
- package/dist/client/attachment.d.ts.map +1 -0
- package/dist/client/attachment.js +402 -0
- package/dist/client/attachment.js.map +1 -0
- package/dist/client/binary-encoding.d.ts +45 -0
- package/dist/client/binary-encoding.d.ts.map +1 -0
- package/dist/client/binary-encoding.js +90 -0
- package/dist/client/binary-encoding.js.map +1 -0
- package/dist/client/collection.d.ts +10 -0
- package/dist/client/collection.d.ts.map +1 -0
- package/dist/client/collection.js +924 -0
- package/dist/client/collection.js.map +1 -0
- package/dist/client/compression.d.ts +56 -0
- package/dist/client/compression.d.ts.map +1 -0
- package/dist/client/compression.js +173 -0
- package/dist/client/compression.js.map +1 -0
- package/dist/client/crdt/index.d.ts +2 -0
- package/dist/client/crdt/index.d.ts.map +1 -0
- package/dist/client/crdt/index.js +2 -0
- package/dist/client/crdt/index.js.map +1 -0
- package/dist/client/crdt/yjs-doc.d.ts +88 -0
- package/dist/client/crdt/yjs-doc.d.ts.map +1 -0
- package/dist/client/crdt/yjs-doc.js +123 -0
- package/dist/client/crdt/yjs-doc.js.map +1 -0
- package/dist/client/index.d.ts +66 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +233 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/mock-transport.d.ts +155 -0
- package/dist/client/mock-transport.d.ts.map +1 -0
- package/dist/client/mock-transport.js +292 -0
- package/dist/client/mock-transport.js.map +1 -0
- package/dist/client/network-detector.d.ts +65 -0
- package/dist/client/network-detector.d.ts.map +1 -0
- package/dist/client/network-detector.js +147 -0
- package/dist/client/network-detector.js.map +1 -0
- package/dist/client/provisioning.d.ts +126 -0
- package/dist/client/provisioning.d.ts.map +1 -0
- package/dist/client/provisioning.js +125 -0
- package/dist/client/provisioning.js.map +1 -0
- package/dist/client/signal.d.ts +13 -0
- package/dist/client/signal.d.ts.map +1 -0
- package/dist/client/signal.js +27 -0
- package/dist/client/signal.js.map +1 -0
- package/dist/client/sync-engine.d.ts +298 -0
- package/dist/client/sync-engine.d.ts.map +1 -0
- package/dist/client/sync-engine.js +904 -0
- package/dist/client/sync-engine.js.map +1 -0
- package/dist/client/synced-edge.d.ts +109 -0
- package/dist/client/synced-edge.d.ts.map +1 -0
- package/dist/client/synced-edge.js +179 -0
- package/dist/client/synced-edge.js.map +1 -0
- package/dist/client/synced-offline-edge-types.d.ts +540 -0
- package/dist/client/synced-offline-edge-types.d.ts.map +1 -0
- package/dist/client/synced-offline-edge-types.js +10 -0
- package/dist/client/synced-offline-edge-types.js.map +1 -0
- package/dist/client/synced-offline-edge.d.ts +54 -0
- package/dist/client/synced-offline-edge.d.ts.map +1 -0
- package/dist/client/synced-offline-edge.js +731 -0
- package/dist/client/synced-offline-edge.js.map +1 -0
- package/dist/client/transport.d.ts +202 -0
- package/dist/client/transport.d.ts.map +1 -0
- package/dist/client/transport.js +409 -0
- package/dist/client/transport.js.map +1 -0
- package/dist/client/types.d.ts +622 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +60 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/validation.d.ts +61 -0
- package/dist/client/validation.d.ts.map +1 -0
- package/dist/client/validation.js +57 -0
- package/dist/client/validation.js.map +1 -0
- package/dist/client/versioning.d.ts +134 -0
- package/dist/client/versioning.d.ts.map +1 -0
- package/dist/client/versioning.js +304 -0
- package/dist/client/versioning.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/persistence/encryption.d.ts +114 -0
- package/dist/persistence/encryption.d.ts.map +1 -0
- package/dist/persistence/encryption.js +286 -0
- package/dist/persistence/encryption.js.map +1 -0
- package/dist/persistence/index.d.ts +21 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +20 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/memory.d.ts +32 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +57 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/migrations.d.ts +106 -0
- package/dist/persistence/migrations.d.ts.map +1 -0
- package/dist/persistence/migrations.js +176 -0
- package/dist/persistence/migrations.js.map +1 -0
- package/dist/persistence/pending-queue.d.ts +109 -0
- package/dist/persistence/pending-queue.d.ts.map +1 -0
- package/dist/persistence/pending-queue.js +249 -0
- package/dist/persistence/pending-queue.js.map +1 -0
- package/dist/persistence/pglite.d.ts +72 -0
- package/dist/persistence/pglite.d.ts.map +1 -0
- package/dist/persistence/pglite.js +126 -0
- package/dist/persistence/pglite.js.map +1 -0
- package/dist/persistence/quota-manager.d.ts +134 -0
- package/dist/persistence/quota-manager.d.ts.map +1 -0
- package/dist/persistence/quota-manager.js +242 -0
- package/dist/persistence/quota-manager.js.map +1 -0
- package/dist/persistence/types.d.ts +54 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/react/OfflineEdgeProvider.d.ts +91 -0
- package/dist/react/OfflineEdgeProvider.d.ts.map +1 -0
- package/dist/react/OfflineEdgeProvider.js +127 -0
- package/dist/react/OfflineEdgeProvider.js.map +1 -0
- package/dist/react/SyncedOfflineEdgeProvider.d.ts +105 -0
- package/dist/react/SyncedOfflineEdgeProvider.d.ts.map +1 -0
- package/dist/react/SyncedOfflineEdgeProvider.js +138 -0
- package/dist/react/SyncedOfflineEdgeProvider.js.map +1 -0
- package/dist/react/index.d.ts +50 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +51 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useCollection.d.ts +77 -0
- package/dist/react/useCollection.d.ts.map +1 -0
- package/dist/react/useCollection.js +113 -0
- package/dist/react/useCollection.js.map +1 -0
- package/dist/react/useCollectionSyncMode.d.ts +61 -0
- package/dist/react/useCollectionSyncMode.d.ts.map +1 -0
- package/dist/react/useCollectionSyncMode.js +93 -0
- package/dist/react/useCollectionSyncMode.js.map +1 -0
- package/dist/react/useConnectionState.d.ts +44 -0
- package/dist/react/useConnectionState.d.ts.map +1 -0
- package/dist/react/useConnectionState.js +46 -0
- package/dist/react/useConnectionState.js.map +1 -0
- package/dist/react/useDocumentSyncStatus.d.ts +72 -0
- package/dist/react/useDocumentSyncStatus.d.ts.map +1 -0
- package/dist/react/useDocumentSyncStatus.js +110 -0
- package/dist/react/useDocumentSyncStatus.js.map +1 -0
- package/dist/react/useOfflineEdge.d.ts +58 -0
- package/dist/react/useOfflineEdge.d.ts.map +1 -0
- package/dist/react/useOfflineEdge.js +54 -0
- package/dist/react/useOfflineEdge.js.map +1 -0
- package/dist/react/usePendingChanges.d.ts +67 -0
- package/dist/react/usePendingChanges.d.ts.map +1 -0
- package/dist/react/usePendingChanges.js +90 -0
- package/dist/react/usePendingChanges.js.map +1 -0
- package/dist/react/useRejectedDocuments.d.ts +112 -0
- package/dist/react/useRejectedDocuments.d.ts.map +1 -0
- package/dist/react/useRejectedDocuments.js +213 -0
- package/dist/react/useRejectedDocuments.js.map +1 -0
- package/dist/react/useSyncControls.d.ts +96 -0
- package/dist/react/useSyncControls.d.ts.map +1 -0
- package/dist/react/useSyncControls.js +112 -0
- package/dist/react/useSyncControls.js.map +1 -0
- package/dist/react/useSyncProgress.d.ts +78 -0
- package/dist/react/useSyncProgress.d.ts.map +1 -0
- package/dist/react/useSyncProgress.js +90 -0
- package/dist/react/useSyncProgress.js.map +1 -0
- package/dist/react/useSyncRejected.d.ts +47 -0
- package/dist/react/useSyncRejected.d.ts.map +1 -0
- package/dist/react/useSyncRejected.js +55 -0
- package/dist/react/useSyncRejected.js.map +1 -0
- package/dist/react/useSyncStatus.d.ts +56 -0
- package/dist/react/useSyncStatus.d.ts.map +1 -0
- package/dist/react/useSyncStatus.js +59 -0
- package/dist/react/useSyncStatus.js.map +1 -0
- package/dist/react/useSyncedOfflineEdge.d.ts +69 -0
- package/dist/react/useSyncedOfflineEdge.d.ts.map +1 -0
- package/dist/react/useSyncedOfflineEdge.js +65 -0
- package/dist/react/useSyncedOfflineEdge.js.map +1 -0
- package/dist/service-worker/index.d.ts +7 -0
- package/dist/service-worker/index.d.ts.map +1 -0
- package/dist/service-worker/index.js +7 -0
- package/dist/service-worker/index.js.map +1 -0
- package/dist/service-worker/sync-worker.d.ts +230 -0
- package/dist/service-worker/sync-worker.d.ts.map +1 -0
- package/dist/service-worker/sync-worker.js +471 -0
- package/dist/service-worker/sync-worker.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync priority levels for documents.
|
|
3
|
+
* Higher priority items are synced before lower priority items.
|
|
4
|
+
*/
|
|
5
|
+
export const SyncPriority = {
|
|
6
|
+
/** High priority - synced first */
|
|
7
|
+
High: 'high',
|
|
8
|
+
/** Normal priority - default */
|
|
9
|
+
Normal: 'normal',
|
|
10
|
+
/** Low priority - synced last */
|
|
11
|
+
Low: 'low',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Sync status for a document.
|
|
15
|
+
* Tracks the synchronization state between local and server.
|
|
16
|
+
*/
|
|
17
|
+
export var SyncStatus;
|
|
18
|
+
(function (SyncStatus) {
|
|
19
|
+
/** Document exists only locally, not yet synced */
|
|
20
|
+
SyncStatus["Local"] = "local";
|
|
21
|
+
/** Document is currently being synced to server */
|
|
22
|
+
SyncStatus["Syncing"] = "syncing";
|
|
23
|
+
/** Document is synced with server */
|
|
24
|
+
SyncStatus["Synced"] = "synced";
|
|
25
|
+
/** Sync was rejected by server (e.g., validation error, unique constraint) */
|
|
26
|
+
SyncStatus["Rejected"] = "rejected";
|
|
27
|
+
})(SyncStatus || (SyncStatus = {}));
|
|
28
|
+
/**
|
|
29
|
+
* Error codes for sync rejection.
|
|
30
|
+
*/
|
|
31
|
+
export var SyncErrorCode;
|
|
32
|
+
(function (SyncErrorCode) {
|
|
33
|
+
/** Server-side unique constraint violation */
|
|
34
|
+
SyncErrorCode["UniqueViolation"] = "UNIQUE_VIOLATION";
|
|
35
|
+
/** Server-side validation error */
|
|
36
|
+
SyncErrorCode["ValidationError"] = "VALIDATION_ERROR";
|
|
37
|
+
/** Permission denied */
|
|
38
|
+
SyncErrorCode["PermissionDenied"] = "PERMISSION_DENIED";
|
|
39
|
+
/** Document not found on server */
|
|
40
|
+
SyncErrorCode["NotFound"] = "NOT_FOUND";
|
|
41
|
+
/** Generic server error */
|
|
42
|
+
SyncErrorCode["ServerError"] = "SERVER_ERROR";
|
|
43
|
+
/** Unknown error */
|
|
44
|
+
SyncErrorCode["Unknown"] = "UNKNOWN";
|
|
45
|
+
})(SyncErrorCode || (SyncErrorCode = {}));
|
|
46
|
+
/**
|
|
47
|
+
* Connection state enum for tracking sync status.
|
|
48
|
+
*/
|
|
49
|
+
export var ConnectionState;
|
|
50
|
+
(function (ConnectionState) {
|
|
51
|
+
/** Not connected to server, operating fully offline */
|
|
52
|
+
ConnectionState["Offline"] = "offline";
|
|
53
|
+
/** Attempting to connect to server */
|
|
54
|
+
ConnectionState["Connecting"] = "connecting";
|
|
55
|
+
/** Connected and syncing with server */
|
|
56
|
+
ConnectionState["Online"] = "online";
|
|
57
|
+
/** Connection lost, attempting to reconnect */
|
|
58
|
+
ConnectionState["Reconnecting"] = "reconnecting";
|
|
59
|
+
})(ConnectionState || (ConnectionState = {}));
|
|
60
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AA4DA;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,mCAAmC;IACnC,IAAI,EAAE,MAAM;IACZ,gCAAgC;IAChC,MAAM,EAAE,QAAQ;IAChB,iCAAiC;IACjC,GAAG,EAAE,KAAK;CACF,CAAC;AAwBX;;;GAGG;AACH,MAAM,CAAN,IAAY,UASX;AATD,WAAY,UAAU;IACpB,mDAAmD;IACnD,6BAAe,CAAA;IACf,mDAAmD;IACnD,iCAAmB,CAAA;IACnB,qCAAqC;IACrC,+BAAiB,CAAA;IACjB,8EAA8E;IAC9E,mCAAqB,CAAA;AACvB,CAAC,EATW,UAAU,KAAV,UAAU,QASrB;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,aAaX;AAbD,WAAY,aAAa;IACvB,8CAA8C;IAC9C,qDAAoC,CAAA;IACpC,mCAAmC;IACnC,qDAAoC,CAAA;IACpC,wBAAwB;IACxB,uDAAsC,CAAA;IACtC,mCAAmC;IACnC,uCAAsB,CAAA;IACtB,2BAA2B;IAC3B,6CAA4B,CAAA;IAC5B,oBAAoB;IACpB,oCAAmB,CAAA;AACrB,CAAC,EAbW,aAAa,KAAb,aAAa,QAaxB;AAmED;;GAEG;AACH,MAAM,CAAN,IAAY,eASX;AATD,WAAY,eAAe;IACzB,uDAAuD;IACvD,sCAAmB,CAAA;IACnB,sCAAsC;IACtC,4CAAyB,CAAA;IACzB,wCAAwC;IACxC,oCAAiB,CAAA;IACjB,+CAA+C;IAC/C,gDAA6B,CAAA;AAC/B,CAAC,EATW,eAAe,KAAf,eAAe,QAS1B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for offline-first sync SDK.
|
|
3
|
+
*
|
|
4
|
+
* Provides error classes and helpers for integrating with validation libraries like Zod.
|
|
5
|
+
*/
|
|
6
|
+
import type { ValidationError, ValidationResult } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when document validation fails.
|
|
9
|
+
* Contains field-level error details.
|
|
10
|
+
*/
|
|
11
|
+
export declare class CollectionValidationError extends Error {
|
|
12
|
+
/** Field-level validation errors */
|
|
13
|
+
readonly errors: ValidationError[];
|
|
14
|
+
constructor(errors: ValidationError[]);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Zod-compatible schema interface.
|
|
18
|
+
* Matches the shape of Zod's safeParse method.
|
|
19
|
+
*/
|
|
20
|
+
export interface ZodLikeSchema<T = unknown> {
|
|
21
|
+
safeParse(data: unknown): {
|
|
22
|
+
success: true;
|
|
23
|
+
data: T;
|
|
24
|
+
} | {
|
|
25
|
+
success: false;
|
|
26
|
+
error: {
|
|
27
|
+
issues: Array<{
|
|
28
|
+
path: (string | number)[];
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a validator function from a Zod-like schema.
|
|
36
|
+
*
|
|
37
|
+
* This adapter allows using Zod schemas (or any schema with a compatible safeParse interface)
|
|
38
|
+
* as collection validators.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { z } from 'zod';
|
|
43
|
+
* import { createZodValidator } from '@fatagnus/dink-sync/client';
|
|
44
|
+
*
|
|
45
|
+
* const TaskSchema = z.object({
|
|
46
|
+
* title: z.string().min(1),
|
|
47
|
+
* completed: z.boolean(),
|
|
48
|
+
* priority: z.number().min(1).max(5).optional(),
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* const validator = createZodValidator(TaskSchema);
|
|
52
|
+
* collection.setValidator(validator);
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param schema - A Zod-like schema with a safeParse method
|
|
56
|
+
* @returns A validator function compatible with collection.setValidator()
|
|
57
|
+
*/
|
|
58
|
+
export declare function createZodValidator<T extends {
|
|
59
|
+
id: string;
|
|
60
|
+
}>(schema: ZodLikeSchema<Omit<T, 'id'>>): (doc: Omit<T, 'id'>) => ValidationResult;
|
|
61
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/client/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE;;;GAGG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;gBAEvB,MAAM,EAAE,eAAe,EAAE;CAMtC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,SAAS,CAAC,IAAI,EAAE,OAAO,GACnB;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,CAAA;KAAE,GAC1B;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE;YAAE,MAAM,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;CAClG;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACzD,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GACnC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,gBAAgB,CAe1C"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation utilities for offline-first sync SDK.
|
|
3
|
+
*
|
|
4
|
+
* Provides error classes and helpers for integrating with validation libraries like Zod.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when document validation fails.
|
|
8
|
+
* Contains field-level error details.
|
|
9
|
+
*/
|
|
10
|
+
export class CollectionValidationError extends Error {
|
|
11
|
+
/** Field-level validation errors */
|
|
12
|
+
errors;
|
|
13
|
+
constructor(errors) {
|
|
14
|
+
const fieldNames = errors.map(e => e.field).join(', ');
|
|
15
|
+
super(`Validation failed: ${fieldNames}`);
|
|
16
|
+
this.name = 'ValidationError';
|
|
17
|
+
this.errors = errors;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a validator function from a Zod-like schema.
|
|
22
|
+
*
|
|
23
|
+
* This adapter allows using Zod schemas (or any schema with a compatible safeParse interface)
|
|
24
|
+
* as collection validators.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import { z } from 'zod';
|
|
29
|
+
* import { createZodValidator } from '@fatagnus/dink-sync/client';
|
|
30
|
+
*
|
|
31
|
+
* const TaskSchema = z.object({
|
|
32
|
+
* title: z.string().min(1),
|
|
33
|
+
* completed: z.boolean(),
|
|
34
|
+
* priority: z.number().min(1).max(5).optional(),
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const validator = createZodValidator(TaskSchema);
|
|
38
|
+
* collection.setValidator(validator);
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @param schema - A Zod-like schema with a safeParse method
|
|
42
|
+
* @returns A validator function compatible with collection.setValidator()
|
|
43
|
+
*/
|
|
44
|
+
export function createZodValidator(schema) {
|
|
45
|
+
return (doc) => {
|
|
46
|
+
const result = schema.safeParse(doc);
|
|
47
|
+
if (result.success) {
|
|
48
|
+
return { valid: true };
|
|
49
|
+
}
|
|
50
|
+
const errors = result.error.issues.map(issue => ({
|
|
51
|
+
field: issue.path.map(p => String(p)).join('.'),
|
|
52
|
+
message: issue.message,
|
|
53
|
+
}));
|
|
54
|
+
return { valid: false, errors };
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/client/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,oCAAoC;IAC3B,MAAM,CAAoB;IAEnC,YAAY,MAAyB;QACnC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,KAAK,CAAC,sBAAsB,UAAU,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAYD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAoC;IAEpC,OAAO,CAAC,GAAkB,EAAoB,EAAE;QAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAErC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,MAAM,MAAM,GAAsB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAC/C,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC,CAAC;QAEJ,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Versioning for Dink Offline-First SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Version snapshots stored at configurable intervals
|
|
6
|
+
* - Version history retrieval
|
|
7
|
+
* - Restoring previous versions
|
|
8
|
+
* - Version diffing between snapshots
|
|
9
|
+
* - Version cleanup policies (max versions, max age)
|
|
10
|
+
*/
|
|
11
|
+
import type { PersistenceProvider } from '../persistence/types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for version management
|
|
14
|
+
*/
|
|
15
|
+
export interface VersionConfig {
|
|
16
|
+
/** Maximum number of versions to keep per document (default: 50) */
|
|
17
|
+
maxVersions?: number;
|
|
18
|
+
/** Maximum age of versions in milliseconds (default: 7 days) */
|
|
19
|
+
maxAge?: number;
|
|
20
|
+
/** Interval for automatic snapshotting (every N changes, default: 1) */
|
|
21
|
+
snapshotInterval?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A version snapshot of a document
|
|
25
|
+
*/
|
|
26
|
+
export interface VersionSnapshot {
|
|
27
|
+
/** Unique identifier for this version */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Collection name */
|
|
30
|
+
collection: string;
|
|
31
|
+
/** Document ID */
|
|
32
|
+
docId: string;
|
|
33
|
+
/** Version number (1-indexed, incrementing) */
|
|
34
|
+
version: number;
|
|
35
|
+
/** Timestamp when this version was created */
|
|
36
|
+
timestamp: number;
|
|
37
|
+
/** Binary data of the document at this version */
|
|
38
|
+
data: Uint8Array;
|
|
39
|
+
/** Optional metadata about the version */
|
|
40
|
+
metadata?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A change between two field values
|
|
44
|
+
*/
|
|
45
|
+
export interface FieldChange {
|
|
46
|
+
/** Field name that changed */
|
|
47
|
+
field: string;
|
|
48
|
+
/** Value in the older version */
|
|
49
|
+
oldValue: unknown;
|
|
50
|
+
/** Value in the newer version */
|
|
51
|
+
newValue: unknown;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Diff result between two versions
|
|
55
|
+
*/
|
|
56
|
+
export interface VersionDiff {
|
|
57
|
+
/** Source version number */
|
|
58
|
+
fromVersion: number;
|
|
59
|
+
/** Target version number */
|
|
60
|
+
toVersion: number;
|
|
61
|
+
/** List of field changes */
|
|
62
|
+
changes: FieldChange[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Version Manager interface
|
|
66
|
+
*/
|
|
67
|
+
export interface VersionManager {
|
|
68
|
+
/**
|
|
69
|
+
* Create a new version snapshot for a document
|
|
70
|
+
* @param collection - Collection name
|
|
71
|
+
* @param docId - Document ID
|
|
72
|
+
* @param data - Binary data to snapshot
|
|
73
|
+
* @param metadata - Optional metadata about the version
|
|
74
|
+
* @returns The created version snapshot
|
|
75
|
+
*/
|
|
76
|
+
createSnapshot(collection: string, docId: string, data: Uint8Array, metadata?: Record<string, unknown>): Promise<VersionSnapshot>;
|
|
77
|
+
/**
|
|
78
|
+
* Get all versions for a document, ordered by version (newest first)
|
|
79
|
+
* @param collection - Collection name
|
|
80
|
+
* @param docId - Document ID
|
|
81
|
+
* @returns Array of version snapshots
|
|
82
|
+
*/
|
|
83
|
+
getVersions(collection: string, docId: string): Promise<VersionSnapshot[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Get a specific version by number
|
|
86
|
+
* @param collection - Collection name
|
|
87
|
+
* @param docId - Document ID
|
|
88
|
+
* @param version - Version number
|
|
89
|
+
* @returns The version snapshot or null if not found
|
|
90
|
+
*/
|
|
91
|
+
getVersion(collection: string, docId: string, version: number): Promise<VersionSnapshot | null>;
|
|
92
|
+
/**
|
|
93
|
+
* Restore a previous version, creating a new version with that data
|
|
94
|
+
* @param collection - Collection name
|
|
95
|
+
* @param docId - Document ID
|
|
96
|
+
* @param version - Version number to restore
|
|
97
|
+
* @returns The restored data
|
|
98
|
+
*/
|
|
99
|
+
restoreVersion(collection: string, docId: string, version: number): Promise<Uint8Array>;
|
|
100
|
+
/**
|
|
101
|
+
* Compute the diff between two versions
|
|
102
|
+
* @param collection - Collection name
|
|
103
|
+
* @param docId - Document ID
|
|
104
|
+
* @param fromVersion - Source version number
|
|
105
|
+
* @param toVersion - Target version number
|
|
106
|
+
* @returns The diff between versions
|
|
107
|
+
*/
|
|
108
|
+
diffVersions(collection: string, docId: string, fromVersion: number, toVersion: number): Promise<VersionDiff>;
|
|
109
|
+
/**
|
|
110
|
+
* Clean up old versions for a document based on config
|
|
111
|
+
* @param collection - Collection name
|
|
112
|
+
* @param docId - Document ID
|
|
113
|
+
*/
|
|
114
|
+
cleanup(collection: string, docId: string): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Clean up old versions for all documents in a collection
|
|
117
|
+
* @param collection - Collection name
|
|
118
|
+
*/
|
|
119
|
+
cleanupAll(collection: string): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Delete all versions for a document
|
|
122
|
+
* @param collection - Collection name
|
|
123
|
+
* @param docId - Document ID
|
|
124
|
+
*/
|
|
125
|
+
deleteVersions(collection: string, docId: string): Promise<void>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create a VersionManager instance
|
|
129
|
+
* @param persistence - Persistence provider for storing versions
|
|
130
|
+
* @param config - Optional configuration
|
|
131
|
+
* @returns VersionManager instance
|
|
132
|
+
*/
|
|
133
|
+
export declare function createVersionManager(persistence: PersistenceProvider, config?: VersionConfig): VersionManager;
|
|
134
|
+
//# sourceMappingURL=versioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versioning.d.ts","sourceRoot":"","sources":["../../src/client/versioning.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,IAAI,EAAE,UAAU,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,iCAAiC;IACjC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,cAAc,CACZ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,UAAU,EAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,eAAe,CAAC,CAAC;IAE5B;;;;;OAKG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAE3E;;;;;;OAMG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAEhG;;;;;;OAMG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAExF;;;;;;;OAOG;IACH,YAAY,CACV,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAoFD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,mBAAmB,EAChC,MAAM,GAAE,aAAkB,GACzB,cAAc,CA4QhB"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Versioning for Dink Offline-First SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Version snapshots stored at configurable intervals
|
|
6
|
+
* - Version history retrieval
|
|
7
|
+
* - Restoring previous versions
|
|
8
|
+
* - Version diffing between snapshots
|
|
9
|
+
* - Version cleanup policies (max versions, max age)
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Reserved collection prefix for version storage
|
|
13
|
+
*/
|
|
14
|
+
const VERSION_COLLECTION_PREFIX = '_versions_';
|
|
15
|
+
/**
|
|
16
|
+
* Generate a unique version ID
|
|
17
|
+
*/
|
|
18
|
+
function generateVersionId() {
|
|
19
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
20
|
+
return crypto.randomUUID();
|
|
21
|
+
}
|
|
22
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 11)}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Encode a version snapshot for storage
|
|
26
|
+
*/
|
|
27
|
+
function encodeVersionSnapshot(snapshot) {
|
|
28
|
+
const metadata = JSON.stringify({
|
|
29
|
+
id: snapshot.id,
|
|
30
|
+
collection: snapshot.collection,
|
|
31
|
+
docId: snapshot.docId,
|
|
32
|
+
version: snapshot.version,
|
|
33
|
+
timestamp: snapshot.timestamp,
|
|
34
|
+
metadata: snapshot.metadata,
|
|
35
|
+
});
|
|
36
|
+
const metadataBytes = new TextEncoder().encode(metadata);
|
|
37
|
+
// Format: [4 bytes metadata length][metadata][data]
|
|
38
|
+
const buffer = new Uint8Array(4 + metadataBytes.length + snapshot.data.length);
|
|
39
|
+
const view = new DataView(buffer.buffer);
|
|
40
|
+
view.setUint32(0, metadataBytes.length, false);
|
|
41
|
+
buffer.set(metadataBytes, 4);
|
|
42
|
+
buffer.set(snapshot.data, 4 + metadataBytes.length);
|
|
43
|
+
return buffer;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Decode a version snapshot from storage
|
|
47
|
+
*/
|
|
48
|
+
function decodeVersionSnapshot(data) {
|
|
49
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
50
|
+
const metadataLength = view.getUint32(0, false);
|
|
51
|
+
const metadataBytes = data.slice(4, 4 + metadataLength);
|
|
52
|
+
const metadata = JSON.parse(new TextDecoder().decode(metadataBytes));
|
|
53
|
+
const snapshotData = data.slice(4 + metadataLength);
|
|
54
|
+
return {
|
|
55
|
+
id: metadata.id,
|
|
56
|
+
collection: metadata.collection,
|
|
57
|
+
docId: metadata.docId,
|
|
58
|
+
version: metadata.version,
|
|
59
|
+
timestamp: metadata.timestamp,
|
|
60
|
+
data: snapshotData,
|
|
61
|
+
metadata: metadata.metadata,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the version collection name for a document
|
|
66
|
+
*/
|
|
67
|
+
function getVersionCollectionName(collection, docId) {
|
|
68
|
+
return `${VERSION_COLLECTION_PREFIX}${collection}_${docId}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Parse data as JSON, handling binary Yjs data
|
|
72
|
+
*/
|
|
73
|
+
function parseVersionData(data) {
|
|
74
|
+
try {
|
|
75
|
+
const text = new TextDecoder().decode(data);
|
|
76
|
+
return JSON.parse(text);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// If it's not JSON (e.g., Yjs binary), return empty object
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create a VersionManager instance
|
|
85
|
+
* @param persistence - Persistence provider for storing versions
|
|
86
|
+
* @param config - Optional configuration
|
|
87
|
+
* @returns VersionManager instance
|
|
88
|
+
*/
|
|
89
|
+
export function createVersionManager(persistence, config = {}) {
|
|
90
|
+
const maxVersions = config.maxVersions ?? 50;
|
|
91
|
+
const maxAge = config.maxAge ?? 7 * 24 * 60 * 60 * 1000; // 7 days default
|
|
92
|
+
// In-memory cache for version counters
|
|
93
|
+
const versionCounters = new Map();
|
|
94
|
+
/**
|
|
95
|
+
* Get the next version number for a document
|
|
96
|
+
*/
|
|
97
|
+
async function getNextVersion(collection, docId) {
|
|
98
|
+
const key = `${collection}:${docId}`;
|
|
99
|
+
// Check cache first
|
|
100
|
+
if (versionCounters.has(key)) {
|
|
101
|
+
const next = versionCounters.get(key) + 1;
|
|
102
|
+
versionCounters.set(key, next);
|
|
103
|
+
return next;
|
|
104
|
+
}
|
|
105
|
+
// Load from persistence
|
|
106
|
+
const versions = await loadVersions(collection, docId);
|
|
107
|
+
const maxVersion = versions.length > 0
|
|
108
|
+
? Math.max(...versions.map(v => v.version))
|
|
109
|
+
: 0;
|
|
110
|
+
const next = maxVersion + 1;
|
|
111
|
+
versionCounters.set(key, next);
|
|
112
|
+
return next;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Load all versions from persistence
|
|
116
|
+
*/
|
|
117
|
+
async function loadVersions(collection, docId) {
|
|
118
|
+
const versionCollection = getVersionCollectionName(collection, docId);
|
|
119
|
+
const versionIds = await persistence.list(versionCollection);
|
|
120
|
+
const versions = [];
|
|
121
|
+
for (const versionId of versionIds) {
|
|
122
|
+
const data = await persistence.load(versionCollection, versionId);
|
|
123
|
+
if (data) {
|
|
124
|
+
try {
|
|
125
|
+
versions.push(decodeVersionSnapshot(data));
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Skip corrupted versions
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Sort by version descending (newest first)
|
|
133
|
+
return versions.sort((a, b) => b.version - a.version);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Save a version to persistence
|
|
137
|
+
*/
|
|
138
|
+
async function saveVersion(snapshot) {
|
|
139
|
+
const versionCollection = getVersionCollectionName(snapshot.collection, snapshot.docId);
|
|
140
|
+
const encoded = encodeVersionSnapshot(snapshot);
|
|
141
|
+
await persistence.save(versionCollection, snapshot.id, encoded);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Delete a version from persistence
|
|
145
|
+
*/
|
|
146
|
+
async function deleteVersion(snapshot) {
|
|
147
|
+
const versionCollection = getVersionCollectionName(snapshot.collection, snapshot.docId);
|
|
148
|
+
await persistence.delete(versionCollection, snapshot.id);
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
async createSnapshot(collection, docId, data, metadata) {
|
|
152
|
+
const version = await getNextVersion(collection, docId);
|
|
153
|
+
const snapshot = {
|
|
154
|
+
id: generateVersionId(),
|
|
155
|
+
collection,
|
|
156
|
+
docId,
|
|
157
|
+
version,
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
data,
|
|
160
|
+
metadata,
|
|
161
|
+
};
|
|
162
|
+
await saveVersion(snapshot);
|
|
163
|
+
// Apply maxVersions cleanup
|
|
164
|
+
if (maxVersions > 0) {
|
|
165
|
+
const versions = await loadVersions(collection, docId);
|
|
166
|
+
if (versions.length > maxVersions) {
|
|
167
|
+
// Delete oldest versions (they're at the end since sorted newest first)
|
|
168
|
+
const toDelete = versions.slice(maxVersions);
|
|
169
|
+
for (const v of toDelete) {
|
|
170
|
+
await deleteVersion(v);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return snapshot;
|
|
175
|
+
},
|
|
176
|
+
async getVersions(collection, docId) {
|
|
177
|
+
return loadVersions(collection, docId);
|
|
178
|
+
},
|
|
179
|
+
async getVersion(collection, docId, version) {
|
|
180
|
+
const versions = await loadVersions(collection, docId);
|
|
181
|
+
return versions.find(v => v.version === version) ?? null;
|
|
182
|
+
},
|
|
183
|
+
async restoreVersion(collection, docId, version) {
|
|
184
|
+
const targetVersion = await this.getVersion(collection, docId, version);
|
|
185
|
+
if (!targetVersion) {
|
|
186
|
+
throw new Error(`Version ${version} not found for ${collection}:${docId}`);
|
|
187
|
+
}
|
|
188
|
+
// Create a new version with the restored data
|
|
189
|
+
await this.createSnapshot(collection, docId, targetVersion.data, {
|
|
190
|
+
restoredFrom: version,
|
|
191
|
+
});
|
|
192
|
+
return targetVersion.data;
|
|
193
|
+
},
|
|
194
|
+
async diffVersions(collection, docId, fromVersion, toVersion) {
|
|
195
|
+
const from = await this.getVersion(collection, docId, fromVersion);
|
|
196
|
+
const to = await this.getVersion(collection, docId, toVersion);
|
|
197
|
+
if (!from) {
|
|
198
|
+
throw new Error(`Version ${fromVersion} not found for ${collection}:${docId}`);
|
|
199
|
+
}
|
|
200
|
+
if (!to) {
|
|
201
|
+
throw new Error(`Version ${toVersion} not found for ${collection}:${docId}`);
|
|
202
|
+
}
|
|
203
|
+
const fromData = parseVersionData(from.data);
|
|
204
|
+
const toData = parseVersionData(to.data);
|
|
205
|
+
const changes = [];
|
|
206
|
+
const allFields = new Set([...Object.keys(fromData), ...Object.keys(toData)]);
|
|
207
|
+
for (const field of allFields) {
|
|
208
|
+
const oldValue = fromData[field];
|
|
209
|
+
const newValue = toData[field];
|
|
210
|
+
// Deep compare for objects/arrays
|
|
211
|
+
const oldStr = JSON.stringify(oldValue);
|
|
212
|
+
const newStr = JSON.stringify(newValue);
|
|
213
|
+
if (oldStr !== newStr) {
|
|
214
|
+
changes.push({
|
|
215
|
+
field,
|
|
216
|
+
oldValue,
|
|
217
|
+
newValue,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
fromVersion,
|
|
223
|
+
toVersion,
|
|
224
|
+
changes,
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
async cleanup(collection, docId) {
|
|
228
|
+
const versions = await loadVersions(collection, docId);
|
|
229
|
+
if (versions.length <= 1) {
|
|
230
|
+
// Always keep at least one version
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
const toDelete = [];
|
|
235
|
+
// Apply maxAge cleanup (but keep at least one version)
|
|
236
|
+
if (maxAge > 0) {
|
|
237
|
+
for (let i = 1; i < versions.length; i++) {
|
|
238
|
+
// Skip the first (newest) version
|
|
239
|
+
const version = versions[i];
|
|
240
|
+
if (now - version.timestamp > maxAge) {
|
|
241
|
+
toDelete.push(version);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Apply maxVersions cleanup
|
|
246
|
+
if (maxVersions > 0 && versions.length > maxVersions) {
|
|
247
|
+
const extraVersions = versions.slice(maxVersions);
|
|
248
|
+
for (const v of extraVersions) {
|
|
249
|
+
if (!toDelete.includes(v)) {
|
|
250
|
+
toDelete.push(v);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (const v of toDelete) {
|
|
255
|
+
await deleteVersion(v);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
async cleanupAll(collection) {
|
|
259
|
+
// Find all version collections for this collection
|
|
260
|
+
// This is a bit tricky since we need to find all docIds
|
|
261
|
+
// We'll scan for collections matching the prefix pattern
|
|
262
|
+
// Get all documents that have versions by checking the version collection prefix
|
|
263
|
+
const prefix = `${VERSION_COLLECTION_PREFIX}${collection}_`;
|
|
264
|
+
// We need to track which docIds we've seen
|
|
265
|
+
const docIds = new Set();
|
|
266
|
+
// Unfortunately, we can't easily list all collections in the persistence interface
|
|
267
|
+
// So we'll need to iterate through known version collections
|
|
268
|
+
// For now, we'll work with the versions we've loaded in memory
|
|
269
|
+
// Get all version collections
|
|
270
|
+
// This is a limitation - we can only clean up documents we know about
|
|
271
|
+
// A proper implementation would require a list of all collections in persistence
|
|
272
|
+
// For each docId we've tracked, run cleanup
|
|
273
|
+
for (const key of versionCounters.keys()) {
|
|
274
|
+
const [col, docId] = key.split(':');
|
|
275
|
+
if (col === collection) {
|
|
276
|
+
docIds.add(docId);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Also try to find versions by scanning persistence
|
|
280
|
+
// We'll check common patterns
|
|
281
|
+
try {
|
|
282
|
+
// Try listing the base version collection to find docIds
|
|
283
|
+
const allCollections = await persistence.list(prefix.slice(0, -1));
|
|
284
|
+
// This won't work directly, but we try anyway
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Expected to fail for some persistence implementations
|
|
288
|
+
}
|
|
289
|
+
for (const docId of docIds) {
|
|
290
|
+
await this.cleanup(collection, docId);
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
async deleteVersions(collection, docId) {
|
|
294
|
+
const versions = await loadVersions(collection, docId);
|
|
295
|
+
for (const version of versions) {
|
|
296
|
+
await deleteVersion(version);
|
|
297
|
+
}
|
|
298
|
+
// Clear the version counter
|
|
299
|
+
const key = `${collection}:${docId}`;
|
|
300
|
+
versionCounters.delete(key);
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=versioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versioning.js","sourceRoot":"","sources":["../../src/client/versioning.ts"],"names":[],"mappings":"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"}
|