@verdant-web/common 2.7.3 → 2.9.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/dist/esm/authz.js.map +1 -1
- package/dist/esm/baseline.d.ts +2 -1
- package/dist/esm/diffing.d.ts +40 -0
- package/dist/esm/diffing.js +317 -0
- package/dist/esm/diffing.js.map +1 -0
- package/dist/esm/diffing.test.d.ts +1 -0
- package/dist/esm/diffing.test.js +1680 -0
- package/dist/esm/diffing.test.js.map +1 -0
- package/dist/esm/index.d.ts +20 -19
- package/dist/esm/index.js +17 -16
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/oids.d.ts +5 -0
- package/dist/esm/oids.js +23 -1
- package/dist/esm/oids.js.map +1 -1
- package/dist/esm/operation.d.ts +11 -24
- package/dist/esm/operation.js +32 -270
- package/dist/esm/operation.js.map +1 -1
- package/dist/esm/operation.test.js +122 -592
- package/dist/esm/operation.test.js.map +1 -1
- package/dist/esm/patch.d.ts +19 -15
- package/dist/esm/patch.js +79 -18
- package/dist/esm/patch.js.map +1 -1
- package/dist/esm/schema/validation.d.ts +8 -1
- package/dist/esm/schema/validation.js +133 -63
- package/dist/esm/schema/validation.js.map +1 -1
- package/dist/esm/schema/validation.test.d.ts +1 -0
- package/dist/esm/schema/validation.test.js +60 -0
- package/dist/esm/schema/validation.test.js.map +1 -0
- package/dist/esm/timestamp.d.ts +1 -0
- package/dist/esm/timestamp.js +3 -0
- package/dist/esm/timestamp.js.map +1 -1
- package/dist/esm/undo.d.ts +2 -1
- package/dist/esm/undo.js +53 -146
- package/dist/esm/undo.js.map +1 -1
- package/dist/esm/undo.test.d.ts +1 -0
- package/dist/esm/undo.test.js +81 -0
- package/dist/esm/undo.test.js.map +1 -0
- package/package.json +1 -1
- package/src/authz.ts +2 -0
- package/src/baseline.ts +3 -1
- package/src/diffing.test.ts +1803 -0
- package/src/diffing.ts +402 -0
- package/src/index.ts +21 -20
- package/src/oids.ts +23 -1
- package/src/operation.test.ts +148 -623
- package/src/operation.ts +45 -378
- package/src/patch.ts +146 -14
- package/src/schema/validation.test.ts +66 -0
- package/src/schema/validation.ts +156 -73
- package/src/timestamp.ts +4 -1
- package/src/undo.test.ts +100 -0
- package/src/undo.ts +83 -144
package/dist/esm/undo.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { applyPatch } from './operation.js';
|
|
2
|
+
import { PatchCreator } from './patch.js';
|
|
3
|
+
import { isRef } from './refs.js';
|
|
2
4
|
import { cloneDeep } from './utils.js';
|
|
3
|
-
export function getUndoOperations(oid, initial, operations, getNow) {
|
|
5
|
+
export function getUndoOperations(oid, initial, operations, getNow, getSubId, authz) {
|
|
6
|
+
const patchCreator = new PatchCreator(getNow, getSubId);
|
|
4
7
|
if (initial === undefined || initial === null) {
|
|
5
8
|
// if the initial state is nothing, then the undo is to delete everything.
|
|
6
9
|
// there's nothing else to worry about!
|
|
@@ -11,6 +14,7 @@ export function getUndoOperations(oid, initial, operations, getNow) {
|
|
|
11
14
|
data: {
|
|
12
15
|
op: 'delete',
|
|
13
16
|
},
|
|
17
|
+
authz,
|
|
14
18
|
},
|
|
15
19
|
];
|
|
16
20
|
}
|
|
@@ -20,190 +24,93 @@ export function getUndoOperations(oid, initial, operations, getNow) {
|
|
|
20
24
|
let state = cloneDeep(initial);
|
|
21
25
|
const undoOperations = [];
|
|
22
26
|
for (const operation of operations) {
|
|
23
|
-
const undo = getUndoOperation(oid, state, operation,
|
|
27
|
+
const undo = getUndoOperation(oid, state, operation, patchCreator, authz);
|
|
24
28
|
undoOperations.unshift(...undo);
|
|
25
29
|
applyPatch(state, operation.data);
|
|
26
30
|
}
|
|
27
31
|
return undoOperations;
|
|
28
32
|
}
|
|
29
|
-
function getUndoOperation(oid, initial, operation,
|
|
33
|
+
function getUndoOperation(oid, initial, operation, patchCreator, authz) {
|
|
34
|
+
var _a, _b;
|
|
30
35
|
const data = operation.data;
|
|
31
36
|
switch (data.op) {
|
|
32
37
|
case 'set':
|
|
38
|
+
if (initial[data.name] === undefined) {
|
|
39
|
+
return patchCreator.createRemove(oid, data.name, authz);
|
|
40
|
+
}
|
|
41
|
+
return patchCreator.createSet(oid, data.name, initial[data.name], authz);
|
|
33
42
|
case 'remove':
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
data: {
|
|
39
|
-
op: 'set',
|
|
40
|
-
name: data.name,
|
|
41
|
-
value: initial[data.name],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
];
|
|
43
|
+
if (initial[data.name] === undefined) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
return patchCreator.createSet(oid, data.name, initial[data.name], authz);
|
|
45
47
|
case 'list-insert':
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
timestamp: getNow(),
|
|
50
|
-
data: {
|
|
51
|
-
op: 'list-delete',
|
|
52
|
-
index: data.index,
|
|
53
|
-
count: 1,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
];
|
|
48
|
+
if (data.value === undefined && ((_a = data.values) === null || _a === void 0 ? void 0 : _a.length) === 0)
|
|
49
|
+
return [];
|
|
50
|
+
return patchCreator.createListDelete(oid, data.index, data.value ? 1 : ((_b = data.values) === null || _b === void 0 ? void 0 : _b.length) || 0, authz);
|
|
57
51
|
case 'list-delete':
|
|
58
|
-
return
|
|
59
|
-
{
|
|
60
|
-
oid,
|
|
61
|
-
timestamp: getNow(),
|
|
62
|
-
data: {
|
|
63
|
-
op: 'list-insert',
|
|
64
|
-
index: data.index,
|
|
65
|
-
values: initial.slice(data.index, data.count),
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
];
|
|
52
|
+
return patchCreator.createListInsertMany(oid, data.index, initial.slice(data.index, data.index + data.count), authz);
|
|
69
53
|
case 'list-move-by-ref':
|
|
70
|
-
return
|
|
71
|
-
{
|
|
72
|
-
oid,
|
|
73
|
-
timestamp: getNow(),
|
|
74
|
-
data: {
|
|
75
|
-
op: 'list-move-by-ref',
|
|
76
|
-
value: data.value,
|
|
77
|
-
index: initial.indexOf(data.value),
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
];
|
|
54
|
+
return patchCreator.createListMoveByRef(oid, data.value, findItemRefIndex(initial, data.value), authz);
|
|
81
55
|
case 'list-move-by-index':
|
|
82
|
-
return
|
|
83
|
-
{
|
|
84
|
-
oid,
|
|
85
|
-
timestamp: getNow(),
|
|
86
|
-
data: {
|
|
87
|
-
op: 'list-move-by-index',
|
|
88
|
-
from: data.to,
|
|
89
|
-
to: data.from,
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
];
|
|
56
|
+
return patchCreator.createListMoveByIndex(oid, data.to, data.from, authz);
|
|
93
57
|
case 'delete':
|
|
94
|
-
return
|
|
95
|
-
{
|
|
96
|
-
oid,
|
|
97
|
-
timestamp: getNow(),
|
|
98
|
-
data: {
|
|
99
|
-
op: 'initialize',
|
|
100
|
-
value: initial,
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
];
|
|
58
|
+
return patchCreator.createInitialize(initial, oid, authz, true);
|
|
104
59
|
case 'list-push':
|
|
105
|
-
return
|
|
106
|
-
{
|
|
107
|
-
oid,
|
|
108
|
-
timestamp: getNow(),
|
|
109
|
-
data: {
|
|
110
|
-
op: 'list-remove',
|
|
111
|
-
value: data.value,
|
|
112
|
-
// best heuristic here - remove the last instance of the item.
|
|
113
|
-
only: 'last',
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
];
|
|
60
|
+
return patchCreator.createListRemove(oid, data.value, 'last', authz);
|
|
117
61
|
case 'list-remove':
|
|
118
62
|
if (data.only === 'last') {
|
|
119
|
-
const index = initial
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
op: 'list-insert',
|
|
126
|
-
index,
|
|
127
|
-
values: [data.value],
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
];
|
|
63
|
+
const index = findItemRefIndex(initial, data.value, 0, 'backward');
|
|
64
|
+
if (index === -1) {
|
|
65
|
+
// if the value isn't in the list, then there's nothing to undo.
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
return patchCreator.createListInsert(oid, index, data.value, authz);
|
|
131
69
|
}
|
|
132
70
|
else if (data.only === 'first') {
|
|
133
|
-
const index = initial
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
op: 'list-insert',
|
|
140
|
-
index,
|
|
141
|
-
values: [data.value],
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
];
|
|
71
|
+
const index = findItemRefIndex(initial, data.value);
|
|
72
|
+
if (index === -1) {
|
|
73
|
+
// if the value isn't in the list, then there's nothing to undo.
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
return patchCreator.createListInsert(oid, index, data.value, authz);
|
|
145
77
|
}
|
|
146
78
|
else {
|
|
147
79
|
// find all instances of value and restore them at their
|
|
148
80
|
// original index
|
|
149
81
|
const indexesOfValue = [];
|
|
150
|
-
let index = initial
|
|
82
|
+
let index = findItemRefIndex(initial, data.value);
|
|
151
83
|
while (index !== -1) {
|
|
152
84
|
indexesOfValue.push(index);
|
|
153
|
-
index = initial
|
|
85
|
+
index = findItemRefIndex(initial, data.value, index + 1);
|
|
154
86
|
}
|
|
155
|
-
return indexesOfValue.
|
|
156
|
-
oid,
|
|
157
|
-
timestamp: getNow(),
|
|
158
|
-
data: {
|
|
159
|
-
op: 'list-insert',
|
|
160
|
-
index,
|
|
161
|
-
value: data.value,
|
|
162
|
-
},
|
|
163
|
-
}));
|
|
87
|
+
return indexesOfValue.flatMap((index) => patchCreator.createListInsert(oid, index, data.value, authz));
|
|
164
88
|
}
|
|
165
89
|
case 'list-add':
|
|
166
90
|
// this one is kind of ambiguous. in theory the set may have
|
|
167
91
|
// already included the value and so no change happened. but
|
|
168
92
|
// basically we infer the intent is to remove what was meant
|
|
169
93
|
// to be added by this change.
|
|
170
|
-
return
|
|
171
|
-
{
|
|
172
|
-
oid,
|
|
173
|
-
timestamp: getNow(),
|
|
174
|
-
data: {
|
|
175
|
-
op: 'list-remove',
|
|
176
|
-
value: data.value,
|
|
177
|
-
only: 'last',
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
];
|
|
94
|
+
return patchCreator.createListRemove(oid, data.value, 'last', authz);
|
|
181
95
|
case 'list-set':
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
data: {
|
|
187
|
-
op: 'list-set',
|
|
188
|
-
index: data.index,
|
|
189
|
-
value: initial[data.index],
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
];
|
|
96
|
+
if (initial[data.index] !== undefined) {
|
|
97
|
+
return patchCreator.createListSet(oid, data.index, initial[data.index], authz);
|
|
98
|
+
}
|
|
99
|
+
return patchCreator.createListDelete(oid, data.index, 1, authz);
|
|
193
100
|
case 'initialize':
|
|
194
|
-
return
|
|
195
|
-
{
|
|
196
|
-
oid,
|
|
197
|
-
timestamp: getNow(),
|
|
198
|
-
data: {
|
|
199
|
-
op: 'delete',
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
];
|
|
101
|
+
return patchCreator.createDelete(oid, authz);
|
|
203
102
|
case 'touch':
|
|
204
103
|
return [];
|
|
205
104
|
default:
|
|
206
105
|
throw new Error(`Cannot undo operation type: ${data.op}`);
|
|
207
106
|
}
|
|
208
107
|
}
|
|
108
|
+
function findItemRefIndex(list, item, from = 0, dir = 'forward') {
|
|
109
|
+
const method = dir === 'forward' ? 'findIndex' : 'findLastIndex';
|
|
110
|
+
// for object items, attempt to find the matching item by OID.
|
|
111
|
+
if (isRef(item)) {
|
|
112
|
+
return list[method]((i, idx) => isRef(i) && i.id === item.id && idx >= from);
|
|
113
|
+
}
|
|
114
|
+
return list[method]((i, idx) => i === item && idx >= from);
|
|
115
|
+
}
|
|
209
116
|
//# sourceMappingURL=undo.js.map
|
package/dist/esm/undo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"undo.js","sourceRoot":"","sources":["../../src/undo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"undo.js","sourceRoot":"","sources":["../../src/undo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { assignOid, createOid, createRef } from './oids.js';
|
|
3
|
+
import { PatchCreator } from './patch.js';
|
|
4
|
+
import { getUndoOperations } from './undo.js';
|
|
5
|
+
function createClock(start = 0) {
|
|
6
|
+
let time = start;
|
|
7
|
+
function clock() {
|
|
8
|
+
return `${time++}`;
|
|
9
|
+
}
|
|
10
|
+
clock.reset = () => {
|
|
11
|
+
time = start;
|
|
12
|
+
};
|
|
13
|
+
return clock;
|
|
14
|
+
}
|
|
15
|
+
describe('undo', () => {
|
|
16
|
+
it('correctly removes added list items', () => {
|
|
17
|
+
const clock = createClock();
|
|
18
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
19
|
+
const initial = [1, 2];
|
|
20
|
+
const oid = createOid('test', 'foo');
|
|
21
|
+
const operations = patchCreator.createListSet(oid, 2, 3);
|
|
22
|
+
clock.reset();
|
|
23
|
+
const undos = getUndoOperations(oid, initial, operations, clock);
|
|
24
|
+
clock.reset();
|
|
25
|
+
expect(undos).toEqual(patchCreator.createListDelete(oid, 2, 1));
|
|
26
|
+
});
|
|
27
|
+
it('correctly restores removed items by ref', () => {
|
|
28
|
+
const clock = createClock();
|
|
29
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
30
|
+
const initial = assignOid([createRef('test/a:1'), createRef('test/a:2'), createRef('test/a:3')], 'test/a');
|
|
31
|
+
const operations = patchCreator.createListRemove('test/a', initial[1], 'last');
|
|
32
|
+
clock.reset();
|
|
33
|
+
const undos = getUndoOperations('test/a', initial, operations, clock);
|
|
34
|
+
clock.reset();
|
|
35
|
+
expect(undos).toEqual(patchCreator.createListInsert('test/a', 1, initial[1]));
|
|
36
|
+
});
|
|
37
|
+
it('undoes list insert with 1 item', () => {
|
|
38
|
+
const clock = createClock();
|
|
39
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
40
|
+
const initial = [1, 2];
|
|
41
|
+
const oid = createOid('test', 'foo');
|
|
42
|
+
const operations = patchCreator.createListInsert(oid, 1, 3);
|
|
43
|
+
clock.reset();
|
|
44
|
+
const undos = getUndoOperations(oid, initial, operations, clock);
|
|
45
|
+
clock.reset();
|
|
46
|
+
expect(undos).toEqual(patchCreator.createListDelete(oid, 1, 1));
|
|
47
|
+
});
|
|
48
|
+
it('undoes list insert with multiple items', () => {
|
|
49
|
+
const clock = createClock();
|
|
50
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
51
|
+
const initial = [1, 2];
|
|
52
|
+
const oid = createOid('test', 'foo');
|
|
53
|
+
const operations = patchCreator.createListInsertMany(oid, 1, [3, 4]);
|
|
54
|
+
clock.reset();
|
|
55
|
+
const undos = getUndoOperations(oid, initial, operations, clock);
|
|
56
|
+
clock.reset();
|
|
57
|
+
expect(undos).toEqual(patchCreator.createListDelete(oid, 1, 2));
|
|
58
|
+
});
|
|
59
|
+
it('undoes initialize with delete', () => {
|
|
60
|
+
const clock = createClock();
|
|
61
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
62
|
+
const initial = { foo: 'bar' };
|
|
63
|
+
const oid = createOid('test', 'foo');
|
|
64
|
+
const operations = patchCreator.createInitialize(initial, oid);
|
|
65
|
+
clock.reset();
|
|
66
|
+
const undos = getUndoOperations(oid, initial, operations, clock);
|
|
67
|
+
clock.reset();
|
|
68
|
+
expect(undos).toEqual(patchCreator.createDelete(oid));
|
|
69
|
+
});
|
|
70
|
+
it('undoes an object move by ref', () => {
|
|
71
|
+
const clock = createClock();
|
|
72
|
+
const patchCreator = new PatchCreator(clock, createClock());
|
|
73
|
+
const initial = assignOid([createRef('test/a:1'), createRef('test/a:2'), createRef('test/a:3')], 'test/a');
|
|
74
|
+
const operations = patchCreator.createListMoveByRef('test/a', initial[1], 0);
|
|
75
|
+
clock.reset();
|
|
76
|
+
const undos = getUndoOperations('test/a', initial, operations, clock);
|
|
77
|
+
clock.reset();
|
|
78
|
+
expect(undos).toEqual(patchCreator.createListMoveByRef('test/a', initial[1], 1));
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=undo.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo.test.js","sourceRoot":"","sources":["../../src/undo.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/authz.ts
CHANGED
package/src/baseline.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
// written upon rebasing. If you apply ops to an undefined
|
|
3
3
|
// snapshot without an initialize, it remains undefined.
|
|
4
4
|
|
|
5
|
+
import { AuthorizationKey } from './authz.js';
|
|
6
|
+
|
|
5
7
|
export type DocumentBaseline<T extends any = any> = {
|
|
6
8
|
oid: string;
|
|
7
9
|
snapshot: T;
|
|
8
10
|
timestamp: string;
|
|
9
|
-
authz?:
|
|
11
|
+
authz?: AuthorizationKey;
|
|
10
12
|
};
|