atom.io 0.6.9 → 0.7.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 +21 -2
- package/dist/index.d.mts +34 -421
- package/dist/index.d.ts +34 -421
- package/dist/index.js +248 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +209 -4
- package/dist/index.mjs.map +1 -1
- package/internal/dist/index.d.mts +342 -0
- package/internal/dist/index.d.ts +342 -0
- package/internal/dist/index.js +1873 -0
- package/internal/dist/index.js.map +1 -0
- package/internal/dist/index.mjs +1798 -0
- package/internal/dist/index.mjs.map +1 -0
- package/internal/package.json +15 -0
- package/internal/src/atom/create-atom.ts +75 -0
- package/internal/src/atom/delete-atom.ts +10 -0
- package/internal/src/atom/index.ts +3 -0
- package/internal/src/atom/is-default.ts +37 -0
- package/internal/src/caching.ts +21 -0
- package/internal/src/families/create-atom-family.ts +59 -0
- package/internal/src/families/create-readonly-selector-family.ts +45 -0
- package/internal/src/families/create-selector-family.ts +67 -0
- package/internal/src/families/index.ts +3 -0
- package/internal/src/get-state-internal.ts +23 -0
- package/internal/src/index.ts +13 -0
- package/internal/src/mutable/create-mutable-atom-family.ts +25 -0
- package/internal/src/mutable/create-mutable-atom.ts +49 -0
- package/internal/src/mutable/get-json-token.ts +22 -0
- package/internal/src/mutable/get-update-token.ts +20 -0
- package/internal/src/mutable/index.ts +17 -0
- package/internal/src/mutable/is-atom-token-mutable.ts +7 -0
- package/internal/src/mutable/tracker-family.ts +61 -0
- package/internal/src/mutable/tracker.ts +164 -0
- package/internal/src/mutable/transceiver.ts +110 -0
- package/internal/src/operation.ts +68 -0
- package/internal/src/selector/create-read-write-selector.ts +65 -0
- package/internal/src/selector/create-readonly-selector.ts +49 -0
- package/internal/src/selector/create-selector.ts +65 -0
- package/internal/src/selector/index.ts +5 -0
- package/internal/src/selector/lookup-selector-sources.ts +20 -0
- package/internal/src/selector/register-selector.ts +61 -0
- package/internal/src/selector/trace-selector-atoms.ts +45 -0
- package/internal/src/selector/update-selector-atoms.ts +34 -0
- package/internal/src/set-state/become.ts +10 -0
- package/internal/src/set-state/copy-mutable-if-needed.ts +23 -0
- package/internal/src/set-state/copy-mutable-in-transaction.ts +59 -0
- package/internal/src/set-state/copy-mutable-into-new-store.ts +34 -0
- package/internal/src/set-state/emit-update.ts +23 -0
- package/internal/src/set-state/evict-downstream.ts +39 -0
- package/internal/src/set-state/index.ts +2 -0
- package/internal/src/set-state/set-atom-state.ts +38 -0
- package/internal/src/set-state/set-selector-state.ts +19 -0
- package/internal/src/set-state/set-state-internal.ts +18 -0
- package/internal/src/set-state/stow-update.ts +42 -0
- package/internal/src/store/deposit.ts +43 -0
- package/internal/src/store/index.ts +5 -0
- package/internal/src/store/lookup.ts +26 -0
- package/internal/src/store/store.ts +154 -0
- package/internal/src/store/withdraw-new-family-member.ts +53 -0
- package/internal/src/store/withdraw.ts +113 -0
- package/internal/src/subject.ts +21 -0
- package/internal/src/subscribe/index.ts +1 -0
- package/internal/src/subscribe/recall-state.ts +19 -0
- package/internal/src/subscribe/subscribe-to-root-atoms.ts +47 -0
- package/internal/src/timeline/add-atom-to-timeline.ts +189 -0
- package/internal/src/timeline/index.ts +3 -0
- package/internal/src/timeline/time-travel-internal.ts +91 -0
- package/internal/src/timeline/timeline-internal.ts +115 -0
- package/internal/src/transaction/abort-transaction.ts +12 -0
- package/internal/src/transaction/apply-transaction.ts +64 -0
- package/internal/src/transaction/build-transaction.ts +39 -0
- package/internal/src/transaction/index.ts +26 -0
- package/internal/src/transaction/redo-transaction.ts +22 -0
- package/internal/src/transaction/transaction-internal.ts +64 -0
- package/internal/src/transaction/undo-transaction.ts +22 -0
- package/introspection/dist/index.d.mts +3 -197
- package/introspection/dist/index.d.ts +3 -197
- package/introspection/dist/index.js +329 -4
- package/introspection/dist/index.js.map +1 -1
- package/introspection/dist/index.mjs +310 -4
- package/introspection/dist/index.mjs.map +1 -1
- package/introspection/src/attach-atom-index.ts +84 -0
- package/introspection/src/attach-introspection-states.ts +38 -0
- package/introspection/src/attach-selector-index.ts +90 -0
- package/introspection/src/attach-timeline-family.ts +59 -0
- package/introspection/src/attach-timeline-index.ts +38 -0
- package/introspection/src/attach-transaction-index.ts +40 -0
- package/introspection/src/attach-transaction-logs.ts +43 -0
- package/introspection/src/index.ts +20 -0
- package/json/dist/index.d.mts +10 -2
- package/json/dist/index.d.ts +10 -2
- package/json/dist/index.js +83 -26
- package/json/dist/index.js.map +1 -1
- package/json/dist/index.mjs +74 -3
- package/json/dist/index.mjs.map +1 -1
- package/json/src/index.ts +5 -0
- package/json/src/select-json-family.ts +35 -0
- package/json/src/select-json.ts +22 -0
- package/package.json +103 -63
- package/react/dist/index.d.mts +9 -17
- package/react/dist/index.d.ts +9 -17
- package/react/dist/index.js +44 -27
- package/react/dist/index.js.map +1 -1
- package/react/dist/index.mjs +24 -4
- package/react/dist/index.mjs.map +1 -1
- package/react/src/index.ts +2 -0
- package/react/src/store-context.tsx +12 -0
- package/react/src/store-hooks.ts +36 -0
- package/react-devtools/dist/index.css +50 -1
- package/react-devtools/dist/index.css.map +1 -1
- package/react-devtools/dist/index.d.mts +104 -71
- package/react-devtools/dist/index.d.ts +104 -71
- package/react-devtools/dist/index.js +2806 -44
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/index.mjs +2775 -10
- package/react-devtools/dist/index.mjs.map +1 -1
- package/react-devtools/src/AtomIODevtools.tsx +109 -0
- package/react-devtools/src/Button.tsx +23 -0
- package/react-devtools/src/StateEditor.tsx +75 -0
- package/react-devtools/src/StateIndex.tsx +159 -0
- package/react-devtools/src/TimelineIndex.tsx +88 -0
- package/react-devtools/src/TransactionIndex.tsx +70 -0
- package/react-devtools/src/Updates.tsx +150 -0
- package/react-devtools/src/devtools.scss +310 -0
- package/react-devtools/src/index.ts +72 -0
- package/realtime-react/dist/index.d.mts +8 -22
- package/realtime-react/dist/index.d.ts +8 -22
- package/realtime-react/dist/index.js +87 -32
- package/realtime-react/dist/index.js.map +1 -1
- package/realtime-react/dist/index.mjs +62 -6
- package/realtime-react/dist/index.mjs.map +1 -1
- package/realtime-react/src/index.ts +7 -0
- package/realtime-react/src/realtime-context.tsx +29 -0
- package/realtime-react/src/use-pull-family-member.ts +15 -0
- package/realtime-react/src/use-pull-mutable-family-member.ts +20 -0
- package/realtime-react/src/use-pull-mutable.ts +17 -0
- package/realtime-react/src/use-pull.ts +15 -0
- package/realtime-react/src/use-push.ts +19 -0
- package/realtime-react/src/use-server-action.ts +18 -0
- package/realtime-testing/dist/index.d.mts +49 -0
- package/realtime-testing/dist/index.d.ts +49 -0
- package/realtime-testing/dist/index.js +147 -0
- package/realtime-testing/dist/index.js.map +1 -0
- package/realtime-testing/dist/index.mjs +116 -0
- package/realtime-testing/dist/index.mjs.map +1 -0
- package/realtime-testing/src/index.ts +1 -0
- package/realtime-testing/src/setup-realtime-test.tsx +161 -0
- package/src/atom.ts +64 -9
- package/src/index.ts +36 -32
- package/src/logger.ts +3 -3
- package/src/selector.ts +3 -3
- package/src/silo.ts +29 -20
- package/src/subscribe.ts +3 -3
- package/src/timeline.ts +2 -2
- package/transceivers/set-rtx/dist/index.d.mts +39 -0
- package/transceivers/set-rtx/dist/index.d.ts +39 -0
- package/transceivers/set-rtx/dist/index.js +213 -0
- package/transceivers/set-rtx/dist/index.js.map +1 -0
- package/transceivers/set-rtx/dist/index.mjs +211 -0
- package/transceivers/set-rtx/dist/index.mjs.map +1 -0
- package/{realtime → transceivers/set-rtx}/package.json +1 -1
- package/transceivers/set-rtx/src/index.ts +1 -0
- package/transceivers/set-rtx/src/set-rtx.ts +242 -0
- package/realtime/dist/index.d.mts +0 -23
- package/realtime/dist/index.d.ts +0 -23
- package/realtime/dist/index.js +0 -32
- package/realtime/dist/index.js.map +0 -1
- package/realtime/dist/index.mjs +0 -7
- package/realtime/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var internal = require('atom.io/internal');
|
|
4
|
+
var json = require('atom.io/json');
|
|
5
|
+
|
|
6
|
+
// src/set-rtx.ts
|
|
7
|
+
var SetRTX = class _SetRTX extends Set {
|
|
8
|
+
constructor(values, cacheLimit = 0) {
|
|
9
|
+
super(values);
|
|
10
|
+
this.mode = `record`;
|
|
11
|
+
this.subject = new internal.Subject();
|
|
12
|
+
this.cacheLimit = 0;
|
|
13
|
+
this.cache = [];
|
|
14
|
+
this.cacheIdx = -1;
|
|
15
|
+
this.cacheUpdateNumber = -1;
|
|
16
|
+
this.child = null;
|
|
17
|
+
this.transactionUpdates = null;
|
|
18
|
+
if (values instanceof _SetRTX) {
|
|
19
|
+
this.parent = values;
|
|
20
|
+
this.cacheUpdateNumber = values.cacheUpdateNumber;
|
|
21
|
+
}
|
|
22
|
+
if (cacheLimit) {
|
|
23
|
+
this.cacheLimit = cacheLimit;
|
|
24
|
+
this.cache = new Array(cacheLimit);
|
|
25
|
+
this.subscribe(`auto cache`, (update) => {
|
|
26
|
+
this.cacheIdx++;
|
|
27
|
+
this.cacheIdx %= this.cacheLimit;
|
|
28
|
+
this.cache[this.cacheIdx] = update;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
toJSON() {
|
|
33
|
+
return {
|
|
34
|
+
members: [...this],
|
|
35
|
+
cache: this.cache,
|
|
36
|
+
cacheLimit: this.cacheLimit,
|
|
37
|
+
cacheIdx: this.cacheIdx,
|
|
38
|
+
cacheUpdateNumber: this.cacheUpdateNumber
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
static fromJSON(json) {
|
|
42
|
+
const set = new _SetRTX(json.members, json.cacheLimit);
|
|
43
|
+
set.cache = json.cache;
|
|
44
|
+
set.cacheIdx = json.cacheIdx;
|
|
45
|
+
set.cacheUpdateNumber = json.cacheUpdateNumber;
|
|
46
|
+
return set;
|
|
47
|
+
}
|
|
48
|
+
add(value) {
|
|
49
|
+
if (this.mode === `record`) {
|
|
50
|
+
this.cacheUpdateNumber++;
|
|
51
|
+
this.emit(`add:${json.stringifyJson(value)}`);
|
|
52
|
+
}
|
|
53
|
+
return super.add(value);
|
|
54
|
+
}
|
|
55
|
+
clear() {
|
|
56
|
+
if (this.mode === `record`) {
|
|
57
|
+
this.cacheUpdateNumber++;
|
|
58
|
+
this.emit(`clear:${JSON.stringify([...this])}`);
|
|
59
|
+
}
|
|
60
|
+
super.clear();
|
|
61
|
+
}
|
|
62
|
+
delete(value) {
|
|
63
|
+
if (this.mode === `record`) {
|
|
64
|
+
this.cacheUpdateNumber++;
|
|
65
|
+
this.emit(`del:${json.stringifyJson(value)}`);
|
|
66
|
+
}
|
|
67
|
+
return super.delete(value);
|
|
68
|
+
}
|
|
69
|
+
transaction(run) {
|
|
70
|
+
this.mode = `transaction`;
|
|
71
|
+
this.transactionUpdates = [];
|
|
72
|
+
this.child = new _SetRTX(this);
|
|
73
|
+
const unsubscribe = this.child._subscribe(`transaction`, (update) => {
|
|
74
|
+
var _a;
|
|
75
|
+
(_a = this.transactionUpdates) == null ? void 0 : _a.push(update);
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
const shouldCommit = run(this.child);
|
|
79
|
+
if (shouldCommit) {
|
|
80
|
+
this.cacheUpdateNumber++;
|
|
81
|
+
this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
|
|
82
|
+
for (const update of this.transactionUpdates) {
|
|
83
|
+
this.doStep(update);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (thrown) {
|
|
87
|
+
console.error(`Failed to apply transaction: ${thrown}`);
|
|
88
|
+
} finally {
|
|
89
|
+
unsubscribe();
|
|
90
|
+
this.child = null;
|
|
91
|
+
this.transactionUpdates = null;
|
|
92
|
+
this.mode = `record`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
_subscribe(key, fn) {
|
|
96
|
+
return this.subject.subscribe(key, fn);
|
|
97
|
+
}
|
|
98
|
+
subscribe(key, fn) {
|
|
99
|
+
return this.subject.subscribe(
|
|
100
|
+
key,
|
|
101
|
+
(update) => fn(`${this.cacheUpdateNumber}=${update}`)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
emit(update) {
|
|
105
|
+
this.subject.next(update);
|
|
106
|
+
}
|
|
107
|
+
doStep(update) {
|
|
108
|
+
const typeValueBreak = update.indexOf(`:`);
|
|
109
|
+
const type = update.substring(0, typeValueBreak);
|
|
110
|
+
const value = update.substring(typeValueBreak + 1);
|
|
111
|
+
switch (type) {
|
|
112
|
+
case `add`:
|
|
113
|
+
this.add(json.parseJson(value));
|
|
114
|
+
break;
|
|
115
|
+
case `clear`:
|
|
116
|
+
this.clear();
|
|
117
|
+
break;
|
|
118
|
+
case `del`:
|
|
119
|
+
this.delete(json.parseJson(value));
|
|
120
|
+
break;
|
|
121
|
+
case `tx`:
|
|
122
|
+
for (const update2 of value.split(`;`)) {
|
|
123
|
+
this.doStep(update2);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
do(update) {
|
|
128
|
+
const breakpoint = update.indexOf(`=`);
|
|
129
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
130
|
+
const eventOffset = updateNumber - this.cacheUpdateNumber;
|
|
131
|
+
const isFuture = eventOffset > 0;
|
|
132
|
+
if (isFuture) {
|
|
133
|
+
if (eventOffset === 1) {
|
|
134
|
+
this.mode = `playback`;
|
|
135
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
136
|
+
this.doStep(innerUpdate);
|
|
137
|
+
this.mode = `record`;
|
|
138
|
+
this.cacheUpdateNumber = updateNumber;
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
return this.cacheUpdateNumber + 1;
|
|
142
|
+
} else {
|
|
143
|
+
if (Math.abs(eventOffset) < this.cacheLimit) {
|
|
144
|
+
const eventIdx = this.cacheIdx + eventOffset;
|
|
145
|
+
const cachedUpdate = this.cache[eventIdx];
|
|
146
|
+
if (cachedUpdate === update) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
this.mode = `playback`;
|
|
150
|
+
let done = false;
|
|
151
|
+
while (!done) {
|
|
152
|
+
this.cacheIdx %= this.cacheLimit;
|
|
153
|
+
const update2 = this.cache[this.cacheIdx];
|
|
154
|
+
this.cacheIdx--;
|
|
155
|
+
if (!update2) {
|
|
156
|
+
return `OUT_OF_RANGE`;
|
|
157
|
+
}
|
|
158
|
+
this.undo(update2);
|
|
159
|
+
done = this.cacheIdx === eventIdx - 1;
|
|
160
|
+
}
|
|
161
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
162
|
+
this.doStep(innerUpdate);
|
|
163
|
+
this.mode = `record`;
|
|
164
|
+
this.cacheUpdateNumber = updateNumber;
|
|
165
|
+
return null;
|
|
166
|
+
} else {
|
|
167
|
+
return `OUT_OF_RANGE`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
undoStep(update) {
|
|
172
|
+
const breakpoint = update.indexOf(`:`);
|
|
173
|
+
const type = update.substring(0, breakpoint);
|
|
174
|
+
const value = update.substring(breakpoint + 1);
|
|
175
|
+
switch (type) {
|
|
176
|
+
case `add`:
|
|
177
|
+
this.delete(json.parseJson(value));
|
|
178
|
+
break;
|
|
179
|
+
case `del`:
|
|
180
|
+
this.add(json.parseJson(value));
|
|
181
|
+
break;
|
|
182
|
+
case `clear`: {
|
|
183
|
+
const values = JSON.parse(value);
|
|
184
|
+
for (const value2 of values)
|
|
185
|
+
this.add(value2);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case `tx`: {
|
|
189
|
+
const updates = value.split(`;`);
|
|
190
|
+
for (let i = updates.length - 1; i >= 0; i--) {
|
|
191
|
+
this.undoStep(updates[i]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
undo(update) {
|
|
197
|
+
const breakpoint = update.indexOf(`=`);
|
|
198
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
199
|
+
if (updateNumber === this.cacheUpdateNumber) {
|
|
200
|
+
this.mode = `playback`;
|
|
201
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
202
|
+
this.undoStep(innerUpdate);
|
|
203
|
+
this.mode = `record`;
|
|
204
|
+
this.cacheUpdateNumber--;
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
return this.cacheUpdateNumber;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
exports.SetRTX = SetRTX;
|
|
212
|
+
//# sourceMappingURL=out.js.map
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/set-rtx.ts"],"names":["update","value"],"mappings":"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","sourcesContent":["import type { Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, Stringified, primitive } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdate =\n\t| `add:${string}`\n\t| `clear:${string}`\n\t| `del:${string}`\n\t| `tx:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<NumberedSetUpdate>\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Set<P> | readonly P[] | null, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.add(value)\n\t}\n\n\tpublic clear(): void {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify([...this])}`)\n\t\t}\n\t\tsuper.clear()\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.delete(value)\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\tconsole.error(`Failed to apply transaction: ${thrown}`)\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) =>\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`),\n\t\t)\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak)\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const update of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(update as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t} else {\n\t\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\t\tif (cachedUpdate === update) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tlet done = false\n\t\t\t\twhile (!done) {\n\t\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\t\tconst update = this.cache[this.cacheIdx]\n\t\t\t\t\tthis.cacheIdx--\n\t\t\t\t\tif (!update) {\n\t\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t\t}\n\t\t\t\t\tconst undoRes = this.undo(update)\n\t\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t\t}\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t} else {\n\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint)\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const value of values) this.add(value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"]}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { Subject } from 'atom.io/internal';
|
|
2
|
+
import { stringifyJson, parseJson } from 'atom.io/json';
|
|
3
|
+
|
|
4
|
+
// src/set-rtx.ts
|
|
5
|
+
var SetRTX = class _SetRTX extends Set {
|
|
6
|
+
constructor(values, cacheLimit = 0) {
|
|
7
|
+
super(values);
|
|
8
|
+
this.mode = `record`;
|
|
9
|
+
this.subject = new Subject();
|
|
10
|
+
this.cacheLimit = 0;
|
|
11
|
+
this.cache = [];
|
|
12
|
+
this.cacheIdx = -1;
|
|
13
|
+
this.cacheUpdateNumber = -1;
|
|
14
|
+
this.child = null;
|
|
15
|
+
this.transactionUpdates = null;
|
|
16
|
+
if (values instanceof _SetRTX) {
|
|
17
|
+
this.parent = values;
|
|
18
|
+
this.cacheUpdateNumber = values.cacheUpdateNumber;
|
|
19
|
+
}
|
|
20
|
+
if (cacheLimit) {
|
|
21
|
+
this.cacheLimit = cacheLimit;
|
|
22
|
+
this.cache = new Array(cacheLimit);
|
|
23
|
+
this.subscribe(`auto cache`, (update) => {
|
|
24
|
+
this.cacheIdx++;
|
|
25
|
+
this.cacheIdx %= this.cacheLimit;
|
|
26
|
+
this.cache[this.cacheIdx] = update;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
toJSON() {
|
|
31
|
+
return {
|
|
32
|
+
members: [...this],
|
|
33
|
+
cache: this.cache,
|
|
34
|
+
cacheLimit: this.cacheLimit,
|
|
35
|
+
cacheIdx: this.cacheIdx,
|
|
36
|
+
cacheUpdateNumber: this.cacheUpdateNumber
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
static fromJSON(json) {
|
|
40
|
+
const set = new _SetRTX(json.members, json.cacheLimit);
|
|
41
|
+
set.cache = json.cache;
|
|
42
|
+
set.cacheIdx = json.cacheIdx;
|
|
43
|
+
set.cacheUpdateNumber = json.cacheUpdateNumber;
|
|
44
|
+
return set;
|
|
45
|
+
}
|
|
46
|
+
add(value) {
|
|
47
|
+
if (this.mode === `record`) {
|
|
48
|
+
this.cacheUpdateNumber++;
|
|
49
|
+
this.emit(`add:${stringifyJson(value)}`);
|
|
50
|
+
}
|
|
51
|
+
return super.add(value);
|
|
52
|
+
}
|
|
53
|
+
clear() {
|
|
54
|
+
if (this.mode === `record`) {
|
|
55
|
+
this.cacheUpdateNumber++;
|
|
56
|
+
this.emit(`clear:${JSON.stringify([...this])}`);
|
|
57
|
+
}
|
|
58
|
+
super.clear();
|
|
59
|
+
}
|
|
60
|
+
delete(value) {
|
|
61
|
+
if (this.mode === `record`) {
|
|
62
|
+
this.cacheUpdateNumber++;
|
|
63
|
+
this.emit(`del:${stringifyJson(value)}`);
|
|
64
|
+
}
|
|
65
|
+
return super.delete(value);
|
|
66
|
+
}
|
|
67
|
+
transaction(run) {
|
|
68
|
+
this.mode = `transaction`;
|
|
69
|
+
this.transactionUpdates = [];
|
|
70
|
+
this.child = new _SetRTX(this);
|
|
71
|
+
const unsubscribe = this.child._subscribe(`transaction`, (update) => {
|
|
72
|
+
var _a;
|
|
73
|
+
(_a = this.transactionUpdates) == null ? void 0 : _a.push(update);
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
const shouldCommit = run(this.child);
|
|
77
|
+
if (shouldCommit) {
|
|
78
|
+
this.cacheUpdateNumber++;
|
|
79
|
+
this.emit(`tx:${this.transactionUpdates.join(`;`)}`);
|
|
80
|
+
for (const update of this.transactionUpdates) {
|
|
81
|
+
this.doStep(update);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch (thrown) {
|
|
85
|
+
console.error(`Failed to apply transaction: ${thrown}`);
|
|
86
|
+
} finally {
|
|
87
|
+
unsubscribe();
|
|
88
|
+
this.child = null;
|
|
89
|
+
this.transactionUpdates = null;
|
|
90
|
+
this.mode = `record`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
_subscribe(key, fn) {
|
|
94
|
+
return this.subject.subscribe(key, fn);
|
|
95
|
+
}
|
|
96
|
+
subscribe(key, fn) {
|
|
97
|
+
return this.subject.subscribe(
|
|
98
|
+
key,
|
|
99
|
+
(update) => fn(`${this.cacheUpdateNumber}=${update}`)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
emit(update) {
|
|
103
|
+
this.subject.next(update);
|
|
104
|
+
}
|
|
105
|
+
doStep(update) {
|
|
106
|
+
const typeValueBreak = update.indexOf(`:`);
|
|
107
|
+
const type = update.substring(0, typeValueBreak);
|
|
108
|
+
const value = update.substring(typeValueBreak + 1);
|
|
109
|
+
switch (type) {
|
|
110
|
+
case `add`:
|
|
111
|
+
this.add(parseJson(value));
|
|
112
|
+
break;
|
|
113
|
+
case `clear`:
|
|
114
|
+
this.clear();
|
|
115
|
+
break;
|
|
116
|
+
case `del`:
|
|
117
|
+
this.delete(parseJson(value));
|
|
118
|
+
break;
|
|
119
|
+
case `tx`:
|
|
120
|
+
for (const update2 of value.split(`;`)) {
|
|
121
|
+
this.doStep(update2);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
do(update) {
|
|
126
|
+
const breakpoint = update.indexOf(`=`);
|
|
127
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
128
|
+
const eventOffset = updateNumber - this.cacheUpdateNumber;
|
|
129
|
+
const isFuture = eventOffset > 0;
|
|
130
|
+
if (isFuture) {
|
|
131
|
+
if (eventOffset === 1) {
|
|
132
|
+
this.mode = `playback`;
|
|
133
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
134
|
+
this.doStep(innerUpdate);
|
|
135
|
+
this.mode = `record`;
|
|
136
|
+
this.cacheUpdateNumber = updateNumber;
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return this.cacheUpdateNumber + 1;
|
|
140
|
+
} else {
|
|
141
|
+
if (Math.abs(eventOffset) < this.cacheLimit) {
|
|
142
|
+
const eventIdx = this.cacheIdx + eventOffset;
|
|
143
|
+
const cachedUpdate = this.cache[eventIdx];
|
|
144
|
+
if (cachedUpdate === update) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
this.mode = `playback`;
|
|
148
|
+
let done = false;
|
|
149
|
+
while (!done) {
|
|
150
|
+
this.cacheIdx %= this.cacheLimit;
|
|
151
|
+
const update2 = this.cache[this.cacheIdx];
|
|
152
|
+
this.cacheIdx--;
|
|
153
|
+
if (!update2) {
|
|
154
|
+
return `OUT_OF_RANGE`;
|
|
155
|
+
}
|
|
156
|
+
this.undo(update2);
|
|
157
|
+
done = this.cacheIdx === eventIdx - 1;
|
|
158
|
+
}
|
|
159
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
160
|
+
this.doStep(innerUpdate);
|
|
161
|
+
this.mode = `record`;
|
|
162
|
+
this.cacheUpdateNumber = updateNumber;
|
|
163
|
+
return null;
|
|
164
|
+
} else {
|
|
165
|
+
return `OUT_OF_RANGE`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
undoStep(update) {
|
|
170
|
+
const breakpoint = update.indexOf(`:`);
|
|
171
|
+
const type = update.substring(0, breakpoint);
|
|
172
|
+
const value = update.substring(breakpoint + 1);
|
|
173
|
+
switch (type) {
|
|
174
|
+
case `add`:
|
|
175
|
+
this.delete(parseJson(value));
|
|
176
|
+
break;
|
|
177
|
+
case `del`:
|
|
178
|
+
this.add(parseJson(value));
|
|
179
|
+
break;
|
|
180
|
+
case `clear`: {
|
|
181
|
+
const values = JSON.parse(value);
|
|
182
|
+
for (const value2 of values)
|
|
183
|
+
this.add(value2);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case `tx`: {
|
|
187
|
+
const updates = value.split(`;`);
|
|
188
|
+
for (let i = updates.length - 1; i >= 0; i--) {
|
|
189
|
+
this.undoStep(updates[i]);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
undo(update) {
|
|
195
|
+
const breakpoint = update.indexOf(`=`);
|
|
196
|
+
const updateNumber = Number(update.substring(0, breakpoint));
|
|
197
|
+
if (updateNumber === this.cacheUpdateNumber) {
|
|
198
|
+
this.mode = `playback`;
|
|
199
|
+
const innerUpdate = update.substring(breakpoint + 1);
|
|
200
|
+
this.undoStep(innerUpdate);
|
|
201
|
+
this.mode = `record`;
|
|
202
|
+
this.cacheUpdateNumber--;
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return this.cacheUpdateNumber;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export { SetRTX };
|
|
210
|
+
//# sourceMappingURL=out.js.map
|
|
211
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/set-rtx.ts"],"names":["update","value"],"mappings":"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","sourcesContent":["import type { Transceiver, TransceiverMode } from \"atom.io/internal\"\nimport { Subject } from \"atom.io/internal\"\nimport type { Json, Stringified, primitive } from \"atom.io/json\"\nimport { parseJson, stringifyJson } from \"atom.io/json\"\n\nexport type SetUpdate =\n\t| `add:${string}`\n\t| `clear:${string}`\n\t| `del:${string}`\n\t| `tx:${string}`\nexport type NumberedSetUpdate = `${number}=${SetUpdate}`\n\nexport interface SetRTXJson<P extends primitive> extends Json.Object {\n\tmembers: P[]\n\tcache: (NumberedSetUpdate | null)[]\n\tcacheLimit: number\n\tcacheIdx: number\n\tcacheUpdateNumber: number\n}\nexport class SetRTX<P extends primitive>\n\textends Set<P>\n\timplements Transceiver<NumberedSetUpdate>\n{\n\tpublic mode: TransceiverMode = `record`\n\tpublic readonly subject = new Subject<SetUpdate>()\n\tpublic cacheLimit = 0\n\tpublic cache: (NumberedSetUpdate | null)[] = []\n\tpublic cacheIdx = -1\n\tpublic cacheUpdateNumber = -1\n\n\tpublic constructor(values?: Set<P> | readonly P[] | null, cacheLimit = 0) {\n\t\tsuper(values)\n\t\tif (values instanceof SetRTX) {\n\t\t\tthis.parent = values\n\t\t\tthis.cacheUpdateNumber = values.cacheUpdateNumber\n\t\t}\n\t\tif (cacheLimit) {\n\t\t\tthis.cacheLimit = cacheLimit\n\t\t\tthis.cache = new Array(cacheLimit)\n\t\t\tthis.subscribe(`auto cache`, (update) => {\n\t\t\t\tthis.cacheIdx++\n\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\tthis.cache[this.cacheIdx] = update\n\t\t\t})\n\t\t}\n\t}\n\n\tpublic toJSON(): SetRTXJson<P> {\n\t\treturn {\n\t\t\tmembers: [...this],\n\t\t\tcache: this.cache,\n\t\t\tcacheLimit: this.cacheLimit,\n\t\t\tcacheIdx: this.cacheIdx,\n\t\t\tcacheUpdateNumber: this.cacheUpdateNumber,\n\t\t}\n\t}\n\n\tpublic static fromJSON<P extends primitive>(json: SetRTXJson<P>): SetRTX<P> {\n\t\tconst set = new SetRTX<P>(json.members, json.cacheLimit)\n\t\tset.cache = json.cache\n\t\tset.cacheIdx = json.cacheIdx\n\t\tset.cacheUpdateNumber = json.cacheUpdateNumber\n\t\treturn set\n\t}\n\n\tpublic add(value: P): this {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`add:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.add(value)\n\t}\n\n\tpublic clear(): void {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`clear:${JSON.stringify([...this])}`)\n\t\t}\n\t\tsuper.clear()\n\t}\n\n\tpublic delete(value: P): boolean {\n\t\tif (this.mode === `record`) {\n\t\t\tthis.cacheUpdateNumber++\n\t\t\tthis.emit(`del:${stringifyJson<P>(value)}`)\n\t\t}\n\t\treturn super.delete(value)\n\t}\n\n\tpublic readonly parent: SetRTX<P> | null\n\tpublic child: SetRTX<P> | null = null\n\tpublic transactionUpdates: SetUpdate[] | null = null\n\tpublic transaction(run: (child: SetRTX<P>) => boolean): void {\n\t\tthis.mode = `transaction`\n\t\tthis.transactionUpdates = []\n\t\tthis.child = new SetRTX(this)\n\t\tconst unsubscribe = this.child._subscribe(`transaction`, (update) => {\n\t\t\tthis.transactionUpdates?.push(update)\n\t\t})\n\t\ttry {\n\t\t\tconst shouldCommit = run(this.child)\n\t\t\tif (shouldCommit) {\n\t\t\t\tthis.cacheUpdateNumber++\n\t\t\t\tthis.emit(`tx:${this.transactionUpdates.join(`;`)}`)\n\t\t\t\tfor (const update of this.transactionUpdates) {\n\t\t\t\t\tthis.doStep(update)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (thrown) {\n\t\t\tconsole.error(`Failed to apply transaction: ${thrown}`)\n\t\t} finally {\n\t\t\tunsubscribe()\n\t\t\tthis.child = null\n\t\t\tthis.transactionUpdates = null\n\t\t\tthis.mode = `record`\n\t\t}\n\t}\n\n\tprotected _subscribe(\n\t\tkey: string,\n\t\tfn: (update: SetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, fn)\n\t}\n\tpublic subscribe(\n\t\tkey: string,\n\t\tfn: (update: NumberedSetUpdate) => void,\n\t): () => void {\n\t\treturn this.subject.subscribe(key, (update) =>\n\t\t\tfn(`${this.cacheUpdateNumber}=${update}`),\n\t\t)\n\t}\n\n\tpublic emit(update: SetUpdate): void {\n\t\tthis.subject.next(update)\n\t}\n\n\tprivate doStep(update: SetUpdate): void {\n\t\tconst typeValueBreak = update.indexOf(`:`)\n\t\tconst type = update.substring(0, typeValueBreak)\n\t\tconst value = update.substring(typeValueBreak + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`:\n\t\t\t\tthis.clear()\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `tx`:\n\t\t\t\tfor (const update of value.split(`;`)) {\n\t\t\t\t\tthis.doStep(update as SetUpdate)\n\t\t\t\t}\n\t\t}\n\t}\n\n\tpublic do(update: NumberedSetUpdate): number | `OUT_OF_RANGE` | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tconst eventOffset = updateNumber - this.cacheUpdateNumber\n\t\tconst isFuture = eventOffset > 0\n\t\tif (isFuture) {\n\t\t\tif (eventOffset === 1) {\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.cacheUpdateNumber + 1\n\t\t} else {\n\t\t\tif (Math.abs(eventOffset) < this.cacheLimit) {\n\t\t\t\tconst eventIdx = this.cacheIdx + eventOffset\n\t\t\t\tconst cachedUpdate = this.cache[eventIdx]\n\t\t\t\tif (cachedUpdate === update) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t\tthis.mode = `playback`\n\t\t\t\tlet done = false\n\t\t\t\twhile (!done) {\n\t\t\t\t\tthis.cacheIdx %= this.cacheLimit\n\t\t\t\t\tconst update = this.cache[this.cacheIdx]\n\t\t\t\t\tthis.cacheIdx--\n\t\t\t\t\tif (!update) {\n\t\t\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t\t\t}\n\t\t\t\t\tconst undoRes = this.undo(update)\n\t\t\t\t\tdone = this.cacheIdx === eventIdx - 1\n\t\t\t\t}\n\t\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\t\tthis.doStep(innerUpdate)\n\t\t\t\tthis.mode = `record`\n\t\t\t\tthis.cacheUpdateNumber = updateNumber\n\t\t\t\treturn null\n\t\t\t} else {\n\t\t\t\treturn `OUT_OF_RANGE`\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undoStep(update: SetUpdate): void {\n\t\tconst breakpoint = update.indexOf(`:`)\n\t\tconst type = update.substring(0, breakpoint)\n\t\tconst value = update.substring(breakpoint + 1)\n\t\tswitch (type) {\n\t\t\tcase `add`:\n\t\t\t\tthis.delete(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `del`:\n\t\t\t\tthis.add(parseJson(value as Stringified<P>))\n\t\t\t\tbreak\n\t\t\tcase `clear`: {\n\t\t\t\tconst values = JSON.parse(value) as P[]\n\t\t\t\tfor (const value of values) this.add(value)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase `tx`: {\n\t\t\t\tconst updates = value.split(`;`) as SetUpdate[]\n\t\t\t\tfor (let i = updates.length - 1; i >= 0; i--) {\n\t\t\t\t\tthis.undoStep(updates[i])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic undo(update: NumberedSetUpdate): number | null {\n\t\tconst breakpoint = update.indexOf(`=`)\n\t\tconst updateNumber = Number(update.substring(0, breakpoint))\n\t\tif (updateNumber === this.cacheUpdateNumber) {\n\t\t\tthis.mode = `playback`\n\t\t\tconst innerUpdate = update.substring(breakpoint + 1) as SetUpdate\n\t\t\tthis.undoStep(innerUpdate)\n\t\t\tthis.mode = `record`\n\t\t\tthis.cacheUpdateNumber--\n\t\t\treturn null\n\t\t}\n\t\treturn this.cacheUpdateNumber\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./set-rtx"
|