@verdant-web/common 1.15.2 → 1.15.3-next.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.
Files changed (163) hide show
  1. package/dist/cjs/EventSubscriber.d.ts +17 -17
  2. package/dist/cjs/EventSubscriber.js +66 -66
  3. package/dist/cjs/baseline.d.ts +5 -5
  4. package/dist/cjs/baseline.js +2 -2
  5. package/dist/cjs/batching.d.ts +42 -42
  6. package/dist/cjs/batching.js +91 -91
  7. package/dist/cjs/files.d.ts +19 -19
  8. package/dist/cjs/files.js +18 -18
  9. package/dist/cjs/files.test.d.ts +1 -0
  10. package/dist/cjs/files.test.js +81 -0
  11. package/dist/cjs/files.test.js.map +1 -0
  12. package/dist/cjs/index.d.ts +19 -18
  13. package/dist/cjs/index.js +41 -36
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/indexes.d.ts +17 -17
  16. package/dist/cjs/indexes.js +142 -142
  17. package/dist/cjs/indexes.test.d.ts +1 -1
  18. package/dist/cjs/indexes.test.js +127 -127
  19. package/dist/cjs/migration.d.ts +172 -172
  20. package/dist/cjs/migration.js +301 -301
  21. package/dist/cjs/oids.d.ts +100 -96
  22. package/dist/cjs/oids.js +457 -439
  23. package/dist/cjs/oids.js.map +1 -1
  24. package/dist/cjs/oids.test.d.ts +1 -1
  25. package/dist/cjs/oids.test.js +348 -272
  26. package/dist/cjs/oids.test.js.map +1 -1
  27. package/dist/cjs/operation.d.ts +139 -139
  28. package/dist/cjs/operation.js +545 -545
  29. package/dist/cjs/operation.test.d.ts +1 -1
  30. package/dist/cjs/operation.test.js +529 -529
  31. package/dist/cjs/patch.d.ts +26 -26
  32. package/dist/cjs/patch.js +226 -226
  33. package/dist/cjs/presence.d.ts +27 -27
  34. package/dist/cjs/presence.js +2 -2
  35. package/dist/cjs/protocol.d.ts +145 -145
  36. package/dist/cjs/protocol.js +3 -3
  37. package/dist/cjs/refs.d.ts +7 -5
  38. package/dist/cjs/refs.js +29 -21
  39. package/dist/cjs/refs.js.map +1 -1
  40. package/dist/cjs/replica.d.ts +28 -28
  41. package/dist/cjs/replica.js +28 -28
  42. package/dist/cjs/schema/defaults.d.ts +4 -0
  43. package/dist/cjs/schema/defaults.js +72 -0
  44. package/dist/cjs/schema/defaults.js.map +1 -0
  45. package/dist/cjs/schema/defaults.test.d.ts +1 -1
  46. package/dist/cjs/schema/defaults.test.js +20 -20
  47. package/dist/cjs/schema/fields.d.ts +9 -9
  48. package/dist/cjs/schema/fields.js +144 -144
  49. package/dist/cjs/schema/index.d.ts +8 -8
  50. package/dist/cjs/schema/index.js +51 -51
  51. package/dist/cjs/schema/indexFilters.d.ts +6 -6
  52. package/dist/cjs/schema/indexFilters.js +30 -30
  53. package/dist/cjs/schema/types/collection.d.ts +23 -23
  54. package/dist/cjs/schema/types/collection.js +2 -2
  55. package/dist/cjs/schema/types/compounds.d.ts +11 -11
  56. package/dist/cjs/schema/types/compounds.js +2 -2
  57. package/dist/cjs/schema/types/fields.d.ts +75 -75
  58. package/dist/cjs/schema/types/fields.js +2 -2
  59. package/dist/cjs/schema/types/filters.d.ts +29 -29
  60. package/dist/cjs/schema/types/filters.js +2 -2
  61. package/dist/cjs/schema/types/shapes.d.ts +21 -21
  62. package/dist/cjs/schema/types/shapes.js +2 -2
  63. package/dist/cjs/schema/types/synthetics.d.ts +37 -37
  64. package/dist/cjs/schema/types/synthetics.js +2 -2
  65. package/dist/cjs/schema/types.d.ts +18 -18
  66. package/dist/cjs/schema/types.js +22 -22
  67. package/dist/cjs/schema/validation.d.ts +3 -3
  68. package/dist/cjs/schema/validation.js +86 -86
  69. package/dist/cjs/timestamp.d.ts +50 -50
  70. package/dist/cjs/timestamp.js +251 -251
  71. package/dist/cjs/timestamp.test.d.ts +1 -1
  72. package/dist/cjs/timestamp.test.js +104 -104
  73. package/dist/cjs/undo.d.ts +3 -3
  74. package/dist/cjs/undo.js +198 -198
  75. package/dist/cjs/utils.d.ts +20 -20
  76. package/dist/cjs/utils.js +145 -145
  77. package/dist/cjs/utils.test.d.ts +1 -1
  78. package/dist/cjs/utils.test.js +36 -36
  79. package/dist/esm/EventSubscriber.d.ts +17 -17
  80. package/dist/esm/EventSubscriber.js +62 -62
  81. package/dist/esm/baseline.d.ts +5 -5
  82. package/dist/esm/baseline.js +1 -1
  83. package/dist/esm/batching.d.ts +42 -42
  84. package/dist/esm/batching.js +86 -86
  85. package/dist/esm/files.d.ts +19 -19
  86. package/dist/esm/files.js +12 -12
  87. package/dist/esm/files.test.d.ts +1 -0
  88. package/dist/esm/files.test.js +79 -0
  89. package/dist/esm/files.test.js.map +1 -0
  90. package/dist/esm/index.d.ts +19 -18
  91. package/dist/esm/index.js +16 -15
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/indexes.d.ts +17 -17
  94. package/dist/esm/indexes.js +130 -130
  95. package/dist/esm/indexes.test.d.ts +1 -1
  96. package/dist/esm/indexes.test.js +125 -125
  97. package/dist/esm/migration.d.ts +172 -172
  98. package/dist/esm/migration.js +294 -294
  99. package/dist/esm/oids.d.ts +100 -96
  100. package/dist/esm/oids.js +422 -407
  101. package/dist/esm/oids.js.map +1 -1
  102. package/dist/esm/oids.test.d.ts +1 -1
  103. package/dist/esm/oids.test.js +346 -270
  104. package/dist/esm/oids.test.js.map +1 -1
  105. package/dist/esm/operation.d.ts +139 -139
  106. package/dist/esm/operation.js +530 -530
  107. package/dist/esm/operation.test.d.ts +1 -1
  108. package/dist/esm/operation.test.js +527 -527
  109. package/dist/esm/patch.d.ts +26 -26
  110. package/dist/esm/patch.js +222 -222
  111. package/dist/esm/presence.d.ts +27 -27
  112. package/dist/esm/presence.js +1 -1
  113. package/dist/esm/protocol.d.ts +145 -145
  114. package/dist/esm/protocol.js +2 -2
  115. package/dist/esm/refs.d.ts +7 -5
  116. package/dist/esm/refs.js +22 -16
  117. package/dist/esm/refs.js.map +1 -1
  118. package/dist/esm/replica.d.ts +28 -28
  119. package/dist/esm/replica.js +25 -25
  120. package/dist/esm/schema/defaults.d.ts +4 -0
  121. package/dist/esm/schema/defaults.js +66 -0
  122. package/dist/esm/schema/defaults.js.map +1 -0
  123. package/dist/esm/schema/defaults.test.d.ts +1 -1
  124. package/dist/esm/schema/defaults.test.js +18 -18
  125. package/dist/esm/schema/fields.d.ts +9 -9
  126. package/dist/esm/schema/fields.js +133 -133
  127. package/dist/esm/schema/index.d.ts +8 -8
  128. package/dist/esm/schema/index.js +32 -32
  129. package/dist/esm/schema/indexFilters.d.ts +6 -6
  130. package/dist/esm/schema/indexFilters.js +22 -22
  131. package/dist/esm/schema/types/collection.d.ts +23 -23
  132. package/dist/esm/schema/types/collection.js +1 -1
  133. package/dist/esm/schema/types/compounds.d.ts +11 -11
  134. package/dist/esm/schema/types/compounds.js +1 -1
  135. package/dist/esm/schema/types/fields.d.ts +75 -75
  136. package/dist/esm/schema/types/fields.js +1 -1
  137. package/dist/esm/schema/types/filters.d.ts +29 -29
  138. package/dist/esm/schema/types/filters.js +1 -1
  139. package/dist/esm/schema/types/shapes.d.ts +21 -21
  140. package/dist/esm/schema/types/shapes.js +1 -1
  141. package/dist/esm/schema/types/synthetics.d.ts +37 -37
  142. package/dist/esm/schema/types/synthetics.js +1 -1
  143. package/dist/esm/schema/types.d.ts +18 -18
  144. package/dist/esm/schema/types.js +6 -6
  145. package/dist/esm/schema/validation.d.ts +3 -3
  146. package/dist/esm/schema/validation.js +81 -81
  147. package/dist/esm/timestamp.d.ts +50 -50
  148. package/dist/esm/timestamp.js +234 -234
  149. package/dist/esm/timestamp.test.d.ts +1 -1
  150. package/dist/esm/timestamp.test.js +102 -102
  151. package/dist/esm/undo.d.ts +3 -3
  152. package/dist/esm/undo.js +194 -194
  153. package/dist/esm/utils.d.ts +20 -20
  154. package/dist/esm/utils.js +127 -127
  155. package/dist/esm/utils.test.d.ts +1 -1
  156. package/dist/esm/utils.test.js +34 -34
  157. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  158. package/dist/tsconfig.tsbuildinfo +1 -1
  159. package/package.json +1 -1
  160. package/src/index.ts +1 -0
  161. package/src/oids.test.ts +82 -0
  162. package/src/oids.ts +17 -0
  163. package/src/refs.ts +8 -0
@@ -1,105 +1,105 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const timestamp_js_1 = require("./timestamp.js");
5
- (0, vitest_1.describe)('the hybrid logical clock', () => {
6
- (0, vitest_1.it)('always produces incrementing timestamps', async () => {
7
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
8
- let prev = clock.now(1);
9
- clock.update(prev);
10
- let now;
11
- for (let i = 0; i < 1000; i++) {
12
- now = clock.now(1);
13
- (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
14
- clock.update(now);
15
- prev = now;
16
- }
17
- let time = new Date().getTime();
18
- for (let i = 0; i < 1000; i++) {
19
- vitest_1.vitest.setSystemTime(time++);
20
- now = clock.now(1);
21
- (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
22
- clock.update(now);
23
- prev = now;
24
- }
25
- });
26
- (0, vitest_1.it)('groups blocks of time by version', () => {
27
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
28
- let prev = clock.now(1);
29
- clock.update(prev);
30
- let now;
31
- for (let i = 0; i < 10; i++) {
32
- now = clock.now(1);
33
- (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
34
- clock.update(now);
35
- prev = now;
36
- }
37
- for (let i = 0; i < 10; i++) {
38
- now = clock.now(2);
39
- (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
40
- clock.update(now);
41
- prev = now;
42
- }
43
- const startOfVersion2 = now;
44
- // jump back to 1
45
- prev = clock.now(1);
46
- clock.update(prev);
47
- for (let i = 0; i < 10; i++) {
48
- now = clock.now(1);
49
- (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
50
- (0, vitest_1.expect)(now < startOfVersion2, `${now} not earlier than ${startOfVersion2}`).toBe(true);
51
- clock.update(now);
52
- prev = now;
53
- }
54
- });
55
- (0, vitest_1.it)('is shorter than the previous format', () => {
56
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
57
- (0, vitest_1.expect)(clock.now(1).length).toBeLessThan(clock.OLD_now(1).length);
58
- });
59
- (0, vitest_1.it)('correctly converts old to new format', () => {
60
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
61
- const oldFormat = clock.OLD_now(1);
62
- const value = clock.timerState();
63
- const converted = (0, timestamp_js_1.convertOldHlcTimestamp)(oldFormat);
64
- const newFormat = clock.get(1, value);
65
- (0, vitest_1.expect)(converted).toEqual(newFormat);
66
- });
67
- // this is mostly to verify as I move to the new format.
68
- // instead of attempting a distributed migration of timestamps, it
69
- // will be easier that the new format just acts as always in the
70
- // future of the old one. this will only mess with offline clients,
71
- // but nobody is using verdant but me yet at time of this change (2022-12-19)
72
- // which is kind of why I'm doing it now anyway.
73
- (0, vitest_1.it)('old format always comes before new format', () => {
74
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
75
- const newFormat = clock.now(1);
76
- const oldFormat = clock.OLD_now(1);
77
- (0, vitest_1.expect)(oldFormat < newFormat).toBe(true);
78
- // even far-future old timestamps are before new timestamps
79
- const oldFormat2 = (0, timestamp_js_1.OLD_serializeHlcTimestamp)({
80
- counter: 999,
81
- node: '9876543210',
82
- time: new Date(3000, 1, 1).getTime(),
83
- });
84
- (0, vitest_1.expect)((0, timestamp_js_1.OLD_encodeVersion)(1) + oldFormat2 < newFormat).toBe(true);
85
- });
86
- (0, vitest_1.it)('decodes timestamps', () => {
87
- const time = new Date();
88
- vitest_1.vitest.setSystemTime(time);
89
- const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
90
- const now = clock.now(1);
91
- (0, vitest_1.expect)(clock.getWallClockTime(now)).toEqual(time.getTime());
92
- });
93
- });
94
- (0, vitest_1.describe)('version encoding', () => {
95
- (0, vitest_1.it)('orders 1 before 2', () => {
96
- (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(1) < (0, timestamp_js_1.encodeVersion)(2)).toBe(true);
97
- });
98
- (0, vitest_1.it)('orders 32 before 33', () => {
99
- (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(32) < (0, timestamp_js_1.encodeVersion)(33)).toBe(true);
100
- });
101
- (0, vitest_1.it)('orders 34 before 35', () => {
102
- (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(34) < (0, timestamp_js_1.encodeVersion)(35)).toBe(true);
103
- });
104
- });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const timestamp_js_1 = require("./timestamp.js");
5
+ (0, vitest_1.describe)('the hybrid logical clock', () => {
6
+ (0, vitest_1.it)('always produces incrementing timestamps', async () => {
7
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
8
+ let prev = clock.now(1);
9
+ clock.update(prev);
10
+ let now;
11
+ for (let i = 0; i < 1000; i++) {
12
+ now = clock.now(1);
13
+ (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
14
+ clock.update(now);
15
+ prev = now;
16
+ }
17
+ let time = new Date().getTime();
18
+ for (let i = 0; i < 1000; i++) {
19
+ vitest_1.vitest.setSystemTime(time++);
20
+ now = clock.now(1);
21
+ (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
22
+ clock.update(now);
23
+ prev = now;
24
+ }
25
+ });
26
+ (0, vitest_1.it)('groups blocks of time by version', () => {
27
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
28
+ let prev = clock.now(1);
29
+ clock.update(prev);
30
+ let now;
31
+ for (let i = 0; i < 10; i++) {
32
+ now = clock.now(1);
33
+ (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
34
+ clock.update(now);
35
+ prev = now;
36
+ }
37
+ for (let i = 0; i < 10; i++) {
38
+ now = clock.now(2);
39
+ (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
40
+ clock.update(now);
41
+ prev = now;
42
+ }
43
+ const startOfVersion2 = now;
44
+ // jump back to 1
45
+ prev = clock.now(1);
46
+ clock.update(prev);
47
+ for (let i = 0; i < 10; i++) {
48
+ now = clock.now(1);
49
+ (0, vitest_1.expect)(now > prev, `${now} not later than ${prev}`).toBe(true);
50
+ (0, vitest_1.expect)(now < startOfVersion2, `${now} not earlier than ${startOfVersion2}`).toBe(true);
51
+ clock.update(now);
52
+ prev = now;
53
+ }
54
+ });
55
+ (0, vitest_1.it)('is shorter than the previous format', () => {
56
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
57
+ (0, vitest_1.expect)(clock.now(1).length).toBeLessThan(clock.OLD_now(1).length);
58
+ });
59
+ (0, vitest_1.it)('correctly converts old to new format', () => {
60
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
61
+ const oldFormat = clock.OLD_now(1);
62
+ const value = clock.timerState();
63
+ const converted = (0, timestamp_js_1.convertOldHlcTimestamp)(oldFormat);
64
+ const newFormat = clock.get(1, value);
65
+ (0, vitest_1.expect)(converted).toEqual(newFormat);
66
+ });
67
+ // this is mostly to verify as I move to the new format.
68
+ // instead of attempting a distributed migration of timestamps, it
69
+ // will be easier that the new format just acts as always in the
70
+ // future of the old one. this will only mess with offline clients,
71
+ // but nobody is using verdant but me yet at time of this change (2022-12-19)
72
+ // which is kind of why I'm doing it now anyway.
73
+ (0, vitest_1.it)('old format always comes before new format', () => {
74
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
75
+ const newFormat = clock.now(1);
76
+ const oldFormat = clock.OLD_now(1);
77
+ (0, vitest_1.expect)(oldFormat < newFormat).toBe(true);
78
+ // even far-future old timestamps are before new timestamps
79
+ const oldFormat2 = (0, timestamp_js_1.OLD_serializeHlcTimestamp)({
80
+ counter: 999,
81
+ node: '9876543210',
82
+ time: new Date(3000, 1, 1).getTime(),
83
+ });
84
+ (0, vitest_1.expect)((0, timestamp_js_1.OLD_encodeVersion)(1) + oldFormat2 < newFormat).toBe(true);
85
+ });
86
+ (0, vitest_1.it)('decodes timestamps', () => {
87
+ const time = new Date();
88
+ vitest_1.vitest.setSystemTime(time);
89
+ const clock = new timestamp_js_1.HybridLogicalClockTimestampProvider();
90
+ const now = clock.now(1);
91
+ (0, vitest_1.expect)(clock.getWallClockTime(now)).toEqual(time.getTime());
92
+ });
93
+ });
94
+ (0, vitest_1.describe)('version encoding', () => {
95
+ (0, vitest_1.it)('orders 1 before 2', () => {
96
+ (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(1) < (0, timestamp_js_1.encodeVersion)(2)).toBe(true);
97
+ });
98
+ (0, vitest_1.it)('orders 32 before 33', () => {
99
+ (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(32) < (0, timestamp_js_1.encodeVersion)(33)).toBe(true);
100
+ });
101
+ (0, vitest_1.it)('orders 34 before 35', () => {
102
+ (0, vitest_1.expect)((0, timestamp_js_1.encodeVersion)(34) < (0, timestamp_js_1.encodeVersion)(35)).toBe(true);
103
+ });
104
+ });
105
105
  //# sourceMappingURL=timestamp.test.js.map
@@ -1,3 +1,3 @@
1
- import { ObjectIdentifier } from './oids.js';
2
- import { Operation } from './operation.js';
3
- export declare function getUndoOperations(oid: ObjectIdentifier, initial: any, operations: Operation[], getNow: () => string): Operation[];
1
+ import { ObjectIdentifier } from './oids.js';
2
+ import { Operation } from './operation.js';
3
+ export declare function getUndoOperations(oid: ObjectIdentifier, initial: any, operations: Operation[], getNow: () => string): Operation[];
package/dist/cjs/undo.js CHANGED
@@ -1,199 +1,199 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUndoOperations = void 0;
4
- const operation_js_1 = require("./operation.js");
5
- const utils_js_1 = require("./utils.js");
6
- function getUndoOperations(oid, initial, operations, getNow) {
7
- if (initial === undefined) {
8
- // if the initial state is nothing, then the undo is to delete everything.
9
- // there's nothing else to worry about!
10
- return [
11
- {
12
- oid,
13
- timestamp: getNow(),
14
- data: {
15
- op: 'delete',
16
- },
17
- },
18
- ];
19
- }
20
- // otherwise, traverse the operations one by one,
21
- // applying them, and using the prior state to determine
22
- // what the undo operation is.
23
- let state = (0, utils_js_1.cloneDeep)(initial);
24
- const undoOperations = [];
25
- for (const operation of operations) {
26
- const undo = getUndoOperation(oid, state, operation, getNow);
27
- undoOperations.unshift(...undo);
28
- (0, operation_js_1.applyPatch)(state, operation.data);
29
- }
30
- return undoOperations;
31
- }
32
- exports.getUndoOperations = getUndoOperations;
33
- function getUndoOperation(oid, initial, operation, getNow) {
34
- const data = operation.data;
35
- switch (data.op) {
36
- case 'set':
37
- case 'remove':
38
- return [
39
- {
40
- oid,
41
- timestamp: getNow(),
42
- data: {
43
- op: 'set',
44
- name: data.name,
45
- value: initial[data.name],
46
- },
47
- },
48
- ];
49
- case 'list-insert':
50
- return [
51
- {
52
- oid,
53
- timestamp: getNow(),
54
- data: {
55
- op: 'list-delete',
56
- index: data.index,
57
- count: 1,
58
- },
59
- },
60
- ];
61
- case 'list-delete':
62
- return [
63
- {
64
- oid,
65
- timestamp: getNow(),
66
- data: {
67
- op: 'list-insert',
68
- index: data.index,
69
- values: initial.slice(data.index, data.count),
70
- },
71
- },
72
- ];
73
- case 'list-move-by-ref':
74
- return [
75
- {
76
- oid,
77
- timestamp: getNow(),
78
- data: {
79
- op: 'list-move-by-ref',
80
- value: data.value,
81
- index: initial.indexOf(data.value),
82
- },
83
- },
84
- ];
85
- case 'list-move-by-index':
86
- return [
87
- {
88
- oid,
89
- timestamp: getNow(),
90
- data: {
91
- op: 'list-move-by-index',
92
- from: data.to,
93
- to: data.from,
94
- },
95
- },
96
- ];
97
- case 'delete':
98
- return [
99
- {
100
- oid,
101
- timestamp: getNow(),
102
- data: {
103
- op: 'initialize',
104
- value: initial,
105
- },
106
- },
107
- ];
108
- case 'list-push':
109
- return [
110
- {
111
- oid,
112
- timestamp: getNow(),
113
- data: {
114
- op: 'list-remove',
115
- value: data.value,
116
- // best heuristic here - remove the last instance of the item.
117
- only: 'last',
118
- },
119
- },
120
- ];
121
- case 'list-remove':
122
- if (data.only === 'last') {
123
- const index = initial.lastIndexOf(data.value);
124
- return [
125
- {
126
- oid,
127
- timestamp: getNow(),
128
- data: {
129
- op: 'list-insert',
130
- index,
131
- values: [data.value],
132
- },
133
- },
134
- ];
135
- }
136
- else if (data.only === 'first') {
137
- const index = initial.indexOf(data.value);
138
- return [
139
- {
140
- oid,
141
- timestamp: getNow(),
142
- data: {
143
- op: 'list-insert',
144
- index,
145
- values: [data.value],
146
- },
147
- },
148
- ];
149
- }
150
- else {
151
- // find all instances of value and restore them at their
152
- // original index
153
- const indexesOfValue = [];
154
- let index = initial.indexOf(data.value);
155
- while (index !== -1) {
156
- indexesOfValue.push(index);
157
- index = initial.indexOf(data.value, index + 1);
158
- }
159
- return indexesOfValue.map((index) => ({
160
- oid,
161
- timestamp: getNow(),
162
- data: {
163
- op: 'list-insert',
164
- index,
165
- value: data.value,
166
- },
167
- }));
168
- }
169
- case 'list-add':
170
- // this one is kind of ambiguous. in theory the set may have
171
- // already included the value and so no change happened. but
172
- // basically we infer the intent is to remove what was meant
173
- // to be added by this change.
174
- return [
175
- {
176
- oid,
177
- timestamp: getNow(),
178
- data: {
179
- op: 'list-remove',
180
- value: data.value,
181
- only: 'last',
182
- },
183
- },
184
- ];
185
- case 'initialize':
186
- return [
187
- {
188
- oid,
189
- timestamp: getNow(),
190
- data: {
191
- op: 'delete',
192
- },
193
- },
194
- ];
195
- default:
196
- throw new Error(`Cannot undo operation type: ${data.op}`);
197
- }
198
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getUndoOperations = void 0;
4
+ const operation_js_1 = require("./operation.js");
5
+ const utils_js_1 = require("./utils.js");
6
+ function getUndoOperations(oid, initial, operations, getNow) {
7
+ if (initial === undefined) {
8
+ // if the initial state is nothing, then the undo is to delete everything.
9
+ // there's nothing else to worry about!
10
+ return [
11
+ {
12
+ oid,
13
+ timestamp: getNow(),
14
+ data: {
15
+ op: 'delete',
16
+ },
17
+ },
18
+ ];
19
+ }
20
+ // otherwise, traverse the operations one by one,
21
+ // applying them, and using the prior state to determine
22
+ // what the undo operation is.
23
+ let state = (0, utils_js_1.cloneDeep)(initial);
24
+ const undoOperations = [];
25
+ for (const operation of operations) {
26
+ const undo = getUndoOperation(oid, state, operation, getNow);
27
+ undoOperations.unshift(...undo);
28
+ (0, operation_js_1.applyPatch)(state, operation.data);
29
+ }
30
+ return undoOperations;
31
+ }
32
+ exports.getUndoOperations = getUndoOperations;
33
+ function getUndoOperation(oid, initial, operation, getNow) {
34
+ const data = operation.data;
35
+ switch (data.op) {
36
+ case 'set':
37
+ case 'remove':
38
+ return [
39
+ {
40
+ oid,
41
+ timestamp: getNow(),
42
+ data: {
43
+ op: 'set',
44
+ name: data.name,
45
+ value: initial[data.name],
46
+ },
47
+ },
48
+ ];
49
+ case 'list-insert':
50
+ return [
51
+ {
52
+ oid,
53
+ timestamp: getNow(),
54
+ data: {
55
+ op: 'list-delete',
56
+ index: data.index,
57
+ count: 1,
58
+ },
59
+ },
60
+ ];
61
+ case 'list-delete':
62
+ return [
63
+ {
64
+ oid,
65
+ timestamp: getNow(),
66
+ data: {
67
+ op: 'list-insert',
68
+ index: data.index,
69
+ values: initial.slice(data.index, data.count),
70
+ },
71
+ },
72
+ ];
73
+ case 'list-move-by-ref':
74
+ return [
75
+ {
76
+ oid,
77
+ timestamp: getNow(),
78
+ data: {
79
+ op: 'list-move-by-ref',
80
+ value: data.value,
81
+ index: initial.indexOf(data.value),
82
+ },
83
+ },
84
+ ];
85
+ case 'list-move-by-index':
86
+ return [
87
+ {
88
+ oid,
89
+ timestamp: getNow(),
90
+ data: {
91
+ op: 'list-move-by-index',
92
+ from: data.to,
93
+ to: data.from,
94
+ },
95
+ },
96
+ ];
97
+ case 'delete':
98
+ return [
99
+ {
100
+ oid,
101
+ timestamp: getNow(),
102
+ data: {
103
+ op: 'initialize',
104
+ value: initial,
105
+ },
106
+ },
107
+ ];
108
+ case 'list-push':
109
+ return [
110
+ {
111
+ oid,
112
+ timestamp: getNow(),
113
+ data: {
114
+ op: 'list-remove',
115
+ value: data.value,
116
+ // best heuristic here - remove the last instance of the item.
117
+ only: 'last',
118
+ },
119
+ },
120
+ ];
121
+ case 'list-remove':
122
+ if (data.only === 'last') {
123
+ const index = initial.lastIndexOf(data.value);
124
+ return [
125
+ {
126
+ oid,
127
+ timestamp: getNow(),
128
+ data: {
129
+ op: 'list-insert',
130
+ index,
131
+ values: [data.value],
132
+ },
133
+ },
134
+ ];
135
+ }
136
+ else if (data.only === 'first') {
137
+ const index = initial.indexOf(data.value);
138
+ return [
139
+ {
140
+ oid,
141
+ timestamp: getNow(),
142
+ data: {
143
+ op: 'list-insert',
144
+ index,
145
+ values: [data.value],
146
+ },
147
+ },
148
+ ];
149
+ }
150
+ else {
151
+ // find all instances of value and restore them at their
152
+ // original index
153
+ const indexesOfValue = [];
154
+ let index = initial.indexOf(data.value);
155
+ while (index !== -1) {
156
+ indexesOfValue.push(index);
157
+ index = initial.indexOf(data.value, index + 1);
158
+ }
159
+ return indexesOfValue.map((index) => ({
160
+ oid,
161
+ timestamp: getNow(),
162
+ data: {
163
+ op: 'list-insert',
164
+ index,
165
+ value: data.value,
166
+ },
167
+ }));
168
+ }
169
+ case 'list-add':
170
+ // this one is kind of ambiguous. in theory the set may have
171
+ // already included the value and so no change happened. but
172
+ // basically we infer the intent is to remove what was meant
173
+ // to be added by this change.
174
+ return [
175
+ {
176
+ oid,
177
+ timestamp: getNow(),
178
+ data: {
179
+ op: 'list-remove',
180
+ value: data.value,
181
+ only: 'last',
182
+ },
183
+ },
184
+ ];
185
+ case 'initialize':
186
+ return [
187
+ {
188
+ oid,
189
+ timestamp: getNow(),
190
+ data: {
191
+ op: 'delete',
192
+ },
193
+ },
194
+ ];
195
+ default:
196
+ throw new Error(`Cannot undo operation type: ${data.op}`);
197
+ }
198
+ }
199
199
  //# sourceMappingURL=undo.js.map
@@ -1,20 +1,20 @@
1
- export declare function take<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Pick<T, Keys>;
2
- export declare function omit<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Omit<T, Keys>;
3
- export declare function getSortedIndex<T>(array: T[], insert: T, compare: (a: T, b: T) => number): number;
4
- /**
5
- * Consistently stringifies an object regardless
6
- * of key insertion order
7
- */
8
- export declare function stableStringify(obj: any): string;
9
- /**
10
- * A version of structured cloning which preserves object identity
11
- * references in the system.
12
- */
13
- export declare function cloneDeep<T>(obj: T, copyOids?: boolean): T;
14
- export declare function hashObject(obj: any): string;
15
- export declare function isObject(obj: any): any;
16
- export declare function roughSizeOfObject(object: any): number;
17
- export declare function assert(condition: any, message?: string): asserts condition;
18
- export declare function generateId(length?: number): string;
19
- export declare function findLastIndex<T>(array: T[], predicate: (item: T) => boolean): number;
20
- export declare function debounce<T extends (...args: any[]) => any>(fn: T, wait: number): T;
1
+ export declare function take<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Pick<T, Keys>;
2
+ export declare function omit<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Omit<T, Keys>;
3
+ export declare function getSortedIndex<T>(array: T[], insert: T, compare: (a: T, b: T) => number): number;
4
+ /**
5
+ * Consistently stringifies an object regardless
6
+ * of key insertion order
7
+ */
8
+ export declare function stableStringify(obj: any): string;
9
+ /**
10
+ * A version of structured cloning which preserves object identity
11
+ * references in the system.
12
+ */
13
+ export declare function cloneDeep<T>(obj: T, copyOids?: boolean): T;
14
+ export declare function hashObject(obj: any): string;
15
+ export declare function isObject(obj: any): any;
16
+ export declare function roughSizeOfObject(object: any): number;
17
+ export declare function assert(condition: any, message?: string): asserts condition;
18
+ export declare function generateId(length?: number): string;
19
+ export declare function findLastIndex<T>(array: T[], predicate: (item: T) => boolean): number;
20
+ export declare function debounce<T extends (...args: any[]) => any>(fn: T, wait: number): T;