@sochdb/sochdb 0.4.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/LICENSE +201 -0
- package/README.md +3349 -0
- package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
- package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
- package/bin/sochdb-bulk.js +80 -0
- package/bin/sochdb-grpc-server.js +80 -0
- package/bin/sochdb-server.js +84 -0
- package/dist/cjs/analytics.js +196 -0
- package/dist/cjs/database.js +929 -0
- package/dist/cjs/embedded/database.js +236 -0
- package/dist/cjs/embedded/ffi/bindings.js +113 -0
- package/dist/cjs/embedded/ffi/library-finder.js +135 -0
- package/dist/cjs/embedded/index.js +14 -0
- package/dist/cjs/embedded/transaction.js +172 -0
- package/dist/cjs/errors.js +71 -0
- package/dist/cjs/format.js +176 -0
- package/dist/cjs/grpc-client.js +328 -0
- package/dist/cjs/index.js +75 -0
- package/dist/cjs/ipc-client.js +504 -0
- package/dist/cjs/query.js +154 -0
- package/dist/cjs/server-manager.js +295 -0
- package/dist/cjs/sql-engine.js +874 -0
- package/dist/esm/analytics.js +196 -0
- package/dist/esm/database.js +931 -0
- package/dist/esm/embedded/database.js +239 -0
- package/dist/esm/embedded/ffi/bindings.js +142 -0
- package/dist/esm/embedded/ffi/library-finder.js +135 -0
- package/dist/esm/embedded/index.js +14 -0
- package/dist/esm/embedded/transaction.js +176 -0
- package/dist/esm/errors.js +71 -0
- package/dist/esm/format.js +179 -0
- package/dist/esm/grpc-client.js +333 -0
- package/dist/esm/index.js +75 -0
- package/dist/esm/ipc-client.js +505 -0
- package/dist/esm/query.js +159 -0
- package/dist/esm/server-manager.js +295 -0
- package/dist/esm/sql-engine.js +875 -0
- package/dist/types/analytics.d.ts +66 -0
- package/dist/types/analytics.d.ts.map +1 -0
- package/dist/types/database.d.ts +523 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/embedded/database.d.ts +105 -0
- package/dist/types/embedded/database.d.ts.map +1 -0
- package/dist/types/embedded/ffi/bindings.d.ts +24 -0
- package/dist/types/embedded/ffi/bindings.d.ts.map +1 -0
- package/dist/types/embedded/ffi/library-finder.d.ts +17 -0
- package/dist/types/embedded/ffi/library-finder.d.ts.map +1 -0
- package/dist/types/embedded/index.d.ts +9 -0
- package/dist/types/embedded/index.d.ts.map +1 -0
- package/dist/types/embedded/transaction.d.ts +21 -0
- package/dist/types/embedded/transaction.d.ts.map +1 -0
- package/dist/types/errors.d.ts +36 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/format.d.ts +117 -0
- package/dist/types/format.d.ts.map +1 -0
- package/dist/types/grpc-client.d.ts +120 -0
- package/dist/types/grpc-client.d.ts.map +1 -0
- package/dist/types/index.d.ts +50 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/ipc-client.d.ts +177 -0
- package/dist/types/ipc-client.d.ts.map +1 -0
- package/dist/types/query.d.ts +85 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/server-manager.d.ts +29 -0
- package/dist/types/server-manager.d.ts.map +1 -0
- package/dist/types/sql-engine.d.ts +100 -0
- package/dist/types/sql-engine.d.ts.map +1 -0
- package/package.json +90 -0
- package/scripts/postinstall.js +50 -0
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SQL Engine for SochDB JavaScript SDK
|
|
4
|
+
*
|
|
5
|
+
* Provides SQL support on top of the KV storage backend.
|
|
6
|
+
* Tables are stored as:
|
|
7
|
+
* - Schema: _sql/tables/{table_name}/schema -> JSON schema definition
|
|
8
|
+
* - Rows: _sql/tables/{table_name}/rows/{row_id} -> JSON row data
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.SQLExecutor = exports.SQLParser = void 0;
|
|
14
|
+
// Copyright 2025 Sushanth (https://github.com/sushanthpy)
|
|
15
|
+
//
|
|
16
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
17
|
+
// you may not use this file except in compliance with the License.
|
|
18
|
+
// You may obtain a copy of the License at
|
|
19
|
+
//
|
|
20
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
21
|
+
const uuid_1 = require("uuid");
|
|
22
|
+
/**
|
|
23
|
+
* Simple SQL parser for DDL and DML operations.
|
|
24
|
+
*/
|
|
25
|
+
class SQLParser {
|
|
26
|
+
/**
|
|
27
|
+
* Parse a SQL statement.
|
|
28
|
+
*/
|
|
29
|
+
static parse(sql) {
|
|
30
|
+
sql = sql.trim();
|
|
31
|
+
const upper = sql.toUpperCase();
|
|
32
|
+
if (upper.startsWith('CREATE TABLE')) {
|
|
33
|
+
return SQLParser.parseCreateTable(sql);
|
|
34
|
+
}
|
|
35
|
+
else if (upper.startsWith('CREATE INDEX')) {
|
|
36
|
+
return SQLParser.parseCreateIndex(sql);
|
|
37
|
+
}
|
|
38
|
+
else if (upper.startsWith('DROP TABLE')) {
|
|
39
|
+
return SQLParser.parseDropTable(sql);
|
|
40
|
+
}
|
|
41
|
+
else if (upper.startsWith('DROP INDEX')) {
|
|
42
|
+
return SQLParser.parseDropIndex(sql);
|
|
43
|
+
}
|
|
44
|
+
else if (upper.startsWith('INSERT')) {
|
|
45
|
+
return SQLParser.parseInsert(sql);
|
|
46
|
+
}
|
|
47
|
+
else if (upper.startsWith('SELECT')) {
|
|
48
|
+
return SQLParser.parseSelect(sql);
|
|
49
|
+
}
|
|
50
|
+
else if (upper.startsWith('UPDATE')) {
|
|
51
|
+
return SQLParser.parseUpdate(sql);
|
|
52
|
+
}
|
|
53
|
+
else if (upper.startsWith('DELETE')) {
|
|
54
|
+
return SQLParser.parseDelete(sql);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new Error(`Unsupported SQL statement: ${sql.substring(0, 50)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
static parseCreateTable(sql) {
|
|
61
|
+
const match = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s*\((.*)\)/is);
|
|
62
|
+
if (!match) {
|
|
63
|
+
throw new Error(`Invalid CREATE TABLE: ${sql}`);
|
|
64
|
+
}
|
|
65
|
+
const tableName = match[1];
|
|
66
|
+
const colsStr = match[2];
|
|
67
|
+
const columns = [];
|
|
68
|
+
let primaryKey;
|
|
69
|
+
const colDefs = SQLParser.splitColumns(colsStr);
|
|
70
|
+
for (const colDef of colDefs) {
|
|
71
|
+
const trimmed = colDef.trim();
|
|
72
|
+
if (!trimmed)
|
|
73
|
+
continue;
|
|
74
|
+
// Check for PRIMARY KEY constraint
|
|
75
|
+
if (trimmed.toUpperCase().startsWith('PRIMARY KEY')) {
|
|
76
|
+
const pkMatch = trimmed.match(/PRIMARY\s+KEY\s*\((\w+)\)/i);
|
|
77
|
+
if (pkMatch) {
|
|
78
|
+
primaryKey = pkMatch[1];
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// Parse column: name TYPE [PRIMARY KEY] [NOT NULL] [DEFAULT value]
|
|
83
|
+
const parts = trimmed.split(/\s+/);
|
|
84
|
+
if (parts.length < 2)
|
|
85
|
+
continue;
|
|
86
|
+
const colName = parts[0];
|
|
87
|
+
let colType = parts[1].toUpperCase();
|
|
88
|
+
// Normalize types
|
|
89
|
+
if (['INTEGER', 'INT', 'BIGINT', 'SMALLINT'].includes(colType)) {
|
|
90
|
+
colType = 'INT';
|
|
91
|
+
}
|
|
92
|
+
else if (['VARCHAR', 'CHAR', 'STRING', 'TEXT'].includes(colType)) {
|
|
93
|
+
colType = 'TEXT';
|
|
94
|
+
}
|
|
95
|
+
else if (['REAL', 'DOUBLE', 'FLOAT', 'DECIMAL', 'NUMERIC'].includes(colType)) {
|
|
96
|
+
colType = 'FLOAT';
|
|
97
|
+
}
|
|
98
|
+
else if (['BOOLEAN', 'BOOL'].includes(colType)) {
|
|
99
|
+
colType = 'BOOL';
|
|
100
|
+
}
|
|
101
|
+
else if (['BLOB', 'BYTES', 'BINARY'].includes(colType)) {
|
|
102
|
+
colType = 'BLOB';
|
|
103
|
+
}
|
|
104
|
+
const colUpper = trimmed.toUpperCase();
|
|
105
|
+
const isPk = colUpper.includes('PRIMARY KEY');
|
|
106
|
+
const nullable = !colUpper.includes('NOT NULL');
|
|
107
|
+
if (isPk) {
|
|
108
|
+
primaryKey = colName;
|
|
109
|
+
}
|
|
110
|
+
columns.push({
|
|
111
|
+
name: colName,
|
|
112
|
+
type: colType,
|
|
113
|
+
nullable,
|
|
114
|
+
primaryKey: isPk,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
operation: 'CREATE_TABLE',
|
|
119
|
+
data: { table: tableName, columns, primaryKey },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
static splitColumns(colsStr) {
|
|
123
|
+
const result = [];
|
|
124
|
+
let current = '';
|
|
125
|
+
let depth = 0;
|
|
126
|
+
for (const char of colsStr) {
|
|
127
|
+
if (char === '(') {
|
|
128
|
+
depth++;
|
|
129
|
+
current += char;
|
|
130
|
+
}
|
|
131
|
+
else if (char === ')') {
|
|
132
|
+
depth--;
|
|
133
|
+
current += char;
|
|
134
|
+
}
|
|
135
|
+
else if (char === ',' && depth === 0) {
|
|
136
|
+
result.push(current);
|
|
137
|
+
current = '';
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
current += char;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (current.trim()) {
|
|
144
|
+
result.push(current);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
static parseDropTable(sql) {
|
|
149
|
+
const match = sql.match(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?(\w+)/i);
|
|
150
|
+
if (!match) {
|
|
151
|
+
throw new Error(`Invalid DROP TABLE: ${sql}`);
|
|
152
|
+
}
|
|
153
|
+
return { operation: 'DROP_TABLE', data: { table: match[1] } };
|
|
154
|
+
}
|
|
155
|
+
static parseCreateIndex(sql) {
|
|
156
|
+
// CREATE INDEX idx_name ON table_name(column_name)
|
|
157
|
+
const match = sql.match(/CREATE\s+INDEX\s+(\w+)\s+ON\s+(\w+)\s*\(\s*(\w+)\s*\)/i);
|
|
158
|
+
if (!match) {
|
|
159
|
+
throw new Error(`Invalid CREATE INDEX syntax: ${sql}`);
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
operation: 'CREATE_INDEX',
|
|
163
|
+
data: {
|
|
164
|
+
indexName: match[1],
|
|
165
|
+
table: match[2],
|
|
166
|
+
column: match[3],
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
static parseDropIndex(sql) {
|
|
171
|
+
// DROP INDEX idx_name ON table_name
|
|
172
|
+
const match = sql.match(/DROP\s+INDEX\s+(\w+)\s+ON\s+(\w+)/i);
|
|
173
|
+
if (!match) {
|
|
174
|
+
throw new Error(`Invalid DROP INDEX syntax: ${sql}`);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
operation: 'DROP_INDEX',
|
|
178
|
+
data: {
|
|
179
|
+
indexName: match[1],
|
|
180
|
+
table: match[2],
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
static parseInsert(sql) {
|
|
185
|
+
// INSERT INTO table (col1, col2) VALUES (val1, val2)
|
|
186
|
+
let match = sql.match(/INSERT\s+INTO\s+(\w+)\s*\(([^)]+)\)\s*VALUES\s*\((.+)\)/is);
|
|
187
|
+
if (match) {
|
|
188
|
+
const table = match[1];
|
|
189
|
+
const columns = match[2].split(',').map((c) => c.trim());
|
|
190
|
+
const values = SQLParser.parseValues(match[3]);
|
|
191
|
+
return { operation: 'INSERT', data: { table, columns, values } };
|
|
192
|
+
}
|
|
193
|
+
// INSERT INTO table VALUES (val1, val2)
|
|
194
|
+
match = sql.match(/INSERT\s+INTO\s+(\w+)\s+VALUES\s*\((.+)\)/is);
|
|
195
|
+
if (match) {
|
|
196
|
+
const table = match[1];
|
|
197
|
+
const values = SQLParser.parseValues(match[2]);
|
|
198
|
+
return { operation: 'INSERT', data: { table, columns: null, values } };
|
|
199
|
+
}
|
|
200
|
+
throw new Error(`Invalid INSERT: ${sql}`);
|
|
201
|
+
}
|
|
202
|
+
static parseValues(valuesStr) {
|
|
203
|
+
const values = [];
|
|
204
|
+
let current = '';
|
|
205
|
+
let inString = false;
|
|
206
|
+
let stringChar = null;
|
|
207
|
+
for (const char of valuesStr) {
|
|
208
|
+
if ((char === '"' || char === "'") && !inString) {
|
|
209
|
+
inString = true;
|
|
210
|
+
stringChar = char;
|
|
211
|
+
current += char;
|
|
212
|
+
}
|
|
213
|
+
else if (char === stringChar && inString) {
|
|
214
|
+
inString = false;
|
|
215
|
+
stringChar = null;
|
|
216
|
+
current += char;
|
|
217
|
+
}
|
|
218
|
+
else if (char === ',' && !inString) {
|
|
219
|
+
values.push(SQLParser.parseValue(current.trim()));
|
|
220
|
+
current = '';
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
current += char;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (current.trim()) {
|
|
227
|
+
values.push(SQLParser.parseValue(current.trim()));
|
|
228
|
+
}
|
|
229
|
+
return values;
|
|
230
|
+
}
|
|
231
|
+
static parseValue(valStr) {
|
|
232
|
+
if (!valStr || valStr.toUpperCase() === 'NULL') {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
// String literals
|
|
236
|
+
if ((valStr.startsWith("'") && valStr.endsWith("'")) ||
|
|
237
|
+
(valStr.startsWith('"') && valStr.endsWith('"'))) {
|
|
238
|
+
return valStr.slice(1, -1);
|
|
239
|
+
}
|
|
240
|
+
// Boolean
|
|
241
|
+
if (valStr.toUpperCase() === 'TRUE')
|
|
242
|
+
return true;
|
|
243
|
+
if (valStr.toUpperCase() === 'FALSE')
|
|
244
|
+
return false;
|
|
245
|
+
// Numbers
|
|
246
|
+
if (valStr.includes('.')) {
|
|
247
|
+
const num = parseFloat(valStr);
|
|
248
|
+
if (!isNaN(num))
|
|
249
|
+
return num;
|
|
250
|
+
}
|
|
251
|
+
const intVal = parseInt(valStr, 10);
|
|
252
|
+
if (!isNaN(intVal))
|
|
253
|
+
return intVal;
|
|
254
|
+
return valStr;
|
|
255
|
+
}
|
|
256
|
+
static parseSelect(sql) {
|
|
257
|
+
// Extract table name first
|
|
258
|
+
const tableMatch = sql.match(/FROM\s+(\w+)/i);
|
|
259
|
+
if (!tableMatch) {
|
|
260
|
+
throw new Error(`Invalid SELECT: ${sql}`);
|
|
261
|
+
}
|
|
262
|
+
const table = tableMatch[1];
|
|
263
|
+
// Extract columns
|
|
264
|
+
const colsMatch = sql.match(/SELECT\s+(.+?)\s+FROM/is);
|
|
265
|
+
let columns = ['*'];
|
|
266
|
+
if (colsMatch) {
|
|
267
|
+
const colsStr = colsMatch[1].trim();
|
|
268
|
+
columns = colsStr === '*' ? ['*'] : colsStr.split(',').map((c) => c.trim());
|
|
269
|
+
}
|
|
270
|
+
// Extract WHERE clause
|
|
271
|
+
let conditions = [];
|
|
272
|
+
const whereMatch = sql.match(/WHERE\s+(.+?)(?:\s+ORDER|\s+LIMIT|\s+OFFSET|$)/is);
|
|
273
|
+
if (whereMatch) {
|
|
274
|
+
conditions = SQLParser.parseWhere(whereMatch[1]);
|
|
275
|
+
}
|
|
276
|
+
// Extract ORDER BY
|
|
277
|
+
let orderBy = [];
|
|
278
|
+
const orderMatch = sql.match(/ORDER\s+BY\s+(.+?)(?:\s+LIMIT|\s+OFFSET|$)/i);
|
|
279
|
+
if (orderMatch) {
|
|
280
|
+
for (const part of orderMatch[1].split(',')) {
|
|
281
|
+
const trimmed = part.trim();
|
|
282
|
+
if (trimmed.toUpperCase().endsWith(' DESC')) {
|
|
283
|
+
orderBy.push([trimmed.slice(0, -5).trim(), 'DESC']);
|
|
284
|
+
}
|
|
285
|
+
else if (trimmed.toUpperCase().endsWith(' ASC')) {
|
|
286
|
+
orderBy.push([trimmed.slice(0, -4).trim(), 'ASC']);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
orderBy.push([trimmed, 'ASC']);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Extract LIMIT
|
|
294
|
+
let limit;
|
|
295
|
+
const limitMatch = sql.match(/LIMIT\s+(\d+)/i);
|
|
296
|
+
if (limitMatch) {
|
|
297
|
+
limit = parseInt(limitMatch[1], 10);
|
|
298
|
+
}
|
|
299
|
+
// Extract OFFSET
|
|
300
|
+
let offset;
|
|
301
|
+
const offsetMatch = sql.match(/OFFSET\s+(\d+)/i);
|
|
302
|
+
if (offsetMatch) {
|
|
303
|
+
offset = parseInt(offsetMatch[1], 10);
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
operation: 'SELECT',
|
|
307
|
+
data: { table, columns, where: conditions, orderBy, limit, offset },
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
static parseWhere(whereClause) {
|
|
311
|
+
const conditions = [];
|
|
312
|
+
const parts = whereClause.split(/\s+AND\s+/i);
|
|
313
|
+
for (const part of parts) {
|
|
314
|
+
const match = part.match(/(\w+)\s*(=|!=|<>|>=|<=|>|<|LIKE|NOT\s+LIKE)\s*(.+)/i);
|
|
315
|
+
if (match) {
|
|
316
|
+
const col = match[1];
|
|
317
|
+
let op = match[2].toUpperCase().replace(/\s+/g, '_');
|
|
318
|
+
if (op === '<>')
|
|
319
|
+
op = '!=';
|
|
320
|
+
const val = SQLParser.parseValue(match[3].trim());
|
|
321
|
+
conditions.push([col, op, val]);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return conditions;
|
|
325
|
+
}
|
|
326
|
+
static parseUpdate(sql) {
|
|
327
|
+
const match = sql.match(/UPDATE\s+(\w+)\s+SET\s+(.+?)(?:\s+WHERE\s+(.+))?$/is);
|
|
328
|
+
if (!match) {
|
|
329
|
+
throw new Error(`Invalid UPDATE: ${sql}`);
|
|
330
|
+
}
|
|
331
|
+
const table = match[1];
|
|
332
|
+
const setClause = match[2];
|
|
333
|
+
const whereClause = match[3];
|
|
334
|
+
// Parse SET clause
|
|
335
|
+
const updates = {};
|
|
336
|
+
for (const part of setClause.split(',')) {
|
|
337
|
+
const eqMatch = part.match(/\s*(\w+)\s*=\s*(.+)\s*/);
|
|
338
|
+
if (eqMatch) {
|
|
339
|
+
updates[eqMatch[1]] = SQLParser.parseValue(eqMatch[2].trim());
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
let conditions = [];
|
|
343
|
+
if (whereClause) {
|
|
344
|
+
conditions = SQLParser.parseWhere(whereClause);
|
|
345
|
+
}
|
|
346
|
+
return { operation: 'UPDATE', data: { table, updates, where: conditions } };
|
|
347
|
+
}
|
|
348
|
+
static parseDelete(sql) {
|
|
349
|
+
const match = sql.match(/DELETE\s+FROM\s+(\w+)(?:\s+WHERE\s+(.+))?$/is);
|
|
350
|
+
if (!match) {
|
|
351
|
+
throw new Error(`Invalid DELETE: ${sql}`);
|
|
352
|
+
}
|
|
353
|
+
const table = match[1];
|
|
354
|
+
let conditions = [];
|
|
355
|
+
if (match[2]) {
|
|
356
|
+
conditions = SQLParser.parseWhere(match[2]);
|
|
357
|
+
}
|
|
358
|
+
return { operation: 'DELETE', data: { table, where: conditions } };
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
exports.SQLParser = SQLParser;
|
|
362
|
+
/**
|
|
363
|
+
* SQL Executor that operates on a KV database.
|
|
364
|
+
*/
|
|
365
|
+
class SQLExecutor {
|
|
366
|
+
db;
|
|
367
|
+
// Key prefixes for SQL data
|
|
368
|
+
TABLE_PREFIX = '_sql/tables/';
|
|
369
|
+
SCHEMA_SUFFIX = '/schema';
|
|
370
|
+
ROWS_PREFIX = '/rows/';
|
|
371
|
+
INDEX_PREFIX = '/indexes/';
|
|
372
|
+
constructor(db) {
|
|
373
|
+
this.db = db;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Execute a SQL statement.
|
|
377
|
+
*/
|
|
378
|
+
async execute(sql) {
|
|
379
|
+
const { operation, data } = SQLParser.parse(sql);
|
|
380
|
+
switch (operation) {
|
|
381
|
+
case 'CREATE_TABLE':
|
|
382
|
+
return this.createTable(data);
|
|
383
|
+
case 'DROP_TABLE':
|
|
384
|
+
return this.dropTable(data);
|
|
385
|
+
case 'CREATE_INDEX':
|
|
386
|
+
return this.createIndex(data);
|
|
387
|
+
case 'DROP_INDEX':
|
|
388
|
+
return this.dropIndex(data);
|
|
389
|
+
case 'INSERT':
|
|
390
|
+
return this.insert(data);
|
|
391
|
+
case 'SELECT':
|
|
392
|
+
return this.select(data);
|
|
393
|
+
case 'UPDATE':
|
|
394
|
+
return this.update(data);
|
|
395
|
+
case 'DELETE':
|
|
396
|
+
return this.deleteRows(data);
|
|
397
|
+
default:
|
|
398
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
schemaKey(table) {
|
|
402
|
+
return this.TABLE_PREFIX + table + this.SCHEMA_SUFFIX;
|
|
403
|
+
}
|
|
404
|
+
rowKey(table, rowId) {
|
|
405
|
+
return this.TABLE_PREFIX + table + this.ROWS_PREFIX + rowId;
|
|
406
|
+
}
|
|
407
|
+
rowPrefix(table) {
|
|
408
|
+
return this.TABLE_PREFIX + table + this.ROWS_PREFIX;
|
|
409
|
+
}
|
|
410
|
+
indexMetaKey(table, indexName) {
|
|
411
|
+
return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/meta';
|
|
412
|
+
}
|
|
413
|
+
indexPrefix(table, indexName) {
|
|
414
|
+
return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/';
|
|
415
|
+
}
|
|
416
|
+
indexKey(table, indexName, columnValue, rowId) {
|
|
417
|
+
return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/' + columnValue + '/' + rowId;
|
|
418
|
+
}
|
|
419
|
+
indexValuePrefix(table, indexName, columnValue) {
|
|
420
|
+
return this.TABLE_PREFIX + table + this.INDEX_PREFIX + indexName + '/' + columnValue + '/';
|
|
421
|
+
}
|
|
422
|
+
async getSchema(table) {
|
|
423
|
+
const data = await this.db.get(this.schemaKey(table));
|
|
424
|
+
if (!data)
|
|
425
|
+
return null;
|
|
426
|
+
return JSON.parse(data.toString());
|
|
427
|
+
}
|
|
428
|
+
async getIndexes(table) {
|
|
429
|
+
// Returns map of index_name -> column_name
|
|
430
|
+
const indexes = {};
|
|
431
|
+
const prefix = this.TABLE_PREFIX + table + this.INDEX_PREFIX;
|
|
432
|
+
const pairs = await this.db.scan(prefix);
|
|
433
|
+
for (const { key, value } of pairs) {
|
|
434
|
+
const keyStr = key.toString();
|
|
435
|
+
if (keyStr.endsWith('/meta')) {
|
|
436
|
+
const info = JSON.parse(value.toString());
|
|
437
|
+
const parts = keyStr.split('/');
|
|
438
|
+
if (parts.length >= 5) {
|
|
439
|
+
const indexName = parts[parts.length - 2];
|
|
440
|
+
indexes[indexName] = info.column;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return indexes;
|
|
445
|
+
}
|
|
446
|
+
async hasIndexForColumn(table, column) {
|
|
447
|
+
const indexes = await this.getIndexes(table);
|
|
448
|
+
for (const [indexName, indexCol] of Object.entries(indexes)) {
|
|
449
|
+
if (indexCol === column) {
|
|
450
|
+
return { has: true, name: indexName };
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return { has: false, name: '' };
|
|
454
|
+
}
|
|
455
|
+
async lookupByIndex(table, indexName, value) {
|
|
456
|
+
const prefix = this.indexValuePrefix(table, indexName, value);
|
|
457
|
+
const pairs = await this.db.scan(prefix);
|
|
458
|
+
return pairs.map(p => p.value.toString());
|
|
459
|
+
}
|
|
460
|
+
async updateIndex(table, indexName, column, oldRow, newRow, rowId) {
|
|
461
|
+
const oldVal = oldRow[column];
|
|
462
|
+
const newVal = newRow[column];
|
|
463
|
+
if (oldVal === newVal) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
// Remove old index entry
|
|
467
|
+
if (oldVal != null) {
|
|
468
|
+
const oldKey = this.indexKey(table, indexName, String(oldVal), rowId);
|
|
469
|
+
await this.db.delete(oldKey);
|
|
470
|
+
}
|
|
471
|
+
// Add new index entry
|
|
472
|
+
if (newVal != null) {
|
|
473
|
+
const newKey = this.indexKey(table, indexName, String(newVal), rowId);
|
|
474
|
+
await this.db.put(newKey, rowId);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
findIndexedEqualityCondition(table, conditions, indexes) {
|
|
478
|
+
for (const [col, op, val] of conditions) {
|
|
479
|
+
if (op === '=' && Object.values(indexes).includes(col)) {
|
|
480
|
+
return [col, val];
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
async createTable(data) {
|
|
486
|
+
const table = data.table;
|
|
487
|
+
const columns = data.columns;
|
|
488
|
+
const primaryKey = data.primaryKey;
|
|
489
|
+
// Check if table exists
|
|
490
|
+
if (await this.getSchema(table)) {
|
|
491
|
+
throw new Error(`Table '${table}' already exists`);
|
|
492
|
+
}
|
|
493
|
+
const schema = { name: table, columns, primaryKey };
|
|
494
|
+
await this.db.put(this.schemaKey(table), JSON.stringify(schema));
|
|
495
|
+
return { rows: [], columns: [], rowsAffected: 0 };
|
|
496
|
+
}
|
|
497
|
+
async dropTable(data) {
|
|
498
|
+
const table = data.table;
|
|
499
|
+
// Delete all indexes first
|
|
500
|
+
const indexes = await this.getIndexes(table);
|
|
501
|
+
for (const indexName of Object.keys(indexes)) {
|
|
502
|
+
const idxPrefix = this.indexPrefix(table, indexName);
|
|
503
|
+
const idxPairs = await this.db.scan(idxPrefix);
|
|
504
|
+
for (const { key } of idxPairs) {
|
|
505
|
+
await this.db.delete(key);
|
|
506
|
+
}
|
|
507
|
+
await this.db.delete(this.indexMetaKey(table, indexName));
|
|
508
|
+
}
|
|
509
|
+
// Delete all rows
|
|
510
|
+
const prefix = this.rowPrefix(table);
|
|
511
|
+
const rows = await this.db.scan(prefix);
|
|
512
|
+
let rowsDeleted = 0;
|
|
513
|
+
for (const { key } of rows) {
|
|
514
|
+
await this.db.delete(key);
|
|
515
|
+
rowsDeleted++;
|
|
516
|
+
}
|
|
517
|
+
// Delete schema
|
|
518
|
+
await this.db.delete(this.schemaKey(table));
|
|
519
|
+
return { rows: [], columns: [], rowsAffected: rowsDeleted };
|
|
520
|
+
}
|
|
521
|
+
async createIndex(data) {
|
|
522
|
+
const indexName = data.indexName;
|
|
523
|
+
const table = data.table;
|
|
524
|
+
const column = data.column;
|
|
525
|
+
const schema = await this.getSchema(table);
|
|
526
|
+
if (!schema) {
|
|
527
|
+
throw new Error(`Table '${table}' does not exist`);
|
|
528
|
+
}
|
|
529
|
+
// Check column exists
|
|
530
|
+
if (!schema.columns.some(c => c.name === column)) {
|
|
531
|
+
throw new Error(`Column '${column}' does not exist in table '${table}'`);
|
|
532
|
+
}
|
|
533
|
+
// Check index doesn't already exist
|
|
534
|
+
const metaKey = this.indexMetaKey(table, indexName);
|
|
535
|
+
const existing = await this.db.get(metaKey);
|
|
536
|
+
if (existing) {
|
|
537
|
+
throw new Error(`Index '${indexName}' already exists on table '${table}'`);
|
|
538
|
+
}
|
|
539
|
+
// Store index metadata
|
|
540
|
+
const meta = { column, table };
|
|
541
|
+
await this.db.put(metaKey, JSON.stringify(meta));
|
|
542
|
+
// Build index from existing rows
|
|
543
|
+
const prefix = this.rowPrefix(table);
|
|
544
|
+
const pairs = await this.db.scan(prefix);
|
|
545
|
+
let indexedCount = 0;
|
|
546
|
+
for (const { value } of pairs) {
|
|
547
|
+
const row = JSON.parse(value.toString());
|
|
548
|
+
const rowId = row['_id'];
|
|
549
|
+
const colValue = row[column];
|
|
550
|
+
if (colValue != null) {
|
|
551
|
+
const idxKey = this.indexKey(table, indexName, String(colValue), rowId);
|
|
552
|
+
await this.db.put(idxKey, rowId);
|
|
553
|
+
indexedCount++;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return { rows: [], columns: [], rowsAffected: indexedCount };
|
|
557
|
+
}
|
|
558
|
+
async dropIndex(data) {
|
|
559
|
+
const indexName = data.indexName;
|
|
560
|
+
const table = data.table;
|
|
561
|
+
// Delete all index entries
|
|
562
|
+
const idxPrefix = this.indexPrefix(table, indexName);
|
|
563
|
+
const pairs = await this.db.scan(idxPrefix);
|
|
564
|
+
let deleted = 0;
|
|
565
|
+
for (const { key } of pairs) {
|
|
566
|
+
await this.db.delete(key);
|
|
567
|
+
deleted++;
|
|
568
|
+
}
|
|
569
|
+
// Delete index metadata
|
|
570
|
+
await this.db.delete(this.indexMetaKey(table, indexName));
|
|
571
|
+
return { rows: [], columns: [], rowsAffected: deleted };
|
|
572
|
+
}
|
|
573
|
+
async insert(data) {
|
|
574
|
+
const table = data.table;
|
|
575
|
+
let columns = data.columns;
|
|
576
|
+
const values = data.values;
|
|
577
|
+
const schema = await this.getSchema(table);
|
|
578
|
+
if (!schema) {
|
|
579
|
+
throw new Error(`Table '${table}' does not exist`);
|
|
580
|
+
}
|
|
581
|
+
// If no columns specified, use schema order
|
|
582
|
+
if (!columns) {
|
|
583
|
+
columns = schema.columns.map((c) => c.name);
|
|
584
|
+
}
|
|
585
|
+
if (columns.length !== values.length) {
|
|
586
|
+
throw new Error(`Column count (${columns.length}) doesn't match value count (${values.length})`);
|
|
587
|
+
}
|
|
588
|
+
// Create row object
|
|
589
|
+
const row = {};
|
|
590
|
+
for (let i = 0; i < columns.length; i++) {
|
|
591
|
+
row[columns[i]] = values[i];
|
|
592
|
+
}
|
|
593
|
+
// Generate row ID
|
|
594
|
+
let rowId;
|
|
595
|
+
if (schema.primaryKey && schema.primaryKey in row) {
|
|
596
|
+
rowId = String(row[schema.primaryKey]);
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
rowId = (0, uuid_1.v4)();
|
|
600
|
+
}
|
|
601
|
+
row['_id'] = rowId;
|
|
602
|
+
await this.db.put(this.rowKey(table, rowId), JSON.stringify(row));
|
|
603
|
+
// Maintain indexes
|
|
604
|
+
const indexes = await this.getIndexes(table);
|
|
605
|
+
for (const [indexName, indexCol] of Object.entries(indexes)) {
|
|
606
|
+
if (row[indexCol] != null) {
|
|
607
|
+
const idxKey = this.indexKey(table, indexName, String(row[indexCol]), rowId);
|
|
608
|
+
await this.db.put(idxKey, rowId);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return { rows: [], columns: [], rowsAffected: 1 };
|
|
612
|
+
}
|
|
613
|
+
async select(data) {
|
|
614
|
+
const table = data.table;
|
|
615
|
+
let columns = data.columns;
|
|
616
|
+
const conditions = data.where;
|
|
617
|
+
const orderBy = data.orderBy;
|
|
618
|
+
const limit = data.limit;
|
|
619
|
+
const offset = data.offset;
|
|
620
|
+
const schema = await this.getSchema(table);
|
|
621
|
+
if (!schema) {
|
|
622
|
+
throw new Error(`Table '${table}' does not exist`);
|
|
623
|
+
}
|
|
624
|
+
// Get column names
|
|
625
|
+
if (columns.length === 1 && columns[0] === '*') {
|
|
626
|
+
columns = schema.columns.map((c) => c.name);
|
|
627
|
+
}
|
|
628
|
+
// Scan all rows
|
|
629
|
+
const prefix = this.rowPrefix(table);
|
|
630
|
+
const scanResults = await this.db.scan(prefix);
|
|
631
|
+
let rows = [];
|
|
632
|
+
for (const { value } of scanResults) {
|
|
633
|
+
const row = JSON.parse(value.toString());
|
|
634
|
+
// Apply WHERE conditions
|
|
635
|
+
if (this.matchesConditions(row, conditions)) {
|
|
636
|
+
// Project columns
|
|
637
|
+
const projected = {};
|
|
638
|
+
for (const col of columns) {
|
|
639
|
+
if (col in row) {
|
|
640
|
+
projected[col] = row[col];
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
rows.push(projected);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
// Apply ORDER BY
|
|
647
|
+
if (orderBy && orderBy.length > 0) {
|
|
648
|
+
rows.sort((a, b) => {
|
|
649
|
+
for (const [col, direction] of orderBy) {
|
|
650
|
+
const aVal = a[col];
|
|
651
|
+
const bVal = b[col];
|
|
652
|
+
// Handle nulls
|
|
653
|
+
if (aVal === null || aVal === undefined)
|
|
654
|
+
return 1;
|
|
655
|
+
if (bVal === null || bVal === undefined)
|
|
656
|
+
return -1;
|
|
657
|
+
let cmp = 0;
|
|
658
|
+
if (aVal < bVal)
|
|
659
|
+
cmp = -1;
|
|
660
|
+
else if (aVal > bVal)
|
|
661
|
+
cmp = 1;
|
|
662
|
+
if (direction === 'DESC')
|
|
663
|
+
cmp = -cmp;
|
|
664
|
+
if (cmp !== 0)
|
|
665
|
+
return cmp;
|
|
666
|
+
}
|
|
667
|
+
return 0;
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
// Apply OFFSET and LIMIT
|
|
671
|
+
if (offset && offset > 0) {
|
|
672
|
+
rows = rows.slice(offset);
|
|
673
|
+
}
|
|
674
|
+
if (limit !== undefined && limit > 0) {
|
|
675
|
+
rows = rows.slice(0, limit);
|
|
676
|
+
}
|
|
677
|
+
return { rows, columns, rowsAffected: 0 };
|
|
678
|
+
}
|
|
679
|
+
matchesConditions(row, conditions) {
|
|
680
|
+
for (const [col, op, val] of conditions) {
|
|
681
|
+
const rowVal = row[col];
|
|
682
|
+
switch (op) {
|
|
683
|
+
case '=':
|
|
684
|
+
if (rowVal !== val)
|
|
685
|
+
return false;
|
|
686
|
+
break;
|
|
687
|
+
case '!=':
|
|
688
|
+
if (rowVal === val)
|
|
689
|
+
return false;
|
|
690
|
+
break;
|
|
691
|
+
case '>':
|
|
692
|
+
if (rowVal === null || rowVal === undefined || rowVal <= val)
|
|
693
|
+
return false;
|
|
694
|
+
break;
|
|
695
|
+
case '>=':
|
|
696
|
+
if (rowVal === null || rowVal === undefined || rowVal < val)
|
|
697
|
+
return false;
|
|
698
|
+
break;
|
|
699
|
+
case '<':
|
|
700
|
+
if (rowVal === null || rowVal === undefined || rowVal >= val)
|
|
701
|
+
return false;
|
|
702
|
+
break;
|
|
703
|
+
case '<=':
|
|
704
|
+
if (rowVal === null || rowVal === undefined || rowVal > val)
|
|
705
|
+
return false;
|
|
706
|
+
break;
|
|
707
|
+
case 'LIKE': {
|
|
708
|
+
if (rowVal === null || rowVal === undefined)
|
|
709
|
+
return false;
|
|
710
|
+
const pattern = String(val).replace(/%/g, '.*').replace(/_/g, '.');
|
|
711
|
+
if (!new RegExp(`^${pattern}$`, 'i').test(String(rowVal)))
|
|
712
|
+
return false;
|
|
713
|
+
break;
|
|
714
|
+
}
|
|
715
|
+
case 'NOT_LIKE': {
|
|
716
|
+
if (rowVal === null || rowVal === undefined)
|
|
717
|
+
return true;
|
|
718
|
+
const pattern = String(val).replace(/%/g, '.*').replace(/_/g, '.');
|
|
719
|
+
if (new RegExp(`^${pattern}$`, 'i').test(String(rowVal)))
|
|
720
|
+
return false;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
727
|
+
async update(data) {
|
|
728
|
+
const table = data.table;
|
|
729
|
+
const updates = data.updates;
|
|
730
|
+
const conditions = data.where;
|
|
731
|
+
const schema = await this.getSchema(table);
|
|
732
|
+
if (!schema) {
|
|
733
|
+
throw new Error(`Table '${table}' does not exist`);
|
|
734
|
+
}
|
|
735
|
+
const indexes = await this.getIndexes(table);
|
|
736
|
+
let rowsAffected = 0;
|
|
737
|
+
// Try index-accelerated path
|
|
738
|
+
const indexedCond = this.findIndexedEqualityCondition(table, conditions, indexes);
|
|
739
|
+
if (indexedCond) {
|
|
740
|
+
// Index-accelerated UPDATE
|
|
741
|
+
const [col, val] = indexedCond;
|
|
742
|
+
const indexResult = await this.hasIndexForColumn(table, col);
|
|
743
|
+
if (indexResult.has) {
|
|
744
|
+
const rowIds = await this.lookupByIndex(table, indexResult.name, String(val));
|
|
745
|
+
for (const rowId of rowIds) {
|
|
746
|
+
const key = this.rowKey(table, rowId);
|
|
747
|
+
const value = await this.db.get(key);
|
|
748
|
+
if (!value)
|
|
749
|
+
continue;
|
|
750
|
+
const oldRow = JSON.parse(value.toString());
|
|
751
|
+
// Apply all WHERE conditions (not just the indexed one)
|
|
752
|
+
if (!this.matchesConditions(oldRow, conditions)) {
|
|
753
|
+
continue;
|
|
754
|
+
}
|
|
755
|
+
// Apply updates
|
|
756
|
+
const newRow = { ...oldRow };
|
|
757
|
+
for (const [ucol, uval] of Object.entries(updates)) {
|
|
758
|
+
newRow[ucol] = uval;
|
|
759
|
+
}
|
|
760
|
+
// Update indexes for changed columns
|
|
761
|
+
for (const [idxName, idxCol] of Object.entries(indexes)) {
|
|
762
|
+
if (idxCol in updates) {
|
|
763
|
+
await this.updateIndex(table, idxName, idxCol, oldRow, newRow, rowId);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
await this.db.put(key, JSON.stringify(newRow));
|
|
767
|
+
rowsAffected++;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
// Fallback: full table scan
|
|
773
|
+
const prefix = this.rowPrefix(table);
|
|
774
|
+
const scanResults = await this.db.scan(prefix);
|
|
775
|
+
for (const { key, value } of scanResults) {
|
|
776
|
+
const oldRow = JSON.parse(value.toString());
|
|
777
|
+
// Apply WHERE conditions
|
|
778
|
+
if (this.matchesConditions(oldRow, conditions)) {
|
|
779
|
+
// Apply updates
|
|
780
|
+
const newRow = { ...oldRow };
|
|
781
|
+
for (const [col, val] of Object.entries(updates)) {
|
|
782
|
+
newRow[col] = val;
|
|
783
|
+
}
|
|
784
|
+
const rowId = oldRow['_id'];
|
|
785
|
+
// Update indexes for changed columns
|
|
786
|
+
for (const [idxName, idxCol] of Object.entries(indexes)) {
|
|
787
|
+
if (idxCol in updates) {
|
|
788
|
+
await this.updateIndex(table, idxName, idxCol, oldRow, newRow, rowId);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
await this.db.put(key, JSON.stringify(newRow));
|
|
792
|
+
rowsAffected++;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return { rows: [], columns: [], rowsAffected };
|
|
797
|
+
}
|
|
798
|
+
async deleteRows(data) {
|
|
799
|
+
const table = data.table;
|
|
800
|
+
const conditions = data.where;
|
|
801
|
+
const schema = await this.getSchema(table);
|
|
802
|
+
if (!schema) {
|
|
803
|
+
throw new Error(`Table '${table}' does not exist`);
|
|
804
|
+
}
|
|
805
|
+
const indexes = await this.getIndexes(table);
|
|
806
|
+
let rowsAffected = 0;
|
|
807
|
+
// Try index-accelerated path
|
|
808
|
+
const indexedCond = this.findIndexedEqualityCondition(table, conditions, indexes);
|
|
809
|
+
if (indexedCond) {
|
|
810
|
+
// Index-accelerated DELETE
|
|
811
|
+
const [col, val] = indexedCond;
|
|
812
|
+
const indexResult = await this.hasIndexForColumn(table, col);
|
|
813
|
+
if (indexResult.has) {
|
|
814
|
+
const rowIds = await this.lookupByIndex(table, indexResult.name, String(val));
|
|
815
|
+
const keysToDelete = [];
|
|
816
|
+
const rowsToDelete = [];
|
|
817
|
+
for (const rowId of rowIds) {
|
|
818
|
+
const key = this.rowKey(table, rowId);
|
|
819
|
+
const value = await this.db.get(key);
|
|
820
|
+
if (!value)
|
|
821
|
+
continue;
|
|
822
|
+
const row = JSON.parse(value.toString());
|
|
823
|
+
// Apply all WHERE conditions (not just the indexed one)
|
|
824
|
+
if (this.matchesConditions(row, conditions)) {
|
|
825
|
+
keysToDelete.push(Buffer.from(key));
|
|
826
|
+
rowsToDelete.push({ row, rowId });
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
// Delete rows and update indexes
|
|
830
|
+
for (let i = 0; i < keysToDelete.length; i++) {
|
|
831
|
+
const key = keysToDelete[i];
|
|
832
|
+
const { row, rowId } = rowsToDelete[i];
|
|
833
|
+
// Remove from all indexes
|
|
834
|
+
for (const [idxName, idxCol] of Object.entries(indexes)) {
|
|
835
|
+
const emptyRow = {};
|
|
836
|
+
await this.updateIndex(table, idxName, idxCol, row, emptyRow, rowId);
|
|
837
|
+
}
|
|
838
|
+
await this.db.delete(key);
|
|
839
|
+
rowsAffected++;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
// Fallback: full table scan
|
|
845
|
+
const prefix = this.rowPrefix(table);
|
|
846
|
+
const scanResults = await this.db.scan(prefix);
|
|
847
|
+
const keysToDelete = [];
|
|
848
|
+
const rowsToDelete = [];
|
|
849
|
+
for (const { key, value } of scanResults) {
|
|
850
|
+
const row = JSON.parse(value.toString());
|
|
851
|
+
// Apply WHERE conditions
|
|
852
|
+
if (this.matchesConditions(row, conditions)) {
|
|
853
|
+
const rowId = row['_id'];
|
|
854
|
+
keysToDelete.push(key);
|
|
855
|
+
rowsToDelete.push({ row, rowId });
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
// Delete collected rows and update indexes
|
|
859
|
+
for (let i = 0; i < keysToDelete.length; i++) {
|
|
860
|
+
const key = keysToDelete[i];
|
|
861
|
+
const { row, rowId } = rowsToDelete[i];
|
|
862
|
+
// Remove from all indexes
|
|
863
|
+
for (const [idxName, idxCol] of Object.entries(indexes)) {
|
|
864
|
+
const emptyRow = {};
|
|
865
|
+
await this.updateIndex(table, idxName, idxCol, row, emptyRow, rowId);
|
|
866
|
+
}
|
|
867
|
+
await this.db.delete(key);
|
|
868
|
+
rowsAffected++;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return { rows: [], columns: [], rowsAffected };
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
exports.SQLExecutor = SQLExecutor;
|
|
875
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3FsLWVuZ2luZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcWwtZW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7O0dBU0c7OztBQUVILDBEQUEwRDtBQUMxRCxFQUFFO0FBQ0Ysa0VBQWtFO0FBQ2xFLG1FQUFtRTtBQUNuRSwwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGLGlEQUFpRDtBQUVqRCwrQkFBb0M7QUFrRHBDOztHQUVHO0FBQ0gsTUFBYSxTQUFTO0lBQ3BCOztPQUVHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFXO1FBQ3RCLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDakIsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRWhDLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sU0FBUyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6QyxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7WUFDMUMsT0FBTyxTQUFTLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUMxQyxPQUFPLFNBQVMsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE9BQU8sU0FBUyxDQUFDLFdBQVcsQ0FB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b0JBQ3hELE1BQU0sUUFBUSxHQUF3QixFQUFFLENBQUM7b0JBQ3pDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN2RSxDQUFDO2dCQUVELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFCLFlBQVksRUFBRSxDQUFDO1lBQ2pCLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0NBQ0Y7QUEvbEJELGtDQStsQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNRTCBFbmdpbmUgZm9yIFNvY2hEQiBKYXZhU2NyaXB0IFNES1xuICpcbiAqIFByb3ZpZGVzIFNRTCBzdXBwb3J0IG9uIHRvcCBvZiB0aGUgS1Ygc3RvcmFnZSBiYWNrZW5kLlxuICogVGFibGVzIGFyZSBzdG9yZWQgYXM6XG4gKiAgIC0gU2NoZW1hOiBfc3FsL3RhYmxlcy97dGFibGVfbmFtZX0vc2NoZW1hIC0+IEpTT04gc2NoZW1hIGRlZmluaXRpb25cbiAqICAgLSBSb3dzOiBfc3FsL3RhYmxlcy97dGFibGVfbmFtZX0vcm93cy97cm93X2lkfSAtPiBKU09OIHJvdyBkYXRhXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cblxuLy8gQ29weXJpZ2h0IDIwMjUgU3VzaGFudGggKGh0dHBzOi8vZ2l0aHViLmNvbS9zdXNoYW50aHB5KVxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cbmltcG9ydCB7IHY0IGFzIHV1aWR2NCB9IGZyb20gJ3V1aWQnO1xuXG4vKipcbiAqIFJlc3VsdCBvZiBhIFNRTCBxdWVyeSBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU1FMUXVlcnlSZXN1bHQge1xuICAvKiogUmVzdWx0IHJvd3MgKi9cbiAgcm93czogQXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj47XG4gIC8qKiBDb2x1bW4gbmFtZXMgKi9cbiAgY29sdW1uczogc3RyaW5nW107XG4gIC8qKiBOdW1iZXIgb2Ygcm93cyBhZmZlY3RlZCAoZm9yIElOU0VSVC9VUERBVEUvREVMRVRFKSAqL1xuICByb3dzQWZmZWN0ZWQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDb2x1bW4gZGVmaW5pdGlvbiBmb3IgYSB0YWJsZS5cbiAqL1xuaW50ZXJmYWNlIENvbHVtbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nOyAvLyBJTlQsIFRFWFQsIEZMT0FULCBCT09MLCBCTE9CXG4gIG51bGxhYmxlOiBib29sZWFuO1xuICBwcmltYXJ5S2V5OiBib29sZWFuO1xuICBkZWZhdWx0PzogYW55O1xufVxuXG4vKipcbiAqIFRhYmxlIHNjaGVtYSBkZWZpbml0aW9uLlxuICovXG5pbnRlcmZhY2UgVGFibGVTY2hlbWEge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNvbHVtbnM6IENvbHVtbltdO1xuICBwcmltYXJ5S2V5Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEluZGV4IG1ldGFkYXRhLlxuICovXG5pbnRlcmZhY2UgSW5kZXhJbmZvIHtcbiAgY29sdW1uOiBzdHJpbmc7XG4gIHRhYmxlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGFyc2VkIFNRTCBvcGVyYXRpb24gcmVzdWx0LlxuICovXG50eXBlIFBhcnNlZFNRTCA9IHtcbiAgb3BlcmF0aW9uOiBzdHJpbmc7XG4gIGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT47XG59O1xuXG4vKipcbiAqIFNpbXBsZSBTUUwgcGFyc2VyIGZvciBEREwgYW5kIERNTCBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgY2xhc3MgU1FMUGFyc2VyIHtcbiAgLyoqXG4gICAqIFBhcnNlIGEgU1FMIHN0YXRlbWVudC5cbiAgICovXG4gIHN0YXRpYyBwYXJzZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgc3FsID0gc3FsLnRyaW0oKTtcbiAgICBjb25zdCB1cHBlciA9IHNxbC50b1VwcGVyQ2FzZSgpO1xuXG4gICAgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0NSRUFURSBUQUJMRScpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlQ3JlYXRlVGFibGUoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0NSRUFURSBJTkRFWCcpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlQ3JlYXRlSW5kZXgoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ0RST1AgVEFCTEUnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZURyb3BUYWJsZShzcWwpO1xuICAgIH0gZWxzZSBpZiAodXBwZXIuc3RhcnRzV2l0aCgnRFJPUCBJTkRFWCcpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlRHJvcEluZGV4KHNxbCk7XG4gICAgfSBlbHNlIGlmICh1cHBlci5zdGFydHNXaXRoKCdJTlNFUlQnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZUluc2VydChzcWwpO1xuICAgIH0gZWxzZSBpZiAodXBwZXIuc3RhcnRzV2l0aCgnU0VMRUNUJykpIHtcbiAgICAgIHJldHVybiBTUUxQYXJzZXIucGFyc2VTZWxlY3Qoc3FsKTtcbiAgICB9IGVsc2UgaWYgKHVwcGVyLnN0YXJ0c1dpdGgoJ1VQREFURScpKSB7XG4gICAgICByZXR1cm4gU1FMUGFyc2VyLnBhcnNlVXBkYXRlKHNxbCk7XG4gICAgfSBlbHNlIGlmICh1cHBlci5zdGFydHNXaXRoKCdERUxFVEUnKSkge1xuICAgICAgcmV0dXJuIFNRTFBhcnNlci5wYXJzZURlbGV0ZShzcWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIFNRTCBzdGF0ZW1lbnQ6ICR7c3FsLnN1YnN0cmluZygwLCA1MCl9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VDcmVhdGVUYWJsZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgY29uc3QgbWF0Y2ggPSBzcWwubWF0Y2goXG4gICAgICAvQ1JFQVRFXFxzK1RBQkxFXFxzKyg/OklGXFxzK05PVFxccytFWElTVFNcXHMrKT8oXFx3KylcXHMqXFwoKC4qKVxcKS9pc1xuICAgICk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIENSRUFURSBUQUJMRTogJHtzcWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgdGFibGVOYW1lID0gbWF0Y2hbMV07XG4gICAgY29uc3QgY29sc1N0ciA9IG1hdGNoWzJdO1xuICAgIGNvbnN0IGNvbHVtbnM6IENvbHVtbltdID0gW107XG4gICAgbGV0IHByaW1hcnlLZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGNvbERlZnMgPSBTUUxQYXJzZXIuc3BsaXRDb2x1bW5zKGNvbHNTdHIpO1xuXG4gICAgZm9yIChjb25zdCBjb2xEZWYgb2YgY29sRGVmcykge1xuICAgICAgY29uc3QgdHJpbW1lZCA9IGNvbERlZi50cmltKCk7XG4gICAgICBpZiAoIXRyaW1tZWQpIGNvbnRpbnVlO1xuXG4gICAgICAvLyBDaGVjayBmb3IgUFJJTUFSWSBLRVkgY29uc3RyYWludFxuICAgICAgaWYgKHRyaW1tZWQudG9VcHBlckNhc2UoKS5zdGFydHNXaXRoKCdQUklNQVJZIEtFWScpKSB7XG4gICAgICAgIGNvbnN0IHBrTWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9QUklNQVJZXFxzK0tFWVxccypcXCgoXFx3KylcXCkvaSk7XG4gICAgICAgIGlmIChwa01hdGNoKSB7XG4gICAgICAgICAgcHJpbWFyeUtleSA9IHBrTWF0Y2hbMV07XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFBhcnNlIGNvbHVtbjogbmFtZSBUWVBFIFtQUklNQVJZIEtFWV0gW05PVCBOVUxMXSBbREVGQVVMVCB2YWx1ZV1cbiAgICAgIGNvbnN0IHBhcnRzID0gdHJpbW1lZC5zcGxpdCgvXFxzKy8pO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA8IDIpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCBjb2xOYW1lID0gcGFydHNbMF07XG4gICAgICBsZXQgY29sVHlwZSA9IHBhcnRzWzFdLnRvVXBwZXJDYXNlKCk7XG5cbiAgICAgIC8vIE5vcm1hbGl6ZSB0eXBlc1xuICAgICAgaWYgKFsnSU5URUdFUicsICdJTlQnLCAnQklHSU5UJywgJ1NNQUxMSU5UJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdJTlQnO1xuICAgICAgfSBlbHNlIGlmIChbJ1ZBUkNIQVInLCAnQ0hBUicsICdTVFJJTkcnLCAnVEVYVCddLmluY2x1ZGVzKGNvbFR5cGUpKSB7XG4gICAgICAgIGNvbFR5cGUgPSAnVEVYVCc7XG4gICAgICB9IGVsc2UgaWYgKFsnUkVBTCcsICdET1VCTEUnLCAnRkxPQVQnLCAnREVDSU1BTCcsICdOVU1FUklDJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdGTE9BVCc7XG4gICAgICB9IGVsc2UgaWYgKFsnQk9PTEVBTicsICdCT09MJ10uaW5jbHVkZXMoY29sVHlwZSkpIHtcbiAgICAgICAgY29sVHlwZSA9ICdCT09MJztcbiAgICAgIH0gZWxzZSBpZiAoWydCTE9CJywgJ0JZVEVTJywgJ0JJTkFSWSddLmluY2x1ZGVzKGNvbFR5cGUpKSB7XG4gICAgICAgIGNvbFR5cGUgPSAnQkxPQic7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbFVwcGVyID0gdHJpbW1lZC50b1VwcGVyQ2FzZSgpO1xuICAgICAgY29uc3QgaXNQayA9IGNvbFVwcGVyLmluY2x1ZGVzKCdQUklNQVJZIEtFWScpO1xuICAgICAgY29uc3QgbnVsbGFibGUgPSAhY29sVXBwZXIuaW5jbHVkZXMoJ05PVCBOVUxMJyk7XG5cbiAgICAgIGlmIChpc1BrKSB7XG4gICAgICAgIHByaW1hcnlLZXkgPSBjb2xOYW1lO1xuICAgICAgfVxuXG4gICAgICBjb2x1bW5zLnB1c2goe1xuICAgICAgICBuYW1lOiBjb2xOYW1lLFxuICAgICAgICB0eXBlOiBjb2xUeXBlLFxuICAgICAgICBudWxsYWJsZSxcbiAgICAgICAgcHJpbWFyeUtleTogaXNQayxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvcGVyYXRpb246ICdDUkVBVEVfVEFCTEUnLFxuICAgICAgZGF0YTogeyB0YWJsZTogdGFibGVOYW1lLCBjb2x1bW5zLCBwcmltYXJ5S2V5IH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHNwbGl0Q29sdW1ucyhjb2xzU3RyOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgcmVzdWx0OiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBjdXJyZW50ID0gJyc7XG4gICAgbGV0IGRlcHRoID0gMDtcblxuICAgIGZvciAoY29uc3QgY2hhciBvZiBjb2xzU3RyKSB7XG4gICAgICBpZiAoY2hhciA9PT0gJygnKSB7XG4gICAgICAgIGRlcHRoKys7XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJyknKSB7XG4gICAgICAgIGRlcHRoLS07XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJywnICYmIGRlcHRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnQpO1xuICAgICAgICBjdXJyZW50ID0gJyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGN1cnJlbnQudHJpbSgpKSB7XG4gICAgICByZXN1bHQucHVzaChjdXJyZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VEcm9wVGFibGUoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9EUk9QXFxzK1RBQkxFXFxzKyg/OklGXFxzK0VYSVNUU1xccyspPyhcXHcrKS9pKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgRFJPUCBUQUJMRTogJHtzcWx9YCk7XG4gICAgfVxuICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0RST1BfVEFCTEUnLCBkYXRhOiB7IHRhYmxlOiBtYXRjaFsxXSB9IH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZUNyZWF0ZUluZGV4KHNxbDogc3RyaW5nKTogUGFyc2VkU1FMIHtcbiAgICAvLyBDUkVBVEUgSU5ERVggaWR4X25hbWUgT04gdGFibGVfbmFtZShjb2x1bW5fbmFtZSlcbiAgICBjb25zdCBtYXRjaCA9IHNxbC5tYXRjaCgvQ1JFQVRFXFxzK0lOREVYXFxzKyhcXHcrKVxccytPTlxccysoXFx3KylcXHMqXFwoXFxzKihcXHcrKVxccypcXCkvaSk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIENSRUFURSBJTkRFWCBzeW50YXg6ICR7c3FsfWApO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgb3BlcmF0aW9uOiAnQ1JFQVRFX0lOREVYJyxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgaW5kZXhOYW1lOiBtYXRjaFsxXSxcbiAgICAgICAgdGFibGU6IG1hdGNoWzJdLFxuICAgICAgICBjb2x1bW46IG1hdGNoWzNdLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VEcm9wSW5kZXgoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIC8vIERST1AgSU5ERVggaWR4X25hbWUgT04gdGFibGVfbmFtZVxuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9EUk9QXFxzK0lOREVYXFxzKyhcXHcrKVxccytPTlxccysoXFx3KykvaSk7XG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIERST1AgSU5ERVggc3ludGF4OiAke3NxbH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIG9wZXJhdGlvbjogJ0RST1BfSU5ERVgnLFxuICAgICAgZGF0YToge1xuICAgICAgICBpbmRleE5hbWU6IG1hdGNoWzFdLFxuICAgICAgICB0YWJsZTogbWF0Y2hbMl0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZUluc2VydChzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgLy8gSU5TRVJUIElOVE8gdGFibGUgKGNvbDEsIGNvbDIpIFZBTFVFUyAodmFsMSwgdmFsMilcbiAgICBsZXQgbWF0Y2ggPSBzcWwubWF0Y2goXG4gICAgICAvSU5TRVJUXFxzK0lOVE9cXHMrKFxcdyspXFxzKlxcKChbXildKylcXClcXHMqVkFMVUVTXFxzKlxcKCguKylcXCkvaXNcbiAgICApO1xuXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgICAgY29uc3QgY29sdW1ucyA9IG1hdGNoWzJdLnNwbGl0KCcsJykubWFwKChjKSA9PiBjLnRyaW0oKSk7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBTUUxQYXJzZXIucGFyc2VWYWx1ZXMobWF0Y2hbM10pO1xuICAgICAgcmV0dXJuIHsgb3BlcmF0aW9uOiAnSU5TRVJUJywgZGF0YTogeyB0YWJsZSwgY29sdW1ucywgdmFsdWVzIH0gfTtcbiAgICB9XG5cbiAgICAvLyBJTlNFUlQgSU5UTyB0YWJsZSBWQUxVRVMgKHZhbDEsIHZhbDIpXG4gICAgbWF0Y2ggPSBzcWwubWF0Y2goL0lOU0VSVFxccytJTlRPXFxzKyhcXHcrKVxccytWQUxVRVNcXHMqXFwoKC4rKVxcKS9pcyk7XG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgICAgY29uc3QgdmFsdWVzID0gU1FMUGFyc2VyLnBhcnNlVmFsdWVzKG1hdGNoWzJdKTtcbiAgICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0lOU0VSVCcsIGRhdGE6IHsgdGFibGUsIGNvbHVtbnM6IG51bGwsIHZhbHVlcyB9IH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIElOU0VSVDogJHtzcWx9YCk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVZhbHVlcyh2YWx1ZXNTdHI6IHN0cmluZyk6IGFueVtdIHtcbiAgICBjb25zdCB2YWx1ZXM6IGFueVtdID0gW107XG4gICAgbGV0IGN1cnJlbnQgPSAnJztcbiAgICBsZXQgaW5TdHJpbmcgPSBmYWxzZTtcbiAgICBsZXQgc3RyaW5nQ2hhcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBmb3IgKGNvbnN0IGNoYXIgb2YgdmFsdWVzU3RyKSB7XG4gICAgICBpZiAoKGNoYXIgPT09ICdcIicgfHwgY2hhciA9PT0gXCInXCIpICYmICFpblN0cmluZykge1xuICAgICAgICBpblN0cmluZyA9IHRydWU7XG4gICAgICAgIHN0cmluZ0NoYXIgPSBjaGFyO1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9IGVsc2UgaWYgKGNoYXIgPT09IHN0cmluZ0NoYXIgJiYgaW5TdHJpbmcpIHtcbiAgICAgICAgaW5TdHJpbmcgPSBmYWxzZTtcbiAgICAgICAgc3RyaW5nQ2hhciA9IG51bGw7XG4gICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gJywnICYmICFpblN0cmluZykge1xuICAgICAgICB2YWx1ZXMucHVzaChTUUxQYXJzZXIucGFyc2VWYWx1ZShjdXJyZW50LnRyaW0oKSkpO1xuICAgICAgICBjdXJyZW50ID0gJyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50ICs9IGNoYXI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGN1cnJlbnQudHJpbSgpKSB7XG4gICAgICB2YWx1ZXMucHVzaChTUUxQYXJzZXIucGFyc2VWYWx1ZShjdXJyZW50LnRyaW0oKSkpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVZhbHVlKHZhbFN0cjogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoIXZhbFN0ciB8fCB2YWxTdHIudG9VcHBlckNhc2UoKSA9PT0gJ05VTEwnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTdHJpbmcgbGl0ZXJhbHNcbiAgICBpZiAoXG4gICAgICAodmFsU3RyLnN0YXJ0c1dpdGgoXCInXCIpICYmIHZhbFN0ci5lbmRzV2l0aChcIidcIikpIHx8XG4gICAgICAodmFsU3RyLnN0YXJ0c1dpdGgoJ1wiJykgJiYgdmFsU3RyLmVuZHNXaXRoKCdcIicpKVxuICAgICkge1xuICAgICAgcmV0dXJuIHZhbFN0ci5zbGljZSgxLCAtMSk7XG4gICAgfVxuXG4gICAgLy8gQm9vbGVhblxuICAgIGlmICh2YWxTdHIudG9VcHBlckNhc2UoKSA9PT0gJ1RSVUUnKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAodmFsU3RyLnRvVXBwZXJDYXNlKCkgPT09ICdGQUxTRScpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIE51bWJlcnNcbiAgICBpZiAodmFsU3RyLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgIGNvbnN0IG51bSA9IHBhcnNlRmxvYXQodmFsU3RyKTtcbiAgICAgIGlmICghaXNOYU4obnVtKSkgcmV0dXJuIG51bTtcbiAgICB9XG4gICAgY29uc3QgaW50VmFsID0gcGFyc2VJbnQodmFsU3RyLCAxMCk7XG4gICAgaWYgKCFpc05hTihpbnRWYWwpKSByZXR1cm4gaW50VmFsO1xuXG4gICAgcmV0dXJuIHZhbFN0cjtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIHBhcnNlU2VsZWN0KHNxbDogc3RyaW5nKTogUGFyc2VkU1FMIHtcbiAgICAvLyBFeHRyYWN0IHRhYmxlIG5hbWUgZmlyc3RcbiAgICBjb25zdCB0YWJsZU1hdGNoID0gc3FsLm1hdGNoKC9GUk9NXFxzKyhcXHcrKS9pKTtcbiAgICBpZiAoIXRhYmxlTWF0Y2gpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBTRUxFQ1Q6ICR7c3FsfWApO1xuICAgIH1cbiAgICBjb25zdCB0YWJsZSA9IHRhYmxlTWF0Y2hbMV07XG5cbiAgICAvLyBFeHRyYWN0IGNvbHVtbnNcbiAgICBjb25zdCBjb2xzTWF0Y2ggPSBzcWwubWF0Y2goL1NFTEVDVFxccysoLis/KVxccytGUk9NL2lzKTtcbiAgICBsZXQgY29sdW1uczogc3RyaW5nW10gPSBbJyonXTtcbiAgICBpZiAoY29sc01hdGNoKSB7XG4gICAgICBjb25zdCBjb2xzU3RyID0gY29sc01hdGNoWzFdLnRyaW0oKTtcbiAgICAgIGNvbHVtbnMgPSBjb2xzU3RyID09PSAnKicgPyBbJyonXSA6IGNvbHNTdHIuc3BsaXQoJywnKS5tYXAoKGMpID0+IGMudHJpbSgpKTtcbiAgICB9XG5cbiAgICAvLyBFeHRyYWN0IFdIRVJFIGNsYXVzZVxuICAgIGxldCBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+ID0gW107XG4gICAgY29uc3Qgd2hlcmVNYXRjaCA9IHNxbC5tYXRjaCgvV0hFUkVcXHMrKC4rPykoPzpcXHMrT1JERVJ8XFxzK0xJTUlUfFxccytPRkZTRVR8JCkvaXMpO1xuICAgIGlmICh3aGVyZU1hdGNoKSB7XG4gICAgICBjb25kaXRpb25zID0gU1FMUGFyc2VyLnBhcnNlV2hlcmUod2hlcmVNYXRjaFsxXSk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBPUkRFUiBCWVxuICAgIGxldCBvcmRlckJ5OiBBcnJheTxbc3RyaW5nLCBzdHJpbmddPiA9IFtdO1xuICAgIGNvbnN0IG9yZGVyTWF0Y2ggPSBzcWwubWF0Y2goL09SREVSXFxzK0JZXFxzKyguKz8pKD86XFxzK0xJTUlUfFxccytPRkZTRVR8JCkvaSk7XG4gICAgaWYgKG9yZGVyTWF0Y2gpIHtcbiAgICAgIGZvciAoY29uc3QgcGFydCBvZiBvcmRlck1hdGNoWzFdLnNwbGl0KCcsJykpIHtcbiAgICAgICAgY29uc3QgdHJpbW1lZCA9IHBhcnQudHJpbSgpO1xuICAgICAgICBpZiAodHJpbW1lZC50b1VwcGVyQ2FzZSgpLmVuZHNXaXRoKCcgREVTQycpKSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLnNsaWNlKDAsIC01KS50cmltKCksICdERVNDJ10pO1xuICAgICAgICB9IGVsc2UgaWYgKHRyaW1tZWQudG9VcHBlckNhc2UoKS5lbmRzV2l0aCgnIEFTQycpKSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLnNsaWNlKDAsIC00KS50cmltKCksICdBU0MnXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3JkZXJCeS5wdXNoKFt0cmltbWVkLCAnQVNDJ10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBMSU1JVFxuICAgIGxldCBsaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxpbWl0TWF0Y2ggPSBzcWwubWF0Y2goL0xJTUlUXFxzKyhcXGQrKS9pKTtcbiAgICBpZiAobGltaXRNYXRjaCkge1xuICAgICAgbGltaXQgPSBwYXJzZUludChsaW1pdE1hdGNoWzFdLCAxMCk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBPRkZTRVRcbiAgICBsZXQgb2Zmc2V0OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb2Zmc2V0TWF0Y2ggPSBzcWwubWF0Y2goL09GRlNFVFxccysoXFxkKykvaSk7XG4gICAgaWYgKG9mZnNldE1hdGNoKSB7XG4gICAgICBvZmZzZXQgPSBwYXJzZUludChvZmZzZXRNYXRjaFsxXSwgMTApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvcGVyYXRpb246ICdTRUxFQ1QnLFxuICAgICAgZGF0YTogeyB0YWJsZSwgY29sdW1ucywgd2hlcmU6IGNvbmRpdGlvbnMsIG9yZGVyQnksIGxpbWl0LCBvZmZzZXQgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VXaGVyZSh3aGVyZUNsYXVzZTogc3RyaW5nKTogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiB7XG4gICAgY29uc3QgY29uZGl0aW9uczogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiA9IFtdO1xuICAgIGNvbnN0IHBhcnRzID0gd2hlcmVDbGF1c2Uuc3BsaXQoL1xccytBTkRcXHMrL2kpO1xuXG4gICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICBjb25zdCBtYXRjaCA9IHBhcnQubWF0Y2goLyhcXHcrKVxccyooPXwhPXw8Pnw+PXw8PXw+fDx8TElLRXxOT1RcXHMrTElLRSlcXHMqKC4rKS9pKTtcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBjb25zdCBjb2wgPSBtYXRjaFsxXTtcbiAgICAgICAgbGV0IG9wID0gbWF0Y2hbMl0udG9VcHBlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2csICdfJyk7XG4gICAgICAgIGlmIChvcCA9PT0gJzw+Jykgb3AgPSAnIT0nO1xuICAgICAgICBjb25zdCB2YWwgPSBTUUxQYXJzZXIucGFyc2VWYWx1ZShtYXRjaFszXS50cmltKCkpO1xuICAgICAgICBjb25kaXRpb25zLnB1c2goW2NvbCwgb3AsIHZhbF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb25kaXRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VVcGRhdGUoc3FsOiBzdHJpbmcpOiBQYXJzZWRTUUwge1xuICAgIGNvbnN0IG1hdGNoID0gc3FsLm1hdGNoKC9VUERBVEVcXHMrKFxcdyspXFxzK1NFVFxccysoLis/KSg/OlxccytXSEVSRVxccysoLispKT8kL2lzKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgVVBEQVRFOiAke3NxbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgIGNvbnN0IHNldENsYXVzZSA9IG1hdGNoWzJdO1xuICAgIGNvbnN0IHdoZXJlQ2xhdXNlID0gbWF0Y2hbM107XG5cbiAgICAvLyBQYXJzZSBTRVQgY2xhdXNlXG4gICAgY29uc3QgdXBkYXRlczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIGZvciAoY29uc3QgcGFydCBvZiBzZXRDbGF1c2Uuc3BsaXQoJywnKSkge1xuICAgICAgY29uc3QgZXFNYXRjaCA9IHBhcnQubWF0Y2goL1xccyooXFx3KylcXHMqPVxccyooLispXFxzKi8pO1xuICAgICAgaWYgKGVxTWF0Y2gpIHtcbiAgICAgICAgdXBkYXRlc1tlcU1hdGNoWzFdXSA9IFNRTFBhcnNlci5wYXJzZVZhbHVlKGVxTWF0Y2hbMl0udHJpbSgpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgY29uZGl0aW9uczogQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPiA9IFtdO1xuICAgIGlmICh3aGVyZUNsYXVzZSkge1xuICAgICAgY29uZGl0aW9ucyA9IFNRTFBhcnNlci5wYXJzZVdoZXJlKHdoZXJlQ2xhdXNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBvcGVyYXRpb246ICdVUERBVEUnLCBkYXRhOiB7IHRhYmxlLCB1cGRhdGVzLCB3aGVyZTogY29uZGl0aW9ucyB9IH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZURlbGV0ZShzcWw6IHN0cmluZyk6IFBhcnNlZFNRTCB7XG4gICAgY29uc3QgbWF0Y2ggPSBzcWwubWF0Y2goL0RFTEVURVxccytGUk9NXFxzKyhcXHcrKSg/OlxccytXSEVSRVxccysoLispKT8kL2lzKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgREVMRVRFOiAke3NxbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB0YWJsZSA9IG1hdGNoWzFdO1xuICAgIGxldCBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+ID0gW107XG4gICAgaWYgKG1hdGNoWzJdKSB7XG4gICAgICBjb25kaXRpb25zID0gU1FMUGFyc2VyLnBhcnNlV2hlcmUobWF0Y2hbMl0pO1xuICAgIH1cblxuICAgIHJldHVybiB7IG9wZXJhdGlvbjogJ0RFTEVURScsIGRhdGE6IHsgdGFibGUsIHdoZXJlOiBjb25kaXRpb25zIH0gfTtcbiAgfVxufVxuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9ucyByZXF1aXJlZCBieSBTUUxFeGVjdXRvci5cbiAqL1xuaW50ZXJmYWNlIERhdGFiYXNlSW50ZXJmYWNlIHtcbiAgZ2V0KGtleTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPjtcbiAgcHV0KGtleTogQnVmZmVyIHwgc3RyaW5nLCB2YWx1ZTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgZGVsZXRlKGtleTogQnVmZmVyIHwgc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgc2NhbihwcmVmaXg6IHN0cmluZyk6IFByb21pc2U8QXJyYXk8eyBrZXk6IEJ1ZmZlcjsgdmFsdWU6IEJ1ZmZlciB9Pj47XG59XG5cbi8qKlxuICogU1FMIEV4ZWN1dG9yIHRoYXQgb3BlcmF0ZXMgb24gYSBLViBkYXRhYmFzZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNRTEV4ZWN1dG9yIHtcbiAgcHJpdmF0ZSBkYjogRGF0YWJhc2VJbnRlcmZhY2U7XG5cbiAgLy8gS2V5IHByZWZpeGVzIGZvciBTUUwgZGF0YVxuICBwcml2YXRlIHJlYWRvbmx5IFRBQkxFX1BSRUZJWCA9ICdfc3FsL3RhYmxlcy8nO1xuICBwcml2YXRlIHJlYWRvbmx5IFNDSEVNQV9TVUZGSVggPSAnL3NjaGVtYSc7XG4gIHByaXZhdGUgcmVhZG9ubHkgUk9XU19QUkVGSVggPSAnL3Jvd3MvJztcbiAgcHJpdmF0ZSByZWFkb25seSBJTkRFWF9QUkVGSVggPSAnL2luZGV4ZXMvJztcblxuICBjb25zdHJ1Y3RvcihkYjogRGF0YWJhc2VJbnRlcmZhY2UpIHtcbiAgICB0aGlzLmRiID0gZGI7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBhIFNRTCBzdGF0ZW1lbnQuXG4gICAqL1xuICBhc3luYyBleGVjdXRlKHNxbDogc3RyaW5nKTogUHJvbWlzZTxTUUxRdWVyeVJlc3VsdD4ge1xuICAgIGNvbnN0IHsgb3BlcmF0aW9uLCBkYXRhIH0gPSBTUUxQYXJzZXIucGFyc2Uoc3FsKTtcblxuICAgIHN3aXRjaCAob3BlcmF0aW9uKSB7XG4gICAgICBjYXNlICdDUkVBVEVfVEFCTEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVUYWJsZShkYXRhKTtcbiAgICAgIGNhc2UgJ0RST1BfVEFCTEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5kcm9wVGFibGUoZGF0YSk7XG4gICAgICBjYXNlICdDUkVBVEVfSU5ERVgnOlxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVJbmRleChkYXRhKTtcbiAgICAgIGNhc2UgJ0RST1BfSU5ERVgnOlxuICAgICAgICByZXR1cm4gdGhpcy5kcm9wSW5kZXgoZGF0YSk7XG4gICAgICBjYXNlICdJTlNFUlQnOlxuICAgICAgICByZXR1cm4gdGhpcy5pbnNlcnQoZGF0YSk7XG4gICAgICBjYXNlICdTRUxFQ1QnOlxuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3QoZGF0YSk7XG4gICAgICBjYXNlICdVUERBVEUnOlxuICAgICAgICByZXR1cm4gdGhpcy51cGRhdGUoZGF0YSk7XG4gICAgICBjYXNlICdERUxFVEUnOlxuICAgICAgICByZXR1cm4gdGhpcy5kZWxldGVSb3dzKGRhdGEpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIG9wZXJhdGlvbjogJHtvcGVyYXRpb259YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzY2hlbWFLZXkodGFibGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLlNDSEVNQV9TVUZGSVg7XG4gIH1cblxuICBwcml2YXRlIHJvd0tleSh0YWJsZTogc3RyaW5nLCByb3dJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuUk9XU19QUkVGSVggKyByb3dJZDtcbiAgfVxuXG4gIHByaXZhdGUgcm93UHJlZml4KHRhYmxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLlRBQkxFX1BSRUZJWCArIHRhYmxlICsgdGhpcy5ST1dTX1BSRUZJWDtcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhNZXRhS2V5KHRhYmxlOiBzdHJpbmcsIGluZGV4TmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuSU5ERVhfUFJFRklYICsgaW5kZXhOYW1lICsgJy9tZXRhJztcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhQcmVmaXgodGFibGU6IHN0cmluZywgaW5kZXhOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLlRBQkxFX1BSRUZJWCArIHRhYmxlICsgdGhpcy5JTkRFWF9QUkVGSVggKyBpbmRleE5hbWUgKyAnLyc7XG4gIH1cblxuICBwcml2YXRlIGluZGV4S2V5KHRhYmxlOiBzdHJpbmcsIGluZGV4TmFtZTogc3RyaW5nLCBjb2x1bW5WYWx1ZTogc3RyaW5nLCByb3dJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5UQUJMRV9QUkVGSVggKyB0YWJsZSArIHRoaXMuSU5ERVhfUFJFRklYICsgaW5kZXhOYW1lICsgJy8nICsgY29sdW1uVmFsdWUgKyAnLycgKyByb3dJZDtcbiAgfVxuXG4gIHByaXZhdGUgaW5kZXhWYWx1ZVByZWZpeCh0YWJsZTogc3RyaW5nLCBpbmRleE5hbWU6IHN0cmluZywgY29sdW1uVmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLklOREVYX1BSRUZJWCArIGluZGV4TmFtZSArICcvJyArIGNvbHVtblZhbHVlICsgJy8nO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRTY2hlbWEodGFibGU6IHN0cmluZyk6IFByb21pc2U8VGFibGVTY2hlbWEgfCBudWxsPiB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuZGIuZ2V0KHRoaXMuc2NoZW1hS2V5KHRhYmxlKSk7XG4gICAgaWYgKCFkYXRhKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhLnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRJbmRleGVzKHRhYmxlOiBzdHJpbmcpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICAvLyBSZXR1cm5zIG1hcCBvZiBpbmRleF9uYW1lIC0+IGNvbHVtbl9uYW1lXG4gICAgY29uc3QgaW5kZXhlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMuVEFCTEVfUFJFRklYICsgdGFibGUgKyB0aGlzLklOREVYX1BSRUZJWDtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuXG4gICAgZm9yIChjb25zdCB7IGtleSwgdmFsdWUgfSBvZiBwYWlycykge1xuICAgICAgY29uc3Qga2V5U3RyID0ga2V5LnRvU3RyaW5nKCk7XG4gICAgICBpZiAoa2V5U3RyLmVuZHNXaXRoKCcvbWV0YScpKSB7XG4gICAgICAgIGNvbnN0IGluZm86IEluZGV4SW5mbyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICAgIGNvbnN0IHBhcnRzID0ga2V5U3RyLnNwbGl0KCcvJyk7XG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGggPj0gNSkge1xuICAgICAgICAgIGNvbnN0IGluZGV4TmFtZSA9IHBhcnRzW3BhcnRzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgIGluZGV4ZXNbaW5kZXhOYW1lXSA9IGluZm8uY29sdW1uO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGV4ZXM7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlOiBzdHJpbmcsIGNvbHVtbjogc3RyaW5nKTogUHJvbWlzZTx7IGhhczogYm9vbGVhbjsgbmFtZTogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBpbmRleGVzID0gYXdhaXQgdGhpcy5nZXRJbmRleGVzKHRhYmxlKTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleE5hbWUsIGluZGV4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgaWYgKGluZGV4Q29sID09PSBjb2x1bW4pIHtcbiAgICAgICAgcmV0dXJuIHsgaGFzOiB0cnVlLCBuYW1lOiBpbmRleE5hbWUgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgaGFzOiBmYWxzZSwgbmFtZTogJycgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9va3VwQnlJbmRleCh0YWJsZTogc3RyaW5nLCBpbmRleE5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmluZGV4VmFsdWVQcmVmaXgodGFibGUsIGluZGV4TmFtZSwgdmFsdWUpO1xuICAgIGNvbnN0IHBhaXJzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG4gICAgcmV0dXJuIHBhaXJzLm1hcChwID0+IHAudmFsdWUudG9TdHJpbmcoKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUluZGV4KFxuICAgIHRhYmxlOiBzdHJpbmcsXG4gICAgaW5kZXhOYW1lOiBzdHJpbmcsXG4gICAgY29sdW1uOiBzdHJpbmcsXG4gICAgb2xkUm93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIG5ld1JvdzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICByb3dJZDogc3RyaW5nXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9sZFZhbCA9IG9sZFJvd1tjb2x1bW5dO1xuICAgIGNvbnN0IG5ld1ZhbCA9IG5ld1Jvd1tjb2x1bW5dO1xuXG4gICAgaWYgKG9sZFZhbCA9PT0gbmV3VmFsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIG9sZCBpbmRleCBlbnRyeVxuICAgIGlmIChvbGRWYWwgIT0gbnVsbCkge1xuICAgICAgY29uc3Qgb2xkS2V5ID0gdGhpcy5pbmRleEtleSh0YWJsZSwgaW5kZXhOYW1lLCBTdHJpbmcob2xkVmFsKSwgcm93SWQpO1xuICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUob2xkS2V5KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgbmV3IGluZGV4IGVudHJ5XG4gICAgaWYgKG5ld1ZhbCAhPSBudWxsKSB7XG4gICAgICBjb25zdCBuZXdLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhuZXdWYWwpLCByb3dJZCk7XG4gICAgICBhd2FpdCB0aGlzLmRiLnB1dChuZXdLZXksIHJvd0lkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRJbmRleGVkRXF1YWxpdHlDb25kaXRpb24oXG4gICAgdGFibGU6IHN0cmluZyxcbiAgICBjb25kaXRpb25zOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcsIGFueV0+LFxuICAgIGluZGV4ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgKTogW3N0cmluZywgYW55XSB8IG51bGwge1xuICAgIGZvciAoY29uc3QgW2NvbCwgb3AsIHZhbF0gb2YgY29uZGl0aW9ucykge1xuICAgICAgaWYgKG9wID09PSAnPScgJiYgT2JqZWN0LnZhbHVlcyhpbmRleGVzKS5pbmNsdWRlcyhjb2wpKSB7XG4gICAgICAgIHJldHVybiBbY29sLCB2YWxdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY3JlYXRlVGFibGUoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgY29uc3QgY29sdW1ucyA9IGRhdGEuY29sdW1ucyBhcyBDb2x1bW5bXTtcbiAgICBjb25zdCBwcmltYXJ5S2V5ID0gZGF0YS5wcmltYXJ5S2V5O1xuXG4gICAgLy8gQ2hlY2sgaWYgdGFibGUgZXhpc3RzXG4gICAgaWYgKGF3YWl0IHRoaXMuZ2V0U2NoZW1hKHRhYmxlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYWJsZSAnJHt0YWJsZX0nIGFscmVhZHkgZXhpc3RzYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2NoZW1hOiBUYWJsZVNjaGVtYSA9IHsgbmFtZTogdGFibGUsIGNvbHVtbnMsIHByaW1hcnlLZXkgfTtcbiAgICBhd2FpdCB0aGlzLmRiLnB1dCh0aGlzLnNjaGVtYUtleSh0YWJsZSksIEpTT04uc3RyaW5naWZ5KHNjaGVtYSkpO1xuXG4gICAgcmV0dXJuIHsgcm93czogW10sIGNvbHVtbnM6IFtdLCByb3dzQWZmZWN0ZWQ6IDAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJvcFRhYmxlKGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuXG4gICAgLy8gRGVsZXRlIGFsbCBpbmRleGVzIGZpcnN0XG4gICAgY29uc3QgaW5kZXhlcyA9IGF3YWl0IHRoaXMuZ2V0SW5kZXhlcyh0YWJsZSk7XG4gICAgZm9yIChjb25zdCBpbmRleE5hbWUgb2YgT2JqZWN0LmtleXMoaW5kZXhlcykpIHtcbiAgICAgIGNvbnN0IGlkeFByZWZpeCA9IHRoaXMuaW5kZXhQcmVmaXgodGFibGUsIGluZGV4TmFtZSk7XG4gICAgICBjb25zdCBpZHhQYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihpZHhQcmVmaXgpO1xuICAgICAgZm9yIChjb25zdCB7IGtleSB9IG9mIGlkeFBhaXJzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGIuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLmluZGV4TWV0YUtleSh0YWJsZSwgaW5kZXhOYW1lKSk7XG4gICAgfVxuXG4gICAgLy8gRGVsZXRlIGFsbCByb3dzXG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5yb3dQcmVmaXgodGFibGUpO1xuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCB0aGlzLmRiLnNjYW4ocHJlZml4KTtcbiAgICBsZXQgcm93c0RlbGV0ZWQgPSAwO1xuXG4gICAgZm9yIChjb25zdCB7IGtleSB9IG9mIHJvd3MpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGIuZGVsZXRlKGtleSk7XG4gICAgICByb3dzRGVsZXRlZCsrO1xuICAgIH1cblxuICAgIC8vIERlbGV0ZSBzY2hlbWFcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLnNjaGVtYUtleSh0YWJsZSkpO1xuXG4gICAgcmV0dXJuIHsgcm93czogW10sIGNvbHVtbnM6IFtdLCByb3dzQWZmZWN0ZWQ6IHJvd3NEZWxldGVkIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZUluZGV4KGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgaW5kZXhOYW1lID0gZGF0YS5pbmRleE5hbWU7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuICAgIGNvbnN0IGNvbHVtbiA9IGRhdGEuY29sdW1uO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBjb2x1bW4gZXhpc3RzXG4gICAgaWYgKCFzY2hlbWEuY29sdW1ucy5zb21lKGMgPT4gYy5uYW1lID09PSBjb2x1bW4pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvbHVtbiAnJHtjb2x1bW59JyBkb2VzIG5vdCBleGlzdCBpbiB0YWJsZSAnJHt0YWJsZX0nYCk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaW5kZXggZG9lc24ndCBhbHJlYWR5IGV4aXN0XG4gICAgY29uc3QgbWV0YUtleSA9IHRoaXMuaW5kZXhNZXRhS2V5KHRhYmxlLCBpbmRleE5hbWUpO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy5kYi5nZXQobWV0YUtleSk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEluZGV4ICcke2luZGV4TmFtZX0nIGFscmVhZHkgZXhpc3RzIG9uIHRhYmxlICcke3RhYmxlfSdgKTtcbiAgICB9XG5cbiAgICAvLyBTdG9yZSBpbmRleCBtZXRhZGF0YVxuICAgIGNvbnN0IG1ldGE6IEluZGV4SW5mbyA9IHsgY29sdW1uLCB0YWJsZSB9O1xuICAgIGF3YWl0IHRoaXMuZGIucHV0KG1ldGFLZXksIEpTT04uc3RyaW5naWZ5KG1ldGEpKTtcblxuICAgIC8vIEJ1aWxkIGluZGV4IGZyb20gZXhpc3Rpbmcgcm93c1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMucm93UHJlZml4KHRhYmxlKTtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuICAgIGxldCBpbmRleGVkQ291bnQgPSAwO1xuXG4gICAgZm9yIChjb25zdCB7IHZhbHVlIH0gb2YgcGFpcnMpIHtcbiAgICAgIGNvbnN0IHJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICBjb25zdCByb3dJZCA9IHJvd1snX2lkJ107XG4gICAgICBjb25zdCBjb2xWYWx1ZSA9IHJvd1tjb2x1bW5dO1xuXG4gICAgICBpZiAoY29sVmFsdWUgIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBpZHhLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhjb2xWYWx1ZSksIHJvd0lkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kYi5wdXQoaWR4S2V5LCByb3dJZCk7XG4gICAgICAgIGluZGV4ZWRDb3VudCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IHJvd3M6IFtdLCBjb2x1bW5zOiBbXSwgcm93c0FmZmVjdGVkOiBpbmRleGVkQ291bnQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZHJvcEluZGV4KGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgaW5kZXhOYW1lID0gZGF0YS5pbmRleE5hbWU7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuXG4gICAgLy8gRGVsZXRlIGFsbCBpbmRleCBlbnRyaWVzXG4gICAgY29uc3QgaWR4UHJlZml4ID0gdGhpcy5pbmRleFByZWZpeCh0YWJsZSwgaW5kZXhOYW1lKTtcbiAgICBjb25zdCBwYWlycyA9IGF3YWl0IHRoaXMuZGIuc2NhbihpZHhQcmVmaXgpO1xuICAgIGxldCBkZWxldGVkID0gMDtcblxuICAgIGZvciAoY29uc3QgeyBrZXkgfSBvZiBwYWlycykge1xuICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUoa2V5KTtcbiAgICAgIGRlbGV0ZWQrKztcbiAgICB9XG5cbiAgICAvLyBEZWxldGUgaW5kZXggbWV0YWRhdGFcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh0aGlzLmluZGV4TWV0YUtleSh0YWJsZSwgaW5kZXhOYW1lKSk7XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZDogZGVsZXRlZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbnNlcnQoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgbGV0IGNvbHVtbnMgPSBkYXRhLmNvbHVtbnMgYXMgc3RyaW5nW10gfCBudWxsO1xuICAgIGNvbnN0IHZhbHVlcyA9IGRhdGEudmFsdWVzIGFzIGFueVtdO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBJZiBubyBjb2x1bW5zIHNwZWNpZmllZCwgdXNlIHNjaGVtYSBvcmRlclxuICAgIGlmICghY29sdW1ucykge1xuICAgICAgY29sdW1ucyA9IHNjaGVtYS5jb2x1bW5zLm1hcCgoYykgPT4gYy5uYW1lKTtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1ucy5sZW5ndGggIT09IHZhbHVlcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENvbHVtbiBjb3VudCAoJHtjb2x1bW5zLmxlbmd0aH0pIGRvZXNuJ3QgbWF0Y2ggdmFsdWUgY291bnQgKCR7dmFsdWVzLmxlbmd0aH0pYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgcm93IG9iamVjdFxuICAgIGNvbnN0IHJvdzogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgcm93W2NvbHVtbnNbaV1dID0gdmFsdWVzW2ldO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIHJvdyBJRFxuICAgIGxldCByb3dJZDogc3RyaW5nO1xuICAgIGlmIChzY2hlbWEucHJpbWFyeUtleSAmJiBzY2hlbWEucHJpbWFyeUtleSBpbiByb3cpIHtcbiAgICAgIHJvd0lkID0gU3RyaW5nKHJvd1tzY2hlbWEucHJpbWFyeUtleV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByb3dJZCA9IHV1aWR2NCgpO1xuICAgIH1cbiAgICByb3dbJ19pZCddID0gcm93SWQ7XG5cbiAgICBhd2FpdCB0aGlzLmRiLnB1dCh0aGlzLnJvd0tleSh0YWJsZSwgcm93SWQpLCBKU09OLnN0cmluZ2lmeShyb3cpKTtcblxuICAgIC8vIE1haW50YWluIGluZGV4ZXNcbiAgICBjb25zdCBpbmRleGVzID0gYXdhaXQgdGhpcy5nZXRJbmRleGVzKHRhYmxlKTtcbiAgICBmb3IgKGNvbnN0IFtpbmRleE5hbWUsIGluZGV4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgaWYgKHJvd1tpbmRleENvbF0gIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBpZHhLZXkgPSB0aGlzLmluZGV4S2V5KHRhYmxlLCBpbmRleE5hbWUsIFN0cmluZyhyb3dbaW5kZXhDb2xdKSwgcm93SWQpO1xuICAgICAgICBhd2FpdCB0aGlzLmRiLnB1dChpZHhLZXksIHJvd0lkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZDogMSB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZWxlY3QoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgbGV0IGNvbHVtbnMgPSBkYXRhLmNvbHVtbnMgYXMgc3RyaW5nW107XG4gICAgY29uc3QgY29uZGl0aW9ucyA9IGRhdGEud2hlcmUgYXMgQXJyYXk8W3N0cmluZywgc3RyaW5nLCBhbnldPjtcbiAgICBjb25zdCBvcmRlckJ5ID0gZGF0YS5vcmRlckJ5IGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZ10+O1xuICAgIGNvbnN0IGxpbWl0ID0gZGF0YS5saW1pdCBhcyBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb2Zmc2V0ID0gZGF0YS5vZmZzZXQgYXMgbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gYXdhaXQgdGhpcy5nZXRTY2hlbWEodGFibGUpO1xuICAgIGlmICghc2NoZW1hKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlICcke3RhYmxlfScgZG9lcyBub3QgZXhpc3RgKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgY29sdW1uIG5hbWVzXG4gICAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAxICYmIGNvbHVtbnNbMF0gPT09ICcqJykge1xuICAgICAgY29sdW1ucyA9IHNjaGVtYS5jb2x1bW5zLm1hcCgoYykgPT4gYy5uYW1lKTtcbiAgICB9XG5cbiAgICAvLyBTY2FuIGFsbCByb3dzXG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5yb3dQcmVmaXgodGFibGUpO1xuICAgIGNvbnN0IHNjYW5SZXN1bHRzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG4gICAgbGV0IHJvd3M6IEFycmF5PFJlY29yZDxzdHJpbmcsIGFueT4+ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHsgdmFsdWUgfSBvZiBzY2FuUmVzdWx0cykge1xuICAgICAgY29uc3Qgcm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgLy8gQXBwbHkgV0hFUkUgY29uZGl0aW9uc1xuICAgICAgaWYgKHRoaXMubWF0Y2hlc0NvbmRpdGlvbnMocm93LCBjb25kaXRpb25zKSkge1xuICAgICAgICAvLyBQcm9qZWN0IGNvbHVtbnNcbiAgICAgICAgY29uc3QgcHJvamVjdGVkOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICAgIGZvciAoY29uc3QgY29sIG9mIGNvbHVtbnMpIHtcbiAgICAgICAgICBpZiAoY29sIGluIHJvdykge1xuICAgICAgICAgICAgcHJvamVjdGVkW2NvbF0gPSByb3dbY29sXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcm93cy5wdXNoKHByb2plY3RlZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQXBwbHkgT1JERVIgQllcbiAgICBpZiAob3JkZXJCeSAmJiBvcmRlckJ5Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJvd3Muc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IFtjb2wsIGRpcmVjdGlvbl0gb2Ygb3JkZXJCeSkge1xuICAgICAgICAgIGNvbnN0IGFWYWwgPSBhW2NvbF07XG4gICAgICAgICAgY29uc3QgYlZhbCA9IGJbY29sXTtcblxuICAgICAgICAgIC8vIEhhbmRsZSBudWxsc1xuICAgICAgICAgIGlmIChhVmFsID09PSBudWxsIHx8IGFWYWwgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDE7XG4gICAgICAgICAgaWYgKGJWYWwgPT09IG51bGwgfHwgYlZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gLTE7XG5cbiAgICAgICAgICBsZXQgY21wID0gMDtcbiAgICAgICAgICBpZiAoYVZhbCA8IGJWYWwpIGNtcCA9IC0xO1xuICAgICAgICAgIGVsc2UgaWYgKGFWYWwgPiBiVmFsKSBjbXAgPSAxO1xuXG4gICAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ0RFU0MnKSBjbXAgPSAtY21wO1xuICAgICAgICAgIGlmIChjbXAgIT09IDApIHJldHVybiBjbXA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBcHBseSBPRkZTRVQgYW5kIExJTUlUXG4gICAgaWYgKG9mZnNldCAmJiBvZmZzZXQgPiAwKSB7XG4gICAgICByb3dzID0gcm93cy5zbGljZShvZmZzZXQpO1xuICAgIH1cbiAgICBpZiAobGltaXQgIT09IHVuZGVmaW5lZCAmJiBsaW1pdCA+IDApIHtcbiAgICAgIHJvd3MgPSByb3dzLnNsaWNlKDAsIGxpbWl0KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzLCBjb2x1bW5zLCByb3dzQWZmZWN0ZWQ6IDAgfTtcbiAgfVxuXG4gIHByaXZhdGUgbWF0Y2hlc0NvbmRpdGlvbnMoXG4gICAgcm93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNvbmRpdGlvbnM6IEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT5cbiAgKTogYm9vbGVhbiB7XG4gICAgZm9yIChjb25zdCBbY29sLCBvcCwgdmFsXSBvZiBjb25kaXRpb25zKSB7XG4gICAgICBjb25zdCByb3dWYWwgPSByb3dbY29sXTtcblxuICAgICAgc3dpdGNoIChvcCkge1xuICAgICAgICBjYXNlICc9JzpcbiAgICAgICAgICBpZiAocm93VmFsICE9PSB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IHZhbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICc+JzpcbiAgICAgICAgICBpZiAocm93VmFsID09PSBudWxsIHx8IHJvd1ZhbCA9PT0gdW5kZWZpbmVkIHx8IHJvd1ZhbCA8PSB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQgfHwgcm93VmFsIDwgdmFsKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQgfHwgcm93VmFsID49IHZhbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICc8PSc6XG4gICAgICAgICAgaWYgKHJvd1ZhbCA9PT0gbnVsbCB8fCByb3dWYWwgPT09IHVuZGVmaW5lZCB8fCByb3dWYWwgPiB2YWwpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnTElLRSc6IHtcbiAgICAgICAgICBpZiAocm93VmFsID09PSBudWxsIHx8IHJvd1ZhbCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgY29uc3QgcGF0dGVybiA9IFN0cmluZyh2YWwpLnJlcGxhY2UoLyUvZywgJy4qJykucmVwbGFjZSgvXy9nLCAnLicpO1xuICAgICAgICAgIGlmICghbmV3IFJlZ0V4cChgXiR7cGF0dGVybn0kYCwgJ2knKS50ZXN0KFN0cmluZyhyb3dWYWwpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ05PVF9MSUtFJzoge1xuICAgICAgICAgIGlmIChyb3dWYWwgPT09IG51bGwgfHwgcm93VmFsID09PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSBTdHJpbmcodmFsKS5yZXBsYWNlKC8lL2csICcuKicpLnJlcGxhY2UoL18vZywgJy4nKTtcbiAgICAgICAgICBpZiAobmV3IFJlZ0V4cChgXiR7cGF0dGVybn0kYCwgJ2knKS50ZXN0KFN0cmluZyhyb3dWYWwpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGUoZGF0YTogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8U1FMUXVlcnlSZXN1bHQ+IHtcbiAgICBjb25zdCB0YWJsZSA9IGRhdGEudGFibGU7XG4gICAgY29uc3QgdXBkYXRlcyA9IGRhdGEudXBkYXRlcyBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBkYXRhLndoZXJlIGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT47XG5cbiAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLmdldFNjaGVtYSh0YWJsZSk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgJyR7dGFibGV9JyBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ZXMgPSBhd2FpdCB0aGlzLmdldEluZGV4ZXModGFibGUpO1xuICAgIGxldCByb3dzQWZmZWN0ZWQgPSAwO1xuXG4gICAgLy8gVHJ5IGluZGV4LWFjY2VsZXJhdGVkIHBhdGhcbiAgICBjb25zdCBpbmRleGVkQ29uZCA9IHRoaXMuZmluZEluZGV4ZWRFcXVhbGl0eUNvbmRpdGlvbih0YWJsZSwgY29uZGl0aW9ucywgaW5kZXhlcyk7XG5cbiAgICBpZiAoaW5kZXhlZENvbmQpIHtcbiAgICAgIC8vIEluZGV4LWFjY2VsZXJhdGVkIFVQREFURVxuICAgICAgY29uc3QgW2NvbCwgdmFsXSA9IGluZGV4ZWRDb25kO1xuICAgICAgY29uc3QgaW5kZXhSZXN1bHQgPSBhd2FpdCB0aGlzLmhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlLCBjb2wpO1xuICAgICAgXG4gICAgICBpZiAoaW5kZXhSZXN1bHQuaGFzKSB7XG4gICAgICAgIGNvbnN0IHJvd0lkcyA9IGF3YWl0IHRoaXMubG9va3VwQnlJbmRleCh0YWJsZSwgaW5kZXhSZXN1bHQubmFtZSwgU3RyaW5nKHZhbCkpO1xuICAgICAgICBcbiAgICAgICAgZm9yIChjb25zdCByb3dJZCBvZiByb3dJZHMpIHtcbiAgICAgICAgICBjb25zdCBrZXkgPSB0aGlzLnJvd0tleSh0YWJsZSwgcm93SWQpO1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgdGhpcy5kYi5nZXQoa2V5KTtcbiAgICAgICAgICBpZiAoIXZhbHVlKSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IG9sZFJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG5cbiAgICAgICAgICAvLyBBcHBseSBhbGwgV0hFUkUgY29uZGl0aW9ucyAobm90IGp1c3QgdGhlIGluZGV4ZWQgb25lKVxuICAgICAgICAgIGlmICghdGhpcy5tYXRjaGVzQ29uZGl0aW9ucyhvbGRSb3csIGNvbmRpdGlvbnMpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBBcHBseSB1cGRhdGVzXG4gICAgICAgICAgY29uc3QgbmV3Um93ID0geyAuLi5vbGRSb3cgfTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFt1Y29sLCB1dmFsXSBvZiBPYmplY3QuZW50cmllcyh1cGRhdGVzKSkge1xuICAgICAgICAgICAgbmV3Um93W3Vjb2xdID0gdXZhbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBVcGRhdGUgaW5kZXhlcyBmb3IgY2hhbmdlZCBjb2x1bW5zXG4gICAgICAgICAgZm9yIChjb25zdCBbaWR4TmFtZSwgaWR4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgICAgICAgaWYgKGlkeENvbCBpbiB1cGRhdGVzKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMudXBkYXRlSW5kZXgodGFibGUsIGlkeE5hbWUsIGlkeENvbCwgb2xkUm93LCBuZXdSb3csIHJvd0lkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmRiLnB1dChrZXksIEpTT04uc3RyaW5naWZ5KG5ld1JvdykpO1xuICAgICAgICAgIHJvd3NBZmZlY3RlZCsrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEZhbGxiYWNrOiBmdWxsIHRhYmxlIHNjYW5cbiAgICAgIGNvbnN0IHByZWZpeCA9IHRoaXMucm93UHJlZml4KHRhYmxlKTtcbiAgICAgIGNvbnN0IHNjYW5SZXN1bHRzID0gYXdhaXQgdGhpcy5kYi5zY2FuKHByZWZpeCk7XG5cbiAgICAgIGZvciAoY29uc3QgeyBrZXksIHZhbHVlIH0gb2Ygc2NhblJlc3VsdHMpIHtcbiAgICAgICAgY29uc3Qgb2xkUm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgICAvLyBBcHBseSBXSEVSRSBjb25kaXRpb25zXG4gICAgICAgIGlmICh0aGlzLm1hdGNoZXNDb25kaXRpb25zKG9sZFJvdywgY29uZGl0aW9ucykpIHtcbiAgICAgICAgICAvLyBBcHBseSB1cGRhdGVzXG4gICAgICAgICAgY29uc3QgbmV3Um93ID0geyAuLi5vbGRSb3cgfTtcbiAgICAgICAgICBmb3IgKGNvbnN0IFtjb2wsIHZhbF0gb2YgT2JqZWN0LmVudHJpZXModXBkYXRlcykpIHtcbiAgICAgICAgICAgIG5ld1Jvd1tjb2xdID0gdmFsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJvd0lkID0gb2xkUm93WydfaWQnXTtcblxuICAgICAgICAgIC8vIFVwZGF0ZSBpbmRleGVzIGZvciBjaGFuZ2VkIGNvbHVtbnNcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpZHhOYW1lLCBpZHhDb2xdIG9mIE9iamVjdC5lbnRyaWVzKGluZGV4ZXMpKSB7XG4gICAgICAgICAgICBpZiAoaWR4Q29sIGluIHVwZGF0ZXMpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCBvbGRSb3csIG5ld1Jvdywgcm93SWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGF3YWl0IHRoaXMuZGIucHV0KGtleSwgSlNPTi5zdHJpbmdpZnkobmV3Um93KSk7XG4gICAgICAgICAgcm93c0FmZmVjdGVkKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkZWxldGVSb3dzKGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQcm9taXNlPFNRTFF1ZXJ5UmVzdWx0PiB7XG4gICAgY29uc3QgdGFibGUgPSBkYXRhLnRhYmxlO1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBkYXRhLndoZXJlIGFzIEFycmF5PFtzdHJpbmcsIHN0cmluZywgYW55XT47XG5cbiAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLmdldFNjaGVtYSh0YWJsZSk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgJyR7dGFibGV9JyBkb2VzIG5vdCBleGlzdGApO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGV4ZXMgPSBhd2FpdCB0aGlzLmdldEluZGV4ZXModGFibGUpO1xuICAgIGxldCByb3dzQWZmZWN0ZWQgPSAwO1xuXG4gICAgLy8gVHJ5IGluZGV4LWFjY2VsZXJhdGVkIHBhdGhcbiAgICBjb25zdCBpbmRleGVkQ29uZCA9IHRoaXMuZmluZEluZGV4ZWRFcXVhbGl0eUNvbmRpdGlvbih0YWJsZSwgY29uZGl0aW9ucywgaW5kZXhlcyk7XG5cbiAgICBpZiAoaW5kZXhlZENvbmQpIHtcbiAgICAgIC8vIEluZGV4LWFjY2VsZXJhdGVkIERFTEVURVxuICAgICAgY29uc3QgW2NvbCwgdmFsXSA9IGluZGV4ZWRDb25kO1xuICAgICAgY29uc3QgaW5kZXhSZXN1bHQgPSBhd2FpdCB0aGlzLmhhc0luZGV4Rm9yQ29sdW1uKHRhYmxlLCBjb2wpO1xuICAgICAgXG4gICAgICBpZiAoaW5kZXhSZXN1bHQuaGFzKSB7XG4gICAgICAgIGNvbnN0IHJvd0lkcyA9IGF3YWl0IHRoaXMubG9va3VwQnlJbmRleCh0YWJsZSwgaW5kZXhSZXN1bHQubmFtZSwgU3RyaW5nKHZhbCkpO1xuICAgICAgICBjb25zdCBrZXlzVG9EZWxldGU6IEJ1ZmZlcltdID0gW107XG4gICAgICAgIGNvbnN0IHJvd3NUb0RlbGV0ZTogQXJyYXk8eyByb3c6IFJlY29yZDxzdHJpbmcsIGFueT47IHJvd0lkOiBzdHJpbmcgfT4gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IHJvd0lkIG9mIHJvd0lkcykge1xuICAgICAgICAgIGNvbnN0IGtleSA9IHRoaXMucm93S2V5KHRhYmxlLCByb3dJZCk7XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0aGlzLmRiLmdldChrZXkpO1xuICAgICAgICAgIGlmICghdmFsdWUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3Qgcm93ID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcblxuICAgICAgICAgIC8vIEFwcGx5IGFsbCBXSEVSRSBjb25kaXRpb25zIChub3QganVzdCB0aGUgaW5kZXhlZCBvbmUpXG4gICAgICAgICAgaWYgKHRoaXMubWF0Y2hlc0NvbmRpdGlvbnMocm93LCBjb25kaXRpb25zKSkge1xuICAgICAgICAgICAga2V5c1RvRGVsZXRlLnB1c2goQnVmZmVyLmZyb20oa2V5KSk7XG4gICAgICAgICAgICByb3dzVG9EZWxldGUucHVzaCh7IHJvdywgcm93SWQgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVsZXRlIHJvd3MgYW5kIHVwZGF0ZSBpbmRleGVzXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5c1RvRGVsZXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY29uc3Qga2V5ID0ga2V5c1RvRGVsZXRlW2ldO1xuICAgICAgICAgIGNvbnN0IHsgcm93LCByb3dJZCB9ID0gcm93c1RvRGVsZXRlW2ldO1xuXG4gICAgICAgICAgLy8gUmVtb3ZlIGZyb20gYWxsIGluZGV4ZXNcbiAgICAgICAgICBmb3IgKGNvbnN0IFtpZHhOYW1lLCBpZHhDb2xdIG9mIE9iamVjdC5lbnRyaWVzKGluZGV4ZXMpKSB7XG4gICAgICAgICAgICBjb25zdCBlbXB0eVJvdzogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCByb3csIGVtcHR5Um93LCByb3dJZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYXdhaXQgdGhpcy5kYi5kZWxldGUoa2V5KTtcbiAgICAgICAgICByb3dzQWZmZWN0ZWQrKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGYWxsYmFjazogZnVsbCB0YWJsZSBzY2FuXG4gICAgICBjb25zdCBwcmVmaXggPSB0aGlzLnJvd1ByZWZpeCh0YWJsZSk7XG4gICAgICBjb25zdCBzY2FuUmVzdWx0cyA9IGF3YWl0IHRoaXMuZGIuc2NhbihwcmVmaXgpO1xuICAgICAgY29uc3Qga2V5c1RvRGVsZXRlOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgY29uc3Qgcm93c1RvRGVsZXRlOiBBcnJheTx7IHJvdzogUmVjb3JkPHN0cmluZywgYW55Pjsgcm93SWQ6IHN0cmluZyB9PiA9IFtdO1xuXG4gICAgICBmb3IgKGNvbnN0IHsga2V5LCB2YWx1ZSB9IG9mIHNjYW5SZXN1bHRzKSB7XG4gICAgICAgIGNvbnN0IHJvdyA9IEpTT04ucGFyc2UodmFsdWUudG9TdHJpbmcoKSk7XG5cbiAgICAgICAgLy8gQXBwbHkgV0hFUkUgY29uZGl0aW9uc1xuICAgICAgICBpZiAodGhpcy5tYXRjaGVzQ29uZGl0aW9ucyhyb3csIGNvbmRpdGlvbnMpKSB7XG4gICAgICAgICAgY29uc3Qgcm93SWQgPSByb3dbJ19pZCddO1xuICAgICAgICAgIGtleXNUb0RlbGV0ZS5wdXNoKGtleSk7XG4gICAgICAgICAgcm93c1RvRGVsZXRlLnB1c2goeyByb3csIHJvd0lkIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIERlbGV0ZSBjb2xsZWN0ZWQgcm93cyBhbmQgdXBkYXRlIGluZGV4ZXNcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5c1RvRGVsZXRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IGtleXNUb0RlbGV0ZVtpXTtcbiAgICAgICAgY29uc3QgeyByb3csIHJvd0lkIH0gPSByb3dzVG9EZWxldGVbaV07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGZyb20gYWxsIGluZGV4ZXNcbiAgICAgICAgZm9yIChjb25zdCBbaWR4TmFtZSwgaWR4Q29sXSBvZiBPYmplY3QuZW50cmllcyhpbmRleGVzKSkge1xuICAgICAgICAgIGNvbnN0IGVtcHR5Um93OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVJbmRleCh0YWJsZSwgaWR4TmFtZSwgaWR4Q29sLCByb3csIGVtcHR5Um93LCByb3dJZCk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShrZXkpO1xuICAgICAgICByb3dzQWZmZWN0ZWQrKztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyByb3dzOiBbXSwgY29sdW1uczogW10sIHJvd3NBZmZlY3RlZCB9O1xuICB9XG59XG4iXX0=
|