@dabble/patches 0.3.1 → 0.3.2
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/dist/algorithms/client/makeChange.d.ts +2 -2
- package/dist/client/PatchesDoc.d.ts +2 -2
- package/dist/json-patch/createJSONPatch.d.ts +2 -1
- package/dist/json-patch/patchProxy.d.ts +3 -2
- package/dist/net/PatchesSync.d.ts +14 -7
- package/dist/net/PatchesSync.js +16 -5
- package/dist/server/PatchesServer.d.ts +2 -2
- package/dist/types.d.ts +10 -0
- package/package.json +13 -11
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { JSONPatch } from '../..';
|
|
2
|
-
import type { Change, PatchesSnapshot } from '../../types.js';
|
|
3
|
-
export declare function makeChange<T = any>(snapshot: PatchesSnapshot<T>, mutator: (draft: T
|
|
2
|
+
import type { Change, DeepRequired, PatchesSnapshot } from '../../types.js';
|
|
3
|
+
export declare function makeChange<T = any>(snapshot: PatchesSnapshot<T>, mutator: (draft: DeepRequired<T>, patch: JSONPatch) => void, changeMetadata?: Record<string, any>, maxPayloadBytes?: number): Change[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Unsubscriber } from '../event-signal.js';
|
|
2
2
|
import type { JSONPatch } from '../json-patch/JSONPatch.js';
|
|
3
|
-
import type { Change, PatchesSnapshot, SyncingState } from '../types.js';
|
|
3
|
+
import type { Change, DeepRequired, PatchesSnapshot, SyncingState } from '../types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Options for creating a PatchesDoc instance
|
|
6
6
|
*/
|
|
@@ -71,7 +71,7 @@ export declare class PatchesDoc<T extends object = object> {
|
|
|
71
71
|
* @param mutator Function modifying a draft state.
|
|
72
72
|
* @returns The generated Change object or null if no changes occurred.
|
|
73
73
|
*/
|
|
74
|
-
change(mutator: (draft: T
|
|
74
|
+
change(mutator: (draft: DeepRequired<T>, patch: JSONPatch) => void): Change[];
|
|
75
75
|
/**
|
|
76
76
|
* Returns the pending changes for this document.
|
|
77
77
|
* @returns The pending changes.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DeepRequired } from '../types.js';
|
|
1
2
|
import { JSONPatch } from './JSONPatch.js';
|
|
2
3
|
/**
|
|
3
4
|
* Creates a `JSONPatch` instance by tracking changes made to a proxy object within an updater function.
|
|
@@ -32,4 +33,4 @@ import { JSONPatch } from './JSONPatch.js';
|
|
|
32
33
|
* // ]
|
|
33
34
|
* ```
|
|
34
35
|
*/
|
|
35
|
-
export declare function createJSONPatch<T>(target: T, updater: (proxy: T
|
|
36
|
+
export declare function createJSONPatch<T>(target: T, updater: (proxy: DeepRequired<T>, patch: JSONPatch) => void): JSONPatch;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DeepRequired } from '../types.js';
|
|
1
2
|
import { JSONPatch } from './JSONPatch.js';
|
|
2
3
|
/**
|
|
3
4
|
* Creates a proxy object that can be used in two ways:
|
|
@@ -37,5 +38,5 @@ import { JSONPatch } from './JSONPatch.js';
|
|
|
37
38
|
* @param patch The `JSONPatch` instance to add generated operations to (required for automatic patch generation mode).
|
|
38
39
|
* @returns A proxy object of type T.
|
|
39
40
|
*/
|
|
40
|
-
export declare function createPatchProxy<T>(): T
|
|
41
|
-
export declare function createPatchProxy<T>(target: T, patch: JSONPatch): T
|
|
41
|
+
export declare function createPatchProxy<T>(): DeepRequired<T>;
|
|
42
|
+
export declare function createPatchProxy<T>(target: T, patch: JSONPatch): DeepRequired<T>;
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { Patches } from '../client/Patches.js';
|
|
2
|
+
import type { PatchesStore } from '../client/PatchesStore.js';
|
|
2
3
|
import type { Change, SyncingState } from '../types.js';
|
|
3
4
|
import type { ConnectionState } from './protocol/types.js';
|
|
5
|
+
import { PatchesWebSocket } from './websocket/PatchesWebSocket.js';
|
|
4
6
|
import type { WebSocketOptions } from './websocket/WebSocketTransport.js';
|
|
5
7
|
export interface PatchesSyncState {
|
|
6
8
|
online: boolean;
|
|
7
9
|
connected: boolean;
|
|
8
10
|
syncing: SyncingState;
|
|
9
11
|
}
|
|
12
|
+
export interface PatchesSyncOptions {
|
|
13
|
+
subscribeFilter?: (docIds: string[]) => string[];
|
|
14
|
+
websocket?: WebSocketOptions;
|
|
15
|
+
}
|
|
10
16
|
/**
|
|
11
17
|
* Handles WebSocket connection, document subscriptions, and syncing logic between
|
|
12
18
|
* the Patches instance and the server.
|
|
13
19
|
*/
|
|
14
20
|
export declare class PatchesSync {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
protected options?: PatchesSyncOptions | undefined;
|
|
22
|
+
protected ws: PatchesWebSocket;
|
|
23
|
+
protected patches: Patches;
|
|
24
|
+
protected store: PatchesStore;
|
|
25
|
+
protected maxPayloadBytes?: number;
|
|
26
|
+
protected trackedDocs: Set<string>;
|
|
27
|
+
protected _state: PatchesSyncState;
|
|
21
28
|
/**
|
|
22
29
|
* Signal emitted when the sync state changes.
|
|
23
30
|
*/
|
|
@@ -28,7 +35,7 @@ export declare class PatchesSync {
|
|
|
28
35
|
readonly onError: import("../event-signal.js").Signal<(error: Error, context?: {
|
|
29
36
|
docId?: string;
|
|
30
37
|
}) => void>;
|
|
31
|
-
constructor(patches: Patches, url: string,
|
|
38
|
+
constructor(patches: Patches, url: string, options?: PatchesSyncOptions | undefined);
|
|
32
39
|
/**
|
|
33
40
|
* Gets the current sync state.
|
|
34
41
|
*/
|
package/dist/net/PatchesSync.js
CHANGED
|
@@ -50,8 +50,8 @@ let PatchesSync = (() => {
|
|
|
50
50
|
let _syncDoc_decorators;
|
|
51
51
|
let __receiveCommittedChanges_decorators;
|
|
52
52
|
return _a = class PatchesSync {
|
|
53
|
-
constructor(patches, url,
|
|
54
|
-
this.
|
|
53
|
+
constructor(patches, url, options) {
|
|
54
|
+
this.options = (__runInitializers(this, _instanceExtraInitializers), options);
|
|
55
55
|
this._state = { online: false, connected: false, syncing: null };
|
|
56
56
|
/**
|
|
57
57
|
* Signal emitted when the sync state changes.
|
|
@@ -64,7 +64,7 @@ let PatchesSync = (() => {
|
|
|
64
64
|
this.patches = patches;
|
|
65
65
|
this.store = patches.store;
|
|
66
66
|
this.maxPayloadBytes = patches.docOptions?.maxPayloadBytes;
|
|
67
|
-
this.ws = new PatchesWebSocket(url,
|
|
67
|
+
this.ws = new PatchesWebSocket(url, options?.websocket);
|
|
68
68
|
this._state.online = onlineState.isOnline;
|
|
69
69
|
this.trackedDocs = new Set(patches.trackedDocs);
|
|
70
70
|
// --- Event Listeners ---
|
|
@@ -131,7 +131,10 @@ let PatchesSync = (() => {
|
|
|
131
131
|
// Subscribe to active docs
|
|
132
132
|
if (activeDocIds.length > 0) {
|
|
133
133
|
try {
|
|
134
|
-
|
|
134
|
+
const subscribeIds = this.options?.subscribeFilter?.(activeDocIds) || activeDocIds;
|
|
135
|
+
if (subscribeIds.length) {
|
|
136
|
+
await this.ws.subscribe(subscribeIds);
|
|
137
|
+
}
|
|
135
138
|
}
|
|
136
139
|
catch (err) {
|
|
137
140
|
console.warn('Error subscribing to active docs during sync:', err);
|
|
@@ -338,9 +341,17 @@ let PatchesSync = (() => {
|
|
|
338
341
|
if (!newIds.length)
|
|
339
342
|
return;
|
|
340
343
|
newIds.forEach(id => this.trackedDocs.add(id));
|
|
344
|
+
let subscribeIds = newIds;
|
|
345
|
+
// If a subscribe filter is provided, filter out docs that are already tracked
|
|
346
|
+
if (this.options?.subscribeFilter) {
|
|
347
|
+
const alreadyTracked = this.options.subscribeFilter([...this.trackedDocs]);
|
|
348
|
+
subscribeIds = subscribeIds.filter(id => !alreadyTracked.includes(id));
|
|
349
|
+
}
|
|
341
350
|
if (this.state.connected) {
|
|
342
351
|
try {
|
|
343
|
-
|
|
352
|
+
if (subscribeIds.length) {
|
|
353
|
+
await this.ws.subscribe(subscribeIds);
|
|
354
|
+
}
|
|
344
355
|
// Trigger sync for newly tracked docs immediately
|
|
345
356
|
await Promise.all(newIds.map(id => this.syncDoc(id)));
|
|
346
357
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JSONPatch } from '../json-patch/JSONPatch.js';
|
|
2
|
-
import type { Change, EditableVersionMetadata, PatchesState } from '../types.js';
|
|
2
|
+
import type { Change, DeepRequired, EditableVersionMetadata, PatchesState } from '../types.js';
|
|
3
3
|
import type { PatchesStoreBackend } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Configuration options for the PatchesServer.
|
|
@@ -61,7 +61,7 @@ export declare class PatchesServer {
|
|
|
61
61
|
* @param mutator
|
|
62
62
|
* @returns
|
|
63
63
|
*/
|
|
64
|
-
change<T = Record<string, any>>(docId: string, mutator: (draft: T
|
|
64
|
+
change<T = Record<string, any>>(docId: string, mutator: (draft: DeepRequired<T>, patch: JSONPatch) => void, metadata?: Record<string, any>): Promise<Change | null>;
|
|
65
65
|
/**
|
|
66
66
|
* Deletes a document.
|
|
67
67
|
* @param docId The document ID.
|
package/dist/types.d.ts
CHANGED
|
@@ -124,4 +124,14 @@ export interface ListVersionsOptions {
|
|
|
124
124
|
/** Filter by the group ID (branch ID or offline batch ID). */
|
|
125
125
|
groupId?: string;
|
|
126
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Makes optional object properties required for Proxies that allow setting deep properties.
|
|
129
|
+
*/
|
|
130
|
+
export type DeepRequired<T> = {
|
|
131
|
+
[P in keyof T as undefined extends T[P] ? never : P]: T[P] extends object ? DeepRequired<T[P]> : T[P];
|
|
132
|
+
} & {
|
|
133
|
+
[P in keyof T as undefined extends T[P] ? T[P] extends object | undefined ? T[P] extends Function | Date | RegExp | Array<any> | null | undefined ? never : P : never : never]-?: T[P] extends object | undefined ? DeepRequired<T[P]> : T[P];
|
|
134
|
+
} & {
|
|
135
|
+
[P in keyof T as undefined extends T[P] ? T[P] extends object | undefined ? T[P] extends Function | Date | RegExp | Array<any> | null | undefined ? P : never : P : never]?: T[P];
|
|
136
|
+
};
|
|
127
137
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dabble/patches",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
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": {
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"prepare": "npm run build",
|
|
57
57
|
"test": "vitest run",
|
|
58
58
|
"tdd": "vitest",
|
|
59
|
+
"format": "prettier --write src/",
|
|
60
|
+
"format:check": "prettier --check src/",
|
|
59
61
|
"lint": "eslint src tests",
|
|
60
62
|
"lint:fix": "eslint src tests --fix"
|
|
61
63
|
},
|
|
@@ -67,16 +69,16 @@
|
|
|
67
69
|
"simplified-concurrency": "^0.2.0"
|
|
68
70
|
},
|
|
69
71
|
"devDependencies": {
|
|
70
|
-
"@sveltejs/package": "^2.
|
|
72
|
+
"@sveltejs/package": "^2.5.0",
|
|
71
73
|
"@types/simple-peer": "^9.11.8",
|
|
72
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
73
|
-
"@typescript-eslint/parser": "^8.
|
|
74
|
-
"eslint": "^9.
|
|
75
|
-
"fake-indexeddb": "^6.
|
|
76
|
-
"prettier": "^3.
|
|
77
|
-
"typescript": "^5.
|
|
78
|
-
"vite": "^
|
|
79
|
-
"vite-plugin-dts": "^4.5.
|
|
80
|
-
"vitest": "^3.
|
|
74
|
+
"@typescript-eslint/eslint-plugin": "^8.42.0",
|
|
75
|
+
"@typescript-eslint/parser": "^8.42.0",
|
|
76
|
+
"eslint": "^9.35.0",
|
|
77
|
+
"fake-indexeddb": "^6.2.2",
|
|
78
|
+
"prettier": "^3.6.2",
|
|
79
|
+
"typescript": "^5.9.2",
|
|
80
|
+
"vite": "^7.1.4",
|
|
81
|
+
"vite-plugin-dts": "^4.5.4",
|
|
82
|
+
"vitest": "^3.2.4"
|
|
81
83
|
}
|
|
82
84
|
}
|