sliftutils 1.4.81 → 1.4.83
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/index.d.ts +65 -13
- package/package.json +1 -1
- package/spec.txt +18 -0
- package/storage/dist/embeddingFormats.ts.cache +340 -0
- package/storage/dist/faceFramesData.ts.cache +55 -0
- package/storage/embeddingBench.d.ts +1 -0
- package/storage/embeddingBench.ts +152 -0
- package/storage/embeddingFormats.d.ts +4 -1
- package/storage/embeddingFormats.ts +173 -111
- package/storage/faceFramesData.d.ts +1 -0
- package/storage/faceFramesData.ts +49 -0
- package/storage/faceFramesServer.d.ts +1 -0
- package/storage/faceFramesServer.ts +56 -0
- package/storage/proxydatabase/dist/Database.ts.cache +13 -0
- package/storage/proxydatabase/dist/inMemoryDatabase.ts.cache +105 -0
- package/storage/proxydatabase/dist/ivfDbCheck.ts.cache +81 -0
- package/storage/proxydatabase/dist/ivfEmbeddingDatabase.ts.cache +334 -0
- package/storage/proxydatabase/dist/transactionSet.ts.cache +108 -0
- package/storage/proxydatabase/inMemoryDatabase.d.ts +13 -0
- package/storage/proxydatabase/inMemoryDatabase.ts +108 -0
- package/storage/proxydatabase/ivfDbCheck.d.ts +1 -0
- package/storage/proxydatabase/ivfDbCheck.ts +85 -0
- package/storage/proxydatabase/ivfEmbeddingDatabase.d.ts +15 -7
- package/storage/proxydatabase/ivfEmbeddingDatabase.ts +341 -144
- package/storage/proxydatabase/transactionSet.d.ts +9 -5
- package/storage/proxydatabase/transactionSet.ts +43 -22
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
3
|
+
//exports.removeEmbeddings = exports.insertEmbeddings = exports.searchEmbeddings = exports.rebuildStructure = void 0;
|
|
4
|
+
const Database_1 = require("./Database");
|
|
5
|
+
const transactionSet_1 = require("./transactionSet");
|
|
6
|
+
const embeddingFormats_1 = require("../embeddingFormats");
|
|
7
|
+
// Below this many embeddings we skip the IVF entirely (flat store). 1024 = a clean power of two.
|
|
8
|
+
const FLAT_LIMIT = 1024;
|
|
9
|
+
// Force a from-scratch rebuild once at each of these (multiples of 4 above FLAT_LIMIT, up to ~16k), gated by a step flag so each runs at most once ever.
|
|
10
|
+
const REGENERATE_AT = [4096, 16384];
|
|
11
|
+
const STEP_IVF = "ivf";
|
|
12
|
+
// On delete, the member's exact cell plus this many nearby cells are checked, in case a rebuild left it non-optimal.
|
|
13
|
+
const DELETE_FALLBACK_CELLS = 10;
|
|
14
|
+
const REBALANCE_ITERATIONS = 4;
|
|
15
|
+
function flatStore(database) {
|
|
16
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.flat);
|
|
17
|
+
}
|
|
18
|
+
function centroidStore(database) {
|
|
19
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.centroids);
|
|
20
|
+
}
|
|
21
|
+
function cellStore(database, cellId) {
|
|
22
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.cells[cellId]);
|
|
23
|
+
}
|
|
24
|
+
function readSteps(database) {
|
|
25
|
+
var _a;
|
|
26
|
+
return (_a = database.readData(root => root.steps)) !== null && _a !== void 0 ? _a : {};
|
|
27
|
+
}
|
|
28
|
+
function readCount(database) {
|
|
29
|
+
var _a;
|
|
30
|
+
return (_a = database.readData(root => root.count)) !== null && _a !== void 0 ? _a : 0;
|
|
31
|
+
}
|
|
32
|
+
function rankCellsByCloseness(embedding, centroids) {
|
|
33
|
+
const ranked = [];
|
|
34
|
+
for (const cellId of centroids.keys()) {
|
|
35
|
+
ranked.push({ cellId, closeness: (0, embeddingFormats_1.getCloseness)(embedding, centroids.get(cellId)) });
|
|
36
|
+
}
|
|
37
|
+
ranked.sort((left, right) => right.closeness - left.closeness);
|
|
38
|
+
return ranked.map(entry => entry.cellId);
|
|
39
|
+
}
|
|
40
|
+
// Per-write chance of a full rebuild. Zero at/under the target size, then rises (cubically) past it so cells
|
|
41
|
+
// stay roughly between target and ~2x target.
|
|
42
|
+
function rebalanceProbability(fillRatio) {
|
|
43
|
+
if (fillRatio <= 1) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
const over = fillRatio - 1;
|
|
47
|
+
return Math.min(1, over * over * over * 0.25);
|
|
48
|
+
}
|
|
49
|
+
// k-means. Decodes every member to a pooled float32 buffer ONCE, then assigns with a plain internal float
|
|
50
|
+
// dot (no getCloseness call — comparing two float vectors is trivial) and keeps centroids as float means,
|
|
51
|
+
// encoding them to StoredEmbedding only at the end. Releases the borrowed buffers when done.
|
|
52
|
+
function clusterMembers(members, clusterCount, config) {
|
|
53
|
+
const memberFloats = [];
|
|
54
|
+
for (const member of members) {
|
|
55
|
+
memberFloats.push((0, embeddingFormats_1.embeddingToFloat32)(member.embedding, true));
|
|
56
|
+
}
|
|
57
|
+
const length = memberFloats.length ? memberFloats[0].length : 0;
|
|
58
|
+
let centroids = [];
|
|
59
|
+
const seedStep = members.length / clusterCount;
|
|
60
|
+
for (let clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) {
|
|
61
|
+
centroids.push(new Float32Array(memberFloats[Math.floor(clusterIndex * seedStep)]));
|
|
62
|
+
}
|
|
63
|
+
let groups = [];
|
|
64
|
+
for (let iteration = 0; iteration < REBALANCE_ITERATIONS; iteration++) {
|
|
65
|
+
groups = [];
|
|
66
|
+
for (let clusterIndex = 0; clusterIndex < centroids.length; clusterIndex++) {
|
|
67
|
+
groups.push([]);
|
|
68
|
+
}
|
|
69
|
+
for (let memberIndex = 0; memberIndex < memberFloats.length; memberIndex++) {
|
|
70
|
+
const memberFloat = memberFloats[memberIndex];
|
|
71
|
+
let bestIndex = 0;
|
|
72
|
+
let bestDot = -Infinity;
|
|
73
|
+
for (let centroidIndex = 0; centroidIndex < centroids.length; centroidIndex++) {
|
|
74
|
+
const centroidFloat = centroids[centroidIndex];
|
|
75
|
+
let dot = 0;
|
|
76
|
+
for (let dim = 0; dim < length; dim++) {
|
|
77
|
+
dot += memberFloat[dim] * centroidFloat[dim];
|
|
78
|
+
}
|
|
79
|
+
if (dot > bestDot) {
|
|
80
|
+
bestDot = dot;
|
|
81
|
+
bestIndex = centroidIndex;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
groups[bestIndex].push(memberIndex);
|
|
85
|
+
}
|
|
86
|
+
const nextCentroids = [];
|
|
87
|
+
const nextGroups = [];
|
|
88
|
+
for (const group of groups) {
|
|
89
|
+
if (!group.length) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const mean = new Float32Array(length);
|
|
93
|
+
for (const memberIndex of group) {
|
|
94
|
+
const memberFloat = memberFloats[memberIndex];
|
|
95
|
+
for (let dim = 0; dim < length; dim++) {
|
|
96
|
+
mean[dim] += memberFloat[dim];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let norm = 0;
|
|
100
|
+
for (let dim = 0; dim < length; dim++) {
|
|
101
|
+
norm += mean[dim] * mean[dim];
|
|
102
|
+
}
|
|
103
|
+
const magnitude = Math.sqrt(norm) || 1;
|
|
104
|
+
for (let dim = 0; dim < length; dim++) {
|
|
105
|
+
mean[dim] /= magnitude;
|
|
106
|
+
}
|
|
107
|
+
nextCentroids.push(mean);
|
|
108
|
+
nextGroups.push(group);
|
|
109
|
+
}
|
|
110
|
+
centroids = nextCentroids;
|
|
111
|
+
groups = nextGroups;
|
|
112
|
+
}
|
|
113
|
+
const result = [];
|
|
114
|
+
for (let clusterIndex = 0; clusterIndex < centroids.length; clusterIndex++) {
|
|
115
|
+
const centroid = (0, embeddingFormats_1.encodeEmbedding)({ input: centroids[clusterIndex], format: config.format, model: config.model });
|
|
116
|
+
const cellMembers = [];
|
|
117
|
+
for (const memberIndex of groups[clusterIndex]) {
|
|
118
|
+
cellMembers.push(members[memberIndex]);
|
|
119
|
+
}
|
|
120
|
+
result.push({ centroid, members: cellMembers });
|
|
121
|
+
}
|
|
122
|
+
for (const memberFloat of memberFloats) {
|
|
123
|
+
(0, embeddingFormats_1.releaseFloat32)(memberFloat);
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
// Re-cluster EVERY embedding (flat tier + all cells) into a fresh IVF, clear the flat tier, and mark IVF
|
|
128
|
+
// mode. This is the rearranger: run probabilistically as the set grows, once at each regenerate threshold,
|
|
129
|
+
// and once to upgrade from flat. Reads everything it uses, so it bails (does nothing) if anything isn't
|
|
130
|
+
// synced and the caller's retry re-runs it; no caller cares about its result.
|
|
131
|
+
function rebuildStructure(database) {
|
|
132
|
+
const config = database.readData(root => root.config);
|
|
133
|
+
if (!config)
|
|
134
|
+
return;
|
|
135
|
+
const allMembers = [];
|
|
136
|
+
const flat = (0, transactionSet_1.transactionRead)(flatStore(database));
|
|
137
|
+
if (!flat)
|
|
138
|
+
return;
|
|
139
|
+
for (const ref of flat.keys()) {
|
|
140
|
+
allMembers.push({ ref, embedding: flat.get(ref) });
|
|
141
|
+
}
|
|
142
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
143
|
+
if (!centroids)
|
|
144
|
+
return;
|
|
145
|
+
const oldCellIds = Array.from(centroids.keys());
|
|
146
|
+
const cellStores = database.readData(root => oldCellIds.map(cellId => root.cells[cellId]));
|
|
147
|
+
if (!cellStores)
|
|
148
|
+
return;
|
|
149
|
+
for (const store of cellStores) {
|
|
150
|
+
const members = (0, transactionSet_1.replayTransactionStore)(store);
|
|
151
|
+
for (const ref of members.keys()) {
|
|
152
|
+
allMembers.push({ ref, embedding: members.get(ref) });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!allMembers.length)
|
|
156
|
+
return;
|
|
157
|
+
const clusterCount = Math.max(1, Math.round(allMembers.length / config.cellTargetSize));
|
|
158
|
+
const clusters = clusterMembers(allMembers, clusterCount, config);
|
|
159
|
+
const newCellIds = new Set();
|
|
160
|
+
const centroidWrites = [];
|
|
161
|
+
for (const cluster of clusters) {
|
|
162
|
+
const cellId = (0, embeddingFormats_1.hashEmbedding)(cluster.centroid);
|
|
163
|
+
newCellIds.add(cellId);
|
|
164
|
+
centroidWrites.push({ key: cellId, value: cluster.centroid });
|
|
165
|
+
const memberWrites = cluster.members.map(member => ({ key: member.ref, value: member.embedding }));
|
|
166
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberWrites);
|
|
167
|
+
}
|
|
168
|
+
for (const oldCellId of oldCellIds) {
|
|
169
|
+
if (newCellIds.has(oldCellId)) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
centroidWrites.push({ key: oldCellId, value: undefined });
|
|
173
|
+
database.deleteData(root => root.cells[oldCellId]);
|
|
174
|
+
}
|
|
175
|
+
(0, transactionSet_1.transactionMutate)(centroidStore(database), centroidWrites);
|
|
176
|
+
database.deleteData(root => root.flat);
|
|
177
|
+
database.writeData(root => root.count, allMembers.length);
|
|
178
|
+
database.writeData(root => root.steps[STEP_IVF], true);
|
|
179
|
+
}
|
|
180
|
+
exports.rebuildStructure = rebuildStructure;
|
|
181
|
+
function searchEmbeddings(database, query, options) {
|
|
182
|
+
const config = database.readData(root => root.config);
|
|
183
|
+
if (!config)
|
|
184
|
+
return undefined;
|
|
185
|
+
const steps = readSteps(database);
|
|
186
|
+
const hits = [];
|
|
187
|
+
if (!steps[STEP_IVF]) {
|
|
188
|
+
const flat = (0, transactionSet_1.transactionRead)(flatStore(database));
|
|
189
|
+
if (!flat)
|
|
190
|
+
return undefined;
|
|
191
|
+
for (const ref of flat.keys()) {
|
|
192
|
+
hits.push({ ref, closeness: (0, embeddingFormats_1.getCloseness)(query, flat.get(ref)) });
|
|
193
|
+
}
|
|
194
|
+
hits.sort((left, right) => right.closeness - left.closeness);
|
|
195
|
+
return hits.slice(0, options.resultCount);
|
|
196
|
+
}
|
|
197
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
198
|
+
if (!centroids)
|
|
199
|
+
return undefined;
|
|
200
|
+
if (!centroids.size)
|
|
201
|
+
return [];
|
|
202
|
+
const probeCellCount = Math.max(1, Math.ceil(options.probeBudget / config.cellTargetSize));
|
|
203
|
+
const probeCellIds = rankCellsByCloseness(query, centroids).slice(0, probeCellCount);
|
|
204
|
+
const stores = database.readData(root => probeCellIds.map(cellId => root.cells[cellId]));
|
|
205
|
+
if (!stores)
|
|
206
|
+
return undefined;
|
|
207
|
+
for (const store of stores) {
|
|
208
|
+
const members = (0, transactionSet_1.replayTransactionStore)(store);
|
|
209
|
+
for (const ref of members.keys()) {
|
|
210
|
+
hits.push({ ref, closeness: (0, embeddingFormats_1.getCloseness)(query, members.get(ref)) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
hits.sort((left, right) => right.closeness - left.closeness);
|
|
214
|
+
return hits.slice(0, options.resultCount);
|
|
215
|
+
}
|
|
216
|
+
exports.searchEmbeddings = searchEmbeddings;
|
|
217
|
+
function insertEmbeddings(database, items) {
|
|
218
|
+
if (!items.length)
|
|
219
|
+
return true;
|
|
220
|
+
const config = database.readData(root => root.config);
|
|
221
|
+
if (!config)
|
|
222
|
+
return undefined;
|
|
223
|
+
const steps = readSteps(database);
|
|
224
|
+
const newCount = readCount(database) + items.length;
|
|
225
|
+
if (!steps[STEP_IVF]) {
|
|
226
|
+
const flatWrites = items.map(item => ({ key: item.ref, value: item.embedding }));
|
|
227
|
+
(0, transactionSet_1.transactionMutate)(flatStore(database), flatWrites);
|
|
228
|
+
database.writeData(root => root.count, newCount);
|
|
229
|
+
if (newCount > FLAT_LIMIT) {
|
|
230
|
+
rebuildStructure(database);
|
|
231
|
+
}
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
235
|
+
if (!centroids)
|
|
236
|
+
return undefined;
|
|
237
|
+
const itemsByCell = new Map();
|
|
238
|
+
for (const item of items) {
|
|
239
|
+
const cellId = rankCellsByCloseness(item.embedding, centroids)[0];
|
|
240
|
+
let group = itemsByCell.get(cellId);
|
|
241
|
+
if (!group) {
|
|
242
|
+
group = [];
|
|
243
|
+
itemsByCell.set(cellId, group);
|
|
244
|
+
}
|
|
245
|
+
group.push(item);
|
|
246
|
+
}
|
|
247
|
+
for (const cellId of itemsByCell.keys()) {
|
|
248
|
+
const group = itemsByCell.get(cellId);
|
|
249
|
+
const memberWrites = group.map(item => ({ key: item.ref, value: item.embedding }));
|
|
250
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberWrites);
|
|
251
|
+
}
|
|
252
|
+
database.writeData(root => root.count, newCount);
|
|
253
|
+
let regenerated = false;
|
|
254
|
+
for (const threshold of REGENERATE_AT) {
|
|
255
|
+
const stepName = "regen" + threshold;
|
|
256
|
+
if (!steps[stepName] && newCount > threshold) {
|
|
257
|
+
rebuildStructure(database);
|
|
258
|
+
database.writeData(root => root.steps[stepName], true);
|
|
259
|
+
regenerated = true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!regenerated) {
|
|
263
|
+
const averageFill = newCount / Math.max(1, centroids.size) / config.cellTargetSize;
|
|
264
|
+
if (Math.random() < rebalanceProbability(averageFill)) {
|
|
265
|
+
rebuildStructure(database);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
exports.insertEmbeddings = insertEmbeddings;
|
|
271
|
+
function removeEmbeddings(database, items) {
|
|
272
|
+
if (!items.length)
|
|
273
|
+
return true;
|
|
274
|
+
const steps = readSteps(database);
|
|
275
|
+
const count = readCount(database);
|
|
276
|
+
if (!steps[STEP_IVF]) {
|
|
277
|
+
const flatDeletes = items.map(item => ({ key: item.ref, value: undefined }));
|
|
278
|
+
(0, transactionSet_1.transactionMutate)(flatStore(database), flatDeletes);
|
|
279
|
+
database.writeData(root => root.count, Math.max(0, count - items.length));
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
283
|
+
if (!centroids)
|
|
284
|
+
return undefined;
|
|
285
|
+
if (!centroids.size)
|
|
286
|
+
return true;
|
|
287
|
+
const candidatesByItem = [];
|
|
288
|
+
const candidateSet = new Set();
|
|
289
|
+
for (const item of items) {
|
|
290
|
+
const cellIds = rankCellsByCloseness(item.embedding, centroids).slice(0, 1 + DELETE_FALLBACK_CELLS);
|
|
291
|
+
candidatesByItem.push({ ref: item.ref, cellIds });
|
|
292
|
+
for (const cellId of cellIds) {
|
|
293
|
+
candidateSet.add(cellId);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const candidateCellIds = Array.from(candidateSet);
|
|
297
|
+
const stores = database.readData(root => candidateCellIds.map(cellId => root.cells[cellId]));
|
|
298
|
+
if (!stores)
|
|
299
|
+
return undefined;
|
|
300
|
+
const membersByCell = new Map();
|
|
301
|
+
for (let index = 0; index < candidateCellIds.length; index++) {
|
|
302
|
+
membersByCell.set(candidateCellIds[index], (0, transactionSet_1.replayTransactionStore)(stores[index]));
|
|
303
|
+
}
|
|
304
|
+
const deletesByCell = new Map();
|
|
305
|
+
for (const candidate of candidatesByItem) {
|
|
306
|
+
for (const cellId of candidate.cellIds) {
|
|
307
|
+
const members = membersByCell.get(cellId);
|
|
308
|
+
if (!members || !members.has(candidate.ref)) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
let refs = deletesByCell.get(cellId);
|
|
312
|
+
if (!refs) {
|
|
313
|
+
refs = [];
|
|
314
|
+
deletesByCell.set(cellId, refs);
|
|
315
|
+
}
|
|
316
|
+
refs.push(candidate.ref);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
let deletedCount = 0;
|
|
321
|
+
for (const cellId of deletesByCell.keys()) {
|
|
322
|
+
const refs = deletesByCell.get(cellId);
|
|
323
|
+
deletedCount += refs.length;
|
|
324
|
+
const memberDeletes = refs.map(ref => ({ key: ref, value: undefined }));
|
|
325
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberDeletes);
|
|
326
|
+
}
|
|
327
|
+
if (deletedCount) {
|
|
328
|
+
database.writeData(root => root.count, Math.max(0, count - deletedCount));
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
exports.removeEmbeddings = removeEmbeddings;
|
|
333
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXZmRW1iZWRkaW5nRGF0YWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpdmZFbWJlZGRpbmdEYXRhYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBeUQ7QUFDekQscURBQW1IO0FBQ25ILDBEQUF5SjtBQTBCekosaUdBQWlHO0FBQ2pHLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQztBQUN4Qix5SkFBeUo7QUFDekosTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDcEMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQ3ZCLHFIQUFxSDtBQUNySCxNQUFNLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztBQUNqQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUUvQixTQUFTLFNBQVMsQ0FBQyxRQUFvQztJQUNuRCxPQUFPLElBQUEsNEJBQWlCLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFDRCxTQUFTLGFBQWEsQ0FBQyxRQUFvQztJQUN2RCxPQUFPLElBQUEsNEJBQWlCLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUFDRCxTQUFTLFNBQVMsQ0FBQyxRQUFvQyxFQUFFLE1BQWM7SUFDbkUsT0FBTyxJQUFBLDRCQUFpQixFQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNuRSxDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsUUFBb0M7O0lBQ25ELE9BQU8sTUFBQSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxtQ0FBSSxFQUFFLENBQUM7QUFDdkQsQ0FBQztB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QUFZLENBQUMsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNoQixDQUFDO0FBakVELDRDQWlFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFiYXNlLCBuYW1lc3BhY2VEYXRhYmFzZSB9IGZyb20gXCIuL0RhdGFiYXNlXCI7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblNldFN0b3JlLCB0cmFuc2FjdGlvblJlYWQsIHRyYW5zYWN0aW9uTXV0YXRlLCByZXBsYXlUcmFuc2FjdGlvblN0b3JlIH0gZnJvbSBcIi4vdHJhbnNhY3Rpb25TZXRcIjtcbmltcG9ydCB7IFN0b3JlZEVtYmVkZGluZywgRW1iZWRkaW5nRm9ybWF0LCBnZXRDbG9zZW5lc3MsIGVtYmVkZGluZ1RvRmxvYXQzMiwgcmVsZWFzZUZsb2F0MzIsIGVuY29kZUVtYmVkZGluZywgaGFzaEVtYmVkZGluZyB9IGZyb20gXCIuLi9lbWJlZGRpbmdGb3JtYXRzXCI7XG5cbmV4cG9ydCB0eXBlIEl2ZkNvbmZpZyA9IHtcbiAgICBtb2RlbDogc3RyaW5nO1xuICAgIGZvcm1hdDogRW1iZWRkaW5nRm9ybWF0O1xuICAgIC8vIFRhcmdldCBudW1iZXIgb2YgZW1iZWRkaW5ncyBwZXIgY2VsbC5cbiAgICBjZWxsVGFyZ2V0U2l6ZTogbnVtYmVyO1xufTtcblxuLy8gVGllcmVkIHN0b3JhZ2UuIEJlbG93IEZMQVRfTElNSVQgZW1iZWRkaW5ncyB0aGUgd2hvbGUgc2V0IGxpdmVzIGluIG9uZSBmbGF0IHRyYW5zYWN0aW9uIHNldCAobm8gSVZGKTtcbi8vIG9uY2UgaXQgZ3Jvd3MgcGFzdCB0aGF0IHdlIGJ1aWxkIHRoZSBJVkYgKGNlbnRyb2lkcyArIHBlci1jZWxsIHNldHMpIGFuZCBzdGF5IHRoZXJlIGZvcmV2ZXIuIGBjb3VudGAgaXNcbi8vIHRoZSBsaXZlIGVtYmVkZGluZyBjb3VudCAocmUtZGVyaXZlZCBleGFjdGx5IG9uIGEgcmVidWlsZCkuIGBzdGVwc2AgcmVjb3JkcyBvbmUtdGltZSB1cGdyYWRlcyB0aGF0IG11c3Rcbi8vIG5ldmVyIHJlLXJ1biBldmVuIGlmIHRoZSBzZXQgbGF0ZXIgc2hyaW5rcyBhbmQgcmVncm93cy5cbmV4cG9ydCB0eXBlIEl2ZkVtYmVkZGluZ1Jvb3QgPSB7XG4gICAgY29uZmlnOiBJdmZDb25maWc7XG4gICAgY291bnQ6IG51bWJlcjtcbiAgICBmbGF0OiBUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz47XG4gICAgc3RlcHM6IHsgW3N0ZXA6IHN0cmluZ106IGJvb2xlYW4gfTtcbiAgICBjZW50cm9pZHM6IFRyYW5zYWN0aW9uU2V0U3RvcmU8U3RvcmVkRW1iZWRkaW5nPjtcbiAgICBjZWxsczogeyBbY2VsbElkOiBzdHJpbmddOiBUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz4gfTtcbn07XG5cbmV4cG9ydCB0eXBlIEVtYmVkZGluZ0lucHV0ID0geyByZWY6IHN0cmluZzsgZW1iZWRkaW5nOiBTdG9yZWRFbWJlZGRpbmcgfTtcbmV4cG9ydCB0eXBlIFNlYXJjaEhpdCA9IHsgcmVmOiBzdHJpbmc7IGNsb3NlbmVzczogbnVtYmVyIH07XG50eXBlIENlbGxFbnRyeSA9IHsgcmVmOiBzdHJpbmc7IGVtYmVkZGluZzogU3RvcmVkRW1iZWRkaW5nIH07XG5cbi8vIEJlbG93IHRoaXMgbWFueSBlbWJlZGRpbmdzIHdlIHNraXAgdGhlIElWRiBlbnRpcmVseSAoZmxhdCBzdG9yZSkuIDEwMjQgPSBhIGNsZWFuIHBvd2VyIG9mIHR3by5cbmNvbnN0IEZMQVRfTElNSVQgPSAxMDI0O1xuLy8gRm9yY2UgYSBmcm9tLXNjcmF0Y2ggcmVidWlsZCBvbmNlIGF0IGVhY2ggb2YgdGhlc2UgKG11bHRpcGxlcyBvZiA0IGFib3ZlIEZMQVRfTElNSVQsIHVwIHRvIH4xNmspLCBnYXRlZCBieSBhIHN0ZXAgZmxhZyBzbyBlYWNoIHJ1bnMgYXQgbW9zdCBvbmNlIGV2ZXIuXG5jb25zdCBSRUdFTkVSQVRFX0FUID0gWzQwOTYsIDE2Mzg0XTtcbmNvbnN0IFNURVBfSVZGID0gXCJpdmZcIjtcbi8vIE9uIGRlbGV0ZSwgdGhlIG1lbWJlcidzIGV4YWN0IGNlbGwgcGx1cyB0aGlzIG1hbnkgbmVhcmJ5IGNlbGxzIGFyZSBjaGVja2VkLCBpbiBjYXNlIGEgcmVidWlsZCBsZWZ0IGl0IG5vbi1vcHRpbWFsLlxuY29uc3QgREVMRVRFX0ZBTExCQUNLX0NFTExTID0gMTA7XG5jb25zdCBSRUJBTEFOQ0VfSVRFUkFUSU9OUyA9IDQ7XG5cbmZ1bmN0aW9uIGZsYXRTdG9yZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiBEYXRhYmFzZTxUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz4+IHtcbiAgICByZXR1cm4gbmFtZXNwYWNlRGF0YWJhc2UoZGF0YWJhc2UsIHJvb3QgPT4gcm9vdC5mbGF0KTtcbn1cbmZ1bmN0aW9uIGNlbnRyb2lkU3RvcmUoZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+KTogRGF0YWJhc2U8VHJhbnNhY3Rpb25TZXRTdG9yZTxTdG9yZWRFbWJlZGRpbmc+PiB7XG4gICAgcmV0dXJuIG5hbWVzcGFjZURhdGFiYXNlKGRhdGFiYXNlLCByb290ID0+IHJvb3QuY2VudHJvaWRzKTtcbn1cbmZ1bmN0aW9uIGNlbGxTdG9yZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4sIGNlbGxJZDogc3RyaW5nKTogRGF0YWJhc2U8VHJhbnNhY3Rpb25TZXRTdG9yZTxTdG9yZWRFbWJlZGRpbmc+PiB7XG4gICAgcmV0dXJuIG5hbWVzcGFjZURhdGFiYXNlKGRhdGFiYXNlLCByb290ID0+IHJvb3QuY2VsbHNbY2VsbElkXSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRTdGVwcyhkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiB7IFtzdGVwOiBzdHJpbmddOiBib29sZWFuIH0ge1xuICAgIHJldHVybiBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHJvb3Quc3RlcHMpID8/IHt9O1xufVxuZnVuY3Rpb24gcmVhZENvdW50KGRhdGFiYXNlOiBEYXRhYmFzZTxJdmZFbWJlZGRpbmdSb290Pik6IG51bWJlciB7XG4gICAgcmV0dXJuIGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb3VudCkgPz8gMDtcbn1cblxuZnVuY3Rpb24gcmFua0NlbGxzQnlDbG9zZW5lc3MoZW1iZWRkaW5nOiBTdG9yZWRFbWJlZGRpbmcsIGNlbnRyb2lkczogTWFwPHN0cmluZywgU3RvcmVkRW1iZWRkaW5nPik6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByYW5rZWQ6IHsgY2VsbElkOiBzdHJpbmc7IGNsb3NlbmVzczogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY2VsbElkIG9mIGNlbnRyb2lkcy5rZXlzKCkpIHtcbiAgICAgICAgcmFua2VkLnB1c2goeyBjZWxsSWQsIGNsb3NlbmVzczogZ2V0Q2xvc2VuZXNzKGVtYmVkZGluZywgY2VudHJvaWRzLmdldChjZWxsSWQpISkgfSk7XG4gICAgfVxuICAgIHJhbmtlZC5zb3J0KChsZWZ0LCByaWdodCkgPT4gcmlnaHQuY2xvc2VuZXNzIC0gbGVmdC5jbG9zZW5lc3MpO1xuICAgIHJldHVybiByYW5rZWQubWFwKGVudHJ5ID0+IGVudHJ5LmNlbGxJZCk7XG59XG5cbi8vIFBlci13cml0ZSBjaGFuY2Ugb2YgYSBmdWxsIHJlYnVpbGQuIFplcm8gYXQvdW5kZXIgdGhlIHRhcmdldCBzaXplLCB0aGVuIHJpc2VzIChjdWJpY2FsbHkpIHBhc3QgaXQgc28gY2VsbHNcbi8vIHN0YXkgcm91Z2hseSBiZXR3ZWVuIHRhcmdldCBhbmQgfjJ4IHRhcmdldC5cbmZ1bmN0aW9uIHJlYmFsYW5jZVByb2JhYmlsaXR5KGZpbGxSYXRpbzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoZmlsbFJhdGlvIDw9IDEpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IG92ZXIgPSBmaWxsUmF0aW8gLSAxO1xuICAgIHJldHVybiBNYXRoLm1pbigxLCBvdmVyICogb3ZlciAqIG92ZXIgKiAwLjI1KTtcbn1cblxuLy8gay1tZWFucy4gRGVjb2RlcyBldmVyeSBtZW1iZXIgdG8gYSBwb29sZWQgZmxvYXQzMiBidWZmZXIgT05DRSwgdGhlbiBhc3NpZ25zIHdpdGggYSBwbGFpbiBpbnRlcm5hbCBmbG9hdFxuLy8gZG90IChubyBnZXRDbG9zZW5lc3MgY2FsbCDigJQgY29tcGFyaW5nIHR3byBmbG9hdCB2ZWN0b3JzIGlzIHRyaXZpYWwpIGFuZCBrZWVwcyBjZW50cm9pZHMgYXMgZmxvYXQgbWVhbnMsXG4vLyBlbmNvZGluZyB0aGVtIHRvIFN0b3JlZEVtYmVkZGluZyBvbmx5IGF0IHRoZSBlbmQuIFJlbGVhc2VzIHRoZSBib3Jyb3dlZCBidWZmZXJzIHdoZW4gZG9uZS5cbmZ1bmN0aW9uIGNsdXN0ZXJNZW1iZXJzKG1lbWJlcnM6IENlbGxFbnRyeVtdLCBjbHVzdGVyQ291bnQ6IG51bWJlciwgY29uZmlnOiBJdmZDb25maWcpOiB7IGNlbnRyb2lkOiBTdG9yZWRFbWJlZGRpbmc7IG1lbWJlcnM6IENlbGxFbnRyeVtdIH1bXSB7XG4gICAgY29uc3QgbWVtYmVyRmxvYXRzOiBGbG9hdDMyQXJyYXlbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIG1lbWJlcnMpIHtcbiAgICAgICAgbWVtYmVyRmxvYXRzLnB1c2goZW1iZWRkaW5nVG9GbG9hdDMyKG1lbWJlci5lbWJlZGRpbmcsIHRydWUpKTtcbiAgICB9XG4gICAgY29uc3QgbGVuZ3RoID0gbWVtYmVyRmxvYXRzLmxlbmd0aCA/IG1lbWJlckZsb2F0c1swXS5sZW5ndGggOiAwO1xuICAgIGxldCBjZW50cm9pZHM6IEZsb2F0MzJBcnJheVtdID0gW107XG4gICAgY29uc3Qgc2VlZFN0ZXAgPSBtZW1iZXJzLmxlbmd0aCAvIGNsdXN0ZXJDb3VudDtcbiAgICBmb3IgKGxldCBjbHVzdGVySW5kZXggPSAwOyBjbHVzdGVySW5kZXggPCBjbHVzdGVyQ291bnQ7IGNsdXN0ZXJJbmRleCsrKSB7XG4gICAgICAgIGNlbnRyb2lkcy5wdXNoKG5ldyBGbG9hdDMyQXJyYXkobWVtYmVyRmxvYXRzW01hdGguZmxvb3IoY2x1c3RlckluZGV4ICogc2VlZFN0ZXApXSkpO1xuICAgIH1cbiAgICBsZXQgZ3JvdXBzOiBudW1iZXJbXVtdID0gW107XG4gICAgZm9yIChsZXQgaXRlcmF0aW9uID0gMDsgaXRlcmF0aW9uIDwgUkVCQUxBTkNFX0lURVJBVElPTlM7IGl0ZXJhdGlvbisrKSB7XG4gICAgICAgIGdyb3VwcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbHVzdGVySW5kZXggPSAwOyBjbHVzdGVySW5kZXggPCBjZW50cm9pZHMubGVuZ3RoOyBjbHVzdGVySW5kZXgrKykge1xuICAgICAgICAgICAgZ3JvdXBzLnB1c2goW10pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IG1lbWJlckluZGV4ID0gMDsgbWVtYmVySW5kZXggPCBtZW1iZXJGbG9hdHMubGVuZ3RoOyBtZW1iZXJJbmRleCsrKSB7XG4gICAgICAgICAgICBjb25zdCBtZW1iZXJGbG9hdCA9IG1lbWJlckZsb2F0c1ttZW1iZXJJbmRleF07XG4gICAgICAgICAgICBsZXQgYmVzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBiZXN0RG90ID0gLUluZmluaXR5O1xuICAgICAgICAgICAgZm9yIChsZXQgY2VudHJvaWRJbmRleCA9IDA7IGNlbnRyb2lkSW5kZXggPCBjZW50cm9pZHMubGVuZ3RoOyBjZW50cm9pZEluZGV4KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjZW50cm9pZEZsb2F0ID0gY2VudHJvaWRzW2NlbnRyb2lkSW5kZXhdO1xuICAgICAgICAgICAgICAgIGxldCBkb3QgPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGxlbmd0aDsgZGltKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZG90ICs9IG1lbWJlckZsb2F0W2RpbV0gKiBjZW50cm9pZEZsb2F0W2RpbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkb3QgPiBiZXN0RG90KSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3REb3QgPSBkb3Q7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RJbmRleCA9IGNlbnRyb2lkSW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ3JvdXBzW2Jlc3RJbmRleF0ucHVzaChtZW1iZXJJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmV4dENlbnRyb2lkczogRmxvYXQzMkFycmF5W10gPSBbXTtcbiAgICAgICAgY29uc3QgbmV4dEdyb3VwczogbnVtYmVyW11bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIGdyb3Vwcykge1xuICAgICAgICAgICAgaWYgKCFncm91cC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1lYW4gPSBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlckluZGV4IG9mIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWVtYmVyRmxvYXQgPSBtZW1iZXJGbG9hdHNbbWVtYmVySW5kZXhdO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGxlbmd0aDsgZGltKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWVhbltkaW1dICs9IG1lbWJlckZsb2F0W2RpbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG5vcm0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgbGVuZ3RoOyBkaW0rKykge1xuICAgICAgICAgICAgICAgIG5vcm0gKz0gbWVhbltkaW1dICogbWVhbltkaW1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWFnbml0dWRlID0gTWF0aC5zcXJ0KG5vcm0pIHx8IDE7XG4gICAgICAgICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBsZW5ndGg7IGRpbSsrKSB7XG4gICAgICAgICAgICAgICAgbWVhbltkaW1dIC89IG1hZ25pdHVkZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHRDZW50cm9pZHMucHVzaChtZWFuKTtcbiAgICAgICAgICAgIG5leHRHcm91cHMucHVzaChncm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgY2VudHJvaWRzID0gbmV4dENlbnRyb2lkcztcbiAgICAgICAgZ3JvdXBzID0gbmV4dEdyb3VwcztcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0OiB7IGNlbnRyb2lkOiBTdG9yZWRFbWJlZGRpbmc7IG1lbWJlcnM6IENlbGxFbnRyeVtdIH1bXSA9IFtdO1xuICAgIGZvciAobGV0IGNsdXN0ZXJJbmRleCA9IDA7IGNsdXN0ZXJJbmRleCA8IGNlbnRyb2lkcy5sZW5ndGg7IGNsdXN0ZXJJbmRleCsrKSB7XG4gICAgICAgIGNvbnN0IGNlbnRyb2lkID0gZW5jb2RlRW1iZWRkaW5nKHsgaW5wdXQ6IGNlbnRyb2lkc1tjbHVzdGVySW5kZXhdLCBmb3JtYXQ6IGNvbmZpZy5mb3JtYXQsIG1vZGVsOiBjb25maWcubW9kZWwgfSk7XG4gICAgICAgIGNvbnN0IGNlbGxNZW1iZXJzOiBDZWxsRW50cnlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IG1lbWJlckluZGV4IG9mIGdyb3Vwc1tjbHVzdGVySW5kZXhdKSB7XG4gICAgICAgICAgICBjZWxsTWVtYmVycy5wdXNoKG1lbWJlcnNbbWVtYmVySW5kZXhdKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQucHVzaCh7IGNlbnRyb2lkLCBtZW1iZXJzOiBjZWxsTWVtYmVycyB9KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBtZW1iZXJGbG9hdCBvZiBtZW1iZXJGbG9hdHMpIHtcbiAgICAgICAgcmVsZWFzZUZsb2F0MzIobWVtYmVyRmxvYXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vLyBSZS1jbHVzdGVyIEVWRVJZIGVtYmVkZGluZyAoZmxhdCB0aWVyICsgYWxsIGNlbGxzKSBpbnRvIGEgZnJlc2ggSVZGLCBjbGVhciB0aGUgZmxhdCB0aWVyLCBhbmQgbWFyayBJVkZcbi8vIG1vZGUuIFRoaXMgaXMgdGhlIHJlYXJyYW5nZXI6IHJ1biBwcm9iYWJpbGlzdGljYWxseSBhcyB0aGUgc2V0IGdyb3dzLCBvbmNlIGF0IGVhY2ggcmVnZW5lcmF0ZSB0aHJlc2hvbGQsXG4vLyBhbmQgb25jZSB0byB1cGdyYWRlIGZyb20gZmxhdC4gUmVhZHMgZXZlcnl0aGluZyBpdCB1c2VzLCBzbyBpdCBiYWlscyAoZG9lcyBub3RoaW5nKSBpZiBhbnl0aGluZyBpc24ndFxuLy8gc3luY2VkIGFuZCB0aGUgY2FsbGVyJ3MgcmV0cnkgcmUtcnVucyBpdDsgbm8gY2FsbGVyIGNhcmVzIGFib3V0IGl0cyByZXN1bHQuXG5leHBvcnQgZnVuY3Rpb24gcmVidWlsZFN0cnVjdHVyZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHJvb3QuY29uZmlnKTtcbiAgICBpZiAoIWNvbmZpZykgcmV0dXJuO1xuXG4gICAgY29uc3QgYWxsTWVtYmVyczogQ2VsbEVudHJ5W10gPSBbXTtcbiAgICBjb25zdCBmbGF0ID0gdHJhbnNhY3Rpb25SZWFkKGZsYXRTdG9yZShkYXRhYmFzZSkpO1xuICAgIGlmICghZmxhdCkgcmV0dXJuO1xuICAgIGZvciAoY29uc3QgcmVmIG9mIGZsYXQua2V5cygpKSB7XG4gICAgICAgIGFsbE1lbWJlcnMucHVzaCh7IHJlZiwgZW1iZWRkaW5nOiBmbGF0LmdldChyZWYpISB9KTtcbiAgICB9XG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuO1xuICAgIGNvbnN0IG9sZENlbGxJZHMgPSBBcnJheS5mcm9tKGNlbnRyb2lkcy5rZXlzKCkpO1xuICAgIGNvbnN0IGNlbGxTdG9yZXMgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IG9sZENlbGxJZHMubWFwKGNlbGxJZCA9PiByb290LmNlbGxzW2NlbGxJZF0pKTtcbiAgICBpZiAoIWNlbGxTdG9yZXMpIHJldHVybjtcbiAgICBmb3IgKGNvbnN0IHN0b3JlIG9mIGNlbGxTdG9yZXMpIHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IHJlcGxheVRyYW5zYWN0aW9uU3RvcmU8U3RvcmVkRW1iZWRkaW5nPihzdG9yZSk7XG4gICAgICAgIGZvciAoY29uc3QgcmVmIG9mIG1lbWJlcnMua2V5cygpKSB7XG4gICAgICAgICAgICBhbGxNZW1iZXJzLnB1c2goeyByZWYsIGVtYmVkZGluZzogbWVtYmVycy5nZXQocmVmKSEgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFhbGxNZW1iZXJzLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgY2x1c3RlckNvdW50ID0gTWF0aC5tYXgoMSwgTWF0aC5yb3VuZChhbGxNZW1iZXJzLmxlbmd0aCAvIGNvbmZpZy5jZWxsVGFyZ2V0U2l6ZSkpO1xuICAgIGNvbnN0IGNsdXN0ZXJzID0gY2x1c3Rlck1lbWJlcnMoYWxsTWVtYmVycywgY2x1c3RlckNvdW50LCBjb25maWcpO1xuXG4gICAgY29uc3QgbmV3Q2VsbElkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IGNlbnRyb2lkV3JpdGVzOiB7IGtleTogc3RyaW5nOyB2YWx1ZTogU3RvcmVkRW1iZWRkaW5nIHwgdW5kZWZpbmVkIH1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY2x1c3RlciBvZiBjbHVzdGVycykge1xuICAgICAgICBjb25zdCBjZWxsSWQgPSBoYXNoRW1iZWRkaW5nKGNsdXN0ZXIuY2VudHJvaWQpO1xuICAgICAgICBuZXdDZWxsSWRzLmFkZChjZWxsSWQpO1xuICAgICAgICBjZW50cm9pZFdyaXRlcy5wdXNoKHsga2V5OiBjZWxsSWQsIHZhbHVlOiBjbHVzdGVyLmNlbnRyb2lkIH0pO1xuICAgICAgICBjb25zdCBtZW1iZXJXcml0ZXMgPSBjbHVzdGVyLm1lbWJlcnMubWFwKG1lbWJlciA9PiAoeyBrZXk6IG1lbWJlci5yZWYsIHZhbHVlOiBtZW1iZXIuZW1iZWRkaW5nIH0pKTtcbiAgICAgICAgdHJhbnNhY3Rpb25NdXRhdGUoY2VsbFN0b3JlKGRhdGFiYXNlLCBjZWxsSWQpLCBtZW1iZXJXcml0ZXMpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IG9sZENlbGxJZCBvZiBvbGRDZWxsSWRzKSB7XG4gICAgICAgIGlmIChuZXdDZWxsSWRzLmhhcyhvbGRDZWxsSWQpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjZW50cm9pZFdyaXRlcy5wdXNoKHsga2V5OiBvbGRDZWxsSWQsIHZhbHVlOiB1bmRlZmluZWQgfSk7XG4gICAgICAgIGRhdGFiYXNlLmRlbGV0ZURhdGEocm9vdCA9PiByb290LmNlbGxzW29sZENlbGxJZF0pO1xuICAgIH1cbiAgICB0cmFuc2FjdGlvbk11dGF0ZShjZW50cm9pZFN0b3JlKGRhdGFiYXNlKSwgY2VudHJvaWRXcml0ZXMpO1xuICAgIGRhdGFiYXNlLmRlbGV0ZURhdGEocm9vdCA9PiByb290LmZsYXQpO1xuICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIGFsbE1lbWJlcnMubGVuZ3RoKTtcbiAgICBkYXRhYmFzZS53cml0ZURhdGEocm9vdCA9PiByb290LnN0ZXBzW1NURVBfSVZGXSwgdHJ1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hFbWJlZGRpbmdzKFxuICAgIGRhdGFiYXNlOiBEYXRhYmFzZTxJdmZFbWJlZGRpbmdSb290PixcbiAgICBxdWVyeTogU3RvcmVkRW1iZWRkaW5nLFxuICAgIG9wdGlvbnM6IHsgcHJvYmVCdWRnZXQ6IG51bWJlcjsgcmVzdWx0Q291bnQ6IG51bWJlciB9LFxuKTogU2VhcmNoSGl0W10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb25maWcpO1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcblxuICAgIGNvbnN0IGhpdHM6IFNlYXJjaEhpdFtdID0gW107XG4gICAgaWYgKCFzdGVwc1tTVEVQX0lWRl0pIHtcbiAgICAgICAgY29uc3QgZmxhdCA9IHRyYW5zYWN0aW9uUmVhZChmbGF0U3RvcmUoZGF0YWJhc2UpKTtcbiAgICAgICAgaWYgKCFmbGF0KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiBmbGF0LmtleXMoKSkge1xuICAgICAgICAgICAgaGl0cy5wdXNoKHsgcmVmLCBjbG9zZW5lc3M6IGdldENsb3NlbmVzcyhxdWVyeSwgZmxhdC5nZXQocmVmKSEpIH0pO1xuICAgICAgICB9XG4gICAgICAgIGhpdHMuc29ydCgobGVmdCwgcmlnaHQpID0+IHJpZ2h0LmNsb3NlbmVzcyAtIGxlZnQuY2xvc2VuZXNzKTtcbiAgICAgICAgcmV0dXJuIGhpdHMuc2xpY2UoMCwgb3B0aW9ucy5yZXN1bHRDb3VudCk7XG4gICAgfVxuXG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWNlbnRyb2lkcy5zaXplKSByZXR1cm4gW107XG4gICAgY29uc3QgcHJvYmVDZWxsQ291bnQgPSBNYXRoLm1heCgxLCBNYXRoLmNlaWwob3B0aW9ucy5wcm9iZUJ1ZGdldCAvIGNvbmZpZy5jZWxsVGFyZ2V0U2l6ZSkpO1xuICAgIGNvbnN0IHByb2JlQ2VsbElkcyA9IHJhbmtDZWxsc0J5Q2xvc2VuZXNzKHF1ZXJ5LCBjZW50cm9pZHMpLnNsaWNlKDAsIHByb2JlQ2VsbENvdW50KTtcbiAgICBjb25zdCBzdG9yZXMgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHByb2JlQ2VsbElkcy5tYXAoY2VsbElkID0+IHJvb3QuY2VsbHNbY2VsbElkXSkpO1xuICAgIGlmICghc3RvcmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3Qgc3RvcmUgb2Ygc3RvcmVzKSB7XG4gICAgICAgIGNvbnN0IG1lbWJlcnMgPSByZXBsYXlUcmFuc2FjdGlvblN0b3JlPFN0b3JlZEVtYmVkZGluZz4oc3RvcmUpO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiBtZW1iZXJzLmtleXMoKSkge1xuICAgICAgICAgICAgaGl0cy5wdXNoKHsgcmVmLCBjbG9zZW5lc3M6IGdldENsb3NlbmVzcyhxdWVyeSwgbWVtYmVycy5nZXQocmVmKSEpIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhpdHMuc29ydCgobGVmdCwgcmlnaHQpID0+IHJpZ2h0LmNsb3NlbmVzcyAtIGxlZnQuY2xvc2VuZXNzKTtcbiAgICByZXR1cm4gaGl0cy5zbGljZSgwLCBvcHRpb25zLnJlc3VsdENvdW50KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluc2VydEVtYmVkZGluZ3MoXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+LFxuICAgIGl0ZW1zOiBFbWJlZGRpbmdJbnB1dFtdLFxuKTogdHJ1ZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IGNvbmZpZyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb25maWcpO1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcbiAgICBjb25zdCBuZXdDb3VudCA9IHJlYWRDb3VudChkYXRhYmFzZSkgKyBpdGVtcy5sZW5ndGg7XG5cbiAgICBpZiAoIXN0ZXBzW1NURVBfSVZGXSkge1xuICAgICAgICBjb25zdCBmbGF0V3JpdGVzID0gaXRlbXMubWFwKGl0ZW0gPT4gKHsga2V5OiBpdGVtLnJlZiwgdmFsdWU6IGl0ZW0uZW1iZWRkaW5nIH0pKTtcbiAgICAgICAgdHJhbnNhY3Rpb25NdXRhdGUoZmxhdFN0b3JlKGRhdGFiYXNlKSwgZmxhdFdyaXRlcyk7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIG5ld0NvdW50KTtcbiAgICAgICAgaWYgKG5ld0NvdW50ID4gRkxBVF9MSU1JVCkge1xuICAgICAgICAgICAgcmVidWlsZFN0cnVjdHVyZShkYXRhYmFzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBpdGVtc0J5Q2VsbCA9IG5ldyBNYXA8c3RyaW5nLCBFbWJlZGRpbmdJbnB1dFtdPigpO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICBjb25zdCBjZWxsSWQgPSByYW5rQ2VsbHNCeUNsb3NlbmVzcyhpdGVtLmVtYmVkZGluZywgY2VudHJvaWRzKVswXTtcbiAgICAgICAgbGV0IGdyb3VwID0gaXRlbXNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgIGlmICghZ3JvdXApIHtcbiAgICAgICAgICAgIGdyb3VwID0gW107XG4gICAgICAgICAgICBpdGVtc0J5Q2VsbC5zZXQoY2VsbElkLCBncm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgZ3JvdXAucHVzaChpdGVtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBjZWxsSWQgb2YgaXRlbXNCeUNlbGwua2V5cygpKSB7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gaXRlbXNCeUNlbGwuZ2V0KGNlbGxJZCkhO1xuICAgICAgICBjb25zdCBtZW1iZXJXcml0ZXMgPSBncm91cC5tYXAoaXRlbSA9PiAoeyBrZXk6IGl0ZW0ucmVmLCB2YWx1ZTogaXRlbS5lbWJlZGRpbmcgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShjZWxsU3RvcmUoZGF0YWJhc2UsIGNlbGxJZCksIG1lbWJlcldyaXRlcyk7XG4gICAgfVxuICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIG5ld0NvdW50KTtcblxuICAgIGxldCByZWdlbmVyYXRlZCA9IGZhbHNlO1xuICAgIGZvciAoY29uc3QgdGhyZXNob2xkIG9mIFJFR0VORVJBVEVfQVQpIHtcbiAgICAgICAgY29uc3Qgc3RlcE5hbWUgPSBcInJlZ2VuXCIgKyB0aHJlc2hvbGQ7XG4gICAgICAgIGlmICghc3RlcHNbc3RlcE5hbWVdICYmIG5ld0NvdW50ID4gdGhyZXNob2xkKSB7XG4gICAgICAgICAgICByZWJ1aWxkU3RydWN0dXJlKGRhdGFiYXNlKTtcbiAgICAgICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3Quc3RlcHNbc3RlcE5hbWVdLCB0cnVlKTtcbiAgICAgICAgICAgIHJlZ2VuZXJhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXJlZ2VuZXJhdGVkKSB7XG4gICAgICAgIGNvbnN0IGF2ZXJhZ2VGaWxsID0gbmV3Q291bnQgLyBNYXRoLm1heCgxLCBjZW50cm9pZHMuc2l6ZSkgLyBjb25maWcuY2VsbFRhcmdldFNpemU7XG4gICAgICAgIGlmIChNYXRoLnJhbmRvbSgpIDwgcmViYWxhbmNlUHJvYmFiaWxpdHkoYXZlcmFnZUZpbGwpKSB7XG4gICAgICAgICAgICByZWJ1aWxkU3RydWN0dXJlKGRhdGFiYXNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUVtYmVkZGluZ3MoXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+LFxuICAgIGl0ZW1zOiBFbWJlZGRpbmdJbnB1dFtdLFxuKTogdHJ1ZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcbiAgICBjb25zdCBjb3VudCA9IHJlYWRDb3VudChkYXRhYmFzZSk7XG5cbiAgICBpZiAoIXN0ZXBzW1NURVBfSVZGXSkge1xuICAgICAgICBjb25zdCBmbGF0RGVsZXRlcyA9IGl0ZW1zLm1hcChpdGVtID0+ICh7IGtleTogaXRlbS5yZWYsIHZhbHVlOiB1bmRlZmluZWQgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShmbGF0U3RvcmUoZGF0YWJhc2UpLCBmbGF0RGVsZXRlcyk7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIE1hdGgubWF4KDAsIGNvdW50IC0gaXRlbXMubGVuZ3RoKSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGNvbnN0IGNlbnRyb2lkcyA9IHRyYW5zYWN0aW9uUmVhZChjZW50cm9pZFN0b3JlKGRhdGFiYXNlKSk7XG4gICAgaWYgKCFjZW50cm9pZHMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKCFjZW50cm9pZHMuc2l6ZSkgcmV0dXJuIHRydWU7XG5cbiAgICBjb25zdCBjYW5kaWRhdGVzQnlJdGVtOiB7IHJlZjogc3RyaW5nOyBjZWxsSWRzOiBzdHJpbmdbXSB9W10gPSBbXTtcbiAgICBjb25zdCBjYW5kaWRhdGVTZXQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgICAgY29uc3QgY2VsbElkcyA9IHJhbmtDZWxsc0J5Q2xvc2VuZXNzKGl0ZW0uZW1iZWRkaW5nLCBjZW50cm9pZHMpLnNsaWNlKDAsIDEgKyBERUxFVEVfRkFMTEJBQ0tfQ0VMTFMpO1xuICAgICAgICBjYW5kaWRhdGVzQnlJdGVtLnB1c2goeyByZWY6IGl0ZW0ucmVmLCBjZWxsSWRzIH0pO1xuICAgICAgICBmb3IgKGNvbnN0IGNlbGxJZCBvZiBjZWxsSWRzKSB7XG4gICAgICAgICAgICBjYW5kaWRhdGVTZXQuYWRkKGNlbGxJZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjYW5kaWRhdGVDZWxsSWRzID0gQXJyYXkuZnJvbShjYW5kaWRhdGVTZXQpO1xuICAgIGNvbnN0IHN0b3JlcyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gY2FuZGlkYXRlQ2VsbElkcy5tYXAoY2VsbElkID0+IHJvb3QuY2VsbHNbY2VsbElkXSkpO1xuICAgIGlmICghc3RvcmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IG1lbWJlcnNCeUNlbGwgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgU3RvcmVkRW1iZWRkaW5nPj4oKTtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY2FuZGlkYXRlQ2VsbElkcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgbWVtYmVyc0J5Q2VsbC5zZXQoY2FuZGlkYXRlQ2VsbElkc1tpbmRleF0sIHJlcGxheVRyYW5zYWN0aW9uU3RvcmUoc3RvcmVzW2luZGV4XSkpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGV0ZXNCeUNlbGwgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgZm9yIChjb25zdCBjYW5kaWRhdGUgb2YgY2FuZGlkYXRlc0J5SXRlbSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNlbGxJZCBvZiBjYW5kaWRhdGUuY2VsbElkcykge1xuICAgICAgICAgICAgY29uc3QgbWVtYmVycyA9IG1lbWJlcnNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgICAgICBpZiAoIW1lbWJlcnMgfHwgIW1lbWJlcnMuaGFzKGNhbmRpZGF0ZS5yZWYpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVmcyA9IGRlbGV0ZXNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgICAgICBpZiAoIXJlZnMpIHtcbiAgICAgICAgICAgICAgICByZWZzID0gW107XG4gICAgICAgICAgICAgICAgZGVsZXRlc0J5Q2VsbC5zZXQoY2VsbElkLCByZWZzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlZnMucHVzaChjYW5kaWRhdGUucmVmKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGRlbGV0ZWRDb3VudCA9IDA7XG4gICAgZm9yIChjb25zdCBjZWxsSWQgb2YgZGVsZXRlc0J5Q2VsbC5rZXlzKCkpIHtcbiAgICAgICAgY29uc3QgcmVmcyA9IGRlbGV0ZXNCeUNlbGwuZ2V0KGNlbGxJZCkhO1xuICAgICAgICBkZWxldGVkQ291bnQgKz0gcmVmcy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG1lbWJlckRlbGV0ZXMgPSByZWZzLm1hcChyZWYgPT4gKHsga2V5OiByZWYsIHZhbHVlOiB1bmRlZmluZWQgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShjZWxsU3RvcmUoZGF0YWJhc2UsIGNlbGxJZCksIG1lbWJlckRlbGV0ZXMpO1xuICAgIH1cbiAgICBpZiAoZGVsZXRlZENvdW50KSB7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIE1hdGgubWF4KDAsIGNvdW50IC0gZGVsZXRlZENvdW50KSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuIl19
|
|
334
|
+
/* _JS_SOURCE_HASH = "6bb25c321db29d41be7eec5ac48ec8aad9563a1f8c7710e6700a8deb6ed719c9"; */
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
+
//exports.transactionMutate = exports.replayTransactionStore = exports.transactionRead = void 0;
|
|
7
|
+
const cbor_x_1 = __importDefault(require("cbor-x"));
|
|
8
|
+
// structuredClone keeps typed arrays / Maps / undefined intact through the round-trip.
|
|
9
|
+
const transactionCbor = new cbor_x_1.default.Encoder({ structuredClone: true });
|
|
10
|
+
const DEFAULT_COMPACT_AFTER_FILES = 16;
|
|
11
|
+
function maxNumber(values, fallback) {
|
|
12
|
+
let result = fallback;
|
|
13
|
+
for (const value of values) {
|
|
14
|
+
if (value > result) {
|
|
15
|
+
result = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
function decodeBuffers(buffers) {
|
|
21
|
+
const transactions = [];
|
|
22
|
+
for (const buffer of buffers) {
|
|
23
|
+
const decoded = transactionCbor.decode(buffer);
|
|
24
|
+
for (const transaction of decoded) {
|
|
25
|
+
transactions.push(transaction);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return transactions;
|
|
29
|
+
}
|
|
30
|
+
function readTransactionFiles(database) {
|
|
31
|
+
const snapshot = database.readData(store => {
|
|
32
|
+
// A never-written / deleted set reads as empty (vs the whole readData being undefined = not synced).
|
|
33
|
+
const present = store;
|
|
34
|
+
if (!present)
|
|
35
|
+
return { fileKeys: [], buffers: [] };
|
|
36
|
+
return { fileKeys: Object.keys(present), buffers: Object.values(present) };
|
|
37
|
+
});
|
|
38
|
+
if (!snapshot)
|
|
39
|
+
return undefined;
|
|
40
|
+
return { fileKeys: snapshot.fileKeys, transactions: decodeBuffers(snapshot.buffers) };
|
|
41
|
+
}
|
|
42
|
+
function replay(transactions) {
|
|
43
|
+
const ordered = transactions.slice().sort((left, right) => left.sequence - right.sequence);
|
|
44
|
+
const state = new Map();
|
|
45
|
+
for (const transaction of ordered) {
|
|
46
|
+
// undefined (not falsy) is the delete marker, so 0 / "" / false stay real values.
|
|
47
|
+
if (transaction.value === undefined) {
|
|
48
|
+
state.delete(transaction.key);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
state.set(transaction.key, transaction.value);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return state;
|
|
55
|
+
}
|
|
56
|
+
// Deletes old files by their ORIGINAL string key, so a stray non-numeric key still gets removed.
|
|
57
|
+
function compactTransactions(database, allTransactions, oldFileKeys, newFileNumber) {
|
|
58
|
+
const finalState = replay(allTransactions);
|
|
59
|
+
const merged = [];
|
|
60
|
+
for (const key of finalState.keys()) {
|
|
61
|
+
merged.push({ sequence: merged.length, key, value: finalState.get(key) });
|
|
62
|
+
}
|
|
63
|
+
const encoded = transactionCbor.encode(merged);
|
|
64
|
+
database.writeData(store => store[String(newFileNumber)], encoded);
|
|
65
|
+
for (const fileKey of oldFileKeys) {
|
|
66
|
+
database.deleteData(store => store[fileKey]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function transactionRead(database) {
|
|
70
|
+
const files = readTransactionFiles(database);
|
|
71
|
+
if (!files)
|
|
72
|
+
return undefined;
|
|
73
|
+
return replay(files.transactions);
|
|
74
|
+
}
|
|
75
|
+
exports.transactionRead = transactionRead;
|
|
76
|
+
// Replay an already-read store (no read of its own), so a caller can fetch many sets in one batched read and materialize each.
|
|
77
|
+
function replayTransactionStore(store) {
|
|
78
|
+
if (!store)
|
|
79
|
+
return new Map();
|
|
80
|
+
return replay(decodeBuffers(Object.values(store)));
|
|
81
|
+
}
|
|
82
|
+
exports.replayTransactionStore = replayTransactionStore;
|
|
83
|
+
// Fire-and-forget: no caller should care whether this "succeeded". If the set isn't synced for reading
|
|
84
|
+
// yet it simply does nothing this pass and the caller's retry wrapper re-runs the whole operation later.
|
|
85
|
+
function transactionMutate(database, transactions, compactAfterFiles = DEFAULT_COMPACT_AFTER_FILES) {
|
|
86
|
+
if (!transactions.length)
|
|
87
|
+
return;
|
|
88
|
+
const files = readTransactionFiles(database);
|
|
89
|
+
if (!files)
|
|
90
|
+
return;
|
|
91
|
+
const baseSequence = maxNumber(files.transactions.map(transaction => transaction.sequence), -1) + 1;
|
|
92
|
+
const incoming = transactions.map((transaction, index) => ({
|
|
93
|
+
sequence: baseSequence + index,
|
|
94
|
+
key: transaction.key,
|
|
95
|
+
value: transaction.value,
|
|
96
|
+
}));
|
|
97
|
+
const nextFileNumber = maxNumber(files.fileKeys.map(fileKey => Number(fileKey)), -1) + 1;
|
|
98
|
+
if (files.fileKeys.length + 1 >= compactAfterFiles) {
|
|
99
|
+
compactTransactions(database, files.transactions.concat(incoming), files.fileKeys, nextFileNumber);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const encoded = transactionCbor.encode(incoming);
|
|
103
|
+
database.writeData(store => store[String(nextFileNumber)], encoded);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.transactionMutate = transactionMutate;
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25TZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0cmFuc2FjdGlvblNldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxvREFBMkI7QUFHM0IsdUZBQXVGO0FBQ3ZGLE1BQU0sZUFBZSxHQUFHLElBQUksZ0JBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQVdyRSxNQUFNLDJCQUEyQixHQUFHLEVBQUUsQ0FBQztBQUV2QyxTQUFTLFNBQVMsQ0FBQyxNQUFnQixFQUFFLFFBQWdCO0lBQ2pELElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQztJQUN0QixLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ3pCLElBQUksS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDbkIsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsT0FBcUI7SUFDeEMsTUFBTSxZQUFZLEdBQWtCLEVBQUUsQ0FBQztJQUN2QyxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzNCLE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFrQixDQUFDO1FBQ2hFLEtBQUssTUFBTSxXQUFXLElBQUksT0FBTyxFQUFFLENBQUM7WUFDaEMsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sWUFBWSxDQUFDO0FBQ3hCLENBQUM7QUFFRCxTQUFTLG9CQUFvQixDQUN6QixRQUE4QztJQUU5QyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ3ZDLHFHQUFxRztRQUNyRyxNQUFNLE9BQU8sR0FBRyxLQUErQyxDQUFD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RSxLQUFLLENBQUMsUUFBUSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3ZHLENBQUM7U0FBTSxDQUFDO1FBQ0osTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQWUsQ0FBQztRQUMvRCxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3hFLENBQUM7QUFDTCxDQUFDO0FBckJELDhDQXFCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjYm9yeCBmcm9tIFwiY2Jvci14XCI7XG5pbXBvcnQgeyBEYXRhYmFzZSB9IGZyb20gXCIuL0RhdGFiYXNlXCI7XG5cbi8vIHN0cnVjdHVyZWRDbG9uZSBrZWVwcyB0eXBlZCBhcnJheXMgLyBNYXBzIC8gdW5kZWZpbmVkIGludGFjdCB0aHJvdWdoIHRoZSByb3VuZC10cmlwLlxuY29uc3QgdHJhbnNhY3Rpb25DYm9yID0gbmV3IGNib3J4LkVuY29kZXIoeyBzdHJ1Y3R1cmVkQ2xvbmU6IHRydWUgfSk7XG5cbi8vIE9uIHRoZSBzdG9yZTogZmlsZXMga2V5ZWQgYnkgYSBtb25vdG9uaWMgbnVtYmVyLCBlYWNoIGEgQ0JPUiBhcnJheSBvZiB0cmFuc2FjdGlvbnM7IGEgdHJhbnNhY3Rpb24gc2V0cyBvbmUga2V5ICh2YWx1ZSB1bmRlZmluZWQgPSBkZWxldGUpIGFuZCBjYXJyaWVzIGEgZ2xvYmFsIHNlcXVlbmNlIG51bWJlci4gUmVwbGF5aW5nIGV2ZXJ5IHRyYW5zYWN0aW9uIGluIHNlcXVlbmNlIG9yZGVyIChsYXN0IHdyaXRlIHdpbnMpIGdpdmVzIHRoZSBjdXJyZW50IG1hcC4gTXV0YXRpb25zIGFwcGVuZCBhIGZpbGUsIHRoZW4gZm9sZCB0aGUgd2hvbGUgc2V0IGludG8gb25lIG9uY2UgZW5vdWdoIGFjY3VtdWxhdGUuIFZhbHVlIGlzIHBoYW50b20g4oCUIGl0IG9ubHkgcmVjb3JkcyB3aGF0IHRoZSBlbmNvZGVkIHZhbHVlcyBkZXNlcmlhbGl6ZSB0by5cbmRlY2xhcmUgY29uc3QgdmFsdWVUYWc6IHVuaXF1ZSBzeW1ib2w7XG5leHBvcnQgdHlwZSBUcmFuc2FjdGlvblNldFN0b3JlPFZhbHVlPiA9IHtcbiAgICBbZmlsZU51bWJlcjogc3RyaW5nXTogVWludDhBcnJheTtcbiAgICBbdmFsdWVUYWddPzogVmFsdWU7XG59O1xuXG50eXBlIFRyYW5zYWN0aW9uID0geyBzZXF1ZW5jZTogbnVtYmVyOyBrZXk6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfTtcblxuY29uc3QgREVGQVVMVF9DT01QQUNUX0FGVEVSX0ZJTEVTID0gMTY7XG5cbmZ1bmN0aW9uIG1heE51bWJlcih2YWx1ZXM6IG51bWJlcltdLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgcmVzdWx0ID0gZmFsbGJhY2s7XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiB2YWx1ZXMpIHtcbiAgICAgICAgaWYgKHZhbHVlID4gcmVzdWx0KSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBkZWNvZGVCdWZmZXJzKGJ1ZmZlcnM6IFVpbnQ4QXJyYXlbXSk6IFRyYW5zYWN0aW9uW10ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uczogVHJhbnNhY3Rpb25bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgYnVmZmVyIG9mIGJ1ZmZlcnMpIHtcbiAgICAgICAgY29uc3QgZGVjb2RlZCA9IHRyYW5zYWN0aW9uQ2Jvci5kZWNvZGUoYnVmZmVyKSBhcyBUcmFuc2FjdGlvbltdO1xuICAgICAgICBmb3IgKGNvbnN0IHRyYW5zYWN0aW9uIG9mIGRlY29kZWQpIHtcbiAgICAgICAgICAgIHRyYW5zYWN0aW9ucy5wdXNoKHRyYW5zYWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJhbnNhY3Rpb25zO1xufVxuXG5mdW5jdGlvbiByZWFkVHJhbnNhY3Rpb25GaWxlczxWYWx1ZT4oXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPFRyYW5zYWN0aW9uU2V0U3RvcmU8VmFsdWU+Pixcbik6IHsgZmlsZUtleXM6IHN0cmluZ1tdOyB0cmFuc2FjdGlvbnM6IFRyYW5zYWN0aW9uW10gfSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgc25hcHNob3QgPSBkYXRhYmFzZS5yZWFkRGF0YShzdG9yZSA9PiB7XG4gICAgICAgIC8vIEEgbmV2ZXItd3JpdHRlbiAvIGRlbGV0ZWQgc2V0IHJlYWRzIGFzIGVtcHR5ICh2cyB0aGUgd2hvbGUgcmVhZERhdGEgYmVpbmcgdW5kZWZpbmVkID0gbm90IHN5bmNlZCkuXG4gICAgICAgIGNvbnN0IHByZXNlbnQgPSBzdG9yZSBhcyBUcmFuc2FjdGlvblNldFN0b3JlPFZhbHVlPiB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCFwcmVzZW50KSByZXR1cm4geyBmaWxlS2V5czogW10gYXMgc3RyaW5nW10sIGJ1ZmZlcnM6IFtdIGFzIFVpbnQ4QXJyYXlbXSB9O1xuICAgICAgICByZXR1cm4geyBmaWxlS2V5czogT2JqZWN0LmtleXMocHJlc2VudCksIGJ1ZmZlcnM6IE9iamVjdC52YWx1ZXMocHJlc2VudCkgfTtcbiAgICB9KTtcbiAgICBpZiAoIXNuYXBzaG90KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IGZpbGVLZXlzOiBzbmFwc2hvdC5maWxlS2V5cywgdHJhbnNhY3Rpb25zOiBkZWNvZGVCdWZmZXJzKHNuYXBzaG90LmJ1ZmZlcnMpIH07XG59XG5cbmZ1bmN0aW9uIHJlcGxheSh0cmFuc2FjdGlvbnM6IFRyYW5zYWN0aW9uW10pOiBNYXA8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgY29uc3Qgb3JkZXJlZCA9IHRyYW5zYWN0aW9ucy5zbGljZSgpLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0LnNlcXVlbmNlIC0gcmlnaHQuc2VxdWVuY2UpO1xuICAgIGNvbnN0IHN0YXRlID0gbmV3IE1hcDxzdHJpbmcsIHVua25vd24+KCk7XG4gICAgZm9yIChjb25zdCB0cmFuc2FjdGlvbiBvZiBvcmRlcmVkKSB7XG4gICAgICAgIC8vIHVuZGVmaW5lZCAobm90IGZhbHN5KSBpcyB0aGUgZGVsZXRlIG1hcmtlciwgc28gMCAvIFwiXCIgLyBmYWxzZSBzdGF5IHJlYWwgdmFsdWVzLlxuICAgICAgICBpZiAodHJhbnNhY3Rpb24udmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc3RhdGUuZGVsZXRlKHRyYW5zYWN0aW9uLmtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0ZS5zZXQodHJhbnNhY3Rpb24ua2V5LCB0cmFuc2FjdGlvbi52YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlO1xufVxuXG4vLyBEZWxldGVzIG9sZCBmaWxlcyBieSB0aGVpciBPUklHSU5BTCBzdHJpbmcga2V5LCBzbyBhIHN0cmF5IG5vbi1udW1lcmljIGtleSBzdGlsbCBnZXRzIHJlbW92ZWQuXG5mdW5jdGlvbiBjb21wYWN0VHJhbnNhY3Rpb25zPFZhbHVlPihcbiAgICBkYXRhYmFzZTogRGF0YWJhc2U8VHJhbnNhY3Rpb25TZXRTdG9yZTxWYWx1ZT4+LFxuICAgIGFsbFRyYW5zYWN0aW9uczogVHJhbnNhY3Rpb25bXSxcbiAgICBvbGRGaWxlS2V5czogc3RyaW5nW10sXG4gICAgbmV3RmlsZU51bWJlcjogbnVtYmVyLFxuKTogdm9pZCB7XG4gICAgY29uc3QgZmluYWxTdGF0ZSA9IHJlcGxheShhbGxUcmFuc2FjdGlvbnMpO1xuICAgIGNvbnN0IG1lcmdlZDogVHJhbnNhY3Rpb25bXSA9IFtdO1xuICAgIGZvciAoY29uc3Qga2V5IG9mIGZpbmFsU3RhdGUua2V5cygpKSB7XG4gICAgICAgIG1lcmdlZC5wdXNoKHsgc2VxdWVuY2U6IG1lcmdlZC5sZW5ndGgsIGtleSwgdmFsdWU6IGZpbmFsU3RhdGUuZ2V0KGtleSkgfSk7XG4gICAgfVxuICAgIGNvbnN0IGVuY29kZWQgPSB0cmFuc2FjdGlvbkNib3IuZW5jb2RlKG1lcmdlZCkgYXMgVWludDhBcnJheTtcbiAgICBkYXRhYmFzZS53cml0ZURhdGEoc3RvcmUgPT4gc3RvcmVbU3RyaW5nKG5ld0ZpbGVOdW1iZXIpXSwgZW5jb2RlZCk7XG4gICAgZm9yIChjb25zdCBmaWxlS2V5IG9mIG9sZEZpbGVLZXlzKSB7XG4gICAgICAgIGRhdGFiYXNlLmRlbGV0ZURhdGEoc3RvcmUgPT4gc3RvcmVbZmlsZUtleV0pO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zYWN0aW9uUmVhZDxWYWx1ZT4oXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPFRyYW5zYWN0aW9uU2V0U3RvcmU8VmFsdWU+Pixcbik6IE1hcDxzdHJpbmcsIFZhbHVlPiB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZmlsZXMgPSByZWFkVHJhbnNhY3Rpb25GaWxlcyhkYXRhYmFzZSk7XG4gICAgaWYgKCFmaWxlcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gcmVwbGF5KGZpbGVzLnRyYW5zYWN0aW9ucykgYXMgTWFwPHN0cmluZywgVmFsdWU+O1xufVxuXG4vLyBSZXBsYXkgYW4gYWxyZWFkeS1yZWFkIHN0b3JlIChubyByZWFkIG9mIGl0cyBvd24pLCBzbyBhIGNhbGxlciBjYW4gZmV0Y2ggbWFueSBzZXRzIGluIG9uZSBiYXRjaGVkIHJlYWQgYW5kIG1hdGVyaWFsaXplIGVhY2guXG5leHBvcnQgZnVuY3Rpb24gcmVwbGF5VHJhbnNhY3Rpb25TdG9yZTxWYWx1ZT4oc3RvcmU6IFRyYW5zYWN0aW9uU2V0U3RvcmU8VmFsdWU+IHwgdW5kZWZpbmVkKTogTWFwPHN0cmluZywgVmFsdWU+IHtcbiAgICBpZiAoIXN0b3JlKSByZXR1cm4gbmV3IE1hcCgpO1xuICAgIHJldHVybiByZXBsYXkoZGVjb2RlQnVmZmVycyhPYmplY3QudmFsdWVzKHN0b3JlKSkpIGFzIE1hcDxzdHJpbmcsIFZhbHVlPjtcbn1cblxuLy8gRmlyZS1hbmQtZm9yZ2V0OiBubyBjYWxsZXIgc2hvdWxkIGNhcmUgd2hldGhlciB0aGlzIFwic3VjY2VlZGVkXCIuIElmIHRoZSBzZXQgaXNuJ3Qgc3luY2VkIGZvciByZWFkaW5nXG4vLyB5ZXQgaXQgc2ltcGx5IGRvZXMgbm90aGluZyB0aGlzIHBhc3MgYW5kIHRoZSBjYWxsZXIncyByZXRyeSB3cmFwcGVyIHJlLXJ1bnMgdGhlIHdob2xlIG9wZXJhdGlvbiBsYXRlci5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2FjdGlvbk11dGF0ZTxWYWx1ZT4oXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPFRyYW5zYWN0aW9uU2V0U3RvcmU8VmFsdWU+PixcbiAgICB0cmFuc2FjdGlvbnM6IHsga2V5OiBzdHJpbmc7IHZhbHVlOiBWYWx1ZSB8IHVuZGVmaW5lZCB9W10sXG4gICAgY29tcGFjdEFmdGVyRmlsZXM6IG51bWJlciA9IERFRkFVTFRfQ09NUEFDVF9BRlRFUl9GSUxFUyxcbik6IHZvaWQge1xuICAgIGlmICghdHJhbnNhY3Rpb25zLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IGZpbGVzID0gcmVhZFRyYW5zYWN0aW9uRmlsZXMoZGF0YWJhc2UpO1xuICAgIGlmICghZmlsZXMpIHJldHVybjtcbiAgICBjb25zdCBiYXNlU2VxdWVuY2UgPSBtYXhOdW1iZXIoZmlsZXMudHJhbnNhY3Rpb25zLm1hcCh0cmFuc2FjdGlvbiA9PiB0cmFuc2FjdGlvbi5zZXF1ZW5jZSksIC0xKSArIDE7XG4gICAgY29uc3QgaW5jb21pbmc6IFRyYW5zYWN0aW9uW10gPSB0cmFuc2FjdGlvbnMubWFwKCh0cmFuc2FjdGlvbiwgaW5kZXgpID0+ICh7XG4gICAgICAgIHNlcXVlbmNlOiBiYXNlU2VxdWVuY2UgKyBpbmRleCxcbiAgICAgICAga2V5OiB0cmFuc2FjdGlvbi5rZXksXG4gICAgICAgIHZhbHVlOiB0cmFuc2FjdGlvbi52YWx1ZSxcbiAgICB9KSk7XG4gICAgY29uc3QgbmV4dEZpbGVOdW1iZXIgPSBtYXhOdW1iZXIoZmlsZXMuZmlsZUtleXMubWFwKGZpbGVLZXkgPT4gTnVtYmVyKGZpbGVLZXkpKSwgLTEpICsgMTtcbiAgICBpZiAoZmlsZXMuZmlsZUtleXMubGVuZ3RoICsgMSA+PSBjb21wYWN0QWZ0ZXJGaWxlcykge1xuICAgICAgICBjb21wYWN0VHJhbnNhY3Rpb25zKGRhdGFiYXNlLCBmaWxlcy50cmFuc2FjdGlvbnMuY29uY2F0KGluY29taW5nKSwgZmlsZXMuZmlsZUtleXMsIG5leHRGaWxlTnVtYmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBlbmNvZGVkID0gdHJhbnNhY3Rpb25DYm9yLmVuY29kZShpbmNvbWluZykgYXMgVWludDhBcnJheTtcbiAgICAgICAgZGF0YWJhc2Uud3JpdGVEYXRhKHN0b3JlID0+IHN0b3JlW1N0cmluZyhuZXh0RmlsZU51bWJlcildLCBlbmNvZGVkKTtcbiAgICB9XG59XG4iXX0=
|
|
108
|
+
/* _JS_SOURCE_HASH = "5c22d95f86091992a5fc7263774f46e9f486d5f3cb56788139eecadc876b9f16"; */
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Database } from "./Database";
|
|
2
|
+
export declare class InMemoryDatabase<Root> implements Database<Root> {
|
|
3
|
+
readCalls: number;
|
|
4
|
+
writeCalls: number;
|
|
5
|
+
deleteCalls: number;
|
|
6
|
+
bytesRead: number;
|
|
7
|
+
bytesWritten: number;
|
|
8
|
+
private root;
|
|
9
|
+
constructor(initial: Root);
|
|
10
|
+
readData<Value>(deref: (root: Root) => Value): Value | undefined;
|
|
11
|
+
writeData<Value>(deref: (root: Root) => Value, newValue: Value): void;
|
|
12
|
+
deleteData(deref: (root: Root) => unknown): void;
|
|
13
|
+
}
|