@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,504 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SochDB IPC Client
|
|
4
|
+
*
|
|
5
|
+
* Connects to a SochDB IPC server via Unix domain socket.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.IpcClient = exports.OpCode = void 0;
|
|
44
|
+
// Copyright 2025 Sushanth (https://github.com/sushanthpy)
|
|
45
|
+
//
|
|
46
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
47
|
+
// you may not use this file except in compliance with the License.
|
|
48
|
+
// You may obtain a copy of the License at
|
|
49
|
+
//
|
|
50
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
51
|
+
const net = __importStar(require("net"));
|
|
52
|
+
const errors_1 = require("./errors");
|
|
53
|
+
const query_1 = require("./query");
|
|
54
|
+
/**
|
|
55
|
+
* Wire protocol opcodes.
|
|
56
|
+
*/
|
|
57
|
+
exports.OpCode = {
|
|
58
|
+
// Client → Server (must match sochdb-storage/src/ipc_server.rs)
|
|
59
|
+
Put: 0x01,
|
|
60
|
+
Get: 0x02,
|
|
61
|
+
Delete: 0x03,
|
|
62
|
+
BeginTxn: 0x04,
|
|
63
|
+
CommitTxn: 0x05,
|
|
64
|
+
AbortTxn: 0x06,
|
|
65
|
+
Query: 0x07,
|
|
66
|
+
CreateTable: 0x08,
|
|
67
|
+
PutPath: 0x09,
|
|
68
|
+
GetPath: 0x0A,
|
|
69
|
+
Scan: 0x0B,
|
|
70
|
+
Checkpoint: 0x0C,
|
|
71
|
+
Stats: 0x0D,
|
|
72
|
+
Ping: 0x0E,
|
|
73
|
+
// Server → Client
|
|
74
|
+
OK: 0x80,
|
|
75
|
+
Error: 0x81,
|
|
76
|
+
Value: 0x82,
|
|
77
|
+
TxnId: 0x83,
|
|
78
|
+
Row: 0x84,
|
|
79
|
+
EndStream: 0x85,
|
|
80
|
+
StatsResp: 0x86,
|
|
81
|
+
Pong: 0x87,
|
|
82
|
+
};
|
|
83
|
+
// Internal OpCode map for backwards compatibility
|
|
84
|
+
const InternalOpCode = {
|
|
85
|
+
PUT: exports.OpCode.Put,
|
|
86
|
+
GET: exports.OpCode.Get,
|
|
87
|
+
DELETE: exports.OpCode.Delete,
|
|
88
|
+
BEGIN_TXN: exports.OpCode.BeginTxn,
|
|
89
|
+
COMMIT_TXN: exports.OpCode.CommitTxn,
|
|
90
|
+
ABORT_TXN: exports.OpCode.AbortTxn,
|
|
91
|
+
QUERY: exports.OpCode.Query,
|
|
92
|
+
PUT_PATH: exports.OpCode.PutPath,
|
|
93
|
+
GET_PATH: exports.OpCode.GetPath,
|
|
94
|
+
SCAN: exports.OpCode.Scan,
|
|
95
|
+
CHECKPOINT: exports.OpCode.Checkpoint,
|
|
96
|
+
STATS: exports.OpCode.Stats,
|
|
97
|
+
PING: exports.OpCode.Ping,
|
|
98
|
+
OK: exports.OpCode.OK,
|
|
99
|
+
ERROR: exports.OpCode.Error,
|
|
100
|
+
VALUE: exports.OpCode.Value,
|
|
101
|
+
TXN_ID: exports.OpCode.TxnId,
|
|
102
|
+
ROW: exports.OpCode.Row,
|
|
103
|
+
END_STREAM: exports.OpCode.EndStream,
|
|
104
|
+
STATS_RESP: exports.OpCode.StatsResp,
|
|
105
|
+
PONG: exports.OpCode.Pong,
|
|
106
|
+
};
|
|
107
|
+
const MAX_MESSAGE_SIZE = 16 * 1024 * 1024; // 16 MB
|
|
108
|
+
/**
|
|
109
|
+
* IPC Client for SochDB.
|
|
110
|
+
*
|
|
111
|
+
* Connects to a SochDB server via Unix domain socket.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* import { IpcClient } from '@sushanth/sochdb';
|
|
116
|
+
*
|
|
117
|
+
* const client = await IpcClient.connect('/tmp/sochdb.sock');
|
|
118
|
+
*
|
|
119
|
+
* await client.put(Buffer.from('key'), Buffer.from('value'));
|
|
120
|
+
* const value = await client.get(Buffer.from('key'));
|
|
121
|
+
*
|
|
122
|
+
* await client.close();
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
class IpcClient {
|
|
126
|
+
constructor(config) {
|
|
127
|
+
this._socket = null;
|
|
128
|
+
this._pendingReads = [];
|
|
129
|
+
this._readBuffer = Buffer.alloc(0);
|
|
130
|
+
this._closed = false;
|
|
131
|
+
this._config = {
|
|
132
|
+
connectTimeout: 5000,
|
|
133
|
+
readTimeout: 30000,
|
|
134
|
+
...config,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Connect to a SochDB IPC server.
|
|
139
|
+
*
|
|
140
|
+
* @param socketPath - Path to the Unix domain socket
|
|
141
|
+
* @returns A connected IpcClient instance
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const client = await IpcClient.connect('/tmp/sochdb.sock');
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
static async connect(socketPath) {
|
|
149
|
+
const client = new IpcClient({ socketPath });
|
|
150
|
+
await client._connect();
|
|
151
|
+
return client;
|
|
152
|
+
}
|
|
153
|
+
async _connect() {
|
|
154
|
+
return new Promise((resolve, reject) => {
|
|
155
|
+
const socket = net.createConnection({ path: this._config.socketPath }, () => {
|
|
156
|
+
this._socket = socket;
|
|
157
|
+
resolve();
|
|
158
|
+
});
|
|
159
|
+
socket.setTimeout(this._config.connectTimeout);
|
|
160
|
+
socket.on('timeout', () => {
|
|
161
|
+
socket.destroy();
|
|
162
|
+
reject(new errors_1.ConnectionError('Connection timeout'));
|
|
163
|
+
});
|
|
164
|
+
socket.on('error', (err) => {
|
|
165
|
+
reject(new errors_1.ConnectionError(`Connection failed: ${err.message}`));
|
|
166
|
+
});
|
|
167
|
+
socket.on('data', (data) => {
|
|
168
|
+
this._readBuffer = Buffer.concat([this._readBuffer, data]);
|
|
169
|
+
this._processBuffer();
|
|
170
|
+
});
|
|
171
|
+
socket.on('close', () => {
|
|
172
|
+
this._closed = true;
|
|
173
|
+
for (const pending of this._pendingReads) {
|
|
174
|
+
pending.reject(new errors_1.ConnectionError('Connection closed'));
|
|
175
|
+
}
|
|
176
|
+
this._pendingReads = [];
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
_processBuffer() {
|
|
181
|
+
// Process complete messages from the buffer
|
|
182
|
+
while (this._readBuffer.length >= 5 && this._pendingReads.length > 0) {
|
|
183
|
+
const length = this._readBuffer.readUInt32LE(1);
|
|
184
|
+
const totalLength = 5 + length;
|
|
185
|
+
if (this._readBuffer.length >= totalLength) {
|
|
186
|
+
const message = this._readBuffer.subarray(0, totalLength);
|
|
187
|
+
this._readBuffer = this._readBuffer.subarray(totalLength);
|
|
188
|
+
const pending = this._pendingReads.shift();
|
|
189
|
+
if (pending) {
|
|
190
|
+
pending.resolve(message);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async _send(opcode, payload = Buffer.alloc(0)) {
|
|
199
|
+
if (this._closed || !this._socket) {
|
|
200
|
+
throw new errors_1.ConnectionError('Not connected');
|
|
201
|
+
}
|
|
202
|
+
// Encode message: opcode (1) + length (4 LE) + payload
|
|
203
|
+
const message = Buffer.alloc(5 + payload.length);
|
|
204
|
+
message.writeUInt8(opcode, 0);
|
|
205
|
+
message.writeUInt32LE(payload.length, 1);
|
|
206
|
+
payload.copy(message, 5);
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
this._pendingReads.push({ resolve, reject });
|
|
209
|
+
this._socket.write(message, (err) => {
|
|
210
|
+
if (err) {
|
|
211
|
+
this._pendingReads.pop();
|
|
212
|
+
reject(new errors_1.ConnectionError(`Write failed: ${err.message}`));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// Set timeout for response
|
|
216
|
+
setTimeout(() => {
|
|
217
|
+
const idx = this._pendingReads.findIndex((p) => p.resolve === resolve);
|
|
218
|
+
if (idx !== -1) {
|
|
219
|
+
this._pendingReads.splice(idx, 1);
|
|
220
|
+
reject(new errors_1.ConnectionError('Read timeout'));
|
|
221
|
+
}
|
|
222
|
+
}, this._config.readTimeout);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
_parseResponse(response) {
|
|
226
|
+
const opcode = response.readUInt8(0);
|
|
227
|
+
const length = response.readUInt32LE(1);
|
|
228
|
+
const payload = response.subarray(5, 5 + length);
|
|
229
|
+
if (opcode === InternalOpCode.ERROR) {
|
|
230
|
+
throw new errors_1.ProtocolError(payload.toString('utf8'));
|
|
231
|
+
}
|
|
232
|
+
return { opcode, payload };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Encode a key for the wire protocol.
|
|
236
|
+
* @internal
|
|
237
|
+
*/
|
|
238
|
+
static encodeKey(key) {
|
|
239
|
+
// Format: [length:4][op:1][key_len:4][key:...]
|
|
240
|
+
const msgLen = 1 + 4 + key.length;
|
|
241
|
+
const msg = Buffer.alloc(4 + msgLen);
|
|
242
|
+
msg.writeUInt32BE(msgLen, 0);
|
|
243
|
+
msg.writeUInt8(InternalOpCode.GET, 4);
|
|
244
|
+
msg.writeUInt32BE(key.length, 5);
|
|
245
|
+
key.copy(msg, 9);
|
|
246
|
+
return msg;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Encode a key-value pair for the wire protocol.
|
|
250
|
+
* @internal
|
|
251
|
+
*/
|
|
252
|
+
static encodeKeyValue(key, value) {
|
|
253
|
+
// Format: [length:4][op:1][key_len:4][key:...][value_len:4][value:...]
|
|
254
|
+
const msgLen = 1 + 4 + key.length + 4 + value.length;
|
|
255
|
+
const msg = Buffer.alloc(4 + msgLen);
|
|
256
|
+
msg.writeUInt32BE(msgLen, 0);
|
|
257
|
+
msg.writeUInt8(InternalOpCode.PUT, 4);
|
|
258
|
+
msg.writeUInt32BE(key.length, 5);
|
|
259
|
+
key.copy(msg, 9);
|
|
260
|
+
msg.writeUInt32BE(value.length, 9 + key.length);
|
|
261
|
+
value.copy(msg, 13 + key.length);
|
|
262
|
+
return msg;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get a value by key.
|
|
266
|
+
*/
|
|
267
|
+
async get(key) {
|
|
268
|
+
const response = await this._send(InternalOpCode.GET, key);
|
|
269
|
+
const { opcode, payload } = this._parseResponse(response);
|
|
270
|
+
if (opcode === InternalOpCode.VALUE) {
|
|
271
|
+
// If payload is empty, the key doesn't exist
|
|
272
|
+
if (payload.length === 0) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
return payload;
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Put a key-value pair.
|
|
281
|
+
*/
|
|
282
|
+
async put(key, value) {
|
|
283
|
+
// Encode: key_len (4 LE) + key + value
|
|
284
|
+
const payload = Buffer.alloc(4 + key.length + value.length);
|
|
285
|
+
payload.writeUInt32LE(key.length, 0);
|
|
286
|
+
key.copy(payload, 4);
|
|
287
|
+
value.copy(payload, 4 + key.length);
|
|
288
|
+
const response = await this._send(InternalOpCode.PUT, payload);
|
|
289
|
+
this._parseResponse(response);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Delete a key.
|
|
293
|
+
*/
|
|
294
|
+
async delete(key) {
|
|
295
|
+
const response = await this._send(InternalOpCode.DELETE, key);
|
|
296
|
+
this._parseResponse(response);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get a value by path.
|
|
300
|
+
* Wire format: path_count(2 LE) + [path_len(2 LE) + path_segment]...
|
|
301
|
+
*/
|
|
302
|
+
async getPath(path) {
|
|
303
|
+
// Encode path as single segment for now (could split on '/' for multi-segment)
|
|
304
|
+
const pathBuf = Buffer.from(path, 'utf8');
|
|
305
|
+
const payload = Buffer.alloc(2 + 2 + pathBuf.length);
|
|
306
|
+
payload.writeUInt16LE(1, 0); // path_count = 1
|
|
307
|
+
payload.writeUInt16LE(pathBuf.length, 2); // path_len
|
|
308
|
+
pathBuf.copy(payload, 4); // path
|
|
309
|
+
const response = await this._send(InternalOpCode.GET_PATH, payload);
|
|
310
|
+
const { opcode, payload: responsePayload } = this._parseResponse(response);
|
|
311
|
+
if (opcode === InternalOpCode.VALUE) {
|
|
312
|
+
// If payload is empty, the key doesn't exist
|
|
313
|
+
if (responsePayload.length === 0) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return responsePayload;
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Put a value at a path.
|
|
322
|
+
* Wire format: path_count(2 LE) + [path_len(2 LE) + path_segment]... + value
|
|
323
|
+
*/
|
|
324
|
+
async putPath(path, value) {
|
|
325
|
+
const pathBuf = Buffer.from(path, 'utf8');
|
|
326
|
+
const payload = Buffer.alloc(2 + 2 + pathBuf.length + value.length);
|
|
327
|
+
payload.writeUInt16LE(1, 0); // path_count = 1
|
|
328
|
+
payload.writeUInt16LE(pathBuf.length, 2); // path_len
|
|
329
|
+
pathBuf.copy(payload, 4); // path
|
|
330
|
+
value.copy(payload, 4 + pathBuf.length); // value
|
|
331
|
+
const response = await this._send(InternalOpCode.PUT_PATH, payload);
|
|
332
|
+
this._parseResponse(response);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Execute a query and return TOON-formatted results.
|
|
336
|
+
*
|
|
337
|
+
* Wire format: path_len(2) + path + limit(4) + offset(4) + cols_count(2) + [col_len(2) + col]...
|
|
338
|
+
*/
|
|
339
|
+
async query(pathPrefix, options) {
|
|
340
|
+
const opts = options || {};
|
|
341
|
+
const pathBuf = Buffer.from(pathPrefix, 'utf8');
|
|
342
|
+
const columns = opts.columns || [];
|
|
343
|
+
// Calculate payload size
|
|
344
|
+
let size = 2 + pathBuf.length + 4 + 4 + 2;
|
|
345
|
+
for (const col of columns) {
|
|
346
|
+
size += 2 + Buffer.byteLength(col, 'utf8');
|
|
347
|
+
}
|
|
348
|
+
const payload = Buffer.alloc(size);
|
|
349
|
+
let offset = 0;
|
|
350
|
+
// Path: path_len(2 LE) + path
|
|
351
|
+
payload.writeUInt16LE(pathBuf.length, offset);
|
|
352
|
+
offset += 2;
|
|
353
|
+
pathBuf.copy(payload, offset);
|
|
354
|
+
offset += pathBuf.length;
|
|
355
|
+
// Limit (4 LE) - 0 means no limit
|
|
356
|
+
payload.writeUInt32LE(opts.limit || 0, offset);
|
|
357
|
+
offset += 4;
|
|
358
|
+
// Offset (4 LE)
|
|
359
|
+
payload.writeUInt32LE(opts.offset || 0, offset);
|
|
360
|
+
offset += 4;
|
|
361
|
+
// Columns: count(2 LE) + [col_len(2 LE) + col]...
|
|
362
|
+
payload.writeUInt16LE(columns.length, offset);
|
|
363
|
+
offset += 2;
|
|
364
|
+
for (const col of columns) {
|
|
365
|
+
const colBuf = Buffer.from(col, 'utf8');
|
|
366
|
+
payload.writeUInt16LE(colBuf.length, offset);
|
|
367
|
+
offset += 2;
|
|
368
|
+
colBuf.copy(payload, offset);
|
|
369
|
+
offset += colBuf.length;
|
|
370
|
+
}
|
|
371
|
+
const response = await this._send(InternalOpCode.QUERY, payload);
|
|
372
|
+
const { payload: resultPayload } = this._parseResponse(response);
|
|
373
|
+
return resultPayload.toString('utf8');
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Scan for keys with a prefix, returning key-value pairs.
|
|
377
|
+
* This is the preferred method for simple prefix-based iteration.
|
|
378
|
+
*
|
|
379
|
+
* Wire format: prefix string
|
|
380
|
+
* Response format: count(4 LE) + [key_len(2 LE) + key + val_len(4 LE) + val]...
|
|
381
|
+
*/
|
|
382
|
+
async scan(prefix) {
|
|
383
|
+
const prefixBuf = Buffer.from(prefix, 'utf8');
|
|
384
|
+
const response = await this._send(InternalOpCode.SCAN, prefixBuf);
|
|
385
|
+
const { opcode, payload } = this._parseResponse(response);
|
|
386
|
+
if (opcode !== InternalOpCode.VALUE && opcode !== InternalOpCode.OK) {
|
|
387
|
+
throw new errors_1.ProtocolError(`Unexpected scan response opcode: 0x${opcode.toString(16)}`);
|
|
388
|
+
}
|
|
389
|
+
if (payload.length < 4) {
|
|
390
|
+
return []; // Empty result
|
|
391
|
+
}
|
|
392
|
+
// Parse response: count(4 LE) + [key_len(2 LE) + key + val_len(4 LE) + val]...
|
|
393
|
+
const count = payload.readUInt32LE(0);
|
|
394
|
+
const results = [];
|
|
395
|
+
let offset = 4;
|
|
396
|
+
for (let i = 0; i < count; i++) {
|
|
397
|
+
if (offset + 2 > payload.length) {
|
|
398
|
+
throw new errors_1.ProtocolError('Truncated scan response (key_len)');
|
|
399
|
+
}
|
|
400
|
+
const keyLen = payload.readUInt16LE(offset);
|
|
401
|
+
offset += 2;
|
|
402
|
+
if (offset + keyLen + 4 > payload.length) {
|
|
403
|
+
throw new errors_1.ProtocolError('Truncated scan response (key+val_len)');
|
|
404
|
+
}
|
|
405
|
+
const key = payload.subarray(offset, offset + keyLen);
|
|
406
|
+
offset += keyLen;
|
|
407
|
+
const valLen = payload.readUInt32LE(offset);
|
|
408
|
+
offset += 4;
|
|
409
|
+
if (offset + valLen > payload.length) {
|
|
410
|
+
throw new errors_1.ProtocolError('Truncated scan response (value)');
|
|
411
|
+
}
|
|
412
|
+
const value = payload.subarray(offset, offset + valLen);
|
|
413
|
+
offset += valLen;
|
|
414
|
+
results.push({ key, value });
|
|
415
|
+
}
|
|
416
|
+
return results;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Create a query builder.
|
|
420
|
+
*/
|
|
421
|
+
queryBuilder(pathPrefix) {
|
|
422
|
+
return new query_1.Query(this, pathPrefix);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Begin a new transaction.
|
|
426
|
+
*/
|
|
427
|
+
async beginTransaction() {
|
|
428
|
+
const response = await this._send(InternalOpCode.BEGIN_TXN);
|
|
429
|
+
const { opcode, payload } = this._parseResponse(response);
|
|
430
|
+
if (opcode === InternalOpCode.TXN_ID) {
|
|
431
|
+
return payload.readBigUInt64LE(0);
|
|
432
|
+
}
|
|
433
|
+
throw new errors_1.TransactionError('Failed to begin transaction');
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Commit a transaction.
|
|
437
|
+
*/
|
|
438
|
+
async commitTransaction(txnId) {
|
|
439
|
+
const payload = Buffer.alloc(8);
|
|
440
|
+
payload.writeBigUInt64LE(txnId, 0);
|
|
441
|
+
const response = await this._send(InternalOpCode.COMMIT_TXN, payload);
|
|
442
|
+
this._parseResponse(response);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Abort a transaction.
|
|
446
|
+
*/
|
|
447
|
+
async abortTransaction(txnId) {
|
|
448
|
+
const payload = Buffer.alloc(8);
|
|
449
|
+
payload.writeBigUInt64LE(txnId, 0);
|
|
450
|
+
const response = await this._send(InternalOpCode.ABORT_TXN, payload);
|
|
451
|
+
this._parseResponse(response);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Force a checkpoint.
|
|
455
|
+
*/
|
|
456
|
+
async checkpoint() {
|
|
457
|
+
const response = await this._send(InternalOpCode.CHECKPOINT);
|
|
458
|
+
this._parseResponse(response);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Get storage statistics.
|
|
462
|
+
*/
|
|
463
|
+
async stats() {
|
|
464
|
+
const response = await this._send(InternalOpCode.STATS);
|
|
465
|
+
const { payload } = this._parseResponse(response);
|
|
466
|
+
const json = JSON.parse(payload.toString('utf8'));
|
|
467
|
+
return {
|
|
468
|
+
memtableSizeBytes: json.memtable_size_bytes || 0,
|
|
469
|
+
walSizeBytes: json.wal_size_bytes || 0,
|
|
470
|
+
activeTransactions: json.active_transactions || 0,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Ping the server.
|
|
475
|
+
*/
|
|
476
|
+
async ping() {
|
|
477
|
+
try {
|
|
478
|
+
const response = await this._send(InternalOpCode.PING);
|
|
479
|
+
const { opcode } = this._parseResponse(response);
|
|
480
|
+
return opcode === InternalOpCode.PONG;
|
|
481
|
+
}
|
|
482
|
+
catch {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Close the connection.
|
|
488
|
+
*/
|
|
489
|
+
async close() {
|
|
490
|
+
if (this._closed)
|
|
491
|
+
return;
|
|
492
|
+
this._closed = true;
|
|
493
|
+
if (this._socket) {
|
|
494
|
+
return new Promise((resolve) => {
|
|
495
|
+
this._socket.end(() => {
|
|
496
|
+
this._socket = null;
|
|
497
|
+
resolve();
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
exports.IpcClient = IpcClient;
|
|
504
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXBjLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pcGMtY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVILDBEQUEwRDtBQUMxRCxFQUFFO0FBQ0Ysa0VBQWtFO0FBQ2xFLG1FQUFtRTtBQUNuRSwwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGLGlEQUFpRDtBQUVqRCx5Q0FBMkI7QUFDM0IscUNBQTRFO0FBQzVFLG1DQUFnQztBQUVoQzs7R0FFRztBQUNVLFFBQUEsTUFBTSxHQUFHO0lBQ3BCLGdFQUFnRTtJQUNoRSxHQUFHLEVBQUUsSUFBSTtJQUNULEdBQUcsRUFBRSxJQUFJO0lBQ1QsTUFBTSxFQUFFLElBQUk7SUFDWixRQUFRLEVBQUUsSUFBSTtJQUNkLFNBQVMsRUFBRSxJQUFJO0lBQ2YsUUFBUSxFQUFFLElBQUk7SUFDZCxLQUFLLEVBQUUsSUFBSTtJQUNYLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLE9BQU8sRUFBRSxJQUFJO0lBQ2IsT0FBTyxFQUFFLElBQUk7SUFDYixJQUFJLEVBQUUsSUFBSTtJQUNWLFVBQVUsRUFBRSxJQUFJO0lBQ2hCLEtBQUssRUFBRSxJQUFJO0lBQ1gsSUFBSSxFQUFFLElBQUk7SUFFVixrQkFBa0I7SUFDbEIsRUFBRSxFQUFFLElBQUk7SUFDUixLQUFLLEVBQUUsSUFBSTtJQUNYLEtBQUssRUFBRSxJQUFJO0lBQ1gsS0FBSyxFQUFFLElBQUk7SUFDWCxHQUFHLEVBQUUsSUFBSTtJQUNULFNBQVMsRUFBRSxJQUFJO0lBQ2YsU0FBUyxFQUFFLElBQUk7SUFDZixJQUFJLEVBQUUsSUFBSTtDQUNGLENBQUM7QUFFWCxrREFBa0Q7QUFDbEQsTUFBTSxjQUFjLEdBQUc7SUFDckIsR0FBRyxFQUFFLGNBQU0sQ0FBQyxHQUFHO0lBQ2YsR0FBRyxFQUFFLGNBQU0sQ0FBQyxHQUFHO0lBQ2YsTUFB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O0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2pELE9BQU8sTUFBTSxLQUFLLGNBQWMsQ0FBQyxJQUFJLENBQUM7UUFDeEMsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU87UUFDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFFcEIsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUM3QixJQUFJLENBQUMsT0FBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7b0JBQ3JCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO29CQUNwQixPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7Q0FDRjtBQWhjRCw4QkFnY0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNvY2hEQiBJUEMgQ2xpZW50XG4gKlxuICogQ29ubmVjdHMgdG8gYSBTb2NoREIgSVBDIHNlcnZlciB2aWEgVW5peCBkb21haW4gc29ja2V0LlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5cbi8vIENvcHlyaWdodCAyMDI1IFN1c2hhbnRoIChodHRwczovL2dpdGh1Yi5jb20vc3VzaGFudGhweSlcbi8vXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuLy8gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4vL1xuLy8gICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5pbXBvcnQgKiBhcyBuZXQgZnJvbSAnbmV0JztcbmltcG9ydCB7IENvbm5lY3Rpb25FcnJvciwgUHJvdG9jb2xFcnJvciwgVHJhbnNhY3Rpb25FcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IFF1ZXJ5IH0gZnJvbSAnLi9xdWVyeSc7XG5cbi8qKlxuICogV2lyZSBwcm90b2NvbCBvcGNvZGVzLlxuICovXG5leHBvcnQgY29uc3QgT3BDb2RlID0ge1xuICAvLyBDbGllbnQg4oaSIFNlcnZlciAobXVzdCBtYXRjaCBzb2NoZGItc3RvcmFnZS9zcmMvaXBjX3NlcnZlci5ycylcbiAgUHV0OiAweDAxLFxuICBHZXQ6IDB4MDIsXG4gIERlbGV0ZTogMHgwMyxcbiAgQmVnaW5UeG46IDB4MDQsXG4gIENvbW1pdFR4bjogMHgwNSxcbiAgQWJvcnRUeG46IDB4MDYsXG4gIFF1ZXJ5OiAweDA3LFxuICBDcmVhdGVUYWJsZTogMHgwOCxcbiAgUHV0UGF0aDogMHgwOSxcbiAgR2V0UGF0aDogMHgwQSxcbiAgU2NhbjogMHgwQixcbiAgQ2hlY2twb2ludDogMHgwQyxcbiAgU3RhdHM6IDB4MEQsXG4gIFBpbmc6IDB4MEUsXG5cbiAgLy8gU2VydmVyIOKGkiBDbGllbnRcbiAgT0s6IDB4ODAsXG4gIEVycm9yOiAweDgxLFxuICBWYWx1ZTogMHg4MixcbiAgVHhuSWQ6IDB4ODMsXG4gIFJvdzogMHg4NCxcbiAgRW5kU3RyZWFtOiAweDg1LFxuICBTdGF0c1Jlc3A6IDB4ODYsXG4gIFBvbmc6IDB4ODcsXG59IGFzIGNvbnN0O1xuXG4vLyBJbnRlcm5hbCBPcENvZGUgbWFwIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuY29uc3QgSW50ZXJuYWxPcENvZGUgPSB7XG4gIFBVVDogT3BDb2RlLlB1dCxcbiAgR0VUOiBPcENvZGUuR2V0LFxuICBERUxFVEU6IE9wQ29kZS5EZWxldGUsXG4gIEJFR0lOX1RYTjogT3BDb2RlLkJlZ2luVHhuLFxuICBDT01NSVRfVFhOOiBPcENvZGUuQ29tbWl0VHhuLFxuICBBQk9SVF9UWE46IE9wQ29kZS5BYm9ydFR4bixcbiAgUVVFUlk6IE9wQ29kZS5RdWVyeSxcbiAgUFVUX1BBVEg6IE9wQ29kZS5QdXRQYXRoLFxuICBHRVRfUEFUSDogT3BDb2RlLkdldFBhdGgsXG4gIFNDQU46IE9wQ29kZS5TY2FuLFxuICBDSEVDS1BPSU5UOiBPcENvZGUuQ2hlY2twb2ludCxcbiAgU1RBVFM6IE9wQ29kZS5TdGF0cyxcbiAgUElORzogT3BDb2RlLlBpbmcsXG4gIE9LOiBPcENvZGUuT0ssXG4gIEVSUk9SOiBPcENvZGUuRXJyb3IsXG4gIFZBTFVFOiBPcENvZGUuVmFsdWUsXG4gIFRYTl9JRDogT3BDb2RlLlR4bklkLFxuICBST1c6IE9wQ29kZS5Sb3csXG4gIEVORF9TVFJFQU06IE9wQ29kZS5FbmRTdHJlYW0sXG4gIFNUQVRTX1JFU1A6IE9wQ29kZS5TdGF0c1Jlc3AsXG4gIFBPTkc6IE9wQ29kZS5Qb25nLFxufSBhcyBjb25zdDtcblxuY29uc3QgTUFYX01FU1NBR0VfU0laRSA9IDE2ICogMTAyNCAqIDEwMjQ7IC8vIDE2IE1CXG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBJcGNDbGllbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSXBjQ2xpZW50Q29uZmlnIHtcbiAgLyoqIFBhdGggdG8gVW5peCBkb21haW4gc29ja2V0ICovXG4gIHNvY2tldFBhdGg6IHN0cmluZztcbiAgLyoqIENvbm5lY3Rpb24gdGltZW91dCBpbiBtaWxsaXNlY29uZHMgKGRlZmF1bHQ6IDUwMDApICovXG4gIGNvbm5lY3RUaW1lb3V0PzogbnVtYmVyO1xuICAvKiogUmVhZCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogMzAwMDApICovXG4gIHJlYWRUaW1lb3V0PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIElQQyBDbGllbnQgZm9yIFNvY2hEQi5cbiAqXG4gKiBDb25uZWN0cyB0byBhIFNvY2hEQiBzZXJ2ZXIgdmlhIFVuaXggZG9tYWluIHNvY2tldC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgSXBjQ2xpZW50IH0gZnJvbSAnQHN1c2hhbnRoL3NvY2hkYic7XG4gKlxuICogY29uc3QgY2xpZW50ID0gYXdhaXQgSXBjQ2xpZW50LmNvbm5lY3QoJy90bXAvc29jaGRiLnNvY2snKTtcbiAqXG4gKiBhd2FpdCBjbGllbnQucHV0KEJ1ZmZlci5mcm9tKCdrZXknKSwgQnVmZmVyLmZyb20oJ3ZhbHVlJykpO1xuICogY29uc3QgdmFsdWUgPSBhd2FpdCBjbGllbnQuZ2V0KEJ1ZmZlci5mcm9tKCdrZXknKSk7XG4gKlxuICogYXdhaXQgY2xpZW50LmNsb3NlKCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIElwY0NsaWVudCB7XG4gIHByaXZhdGUgX3NvY2tldDogbmV0LlNvY2tldCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9jb25maWc6IFJlcXVpcmVkPElwY0NsaWVudENvbmZpZz47XG4gIHByaXZhdGUgX3BlbmRpbmdSZWFkczogQXJyYXk8e1xuICAgIHJlc29sdmU6IChidWY6IEJ1ZmZlcikgPT4gdm9pZDtcbiAgICByZWplY3Q6IChlcnI6IEVycm9yKSA9PiB2b2lkO1xuICB9PiA9IFtdO1xuICBwcml2YXRlIF9yZWFkQnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoMCk7XG4gIHByaXZhdGUgX2Nsb3NlZCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoY29uZmlnOiBJcGNDbGllbnRDb25maWcpIHtcbiAgICB0aGlzLl9jb25maWcgPSB7XG4gICAgICBjb25uZWN0VGltZW91dDogNTAwMCxcbiAgICAgIHJlYWRUaW1lb3V0OiAzMDAwMCxcbiAgICAgIC4uLmNvbmZpZyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3QgdG8gYSBTb2NoREIgSVBDIHNlcnZlci5cbiAgICpcbiAgICogQHBhcmFtIHNvY2tldFBhdGggLSBQYXRoIHRvIHRoZSBVbml4IGRvbWFpbiBzb2NrZXRcbiAgICogQHJldHVybnMgQSBjb25uZWN0ZWQgSXBjQ2xpZW50IGluc3RhbmNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgY2xpZW50ID0gYXdhaXQgSXBjQ2xpZW50LmNvbm5lY3QoJy90bXAvc29jaGRiLnNvY2snKTtcbiAgICogYGBgXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgY29ubmVjdChzb2NrZXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPElwY0NsaWVudD4ge1xuICAgIGNvbnN0IGNsaWVudCA9IG5ldyBJcGNDbGllbnQoeyBzb2NrZXRQYXRoIH0pO1xuICAgIGF3YWl0IGNsaWVudC5fY29ubmVjdCgpO1xuICAgIHJldHVybiBjbGllbnQ7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9jb25uZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzb2NrZXQgPSBuZXQuY3JlYXRlQ29ubmVjdGlvbihcbiAgICAgICAgeyBwYXRoOiB0aGlzLl9jb25maWcuc29ja2V0UGF0aCB9LFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5fc29ja2V0ID0gc29ja2V0O1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgc29ja2V0LnNldFRpbWVvdXQodGhpcy5fY29uZmlnLmNvbm5lY3RUaW1lb3V0KTtcblxuICAgICAgc29ja2V0Lm9uKCd0aW1lb3V0JywgKCkgPT4ge1xuICAgICAgICBzb2NrZXQuZGVzdHJveSgpO1xuICAgICAgICByZWplY3QobmV3IENvbm5lY3Rpb25FcnJvcignQ29ubmVjdGlvbiB0aW1lb3V0JykpO1xuICAgICAgfSk7XG5cbiAgICAgIHNvY2tldC5vbignZXJyb3InLCAoZXJyKSA9PiB7XG4gICAgICAgIHJlamVjdChuZXcgQ29ubmVjdGlvbkVycm9yKGBDb25uZWN0aW9uIGZhaWxlZDogJHtlcnIubWVzc2FnZX1gKSk7XG4gICAgICB9KTtcblxuICAgICAgc29ja2V0Lm9uKCdkYXRhJywgKGRhdGEpID0+IHtcbiAgICAgICAgdGhpcy5fcmVhZEJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW3RoaXMuX3JlYWRCdWZmZXIsIGRhdGFdKTtcbiAgICAgICAgdGhpcy5fcHJvY2Vzc0J1ZmZlcigpO1xuICAgICAgfSk7XG5cbiAgICAgIHNvY2tldC5vbignY2xvc2UnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuX2Nsb3NlZCA9IHRydWU7XG4gICAgICAgIGZvciAoY29uc3QgcGVuZGluZyBvZiB0aGlzLl9wZW5kaW5nUmVhZHMpIHtcbiAgICAgICAgICBwZW5kaW5nLnJlamVjdChuZXcgQ29ubmVjdGlvbkVycm9yKCdDb25uZWN0aW9uIGNsb3NlZCcpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9wZW5kaW5nUmVhZHMgPSBbXTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcHJvY2Vzc0J1ZmZlcigpOiB2b2lkIHtcbiAgICAvLyBQcm9jZXNzIGNvbXBsZXRlIG1lc3NhZ2VzIGZyb20gdGhlIGJ1ZmZlclxuICAgIHdoaWxlICh0aGlzLl9yZWFkQnVmZmVyLmxlbmd0aCA+PSA1ICYmIHRoaXMuX3BlbmRpbmdSZWFkcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBsZW5ndGggPSB0aGlzLl9yZWFkQnVmZmVyLnJlYWRVSW50MzJMRSgxKTtcbiAgICAgIGNvbnN0IHRvdGFsTGVuZ3RoID0gNSArIGxlbmd0aDtcblxuICAgICAgaWYgKHRoaXMuX3JlYWRCdWZmZXIubGVuZ3RoID49IHRvdGFsTGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLl9yZWFkQnVmZmVyLnN1YmFycmF5KDAsIHRvdGFsTGVuZ3RoKTtcbiAgICAgICAgdGhpcy5fcmVhZEJ1ZmZlciA9IHRoaXMuX3JlYWRCdWZmZXIuc3ViYXJyYXkodG90YWxMZW5ndGgpO1xuXG4gICAgICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nUmVhZHMuc2hpZnQoKTtcbiAgICAgICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgICBwZW5kaW5nLnJlc29sdmUobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX3NlbmQob3Bjb2RlOiBudW1iZXIsIHBheWxvYWQ6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygwKSk6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgaWYgKHRoaXMuX2Nsb3NlZCB8fCAhdGhpcy5fc29ja2V0KSB7XG4gICAgICB0aHJvdyBuZXcgQ29ubmVjdGlvbkVycm9yKCdOb3QgY29ubmVjdGVkJyk7XG4gICAgfVxuXG4gICAgLy8gRW5jb2RlIG1lc3NhZ2U6IG9wY29kZSAoMSkgKyBsZW5ndGggKDQgTEUpICsgcGF5bG9hZFxuICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuYWxsb2MoNSArIHBheWxvYWQubGVuZ3RoKTtcbiAgICBtZXNzYWdlLndyaXRlVUludDgob3Bjb2RlLCAwKTtcbiAgICBtZXNzYWdlLndyaXRlVUludDMyTEUocGF5bG9hZC5sZW5ndGgsIDEpO1xuICAgIHBheWxvYWQuY29weShtZXNzYWdlLCA1KTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLl9wZW5kaW5nUmVhZHMucHVzaCh7IHJlc29sdmUsIHJlamVjdCB9KTtcblxuICAgICAgdGhpcy5fc29ja2V0IS53cml0ZShtZXNzYWdlLCAoZXJyKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICB0aGlzLl9wZW5kaW5nUmVhZHMucG9wKCk7XG4gICAgICAgICAgcmVqZWN0KG5ldyBDb25uZWN0aW9uRXJyb3IoYFdyaXRlIGZhaWxlZDogJHtlcnIubWVzc2FnZX1gKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBTZXQgdGltZW91dCBmb3IgcmVzcG9uc2VcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBjb25zdCBpZHggPSB0aGlzLl9wZW5kaW5nUmVhZHMuZmluZEluZGV4KChwKSA9PiBwLnJlc29sdmUgPT09IHJlc29sdmUpO1xuICAgICAgICBpZiAoaWR4ICE9PSAtMSkge1xuICAgICAgICAgIHRoaXMuX3BlbmRpbmdSZWFkcy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICByZWplY3QobmV3IENvbm5lY3Rpb25FcnJvcignUmVhZCB0aW1lb3V0JykpO1xuICAgICAgICB9XG4gICAgICB9LCB0aGlzLl9jb25maWcucmVhZFRpbWVvdXQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcGFyc2VSZXNwb25zZShyZXNwb25zZTogQnVmZmVyKTogeyBvcGNvZGU6IG51bWJlcjsgcGF5bG9hZDogQnVmZmVyIH0ge1xuICAgIGNvbnN0IG9wY29kZSA9IHJlc3BvbnNlLnJlYWRVSW50OCgwKTtcbiAgICBjb25zdCBsZW5ndGggPSByZXNwb25zZS5yZWFkVUludDMyTEUoMSk7XG4gICAgY29uc3QgcGF5bG9hZCA9IHJlc3BvbnNlLnN1YmFycmF5KDUsIDUgKyBsZW5ndGgpO1xuXG4gICAgaWYgKG9wY29kZSA9PT0gSW50ZXJuYWxPcENvZGUuRVJST1IpIHtcbiAgICAgIHRocm93IG5ldyBQcm90b2NvbEVycm9yKHBheWxvYWQudG9TdHJpbmcoJ3V0ZjgnKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgb3Bjb2RlLCBwYXlsb2FkIH07XG4gIH1cblxuICAvKipcbiAgICogRW5jb2RlIGEga2V5IGZvciB0aGUgd2lyZSBwcm90b2NvbC5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBzdGF0aWMgZW5jb2RlS2V5KGtleTogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAvLyBGb3JtYXQ6IFtsZW5ndGg6NF1bb3A6MV1ba2V5X2xlbjo0XVtrZXk6Li4uXVxuICAgIGNvbnN0IG1zZ0xlbiA9IDEgKyA0ICsga2V5Lmxlbmd0aDtcbiAgICBjb25zdCBtc2cgPSBCdWZmZXIuYWxsb2MoNCArIG1zZ0xlbik7XG4gICAgbXNnLndyaXRlVUludDMyQkUobXNnTGVuLCAwKTtcbiAgICBtc2cud3JpdGVVSW50OChJbnRlcm5hbE9wQ29kZS5HRVQsIDQpO1xuICAgIG1zZy53cml0ZVVJbnQzMkJFKGtleS5sZW5ndGgsIDUpO1xuICAgIGtleS5jb3B5KG1zZywgOSk7XG4gICAgcmV0dXJuIG1zZztcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmNvZGUgYSBrZXktdmFsdWUgcGFpciBmb3IgdGhlIHdpcmUgcHJvdG9jb2wuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgc3RhdGljIGVuY29kZUtleVZhbHVlKGtleTogQnVmZmVyLCB2YWx1ZTogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAvLyBGb3JtYXQ6IFtsZW5ndGg6NF1bb3A6MV1ba2V5X2xlbjo0XVtrZXk6Li4uXVt2YWx1ZV9sZW46NF1bdmFsdWU6Li4uXVxuICAgIGNvbnN0IG1zZ0xlbiA9IDEgKyA0ICsga2V5Lmxlbmd0aCArIDQgKyB2YWx1ZS5sZW5ndGg7XG4gICAgY29uc3QgbXNnID0gQnVmZmVyLmFsbG9jKDQgKyBtc2dMZW4pO1xuICAgIG1zZy53cml0ZVVJbnQzMkJFKG1zZ0xlbiwgMCk7XG4gICAgbXNnLndyaXRlVUludDgoSW50ZXJuYWxPcENvZGUuUFVULCA0KTtcbiAgICBtc2cud3JpdGVVSW50MzJCRShrZXkubGVuZ3RoLCA1KTtcbiAgICBrZXkuY29weShtc2csIDkpO1xuICAgIG1zZy53cml0ZVVJbnQzMkJFKHZhbHVlLmxlbmd0aCwgOSArIGtleS5sZW5ndGgpO1xuICAgIHZhbHVlLmNvcHkobXNnLCAxMyArIGtleS5sZW5ndGgpO1xuICAgIHJldHVybiBtc2c7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgdmFsdWUgYnkga2V5LlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogQnVmZmVyKTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9zZW5kKEludGVybmFsT3BDb2RlLkdFVCwga2V5KTtcbiAgICBjb25zdCB7IG9wY29kZSwgcGF5bG9hZCB9ID0gdGhpcy5fcGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICBpZiAob3Bjb2RlID09PSBJbnRlcm5hbE9wQ29kZS5WQUxVRSkge1xuICAgICAgLy8gSWYgcGF5bG9hZCBpcyBlbXB0eSwgdGhlIGtleSBkb2Vzbid0IGV4aXN0XG4gICAgICBpZiAocGF5bG9hZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcGF5bG9hZDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUHV0IGEga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBwdXQoa2V5OiBCdWZmZXIsIHZhbHVlOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBFbmNvZGU6IGtleV9sZW4gKDQgTEUpICsga2V5ICsgdmFsdWVcbiAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmFsbG9jKDQgKyBrZXkubGVuZ3RoICsgdmFsdWUubGVuZ3RoKTtcbiAgICBwYXlsb2FkLndyaXRlVUludDMyTEUoa2V5Lmxlbmd0aCwgMCk7XG4gICAga2V5LmNvcHkocGF5bG9hZCwgNCk7XG4gICAgdmFsdWUuY29weShwYXlsb2FkLCA0ICsga2V5Lmxlbmd0aCk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuUFVULCBwYXlsb2FkKTtcbiAgICB0aGlzLl9wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBrZXkuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuREVMRVRFLCBrZXkpO1xuICAgIHRoaXMuX3BhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHZhbHVlIGJ5IHBhdGguXG4gICAqIFdpcmUgZm9ybWF0OiBwYXRoX2NvdW50KDIgTEUpICsgW3BhdGhfbGVuKDIgTEUpICsgcGF0aF9zZWdtZW50XS4uLlxuICAgKi9cbiAgYXN5bmMgZ2V0UGF0aChwYXRoOiBzdHJpbmcpOiBQcm9taXNlPEJ1ZmZlciB8IG51bGw+IHtcbiAgICAvLyBFbmNvZGUgcGF0aCBhcyBzaW5nbGUgc2VnbWVudCBmb3Igbm93IChjb3VsZCBzcGxpdCBvbiAnLycgZm9yIG11bHRpLXNlZ21lbnQpXG4gICAgY29uc3QgcGF0aEJ1ZiA9IEJ1ZmZlci5mcm9tKHBhdGgsICd1dGY4Jyk7XG4gICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5hbGxvYygyICsgMiArIHBhdGhCdWYubGVuZ3RoKTtcbiAgICBwYXlsb2FkLndyaXRlVUludDE2TEUoMSwgMCk7IC8vIHBhdGhfY291bnQgPSAxXG4gICAgcGF5bG9hZC53cml0ZVVJbnQxNkxFKHBhdGhCdWYubGVuZ3RoLCAyKTsgLy8gcGF0aF9sZW5cbiAgICBwYXRoQnVmLmNvcHkocGF5bG9hZCwgNCk7IC8vIHBhdGhcbiAgICBcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuR0VUX1BBVEgsIHBheWxvYWQpO1xuICAgIGNvbnN0IHsgb3Bjb2RlLCBwYXlsb2FkOiByZXNwb25zZVBheWxvYWQgfSA9IHRoaXMuX3BhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xuXG4gICAgaWYgKG9wY29kZSA9PT0gSW50ZXJuYWxPcENvZGUuVkFMVUUpIHtcbiAgICAgIC8vIElmIHBheWxvYWQgaXMgZW1wdHksIHRoZSBrZXkgZG9lc24ndCBleGlzdFxuICAgICAgaWYgKHJlc3BvbnNlUGF5bG9hZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzcG9uc2VQYXlsb2FkO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXQgYSB2YWx1ZSBhdCBhIHBhdGguXG4gICAqIFdpcmUgZm9ybWF0OiBwYXRoX2NvdW50KDIgTEUpICsgW3BhdGhfbGVuKDIgTEUpICsgcGF0aF9zZWdtZW50XS4uLiArIHZhbHVlXG4gICAqL1xuICBhc3luYyBwdXRQYXRoKHBhdGg6IHN0cmluZywgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBhdGhCdWYgPSBCdWZmZXIuZnJvbShwYXRoLCAndXRmOCcpO1xuICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuYWxsb2MoMiArIDIgKyBwYXRoQnVmLmxlbmd0aCArIHZhbHVlLmxlbmd0aCk7XG4gICAgcGF5bG9hZC53cml0ZVVJbnQxNkxFKDEsIDApOyAvLyBwYXRoX2NvdW50ID0gMVxuICAgIHBheWxvYWQud3JpdGVVSW50MTZMRShwYXRoQnVmLmxlbmd0aCwgMik7IC8vIHBhdGhfbGVuXG4gICAgcGF0aEJ1Zi5jb3B5KHBheWxvYWQsIDQpOyAvLyBwYXRoXG4gICAgdmFsdWUuY29weShwYXlsb2FkLCA0ICsgcGF0aEJ1Zi5sZW5ndGgpOyAvLyB2YWx1ZVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9zZW5kKEludGVybmFsT3BDb2RlLlBVVF9QQVRILCBwYXlsb2FkKTtcbiAgICB0aGlzLl9wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGEgcXVlcnkgYW5kIHJldHVybiBUT09OLWZvcm1hdHRlZCByZXN1bHRzLlxuICAgKiBcbiAgICogV2lyZSBmb3JtYXQ6IHBhdGhfbGVuKDIpICsgcGF0aCArIGxpbWl0KDQpICsgb2Zmc2V0KDQpICsgY29sc19jb3VudCgyKSArIFtjb2xfbGVuKDIpICsgY29sXS4uLlxuICAgKi9cbiAgYXN5bmMgcXVlcnkoXG4gICAgcGF0aFByZWZpeDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiB7IGxpbWl0PzogbnVtYmVyOyBvZmZzZXQ/OiBudW1iZXI7IGNvbHVtbnM/OiBzdHJpbmdbXSB9XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgb3B0cyA9IG9wdGlvbnMgfHwge307XG4gICAgY29uc3QgcGF0aEJ1ZiA9IEJ1ZmZlci5mcm9tKHBhdGhQcmVmaXgsICd1dGY4Jyk7XG4gICAgY29uc3QgY29sdW1ucyA9IG9wdHMuY29sdW1ucyB8fCBbXTtcbiAgICBcbiAgICAvLyBDYWxjdWxhdGUgcGF5bG9hZCBzaXplXG4gICAgbGV0IHNpemUgPSAyICsgcGF0aEJ1Zi5sZW5ndGggKyA0ICsgNCArIDI7XG4gICAgZm9yIChjb25zdCBjb2wgb2YgY29sdW1ucykge1xuICAgICAgc2l6ZSArPSAyICsgQnVmZmVyLmJ5dGVMZW5ndGgoY29sLCAndXRmOCcpO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBwYXlsb2FkID0gQnVmZmVyLmFsbG9jKHNpemUpO1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIFxuICAgIC8vIFBhdGg6IHBhdGhfbGVuKDIgTEUpICsgcGF0aFxuICAgIHBheWxvYWQud3JpdGVVSW50MTZMRShwYXRoQnVmLmxlbmd0aCwgb2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gMjtcbiAgICBwYXRoQnVmLmNvcHkocGF5bG9hZCwgb2Zmc2V0KTtcbiAgICBvZmZzZXQgKz0gcGF0aEJ1Zi5sZW5ndGg7XG4gICAgXG4gICAgLy8gTGltaXQgKDQgTEUpIC0gMCBtZWFucyBubyBsaW1pdFxuICAgIHBheWxvYWQud3JpdGVVSW50MzJMRShvcHRzLmxpbWl0IHx8IDAsIG9mZnNldCk7XG4gICAgb2Zmc2V0ICs9IDQ7XG4gICAgXG4gICAgLy8gT2Zmc2V0ICg0IExFKVxuICAgIHBheWxvYWQud3JpdGVVSW50MzJMRShvcHRzLm9mZnNldCB8fCAwLCBvZmZzZXQpO1xuICAgIG9mZnNldCArPSA0O1xuICAgIFxuICAgIC8vIENvbHVtbnM6IGNvdW50KDIgTEUpICsgW2NvbF9sZW4oMiBMRSkgKyBjb2xdLi4uXG4gICAgcGF5bG9hZC53cml0ZVVJbnQxNkxFKGNvbHVtbnMubGVuZ3RoLCBvZmZzZXQpO1xuICAgIG9mZnNldCArPSAyO1xuICAgIGZvciAoY29uc3QgY29sIG9mIGNvbHVtbnMpIHtcbiAgICAgIGNvbnN0IGNvbEJ1ZiA9IEJ1ZmZlci5mcm9tKGNvbCwgJ3V0ZjgnKTtcbiAgICAgIHBheWxvYWQud3JpdGVVSW50MTZMRShjb2xCdWYubGVuZ3RoLCBvZmZzZXQpO1xuICAgICAgb2Zmc2V0ICs9IDI7XG4gICAgICBjb2xCdWYuY29weShwYXlsb2FkLCBvZmZzZXQpO1xuICAgICAgb2Zmc2V0ICs9IGNvbEJ1Zi5sZW5ndGg7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9zZW5kKEludGVybmFsT3BDb2RlLlFVRVJZLCBwYXlsb2FkKTtcbiAgICBjb25zdCB7IHBheWxvYWQ6IHJlc3VsdFBheWxvYWQgfSA9IHRoaXMuX3BhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xuXG4gICAgcmV0dXJuIHJlc3VsdFBheWxvYWQudG9TdHJpbmcoJ3V0ZjgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FuIGZvciBrZXlzIHdpdGggYSBwcmVmaXgsIHJldHVybmluZyBrZXktdmFsdWUgcGFpcnMuXG4gICAqIFRoaXMgaXMgdGhlIHByZWZlcnJlZCBtZXRob2QgZm9yIHNpbXBsZSBwcmVmaXgtYmFzZWQgaXRlcmF0aW9uLlxuICAgKiBcbiAgICogV2lyZSBmb3JtYXQ6IHByZWZpeCBzdHJpbmdcbiAgICogUmVzcG9uc2UgZm9ybWF0OiBjb3VudCg0IExFKSArIFtrZXlfbGVuKDIgTEUpICsga2V5ICsgdmFsX2xlbig0IExFKSArIHZhbF0uLi5cbiAgICovXG4gIGFzeW5jIHNjYW4ocHJlZml4OiBzdHJpbmcpOiBQcm9taXNlPEFycmF5PHsga2V5OiBCdWZmZXI7IHZhbHVlOiBCdWZmZXIgfT4+IHtcbiAgICBjb25zdCBwcmVmaXhCdWYgPSBCdWZmZXIuZnJvbShwcmVmaXgsICd1dGY4Jyk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9zZW5kKEludGVybmFsT3BDb2RlLlNDQU4sIHByZWZpeEJ1Zik7XG4gICAgY29uc3QgeyBvcGNvZGUsIHBheWxvYWQgfSA9IHRoaXMuX3BhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xuXG4gICAgaWYgKG9wY29kZSAhPT0gSW50ZXJuYWxPcENvZGUuVkFMVUUgJiYgb3Bjb2RlICE9PSBJbnRlcm5hbE9wQ29kZS5PSykge1xuICAgICAgdGhyb3cgbmV3IFByb3RvY29sRXJyb3IoYFVuZXhwZWN0ZWQgc2NhbiByZXNwb25zZSBvcGNvZGU6IDB4JHtvcGNvZGUudG9TdHJpbmcoMTYpfWApO1xuICAgIH1cblxuICAgIGlmIChwYXlsb2FkLmxlbmd0aCA8IDQpIHtcbiAgICAgIHJldHVybiBbXTsgLy8gRW1wdHkgcmVzdWx0XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgcmVzcG9uc2U6IGNvdW50KDQgTEUpICsgW2tleV9sZW4oMiBMRSkgKyBrZXkgKyB2YWxfbGVuKDQgTEUpICsgdmFsXS4uLlxuICAgIGNvbnN0IGNvdW50ID0gcGF5bG9hZC5yZWFkVUludDMyTEUoMCk7XG4gICAgY29uc3QgcmVzdWx0czogQXJyYXk8eyBrZXk6IEJ1ZmZlcjsgdmFsdWU6IEJ1ZmZlciB9PiA9IFtdO1xuICAgIGxldCBvZmZzZXQgPSA0O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICBpZiAob2Zmc2V0ICsgMiA+IHBheWxvYWQubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBQcm90b2NvbEVycm9yKCdUcnVuY2F0ZWQgc2NhbiByZXNwb25zZSAoa2V5X2xlbiknKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGtleUxlbiA9IHBheWxvYWQucmVhZFVJbnQxNkxFKG9mZnNldCk7XG4gICAgICBvZmZzZXQgKz0gMjtcblxuICAgICAgaWYgKG9mZnNldCArIGtleUxlbiArIDQgPiBwYXlsb2FkLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgUHJvdG9jb2xFcnJvcignVHJ1bmNhdGVkIHNjYW4gcmVzcG9uc2UgKGtleSt2YWxfbGVuKScpO1xuICAgICAgfVxuICAgICAgY29uc3Qga2V5ID0gcGF5bG9hZC5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGtleUxlbik7XG4gICAgICBvZmZzZXQgKz0ga2V5TGVuO1xuXG4gICAgICBjb25zdCB2YWxMZW4gPSBwYXlsb2FkLnJlYWRVSW50MzJMRShvZmZzZXQpO1xuICAgICAgb2Zmc2V0ICs9IDQ7XG5cbiAgICAgIGlmIChvZmZzZXQgKyB2YWxMZW4gPiBwYXlsb2FkLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgUHJvdG9jb2xFcnJvcignVHJ1bmNhdGVkIHNjYW4gcmVzcG9uc2UgKHZhbHVlKScpO1xuICAgICAgfVxuICAgICAgY29uc3QgdmFsdWUgPSBwYXlsb2FkLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgdmFsTGVuKTtcbiAgICAgIG9mZnNldCArPSB2YWxMZW47XG5cbiAgICAgIHJlc3VsdHMucHVzaCh7IGtleSwgdmFsdWUgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgcXVlcnkgYnVpbGRlci5cbiAgICovXG4gIHF1ZXJ5QnVpbGRlcihwYXRoUHJlZml4OiBzdHJpbmcpOiBRdWVyeSB7XG4gICAgcmV0dXJuIG5ldyBRdWVyeSh0aGlzLCBwYXRoUHJlZml4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCZWdpbiBhIG5ldyB0cmFuc2FjdGlvbi5cbiAgICovXG4gIGFzeW5jIGJlZ2luVHJhbnNhY3Rpb24oKTogUHJvbWlzZTxiaWdpbnQ+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuQkVHSU5fVFhOKTtcbiAgICBjb25zdCB7IG9wY29kZSwgcGF5bG9hZCB9ID0gdGhpcy5fcGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICBpZiAob3Bjb2RlID09PSBJbnRlcm5hbE9wQ29kZS5UWE5fSUQpIHtcbiAgICAgIHJldHVybiBwYXlsb2FkLnJlYWRCaWdVSW50NjRMRSgwKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFRyYW5zYWN0aW9uRXJyb3IoJ0ZhaWxlZCB0byBiZWdpbiB0cmFuc2FjdGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbW1pdCBhIHRyYW5zYWN0aW9uLlxuICAgKi9cbiAgYXN5bmMgY29tbWl0VHJhbnNhY3Rpb24odHhuSWQ6IGJpZ2ludCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuYWxsb2MoOCk7XG4gICAgcGF5bG9hZC53cml0ZUJpZ1VJbnQ2NExFKHR4bklkLCAwKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuQ09NTUlUX1RYTiwgcGF5bG9hZCk7XG4gICAgdGhpcy5fcGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG4gIH1cblxuICAvKipcbiAgICogQWJvcnQgYSB0cmFuc2FjdGlvbi5cbiAgICovXG4gIGFzeW5jIGFib3J0VHJhbnNhY3Rpb24odHhuSWQ6IGJpZ2ludCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuYWxsb2MoOCk7XG4gICAgcGF5bG9hZC53cml0ZUJpZ1VJbnQ2NExFKHR4bklkLCAwKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuQUJPUlRfVFhOLCBwYXlsb2FkKTtcbiAgICB0aGlzLl9wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JjZSBhIGNoZWNrcG9pbnQuXG4gICAqL1xuICBhc3luYyBjaGVja3BvaW50KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fc2VuZChJbnRlcm5hbE9wQ29kZS5DSEVDS1BPSU5UKTtcbiAgICB0aGlzLl9wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgc3RvcmFnZSBzdGF0aXN0aWNzLlxuICAgKi9cbiAgYXN5bmMgc3RhdHMoKTogUHJvbWlzZTx7XG4gICAgbWVtdGFibGVTaXplQnl0ZXM6IG51bWJlcjtcbiAgICB3YWxTaXplQnl0ZXM6IG51bWJlcjtcbiAgICBhY3RpdmVUcmFuc2FjdGlvbnM6IG51bWJlcjtcbiAgfT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fc2VuZChJbnRlcm5hbE9wQ29kZS5TVEFUUyk7XG4gICAgY29uc3QgeyBwYXlsb2FkIH0gPSB0aGlzLl9wYXJzZVJlc3BvbnNlKHJlc3BvbnNlKTtcbiAgICBjb25zdCBqc29uID0gSlNPTi5wYXJzZShwYXlsb2FkLnRvU3RyaW5nKCd1dGY4JykpO1xuICAgIHJldHVybiB7XG4gICAgICBtZW10YWJsZVNpemVCeXRlczoganNvbi5tZW10YWJsZV9zaXplX2J5dGVzIHx8IDAsXG4gICAgICB3YWxTaXplQnl0ZXM6IGpzb24ud2FsX3NpemVfYnl0ZXMgfHwgMCxcbiAgICAgIGFjdGl2ZVRyYW5zYWN0aW9uczoganNvbi5hY3RpdmVfdHJhbnNhY3Rpb25zIHx8IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQaW5nIHRoZSBzZXJ2ZXIuXG4gICAqL1xuICBhc3luYyBwaW5nKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmQoSW50ZXJuYWxPcENvZGUuUElORyk7XG4gICAgICBjb25zdCB7IG9wY29kZSB9ID0gdGhpcy5fcGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG4gICAgICByZXR1cm4gb3Bjb2RlID09PSBJbnRlcm5hbE9wQ29kZS5QT05HO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgY29ubmVjdGlvbi5cbiAgICovXG4gIGFzeW5jIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9jbG9zZWQpIHJldHVybjtcbiAgICB0aGlzLl9jbG9zZWQgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHRoaXMuX3NvY2tldCEuZW5kKCgpID0+IHtcbiAgICAgICAgICB0aGlzLl9zb2NrZXQgPSBudWxsO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|