@dabble/patches 0.2.9 → 0.2.10
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/event-signal.js +3 -3
- package/package.json +1 -1
- package/dist/json-patch/patchProxy.d.ts +0 -41
- package/dist/json-patch/patchProxy.js +0 -125
- package/dist/json-patch/state.d.ts +0 -2
- package/dist/json-patch/state.js +0 -8
- package/dist/json-patch/transformPatch.d.ts +0 -19
- package/dist/json-patch/transformPatch.js +0 -37
- package/dist/json-patch/types.d.ts +0 -52
- package/dist/json-patch/types.js +0 -1
- package/dist/json-patch/utils/deepEqual.d.ts +0 -1
- package/dist/json-patch/utils/deepEqual.js +0 -33
- package/dist/json-patch/utils/exit.d.ts +0 -2
- package/dist/json-patch/utils/exit.js +0 -4
- package/dist/json-patch/utils/get.d.ts +0 -2
- package/dist/json-patch/utils/get.js +0 -6
- package/dist/json-patch/utils/getOpData.d.ts +0 -2
- package/dist/json-patch/utils/getOpData.js +0 -10
- package/dist/json-patch/utils/getType.d.ts +0 -3
- package/dist/json-patch/utils/getType.js +0 -6
- package/dist/json-patch/utils/index.d.ts +0 -14
- package/dist/json-patch/utils/index.js +0 -14
- package/dist/json-patch/utils/log.d.ts +0 -2
- package/dist/json-patch/utils/log.js +0 -7
- package/dist/json-patch/utils/ops.d.ts +0 -14
- package/dist/json-patch/utils/ops.js +0 -103
- package/dist/json-patch/utils/paths.d.ts +0 -9
- package/dist/json-patch/utils/paths.js +0 -53
- package/dist/json-patch/utils/pluck.d.ts +0 -5
- package/dist/json-patch/utils/pluck.js +0 -30
- package/dist/json-patch/utils/shallowCopy.d.ts +0 -1
- package/dist/json-patch/utils/shallowCopy.js +0 -20
- package/dist/json-patch/utils/softWrites.d.ts +0 -7
- package/dist/json-patch/utils/softWrites.js +0 -18
- package/dist/json-patch/utils/toArrayIndex.d.ts +0 -1
- package/dist/json-patch/utils/toArrayIndex.js +0 -12
- package/dist/json-patch/utils/toKeys.d.ts +0 -1
- package/dist/json-patch/utils/toKeys.js +0 -15
- package/dist/json-patch/utils/updateArrayIndexes.d.ts +0 -5
- package/dist/json-patch/utils/updateArrayIndexes.js +0 -38
- package/dist/json-patch/utils/updateArrayPath.d.ts +0 -5
- package/dist/json-patch/utils/updateArrayPath.js +0 -45
- package/dist/net/AbstractTransport.d.ts +0 -47
- package/dist/net/AbstractTransport.js +0 -39
- package/dist/net/PatchesSync.d.ts +0 -47
- package/dist/net/PatchesSync.js +0 -289
- package/dist/net/index.d.ts +0 -9
- package/dist/net/index.js +0 -7
- package/dist/net/protocol/JSONRPCClient.d.ts +0 -55
- package/dist/net/protocol/JSONRPCClient.js +0 -106
- package/dist/net/protocol/types.d.ts +0 -142
- package/dist/net/protocol/types.js +0 -1
- package/dist/net/types.d.ts +0 -6
- package/dist/net/types.js +0 -1
- package/dist/net/webrtc/WebRTCAwareness.d.ts +0 -81
- package/dist/net/webrtc/WebRTCAwareness.js +0 -119
- package/dist/net/webrtc/WebRTCTransport.d.ts +0 -80
- package/dist/net/webrtc/WebRTCTransport.js +0 -157
- package/dist/net/websocket/PatchesWebSocket.d.ts +0 -107
- package/dist/net/websocket/PatchesWebSocket.js +0 -144
- package/dist/net/websocket/SignalingService.d.ts +0 -91
- package/dist/net/websocket/SignalingService.js +0 -140
- package/dist/net/websocket/WebSocketTransport.d.ts +0 -58
- package/dist/net/websocket/WebSocketTransport.js +0 -190
- package/dist/net/websocket/onlineState.d.ts +0 -9
- package/dist/net/websocket/onlineState.js +0 -18
- package/dist/persist/InMemoryStore.d.ts +0 -23
- package/dist/persist/InMemoryStore.js +0 -103
- package/dist/persist/IndexedDBStore.d.ts +0 -81
- package/dist/persist/IndexedDBStore.js +0 -377
- package/dist/persist/PatchesStore.d.ts +0 -38
- package/dist/persist/PatchesStore.js +0 -1
- package/dist/persist/index.d.ts +0 -3
- package/dist/persist/index.js +0 -3
- package/dist/server/PatchesBranchManager.d.ts +0 -40
- package/dist/server/PatchesBranchManager.js +0 -138
- package/dist/server/PatchesHistoryManager.d.ts +0 -43
- package/dist/server/PatchesHistoryManager.js +0 -59
- package/dist/server/PatchesServer.d.ts +0 -129
- package/dist/server/PatchesServer.js +0 -358
- package/dist/server/index.d.ts +0 -3
- package/dist/server/index.js +0 -3
- package/dist/types.d.ts +0 -164
- package/dist/types.js +0 -1
- package/dist/utils/batching.d.ts +0 -5
- package/dist/utils/batching.js +0 -38
- package/dist/utils.d.ts +0 -36
- package/dist/utils.js +0 -103
package/dist/event-signal.js
CHANGED
|
@@ -26,15 +26,15 @@ export function signal() {
|
|
|
26
26
|
}
|
|
27
27
|
signal.emit = async (...args) => {
|
|
28
28
|
const listeners = args[0] instanceof Error ? errorListeners : subscribers;
|
|
29
|
-
Array.from(listeners).map(ref => {
|
|
29
|
+
await Promise.all(Array.from(listeners).map(ref => {
|
|
30
30
|
const listener = ref.deref();
|
|
31
31
|
if (listener) {
|
|
32
|
-
listener(...args);
|
|
32
|
+
return listener(...args);
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
35
|
listeners.delete(ref);
|
|
36
36
|
}
|
|
37
|
-
});
|
|
37
|
+
}));
|
|
38
38
|
};
|
|
39
39
|
signal.error = (errorListener) => {
|
|
40
40
|
errorListeners.add(new WeakRef(errorListener));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dabble/patches",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
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,41 +0,0 @@
|
|
|
1
|
-
import { JSONPatch } from './JSONPatch';
|
|
2
|
-
/**
|
|
3
|
-
* Creates a proxy object that can be used in two ways:
|
|
4
|
-
*
|
|
5
|
-
* 1. **Path Generation:** When used without a `JSONPatch` instance, accessing properties
|
|
6
|
-
* on the proxy generates a JSON Pointer path string via `toString()`. This allows
|
|
7
|
-
* for type-safe path creation when using `JSONPatch` methods directly.
|
|
8
|
-
* ```ts
|
|
9
|
-
* const patch = new JSONPatch();
|
|
10
|
-
* const proxy = createPatchProxy<MyType>();
|
|
11
|
-
* patch.text(proxy.content, new Delta().insert('text')); // Path is '/content'
|
|
12
|
-
* patch.increment(proxy.counter, 5); // Path is '/counter'
|
|
13
|
-
* ```
|
|
14
|
-
*
|
|
15
|
-
* 2. **Automatic Patch Generation:** When created with a target object and a `JSONPatch`
|
|
16
|
-
* instance, modifying the proxy (setting properties, calling array methods like
|
|
17
|
-
* `push`, `splice`, etc.) automatically generates the corresponding JSON Patch
|
|
18
|
-
* operations and adds them to the provided `patch` instance.
|
|
19
|
-
* ```ts
|
|
20
|
-
* const patch = new JSONPatch();
|
|
21
|
-
* const myObj = { name: { first: 'Alice' }, tags: ['a'] };
|
|
22
|
-
* const proxy = createPatchProxy(myObj, patch);
|
|
23
|
-
* proxy.name.first = 'Bob'; // Generates replace op
|
|
24
|
-
* proxy.tags.push('b'); // Generates add op
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* The proxy behaves like the original value in most contexts due to the `valueOf` trap.
|
|
28
|
-
* For optional properties, use the non-null assertion operator (!) when setting values:
|
|
29
|
-
* ```ts
|
|
30
|
-
* interface User { middleName?: string }
|
|
31
|
-
* const proxy = createPatchProxy<User>(user, patch);
|
|
32
|
-
* proxy.middleName! = 'John'; // Assert middleName exists before setting
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* @template T The type of the object to proxy.
|
|
36
|
-
* @param target The target object (required for automatic patch generation mode).
|
|
37
|
-
* @param patch The `JSONPatch` instance to add generated operations to (required for automatic patch generation mode).
|
|
38
|
-
* @returns A proxy object of type T.
|
|
39
|
-
*/
|
|
40
|
-
export declare function createPatchProxy<T>(): T;
|
|
41
|
-
export declare function createPatchProxy<T>(target: T, patch: JSONPatch): T;
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
// We use a function as the target so that `push` and other array methods can be called without error.
|
|
2
|
-
const proxyFodder = {};
|
|
3
|
-
export function createPatchProxy(target, patch) {
|
|
4
|
-
// Call the internal implementation
|
|
5
|
-
return createPatchProxyInternal(target, patch);
|
|
6
|
-
}
|
|
7
|
-
// Internal implementation with the path parameter
|
|
8
|
-
function createPatchProxyInternal(target, patch, path = '') {
|
|
9
|
-
// Always use an empty function as the proxy target
|
|
10
|
-
// This allows us to proxy any type of value, including primitives and undefined,
|
|
11
|
-
// and enables calling array methods like push/splice directly on array proxies.
|
|
12
|
-
return new Proxy(proxyFodder, {
|
|
13
|
-
get(_, prop) {
|
|
14
|
-
// Return the value directly for symbol properties (not relevant for JSON paths)
|
|
15
|
-
if (typeof prop === 'symbol') {
|
|
16
|
-
return target?.[prop];
|
|
17
|
-
}
|
|
18
|
-
// Handle toString specially to make properties work as PathLike
|
|
19
|
-
if (prop === 'toString') {
|
|
20
|
-
return function () {
|
|
21
|
-
return path;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
// Handle valueOf to make the proxy behave like the original value in most contexts
|
|
25
|
-
if (prop === 'valueOf') {
|
|
26
|
-
return function () {
|
|
27
|
-
return target;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
// --- Array Method Interception ---
|
|
31
|
-
if (Array.isArray(target)) {
|
|
32
|
-
switch (prop) {
|
|
33
|
-
case 'push':
|
|
34
|
-
return (...items) => {
|
|
35
|
-
const index = target.length;
|
|
36
|
-
for (let i = 0; i < items.length; i++) {
|
|
37
|
-
patch?.add(`${path}/${index + i}`, items[i]);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
case 'pop':
|
|
41
|
-
return () => {
|
|
42
|
-
const index = target.length - 1;
|
|
43
|
-
if (index >= 0) {
|
|
44
|
-
patch?.remove(`${path}/${index}`);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
case 'shift':
|
|
48
|
-
return () => {
|
|
49
|
-
if (target.length > 0) {
|
|
50
|
-
patch?.remove(`${path}/0`);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
case 'unshift':
|
|
54
|
-
return (...items) => {
|
|
55
|
-
for (let i = 0; i < items.length; i++) {
|
|
56
|
-
patch?.add(`${path}/${i}`, items[i]);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
case 'splice':
|
|
60
|
-
return (start, deleteCount, ...items) => {
|
|
61
|
-
const actualStart = start < 0 ? Math.max(target.length + start, 0) : Math.min(start, target.length);
|
|
62
|
-
const actualDeleteCount = Math.min(Math.max(deleteCount === undefined ? target.length - actualStart : deleteCount, 0), target.length - actualStart);
|
|
63
|
-
// Remove deleted elements
|
|
64
|
-
for (let i = 0; i < actualDeleteCount; i++) {
|
|
65
|
-
patch?.remove(`${path}/${actualStart}`); // Path automatically adjusts for subsequent removes
|
|
66
|
-
}
|
|
67
|
-
// Add new elements
|
|
68
|
-
for (let i = 0; i < items.length; i++) {
|
|
69
|
-
patch?.add(`${path}/${actualStart + i}`, items[i]);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// --- End Array Method Interception ---
|
|
75
|
-
// Create a proxy for the property value if it's not an intercepted array method
|
|
76
|
-
// This handles objects, primitives, and undefined values uniformly
|
|
77
|
-
// Call the internal implementation recursively
|
|
78
|
-
return createPatchProxyInternal(target?.[prop], patch, `${path}/${String(prop)}`);
|
|
79
|
-
},
|
|
80
|
-
set(_, prop, value) {
|
|
81
|
-
// Ignore setting the 'length' property on arrays directly
|
|
82
|
-
if (Array.isArray(target) && prop === 'length') {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
if (target?.[prop] === value)
|
|
86
|
-
return true;
|
|
87
|
-
const patchPath = `${path}/${String(prop)}`;
|
|
88
|
-
if (value === undefined) {
|
|
89
|
-
patch?.remove(patchPath);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
patch?.replace(patchPath, value);
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
},
|
|
96
|
-
deleteProperty(_, prop) {
|
|
97
|
-
if (target == null || prop in target) {
|
|
98
|
-
patch?.remove(`${path}/${String(prop)}`);
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
},
|
|
102
|
-
// Make the proxy appear to be the same type as the target
|
|
103
|
-
getPrototypeOf() {
|
|
104
|
-
return Object.getPrototypeOf(target);
|
|
105
|
-
},
|
|
106
|
-
// Support instanceof checks
|
|
107
|
-
isExtensible() {
|
|
108
|
-
return target != null && Object.isExtensible(target);
|
|
109
|
-
},
|
|
110
|
-
// Support Object.keys and other enumeration methods
|
|
111
|
-
ownKeys() {
|
|
112
|
-
return target != null && typeof target === 'object' ? Reflect.ownKeys(target) : [];
|
|
113
|
-
},
|
|
114
|
-
// Support property descriptor access
|
|
115
|
-
getOwnPropertyDescriptor(_, prop) {
|
|
116
|
-
if (target == null || typeof target !== 'object')
|
|
117
|
-
return undefined;
|
|
118
|
-
return Object.getOwnPropertyDescriptor(target, prop);
|
|
119
|
-
},
|
|
120
|
-
// Support Object.hasOwnProperty
|
|
121
|
-
has(_, prop) {
|
|
122
|
-
return target != null && typeof target === 'object' && prop in target;
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
}
|
package/dist/json-patch/state.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Based on work from
|
|
3
|
-
* https://github.com/Palindrom/JSONPatchOT
|
|
4
|
-
* (c) 2017 Tomek Wytrebowicz
|
|
5
|
-
*
|
|
6
|
-
* MIT license
|
|
7
|
-
* (c) 2022 Jacob Wright
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* WARNING: using /array/- syntax to indicate the end of the array makes it impossible to transform arrays correctly in
|
|
11
|
-
* all situaions. Please avoid using this syntax when using Operational Transformations.
|
|
12
|
-
*/
|
|
13
|
-
import type { JSONPatchOp, JSONPatchOpHandlerMap } from './types.js';
|
|
14
|
-
/**
|
|
15
|
-
* Transform an array of JSON Patch operations against another array of JSON Patch operations. Returns a new array with
|
|
16
|
-
* transformed operations. Operations that change are cloned, making the results of this function immutable.
|
|
17
|
-
* `otherOps` are transformed over `thisOps` with thisOps considered to have happened first.
|
|
18
|
-
*/
|
|
19
|
-
export declare function transformPatch(obj: any, thisOps: JSONPatchOp[], otherOps: JSONPatchOp[], custom?: JSONPatchOpHandlerMap): JSONPatchOp[];
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Based on work from
|
|
3
|
-
* https://github.com/Palindrom/JSONPatchOT
|
|
4
|
-
* (c) 2017 Tomek Wytrebowicz
|
|
5
|
-
*
|
|
6
|
-
* MIT license
|
|
7
|
-
* (c) 2022 Jacob Wright
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* WARNING: using /array/- syntax to indicate the end of the array makes it impossible to transform arrays correctly in
|
|
11
|
-
* all situaions. Please avoid using this syntax when using Operational Transformations.
|
|
12
|
-
*/
|
|
13
|
-
import { getTypes } from './ops/index.js';
|
|
14
|
-
import { runWithObject } from './state.js';
|
|
15
|
-
import { getType } from './utils/getType.js';
|
|
16
|
-
import { log } from './utils/log.js';
|
|
17
|
-
/**
|
|
18
|
-
* Transform an array of JSON Patch operations against another array of JSON Patch operations. Returns a new array with
|
|
19
|
-
* transformed operations. Operations that change are cloned, making the results of this function immutable.
|
|
20
|
-
* `otherOps` are transformed over `thisOps` with thisOps considered to have happened first.
|
|
21
|
-
*/
|
|
22
|
-
export function transformPatch(obj, thisOps, otherOps, custom) {
|
|
23
|
-
const types = getTypes(custom);
|
|
24
|
-
return runWithObject(obj, types, false, state => {
|
|
25
|
-
return thisOps.reduce((otherOps, thisOp) => {
|
|
26
|
-
// transform ops with patch operation
|
|
27
|
-
const handler = getType(state, thisOp)?.transform;
|
|
28
|
-
if (typeof handler === 'function') {
|
|
29
|
-
otherOps = handler(state, thisOp, otherOps);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
log('No function to transform against for', thisOp.op);
|
|
33
|
-
}
|
|
34
|
-
return otherOps;
|
|
35
|
-
}, otherOps);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
export interface JSONPatchOpHandler {
|
|
2
|
-
like: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';
|
|
3
|
-
apply(state: State, path: string, valueOrFrom: any): string | void;
|
|
4
|
-
transform(state: State, other: JSONPatchOp, ops: JSONPatchOp[]): JSONPatchOp[];
|
|
5
|
-
invert(state: State, op: JSONPatchOp, value: any, changedObj: any, isIndex: boolean): JSONPatchOp;
|
|
6
|
-
compose?(state: State, value1: any, value2: any): any;
|
|
7
|
-
}
|
|
8
|
-
export interface JSONPatchOpHandlerMap {
|
|
9
|
-
[key: string]: JSONPatchOpHandler;
|
|
10
|
-
}
|
|
11
|
-
export interface ApplyJSONPatchOptions {
|
|
12
|
-
/**
|
|
13
|
-
* Do not reject patches if error occurs (partial patching)
|
|
14
|
-
*/
|
|
15
|
-
partial?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Throw an exception if an error occurs when patching
|
|
18
|
-
*/
|
|
19
|
-
strict?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Stop on error and return the original object (without throwing an exception)
|
|
22
|
-
*/
|
|
23
|
-
rigid?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Don't log errors when they occurs during patching, if strict is not true, errors will be logged if this is false
|
|
26
|
-
*/
|
|
27
|
-
silent?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Saves the patch that caused the error to this property of the options object
|
|
30
|
-
*/
|
|
31
|
-
error?: JSONPatchOp;
|
|
32
|
-
/**
|
|
33
|
-
* Apply changes at a given path prefix
|
|
34
|
-
*/
|
|
35
|
-
atPath?: string;
|
|
36
|
-
}
|
|
37
|
-
export interface JSONPatchOp {
|
|
38
|
-
op: string;
|
|
39
|
-
path: string;
|
|
40
|
-
from?: string;
|
|
41
|
-
value?: any;
|
|
42
|
-
soft?: boolean;
|
|
43
|
-
}
|
|
44
|
-
export interface Root {
|
|
45
|
-
'': any;
|
|
46
|
-
}
|
|
47
|
-
export type State = {
|
|
48
|
-
root: Root;
|
|
49
|
-
types: JSONPatchOpHandlerMap;
|
|
50
|
-
cache: Set<any> | null;
|
|
51
|
-
};
|
|
52
|
-
export type Runner = (state: State) => any;
|
package/dist/json-patch/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function deepEqual(a: any, b: any): boolean;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export function deepEqual(a, b) {
|
|
2
|
-
if (a === b) {
|
|
3
|
-
return true;
|
|
4
|
-
}
|
|
5
|
-
if (!(a && b) || typeof a !== 'object' || typeof b !== 'object') {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
if (a.length !== b.length) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
if (Array.isArray(a)) {
|
|
12
|
-
if (!Array.isArray(b)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
for (let i = 0, imax = a.length; i < imax; i++) {
|
|
16
|
-
if (!deepEqual(a[i], b[i])) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
const aKeys = Object.keys(a);
|
|
23
|
-
if (aKeys.length !== Object.keys(b).length) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
for (let j = 0, jmax = aKeys.length; j < jmax; j++) {
|
|
27
|
-
const key = aKeys[j];
|
|
28
|
-
if (!deepEqual(a[key], b[key])) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { EMPTY, pluck } from './pluck.js';
|
|
2
|
-
import { toKeys } from './toKeys.js';
|
|
3
|
-
export function getOpData(state, path, createMissingObjects) {
|
|
4
|
-
const keys = toKeys(path);
|
|
5
|
-
const lastKey = keys[keys.length - 1];
|
|
6
|
-
let target = pluck(state, keys);
|
|
7
|
-
if (createMissingObjects)
|
|
8
|
-
target = target || EMPTY;
|
|
9
|
-
return [keys, lastKey, target];
|
|
10
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { JSONPatchOp, State } from '../types.js';
|
|
2
|
-
export declare function getType(state: State, patch: JSONPatchOp): import("../types.js").JSONPatchOpHandler;
|
|
3
|
-
export declare function getTypeLike(state: State, patch: JSONPatchOp): "replace" | "add" | "remove" | "move" | "copy" | "test";
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export * from './deepEqual.js';
|
|
2
|
-
export * from './get.js';
|
|
3
|
-
export * from './getOpData.js';
|
|
4
|
-
export * from './getType.js';
|
|
5
|
-
export * from './log.js';
|
|
6
|
-
export * from './ops.js';
|
|
7
|
-
export * from './paths.js';
|
|
8
|
-
export * from './pluck.js';
|
|
9
|
-
export * from './shallowCopy.js';
|
|
10
|
-
export * from './softWrites.js';
|
|
11
|
-
export * from './toArrayIndex.js';
|
|
12
|
-
export * from './toKeys.js';
|
|
13
|
-
export * from './updateArrayIndexes.js';
|
|
14
|
-
export * from './updateArrayPath.js';
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export * from './deepEqual.js';
|
|
2
|
-
export * from './get.js';
|
|
3
|
-
export * from './getOpData.js';
|
|
4
|
-
export * from './getType.js';
|
|
5
|
-
export * from './log.js';
|
|
6
|
-
export * from './ops.js';
|
|
7
|
-
export * from './paths.js';
|
|
8
|
-
export * from './pluck.js';
|
|
9
|
-
export * from './shallowCopy.js';
|
|
10
|
-
export * from './softWrites.js';
|
|
11
|
-
export * from './toArrayIndex.js';
|
|
12
|
-
export * from './toKeys.js';
|
|
13
|
-
export * from './updateArrayIndexes.js';
|
|
14
|
-
export * from './updateArrayPath.js';
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { JSONPatchOp, State } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Check whether this operation is an add operation of some sort (add, copy, move).
|
|
4
|
-
*/
|
|
5
|
-
export declare function isAdd(state: State, op: JSONPatchOp, pathName: 'from' | 'path'): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Transforms an array of ops, returning the original if there is no change, filtering out ops that are dropped.
|
|
8
|
-
*/
|
|
9
|
-
export declare function mapAndFilterOps(ops: JSONPatchOp[], iterator: (op: JSONPatchOp, index: number, breakAfter: (keepRest?: boolean) => {}) => JSONPatchOp | JSONPatchOp[] | null): JSONPatchOp[];
|
|
10
|
-
/**
|
|
11
|
-
* Remove operations that apply to a value which was removed.
|
|
12
|
-
*/
|
|
13
|
-
export declare function updateRemovedOps(state: State, thisPath: string, otherOps: JSONPatchOp[], isRemove?: boolean, updatableObject?: boolean, opOp?: string, customHandler?: (op: JSONPatchOp) => any): JSONPatchOp[];
|
|
14
|
-
export declare function transformRemove(state: State, thisPath: string, otherOps: JSONPatchOp[], isRemove?: boolean): JSONPatchOp[];
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { getTypeLike } from './getType.js';
|
|
2
|
-
import { log } from './log.js';
|
|
3
|
-
import { isArrayPath } from './paths.js';
|
|
4
|
-
import { updateArrayIndexes } from './updateArrayIndexes.js';
|
|
5
|
-
/**
|
|
6
|
-
* Check whether this operation is an add operation of some sort (add, copy, move).
|
|
7
|
-
*/
|
|
8
|
-
export function isAdd(state, op, pathName) {
|
|
9
|
-
const like = getTypeLike(state, op);
|
|
10
|
-
return (like === 'add' || like === 'copy' || like === 'move') && pathName === 'path';
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Transforms an array of ops, returning the original if there is no change, filtering out ops that are dropped.
|
|
14
|
-
*/
|
|
15
|
-
export function mapAndFilterOps(ops, iterator) {
|
|
16
|
-
let changed = false;
|
|
17
|
-
const mapped = [];
|
|
18
|
-
let shouldBreak = false;
|
|
19
|
-
let keepRest;
|
|
20
|
-
const breakAfter = (keep) => (shouldBreak = true) && (keepRest = keep);
|
|
21
|
-
for (let i = 0; i < ops.length; i++) {
|
|
22
|
-
const original = ops[i];
|
|
23
|
-
// If an op was copied or moved to the same path, it is a no-op and should be removed
|
|
24
|
-
if (original.from === original.path) {
|
|
25
|
-
if (!changed)
|
|
26
|
-
changed = true;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
let value = iterator(original, i, breakAfter);
|
|
30
|
-
if (value && !Array.isArray(value) && value.from === value.path)
|
|
31
|
-
value = null;
|
|
32
|
-
if (!changed && value !== original)
|
|
33
|
-
changed = true;
|
|
34
|
-
if (Array.isArray(value))
|
|
35
|
-
mapped.push(...value);
|
|
36
|
-
else if (value)
|
|
37
|
-
mapped.push(value);
|
|
38
|
-
if (shouldBreak) {
|
|
39
|
-
if (keepRest)
|
|
40
|
-
mapped.push(...ops.slice(i + 1));
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return changed ? mapped : ops;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Remove operations that apply to a value which was removed.
|
|
48
|
-
*/
|
|
49
|
-
export function updateRemovedOps(state, thisPath, otherOps, isRemove = false, updatableObject = false, opOp, customHandler) {
|
|
50
|
-
const softPrefixes = new Set();
|
|
51
|
-
return mapAndFilterOps(otherOps, (op, index, breakAfter) => {
|
|
52
|
-
const opLike = getTypeLike(state, op);
|
|
53
|
-
const canMergeCustom = customHandler && opOp === op.op;
|
|
54
|
-
if (thisPath === op.path && opLike !== 'remove' && !canMergeCustom && !op.soft) {
|
|
55
|
-
// Once an operation sets this value again, we can assume the following ops were working on that and not the
|
|
56
|
-
// old value so they can be kept
|
|
57
|
-
if (op.op !== 'test') {
|
|
58
|
-
breakAfter(true); // stop and keep the remaining ops as-is
|
|
59
|
-
}
|
|
60
|
-
return op;
|
|
61
|
-
}
|
|
62
|
-
const { path, from } = op;
|
|
63
|
-
if (path === thisPath && canMergeCustom) {
|
|
64
|
-
const customOp = customHandler(op);
|
|
65
|
-
if (customOp)
|
|
66
|
-
return customOp;
|
|
67
|
-
}
|
|
68
|
-
if (isRemove && !updatableObject && from === thisPath) {
|
|
69
|
-
// Because of the check above, moves and copies will only hit here when the "from" field matches
|
|
70
|
-
if (opLike === 'move') {
|
|
71
|
-
// We need the rest of the otherOps to be adjusted against this "move"
|
|
72
|
-
breakAfter();
|
|
73
|
-
return transformRemove(state, op.path, otherOps.slice(index + 1));
|
|
74
|
-
}
|
|
75
|
-
else if (opLike === 'copy') {
|
|
76
|
-
// We need future ops on the copied object to be removed
|
|
77
|
-
breakAfter();
|
|
78
|
-
let rest = transformRemove(state, thisPath, otherOps.slice(index + 1));
|
|
79
|
-
rest = transformRemove(state, op.path, rest);
|
|
80
|
-
return rest;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (op.soft && path === thisPath) {
|
|
84
|
-
softPrefixes.add(path);
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
const samePath = (!updatableObject && path === thisPath) || (!softPrefixes.has(thisPath) && path.startsWith(`${thisPath}/`));
|
|
88
|
-
const sameFrom = (!updatableObject && from === thisPath) || (!softPrefixes.has(thisPath) && from?.startsWith(`${thisPath}/`));
|
|
89
|
-
if (samePath || sameFrom) {
|
|
90
|
-
log('Removing', op);
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
return op;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
export function transformRemove(state, thisPath, otherOps, isRemove) {
|
|
97
|
-
if (isArrayPath(thisPath, state)) {
|
|
98
|
-
return updateArrayIndexes(state, thisPath, otherOps, -1, isRemove);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
return updateRemovedOps(state, thisPath, otherOps, isRemove);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { State } from '../types.js';
|
|
2
|
-
export declare function getPrefix(path: string): string;
|
|
3
|
-
export declare function getProp(path: string): string;
|
|
4
|
-
export declare function getPrefixAndProp(path: string): [string, string];
|
|
5
|
-
export declare function getPropAfter(path: string, index: number): string;
|
|
6
|
-
export declare function isArrayPath(path: string, state?: State): boolean;
|
|
7
|
-
export declare function getArrayPrefixAndIndex(state: State, path: string, pathLength?: number): [string, number];
|
|
8
|
-
export declare function getArrayIndex(state: State, path: string, pathLength?: number): number;
|
|
9
|
-
export declare function getIndexAndEnd(state: State, path: string | undefined, maxLength: number): number[];
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { getOpData } from './getOpData.js';
|
|
2
|
-
const arrayPathExp = /\/(0|[1-9]\d*)$/;
|
|
3
|
-
const EMPTY = [];
|
|
4
|
-
export function getPrefix(path) {
|
|
5
|
-
const lastSlash = path.lastIndexOf('/');
|
|
6
|
-
return path.slice(0, lastSlash + 1);
|
|
7
|
-
}
|
|
8
|
-
export function getProp(path) {
|
|
9
|
-
const lastSlash = path.lastIndexOf('/');
|
|
10
|
-
return path.slice(lastSlash + 1);
|
|
11
|
-
}
|
|
12
|
-
export function getPrefixAndProp(path) {
|
|
13
|
-
const prefix = getPrefix(path);
|
|
14
|
-
return [prefix, path.slice(prefix.length)];
|
|
15
|
-
}
|
|
16
|
-
export function getPropAfter(path, index) {
|
|
17
|
-
const lastSlash = path.indexOf('/', index);
|
|
18
|
-
return path.slice(index, lastSlash === -1 ? undefined : lastSlash);
|
|
19
|
-
}
|
|
20
|
-
export function isArrayPath(path, state) {
|
|
21
|
-
if (!arrayPathExp.test(path))
|
|
22
|
-
return false;
|
|
23
|
-
if (!state || !state.root || !state.root[''])
|
|
24
|
-
return true;
|
|
25
|
-
// Double-check if this is an array or not
|
|
26
|
-
const [_, __, target] = getOpData(state, path);
|
|
27
|
-
return Array.isArray(target) || target == null;
|
|
28
|
-
}
|
|
29
|
-
export function getArrayPrefixAndIndex(state, path, pathLength) {
|
|
30
|
-
if (pathLength)
|
|
31
|
-
path = path.slice(0, path.indexOf('/', pathLength));
|
|
32
|
-
if (!arrayPathExp.test(path))
|
|
33
|
-
return EMPTY;
|
|
34
|
-
const [_, __, target] = getOpData(state, path);
|
|
35
|
-
if (!Array.isArray(target))
|
|
36
|
-
return EMPTY;
|
|
37
|
-
const [prefix, indexStr] = getPrefixAndProp(path);
|
|
38
|
-
const index = parseInt(indexStr);
|
|
39
|
-
return [prefix, index];
|
|
40
|
-
}
|
|
41
|
-
export function getArrayIndex(state, path, pathLength) {
|
|
42
|
-
return getArrayPrefixAndIndex(state, path, pathLength)[1];
|
|
43
|
-
}
|
|
44
|
-
export function getIndexAndEnd(state, path, maxLength) {
|
|
45
|
-
if (!path)
|
|
46
|
-
return [];
|
|
47
|
-
const prop = getPropAfter(path, maxLength);
|
|
48
|
-
const end = maxLength + prop.length;
|
|
49
|
-
if (!isArrayPath(path.slice(0, end), state))
|
|
50
|
-
return [];
|
|
51
|
-
const index = parseInt(prop);
|
|
52
|
-
return [index, end];
|
|
53
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { State } from '../types.js';
|
|
2
|
-
export declare const EMPTY: {};
|
|
3
|
-
export declare function pluck(state: State, keys: string[]): any;
|
|
4
|
-
export declare function pluckWithShallowCopy(state: State, keys: string[], createMissingObjects?: boolean): any;
|
|
5
|
-
export declare function getValue(state: State, value: any, addKey?: string, addValue?: any): any;
|