@sochdb/sochdb 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -33
- 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 +1 -1
- package/bin/sochdb-grpc-server.js +1 -1
- package/bin/sochdb-server.js +1 -1
- package/dist/cjs/context-builder.js +280 -0
- package/dist/cjs/database.js +2 -2
- package/dist/cjs/embedded/database.js +2 -2
- package/dist/cjs/errors.js +99 -7
- package/dist/cjs/index.js +40 -3
- package/dist/cjs/ipc-client.js +2 -2
- package/dist/cjs/memory/consolidation.js +202 -0
- package/dist/cjs/memory/extraction.js +181 -0
- package/dist/cjs/memory/index.js +26 -0
- package/dist/cjs/memory/retrieval.js +232 -0
- package/dist/cjs/memory/types.js +69 -0
- package/dist/cjs/namespace.js +255 -0
- package/dist/cjs/queue.js +289 -0
- package/dist/cjs/semantic-cache.js +220 -0
- package/dist/esm/context-builder.js +280 -0
- package/dist/esm/database.js +2 -2
- package/dist/esm/embedded/database.js +2 -2
- package/dist/esm/errors.js +107 -7
- package/dist/esm/index.js +40 -3
- package/dist/esm/ipc-client.js +2 -2
- package/dist/esm/memory/consolidation.js +206 -0
- package/dist/esm/memory/extraction.js +185 -0
- package/dist/esm/memory/index.js +26 -0
- package/dist/esm/memory/retrieval.js +243 -0
- package/dist/esm/memory/types.js +72 -0
- package/dist/esm/namespace.js +262 -0
- package/dist/esm/queue.js +291 -0
- package/dist/esm/semantic-cache.js +223 -0
- package/dist/types/context-builder.d.ts +97 -0
- package/dist/types/context-builder.d.ts.map +1 -0
- package/dist/types/database.d.ts +1 -1
- package/dist/types/embedded/database.d.ts +1 -1
- package/dist/types/errors.d.ts +57 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +12 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/ipc-client.d.ts +1 -1
- package/dist/types/memory/consolidation.d.ts +66 -0
- package/dist/types/memory/consolidation.d.ts.map +1 -0
- package/dist/types/memory/extraction.d.ts +82 -0
- package/dist/types/memory/extraction.d.ts.map +1 -0
- package/dist/types/memory/index.d.ts +10 -0
- package/dist/types/memory/index.d.ts.map +1 -0
- package/dist/types/memory/retrieval.d.ts +46 -0
- package/dist/types/memory/retrieval.d.ts.map +1 -0
- package/dist/types/memory/types.d.ts +147 -0
- package/dist/types/memory/types.d.ts.map +1 -0
- package/dist/types/namespace.d.ts +129 -0
- package/dist/types/namespace.d.ts.map +1 -0
- package/dist/types/queue.d.ts +120 -0
- package/dist/types/queue.d.ts.map +1 -0
- package/dist/types/semantic-cache.d.ts +84 -0
- package/dist/types/semantic-cache.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SochDB Namespace API
|
|
4
|
+
*
|
|
5
|
+
* Provides type-safe namespace isolation with first-class namespace handles.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { Database } from '@sochdb/sochdb';
|
|
10
|
+
*
|
|
11
|
+
* const db = await Database.open('./mydb');
|
|
12
|
+
* const ns = await db.createNamespace('tenant_123');
|
|
13
|
+
* const collection = await ns.createCollection('documents', { dimension: 384 });
|
|
14
|
+
* await collection.insert([1.0, 2.0, ...], { source: 'web' });
|
|
15
|
+
* const results = await collection.search(queryVector, 10);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.Namespace = exports.Collection = exports.DistanceMetric = exports.CollectionExistsError = exports.CollectionNotFoundError = exports.NamespaceExistsError = exports.NamespaceNotFoundError = void 0;
|
|
20
|
+
const errors_1 = require("./errors");
|
|
21
|
+
class NamespaceNotFoundError extends errors_1.SochDBError {
|
|
22
|
+
constructor(namespace) {
|
|
23
|
+
super(`Namespace not found: ${namespace}`);
|
|
24
|
+
this.name = 'NamespaceNotFoundError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.NamespaceNotFoundError = NamespaceNotFoundError;
|
|
28
|
+
class NamespaceExistsError extends errors_1.SochDBError {
|
|
29
|
+
constructor(namespace) {
|
|
30
|
+
super(`Namespace already exists: ${namespace}`);
|
|
31
|
+
this.name = 'NamespaceExistsError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.NamespaceExistsError = NamespaceExistsError;
|
|
35
|
+
class CollectionNotFoundError extends errors_1.SochDBError {
|
|
36
|
+
constructor(collection) {
|
|
37
|
+
super(`Collection not found: ${collection}`);
|
|
38
|
+
this.name = 'CollectionNotFoundError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.CollectionNotFoundError = CollectionNotFoundError;
|
|
42
|
+
class CollectionExistsError extends errors_1.SochDBError {
|
|
43
|
+
constructor(collection) {
|
|
44
|
+
super(`Collection already exists: ${collection}`);
|
|
45
|
+
this.name = 'CollectionExistsError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.CollectionExistsError = CollectionExistsError;
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Collection Configuration
|
|
51
|
+
// ============================================================================
|
|
52
|
+
var DistanceMetric;
|
|
53
|
+
(function (DistanceMetric) {
|
|
54
|
+
DistanceMetric["Cosine"] = "cosine";
|
|
55
|
+
DistanceMetric["Euclidean"] = "euclidean";
|
|
56
|
+
DistanceMetric["DotProduct"] = "dot";
|
|
57
|
+
})(DistanceMetric || (exports.DistanceMetric = DistanceMetric = {}));
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Collection Handle
|
|
60
|
+
// ============================================================================
|
|
61
|
+
class Collection {
|
|
62
|
+
constructor(db, namespace, name, config) {
|
|
63
|
+
this.db = db;
|
|
64
|
+
this.namespace = namespace;
|
|
65
|
+
this.name = name;
|
|
66
|
+
this.config = config;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Insert a vector with optional metadata
|
|
70
|
+
*/
|
|
71
|
+
async insert(vector, metadata, id) {
|
|
72
|
+
if (this.config.dimension && vector.length !== this.config.dimension) {
|
|
73
|
+
throw new errors_1.DatabaseError(`Vector dimension mismatch: expected ${this.config.dimension}, got ${vector.length}`);
|
|
74
|
+
}
|
|
75
|
+
const vectorId = id || this.generateId();
|
|
76
|
+
const key = this.vectorKey(vectorId);
|
|
77
|
+
const data = {
|
|
78
|
+
vector,
|
|
79
|
+
metadata: metadata || {},
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
};
|
|
82
|
+
await this.db.put(Buffer.from(key), Buffer.from(JSON.stringify(data)));
|
|
83
|
+
return vectorId;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Insert multiple vectors
|
|
87
|
+
*/
|
|
88
|
+
async insertMany(vectors, metadatas, ids) {
|
|
89
|
+
const resultIds = [];
|
|
90
|
+
for (let i = 0; i < vectors.length; i++) {
|
|
91
|
+
const id = ids ? ids[i] : undefined;
|
|
92
|
+
const metadata = metadatas ? metadatas[i] : undefined;
|
|
93
|
+
const resultId = await this.insert(vectors[i], metadata, id);
|
|
94
|
+
resultIds.push(resultId);
|
|
95
|
+
}
|
|
96
|
+
return resultIds;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Search for similar vectors
|
|
100
|
+
*/
|
|
101
|
+
async search(request) {
|
|
102
|
+
// For now, implement basic linear search
|
|
103
|
+
// In production, this would use HNSW index
|
|
104
|
+
const results = [];
|
|
105
|
+
const prefix = this.vectorKeyPrefix();
|
|
106
|
+
// Scan all vectors in collection
|
|
107
|
+
const allVectors = [];
|
|
108
|
+
// TODO: Implement efficient scanning with range queries
|
|
109
|
+
// For now, this is a placeholder that shows the API structure
|
|
110
|
+
// Sort by similarity score
|
|
111
|
+
allVectors.sort((a, b) => b.score - a.score);
|
|
112
|
+
// Return top-k results
|
|
113
|
+
return allVectors.slice(0, request.k).map(v => ({
|
|
114
|
+
id: v.id,
|
|
115
|
+
score: v.score,
|
|
116
|
+
vector: request.includeMetadata ? v.vector : undefined,
|
|
117
|
+
metadata: request.includeMetadata ? v.metadata : undefined,
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get a vector by ID
|
|
122
|
+
*/
|
|
123
|
+
async get(id) {
|
|
124
|
+
const key = this.vectorKey(id);
|
|
125
|
+
const value = await this.db.get(Buffer.from(key));
|
|
126
|
+
if (!value) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const data = JSON.parse(value.toString());
|
|
130
|
+
return {
|
|
131
|
+
vector: data.vector,
|
|
132
|
+
metadata: data.metadata,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Delete a vector by ID
|
|
137
|
+
*/
|
|
138
|
+
async delete(id) {
|
|
139
|
+
const key = this.vectorKey(id);
|
|
140
|
+
await this.db.delete(Buffer.from(key));
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Count vectors in collection
|
|
145
|
+
*/
|
|
146
|
+
async count() {
|
|
147
|
+
// TODO: Implement efficient counting
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
// Helper methods
|
|
151
|
+
vectorKey(id) {
|
|
152
|
+
return `_collection/${this.namespace}/${this.name}/vectors/${id}`;
|
|
153
|
+
}
|
|
154
|
+
vectorKeyPrefix() {
|
|
155
|
+
return `_collection/${this.namespace}/${this.name}/vectors/`;
|
|
156
|
+
}
|
|
157
|
+
metadataKey() {
|
|
158
|
+
return `_collection/${this.namespace}/${this.name}/metadata`;
|
|
159
|
+
}
|
|
160
|
+
generateId() {
|
|
161
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
162
|
+
}
|
|
163
|
+
// Calculate cosine similarity
|
|
164
|
+
cosineSimilarity(a, b) {
|
|
165
|
+
let dotProduct = 0;
|
|
166
|
+
let normA = 0;
|
|
167
|
+
let normB = 0;
|
|
168
|
+
for (let i = 0; i < a.length; i++) {
|
|
169
|
+
dotProduct += a[i] * b[i];
|
|
170
|
+
normA += a[i] * a[i];
|
|
171
|
+
normB += b[i] * b[i];
|
|
172
|
+
}
|
|
173
|
+
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.Collection = Collection;
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Namespace Handle
|
|
179
|
+
// ============================================================================
|
|
180
|
+
class Namespace {
|
|
181
|
+
constructor(db, name, config) {
|
|
182
|
+
this.db = db;
|
|
183
|
+
this.name = name;
|
|
184
|
+
this.config = config;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Create a new collection in this namespace
|
|
188
|
+
*/
|
|
189
|
+
async createCollection(config) {
|
|
190
|
+
const metadataKey = `_collection/${this.name}/${config.name}/metadata`;
|
|
191
|
+
// Check if collection already exists
|
|
192
|
+
const existing = await this.db.get(Buffer.from(metadataKey));
|
|
193
|
+
if (existing) {
|
|
194
|
+
throw new CollectionExistsError(config.name);
|
|
195
|
+
}
|
|
196
|
+
// Store collection metadata
|
|
197
|
+
const metadata = {
|
|
198
|
+
...config,
|
|
199
|
+
createdAt: Date.now(),
|
|
200
|
+
};
|
|
201
|
+
await this.db.put(Buffer.from(metadataKey), Buffer.from(JSON.stringify(metadata)));
|
|
202
|
+
return new Collection(this.db, this.name, config.name, config);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get an existing collection
|
|
206
|
+
*/
|
|
207
|
+
async collection(name) {
|
|
208
|
+
const metadataKey = `_collection/${this.name}/${name}/metadata`;
|
|
209
|
+
const metadata = await this.db.get(Buffer.from(metadataKey));
|
|
210
|
+
if (!metadata) {
|
|
211
|
+
throw new CollectionNotFoundError(name);
|
|
212
|
+
}
|
|
213
|
+
const config = JSON.parse(metadata.toString());
|
|
214
|
+
return new Collection(this.db, this.name, name, config);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get or create a collection
|
|
218
|
+
*/
|
|
219
|
+
async getOrCreateCollection(config) {
|
|
220
|
+
try {
|
|
221
|
+
return await this.collection(config.name);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (error instanceof CollectionNotFoundError) {
|
|
225
|
+
return await this.createCollection(config);
|
|
226
|
+
}
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Delete a collection
|
|
232
|
+
*/
|
|
233
|
+
async deleteCollection(name) {
|
|
234
|
+
const metadataKey = `_collection/${this.name}/${name}/metadata`;
|
|
235
|
+
const prefix = `_collection/${this.name}/${name}/`;
|
|
236
|
+
// TODO: Delete all keys with prefix
|
|
237
|
+
await this.db.delete(Buffer.from(metadataKey));
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* List all collections in this namespace
|
|
242
|
+
*/
|
|
243
|
+
async listCollections() {
|
|
244
|
+
// TODO: Implement efficient listing with range queries
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
getName() {
|
|
248
|
+
return this.name;
|
|
249
|
+
}
|
|
250
|
+
getConfig() {
|
|
251
|
+
return { ...this.config };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
exports.Namespace = Namespace;
|
|
255
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtZXNwYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25hbWVzcGFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHOzs7QUFFSCxxQ0FBc0Q7QUFhdEQsTUFBYSxzQkFBdUIsU0FBUSxvQkFBVztJQUNyRCxZQUFZLFNBQWlCO1FBQzNCLEtBQUssQ0FBQyx3QkFBd0IsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsSUFBSSxHQUFHLHdCQUF3QixDQUFDO0lBQ3ZDLENBQUM7Q0FDRjtBQUxELHdEQUtDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxvQkFBVztJQUNuRCxZQUFZLFNBQWlCO1FBQzNCLEtBQUssQ0FBQyw2QkFBNkIsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQUxELG9EQUtDO0FBRUQsTUFBYSx1QkFBd0IsU0FBUSxvQkFBVztJQUN0RCxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyx5QkFBeUIsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsSUFBSSxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLENBQUM7Q0FDRjtBQUxELDBEQUtDO0FBRUQsTUFBYSxxQkFBc0IsU0FBUSxvQkFBVztJQUNwRCxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyw4QkFBOEIsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsSUFBSSxHQUFHLHVCQUF1QixDQUFDO0lBQ3RDLENBQUM7Q0FDRjtBQUxELHNEQUtDO0FBRUQsK0VBQStFO0FBQy9FLDJCQUEyQjtBQUMzQiwrRUFBK0U7QUFFL0UsSUFBWSxjQUlYO0FBSkQsV0FBWSxjQUFjO0lBQ3hCLG1DQUFpQixDQUFBO0lBQ2pCLHlDQUF1QixDQUFBO0lBQ3ZCLG9DQUFrQixDQUFBO0FBQ3BCLENBQUMsRUFK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Q0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFZO1FBQ2pDLE1BQU0sV0FBVyxHQUFHLGVBQWUsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLFdBQVcsQ0FBQztRQUNoRSxNQUFNLE1BQU0sR0FBRyxlQUFlLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxHQUFHLENBQUM7UUFFbkQsb0NBQW9DO1FBQ3BDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBRS9DLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGVBQWU7UUFDbkIsdURBQXVEO1FBQ3ZELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUVELFNBQVM7UUFDUCxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBMUZELDhCQTBGQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU29jaERCIE5hbWVzcGFjZSBBUElcbiAqIFxuICogUHJvdmlkZXMgdHlwZS1zYWZlIG5hbWVzcGFjZSBpc29sYXRpb24gd2l0aCBmaXJzdC1jbGFzcyBuYW1lc3BhY2UgaGFuZGxlcy5cbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IERhdGFiYXNlIH0gZnJvbSAnQHNvY2hkYi9zb2NoZGInO1xuICogXG4gKiBjb25zdCBkYiA9IGF3YWl0IERhdGFiYXNlLm9wZW4oJy4vbXlkYicpO1xuICogY29uc3QgbnMgPSBhd2FpdCBkYi5jcmVhdGVOYW1lc3BhY2UoJ3RlbmFudF8xMjMnKTtcbiAqIGNvbnN0IGNvbGxlY3Rpb24gPSBhd2FpdCBucy5jcmVhdGVDb2xsZWN0aW9uKCdkb2N1bWVudHMnLCB7IGRpbWVuc2lvbjogMzg0IH0pO1xuICogYXdhaXQgY29sbGVjdGlvbi5pbnNlcnQoWzEuMCwgMi4wLCAuLi5dLCB7IHNvdXJjZTogJ3dlYicgfSk7XG4gKiBjb25zdCByZXN1bHRzID0gYXdhaXQgY29sbGVjdGlvbi5zZWFyY2gocXVlcnlWZWN0b3IsIDEwKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB7IFNvY2hEQkVycm9yLCBEYXRhYmFzZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBOYW1lc3BhY2UgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIE5hbWVzcGFjZUNvbmZpZyB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG4gIGxhYmVscz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIHJlYWRPbmx5PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIE5hbWVzcGFjZU5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG5hbWVzcGFjZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoYE5hbWVzcGFjZSBub3QgZm91bmQ6ICR7bmFtZXNwYWNlfWApO1xuICAgIHRoaXMubmFtZSA9ICdOYW1lc3BhY2VOb3RGb3VuZEVycm9yJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTmFtZXNwYWNlRXhpc3RzRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG5hbWVzcGFjZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoYE5hbWVzcGFjZSBhbHJlYWR5IGV4aXN0czogJHtuYW1lc3BhY2V9YCk7XG4gICAgdGhpcy5uYW1lID0gJ05hbWVzcGFjZUV4aXN0c0Vycm9yJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbk5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGNvbGxlY3Rpb246IHN0cmluZykge1xuICAgIHN1cGVyKGBDb2xsZWN0aW9uIG5vdCBmb3VuZDogJHtjb2xsZWN0aW9ufWApO1xuICAgIHRoaXMubmFtZSA9ICdDb2xsZWN0aW9uTm90Rm91bmRFcnJvcic7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENvbGxlY3Rpb25FeGlzdHNFcnJvciBleHRlbmRzIFNvY2hEQkVycm9yIHtcbiAgY29uc3RydWN0b3IoY29sbGVjdGlvbjogc3RyaW5nKSB7XG4gICAgc3VwZXIoYENvbGxlY3Rpb24gYWxyZWFkeSBleGlzdHM6ICR7Y29sbGVjdGlvbn1gKTtcbiAgICB0aGlzLm5hbWUgPSAnQ29sbGVjdGlvbkV4aXN0c0Vycm9yJztcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb2xsZWN0aW9uIENvbmZpZ3VyYXRpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGVudW0gRGlzdGFuY2VNZXRyaWMge1xuICBDb3NpbmUgPSAnY29zaW5lJyxcbiAgRXVjbGlkZWFuID0gJ2V1Y2xpZGVhbicsXG4gIERvdFByb2R1Y3QgPSAnZG90Jyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uQ29uZmlnIHtcbiAgbmFtZTogc3RyaW5nO1xuICBkaW1lbnNpb24/OiBudW1iZXI7XG4gIG1ldHJpYz86IERpc3RhbmNlTWV0cmljO1xuICBpbmRleGVkPzogYm9vbGVhbjtcbiAgaG5zd00/OiBudW1iZXI7XG4gIGhuc3dFZkNvbnN0cnVjdGlvbj86IG51bWJlcjtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlYXJjaFJlcXVlc3Qge1xuICBxdWVyeVZlY3RvcjogbnVtYmVyW107XG4gIGs6IG51bWJlcjtcbiAgZmlsdGVyPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgaW5jbHVkZU1ldGFkYXRhPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWFyY2hSZXN1bHQge1xuICBpZDogc3RyaW5nO1xuICBzY29yZTogbnVtYmVyO1xuICB2ZWN0b3I/OiBudW1iZXJbXTtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb2xsZWN0aW9uIEhhbmRsZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZGI6IGFueSxcbiAgICBwcml2YXRlIG5hbWVzcGFjZTogc3RyaW5nLFxuICAgIHByaXZhdGUgbmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgY29uZmlnOiBDb2xsZWN0aW9uQ29uZmlnXG4gICkge31cblxuICAvKipcbiAgICogSW5zZXJ0IGEgdmVjdG9yIHdpdGggb3B0aW9uYWwgbWV0YWRhdGFcbiAgICovXG4gIGFzeW5jIGluc2VydChcbiAgICB2ZWN0b3I6IG51bWJlcltdLFxuICAgIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBpZD86IHN0cmluZ1xuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICh0aGlzLmNvbmZpZy5kaW1lbnNpb24gJiYgdmVjdG9yLmxlbmd0aCAhPT0gdGhpcy5jb25maWcuZGltZW5zaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcihcbiAgICAgICAgYFZlY3RvciBkaW1lbnNpb24gbWlzbWF0Y2g6IGV4cGVjdGVkICR7dGhpcy5jb25maWcuZGltZW5zaW9ufSwgZ290ICR7dmVjdG9yLmxlbmd0aH1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHZlY3RvcklkID0gaWQgfHwgdGhpcy5nZW5lcmF0ZUlkKCk7XG4gICAgY29uc3Qga2V5ID0gdGhpcy52ZWN0b3JLZXkodmVjdG9ySWQpO1xuICAgIFxuICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICB2ZWN0b3IsXG4gICAgICBtZXRhZGF0YTogbWV0YWRhdGEgfHwge30sXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgfTtcblxuICAgIGF3YWl0IHRoaXMuZGIucHV0KEJ1ZmZlci5mcm9tKGtleSksIEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KGRhdGEpKSk7XG4gICAgcmV0dXJuIHZlY3RvcklkO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydCBtdWx0aXBsZSB2ZWN0b3JzXG4gICAqL1xuICBhc3luYyBpbnNlcnRNYW55KFxuICAgIHZlY3RvcnM6IG51bWJlcltdW10sXG4gICAgbWV0YWRhdGFzPzogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIGlkcz86IHN0cmluZ1tdXG4gICk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCByZXN1bHRJZHM6IHN0cmluZ1tdID0gW107XG4gICAgXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpZCA9IGlkcyA/IGlkc1tpXSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gbWV0YWRhdGFzID8gbWV0YWRhdGFzW2ldIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcmVzdWx0SWQgPSBhd2FpdCB0aGlzLmluc2VydCh2ZWN0b3JzW2ldLCBtZXRhZGF0YSwgaWQpO1xuICAgICAgcmVzdWx0SWRzLnB1c2gocmVzdWx0SWQpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gcmVzdWx0SWRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlYXJjaCBmb3Igc2ltaWxhciB2ZWN0b3JzXG4gICAqL1xuICBhc3luYyBzZWFyY2gocmVxdWVzdDogU2VhcmNoUmVxdWVzdCk6IFByb21pc2U8U2VhcmNoUmVzdWx0W10+IHtcbiAgICAvLyBGb3Igbm93LCBpbXBsZW1lbnQgYmFzaWMgbGluZWFyIHNlYXJjaFxuICAgIC8vIEluIHByb2R1Y3Rpb24sIHRoaXMgd291bGQgdXNlIEhOU1cgaW5kZXhcbiAgICBjb25zdCByZXN1bHRzOiBTZWFyY2hSZXN1bHRbXSA9IFtdO1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMudmVjdG9yS2V5UHJlZml4KCk7XG4gICAgXG4gICAgLy8gU2NhbiBhbGwgdmVjdG9ycyBpbiBjb2xsZWN0aW9uXG4gICAgY29uc3QgYWxsVmVjdG9yczogQXJyYXk8eyBpZDogc3RyaW5nOyB2ZWN0b3I6IG51bWJlcltdOyBtZXRhZGF0YT86IGFueTsgc2NvcmU6IG51bWJlciB9PiA9IFtdO1xuICAgIFxuICAgIC8vIFRPRE86IEltcGxlbWVudCBlZmZpY2llbnQgc2Nhbm5pbmcgd2l0aCByYW5nZSBxdWVyaWVzXG4gICAgLy8gRm9yIG5vdywgdGhpcyBpcyBhIHBsYWNlaG9sZGVyIHRoYXQgc2hvd3MgdGhlIEFQSSBzdHJ1Y3R1cmVcbiAgICBcbiAgICAvLyBTb3J0IGJ5IHNpbWlsYXJpdHkgc2NvcmVcbiAgICBhbGxWZWN0b3JzLnNvcnQoKGEsIGIpID0+IGIuc2NvcmUgLSBhLnNjb3JlKTtcbiAgICBcbiAgICAvLyBSZXR1cm4gdG9wLWsgcmVzdWx0c1xuICAgIHJldHVybiBhbGxWZWN0b3JzLnNsaWNlKDAsIHJlcXVlc3QuaykubWFwKHYgPT4gKHtcbiAgICAgIGlkOiB2LmlkLFxuICAgICAgc2NvcmU6IHYuc2NvcmUsXG4gICAgICB2ZWN0b3I6IHJlcXVlc3QuaW5jbHVkZU1ldGFkYXRhID8gdi52ZWN0b3IgOiB1bmRlZmluZWQsXG4gICAgICBtZXRhZGF0YTogcmVxdWVzdC5pbmNsdWRlTWV0YWRhdGEgPyB2Lm1ldGFkYXRhIDogdW5kZWZpbmVkLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSB2ZWN0b3IgYnkgSURcbiAgICovXG4gIGFzeW5jIGdldChpZDogc3RyaW5nKTogUHJvbWlzZTx7IHZlY3RvcjogbnVtYmVyW107IG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PiB9IHwgbnVsbD4ge1xuICAgIGNvbnN0IGtleSA9IHRoaXMudmVjdG9yS2V5KGlkKTtcbiAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHRoaXMuZGIuZ2V0KEJ1ZmZlci5mcm9tKGtleSkpO1xuICAgIFxuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcbiAgICByZXR1cm4ge1xuICAgICAgdmVjdG9yOiBkYXRhLnZlY3RvcixcbiAgICAgIG1ldGFkYXRhOiBkYXRhLm1ldGFkYXRhLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlIGEgdmVjdG9yIGJ5IElEXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGtleSA9IHRoaXMudmVjdG9yS2V5KGlkKTtcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShCdWZmZXIuZnJvbShrZXkpKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3VudCB2ZWN0b3JzIGluIGNvbGxlY3Rpb25cbiAgICovXG4gIGFzeW5jIGNvdW50KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgLy8gVE9ETzogSW1wbGVtZW50IGVmZmljaWVudCBjb3VudGluZ1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgLy8gSGVscGVyIG1ldGhvZHNcbiAgcHJpdmF0ZSB2ZWN0b3JLZXkoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBfY29sbGVjdGlvbi8ke3RoaXMubmFtZXNwYWNlfS8ke3RoaXMubmFtZX0vdmVjdG9ycy8ke2lkfWA7XG4gIH1cblxuICBwcml2YXRlIHZlY3RvcktleVByZWZpeCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgX2NvbGxlY3Rpb24vJHt0aGlzLm5hbWVzcGFjZX0vJHt0aGlzLm5hbWV9L3ZlY3RvcnMvYDtcbiAgfVxuXG4gIHByaXZhdGUgbWV0YWRhdGFLZXkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lc3BhY2V9LyR7dGhpcy5uYW1lfS9tZXRhZGF0YWA7XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcbiAgfVxuXG4gIC8vIENhbGN1bGF0ZSBjb3NpbmUgc2ltaWxhcml0eVxuICBwcml2YXRlIGNvc2luZVNpbWlsYXJpdHkoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBsZXQgZG90UHJvZHVjdCA9IDA7XG4gICAgbGV0IG5vcm1BID0gMDtcbiAgICBsZXQgbm9ybUIgPSAwO1xuICAgIFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgZG90UHJvZHVjdCArPSBhW2ldICogYltpXTtcbiAgICAgIG5vcm1BICs9IGFbaV0gKiBhW2ldO1xuICAgICAgbm9ybUIgKz0gYltpXSAqIGJbaV07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBkb3RQcm9kdWN0IC8gKE1hdGguc3FydChub3JtQSkgKiBNYXRoLnNxcnQobm9ybUIpKTtcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBOYW1lc3BhY2UgSGFuZGxlXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBOYW1lc3BhY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGRiOiBhbnksXG4gICAgcHJpdmF0ZSBuYW1lOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSBjb25maWc6IE5hbWVzcGFjZUNvbmZpZ1xuICApIHt9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBjb2xsZWN0aW9uIGluIHRoaXMgbmFtZXNwYWNlXG4gICAqL1xuICBhc3luYyBjcmVhdGVDb2xsZWN0aW9uKGNvbmZpZzogQ29sbGVjdGlvbkNvbmZpZyk6IFByb21pc2U8Q29sbGVjdGlvbj4ge1xuICAgIGNvbnN0IG1ldGFkYXRhS2V5ID0gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lfS8ke2NvbmZpZy5uYW1lfS9tZXRhZGF0YWA7XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgY29sbGVjdGlvbiBhbHJlYWR5IGV4aXN0c1xuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy5kYi5nZXQoQnVmZmVyLmZyb20obWV0YWRhdGFLZXkpKTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRocm93IG5ldyBDb2xsZWN0aW9uRXhpc3RzRXJyb3IoY29uZmlnLm5hbWUpO1xuICAgIH1cblxuICAgIC8vIFN0b3JlIGNvbGxlY3Rpb24gbWV0YWRhdGFcbiAgICBjb25zdCBtZXRhZGF0YSA9IHtcbiAgICAgIC4uLmNvbmZpZyxcbiAgICAgIGNyZWF0ZWRBdDogRGF0ZS5ub3coKSxcbiAgICB9O1xuICAgIFxuICAgIGF3YWl0IHRoaXMuZGIucHV0KFxuICAgICAgQnVmZmVyLmZyb20obWV0YWRhdGFLZXkpLFxuICAgICAgQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpKVxuICAgICk7XG5cbiAgICByZXR1cm4gbmV3IENvbGxlY3Rpb24odGhpcy5kYiwgdGhpcy5uYW1lLCBjb25maWcubmFtZSwgY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYW4gZXhpc3RpbmcgY29sbGVjdGlvblxuICAgKi9cbiAgYXN5bmMgY29sbGVjdGlvbihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPENvbGxlY3Rpb24+IHtcbiAgICBjb25zdCBtZXRhZGF0YUtleSA9IGBfY29sbGVjdGlvbi8ke3RoaXMubmFtZX0vJHtuYW1lfS9tZXRhZGF0YWA7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBhd2FpdCB0aGlzLmRiLmdldChCdWZmZXIuZnJvbShtZXRhZGF0YUtleSkpO1xuICAgIFxuICAgIGlmICghbWV0YWRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBDb2xsZWN0aW9uTm90Rm91bmRFcnJvcihuYW1lKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWcgPSBKU09OLnBhcnNlKG1ldGFkYXRhLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiBuZXcgQ29sbGVjdGlvbih0aGlzLmRiLCB0aGlzLm5hbWUsIG5hbWUsIGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IG9yIGNyZWF0ZSBhIGNvbGxlY3Rpb25cbiAgICovXG4gIGFzeW5jIGdldE9yQ3JlYXRlQ29sbGVjdGlvbihjb25maWc6IENvbGxlY3Rpb25Db25maWcpOiBQcm9taXNlPENvbGxlY3Rpb24+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29sbGVjdGlvbihjb25maWcubmFtZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIENvbGxlY3Rpb25Ob3RGb3VuZEVycm9yKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNyZWF0ZUNvbGxlY3Rpb24oY29uZmlnKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBjb2xsZWN0aW9uXG4gICAqL1xuICBhc3luYyBkZWxldGVDb2xsZWN0aW9uKG5hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IG1ldGFkYXRhS2V5ID0gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lfS8ke25hbWV9L21ldGFkYXRhYDtcbiAgICBjb25zdCBwcmVmaXggPSBgX2NvbGxlY3Rpb24vJHt0aGlzLm5hbWV9LyR7bmFtZX0vYDtcbiAgICBcbiAgICAvLyBUT0RPOiBEZWxldGUgYWxsIGtleXMgd2l0aCBwcmVmaXhcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShCdWZmZXIuZnJvbShtZXRhZGF0YUtleSkpO1xuICAgIFxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgYWxsIGNvbGxlY3Rpb25zIGluIHRoaXMgbmFtZXNwYWNlXG4gICAqL1xuICBhc3luYyBsaXN0Q29sbGVjdGlvbnMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIC8vIFRPRE86IEltcGxlbWVudCBlZmZpY2llbnQgbGlzdGluZyB3aXRoIHJhbmdlIHF1ZXJpZXNcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgfVxuXG4gIGdldENvbmZpZygpOiBOYW1lc3BhY2VDb25maWcge1xuICAgIHJldHVybiB7IC4uLnRoaXMuY29uZmlnIH07XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SochDB Priority Queue
|
|
4
|
+
*
|
|
5
|
+
* First-class queue API with ordered-key task entries, providing efficient
|
|
6
|
+
* priority queue operations without the O(N) blob rewrite anti-pattern.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Ordered-key representation: Each task has its own key, no blob parsing
|
|
10
|
+
* - O(log N) enqueue/dequeue with ordered scans
|
|
11
|
+
* - Atomic claim protocol for concurrent workers
|
|
12
|
+
* - Visibility timeout for crash recovery
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { Database, PriorityQueue } from '@sochdb/sochdb';
|
|
17
|
+
*
|
|
18
|
+
* const db = await Database.open('./queue_db');
|
|
19
|
+
* const queue = PriorityQueue.fromDatabase(db, 'tasks');
|
|
20
|
+
*
|
|
21
|
+
* // Enqueue task
|
|
22
|
+
* await queue.enqueue(1, Buffer.from('high priority task'));
|
|
23
|
+
*
|
|
24
|
+
* // Dequeue and process
|
|
25
|
+
* const task = await queue.dequeue('worker-1');
|
|
26
|
+
* if (task) {
|
|
27
|
+
* // Process task...
|
|
28
|
+
* await queue.ack(task.taskId);
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.PriorityQueue = exports.TaskState = void 0;
|
|
34
|
+
exports.createQueue = createQueue;
|
|
35
|
+
const errors_1 = require("./errors");
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Task State
|
|
38
|
+
// ============================================================================
|
|
39
|
+
var TaskState;
|
|
40
|
+
(function (TaskState) {
|
|
41
|
+
TaskState["PENDING"] = "pending";
|
|
42
|
+
TaskState["CLAIMED"] = "claimed";
|
|
43
|
+
TaskState["COMPLETED"] = "completed";
|
|
44
|
+
TaskState["DEAD_LETTERED"] = "dead_lettered";
|
|
45
|
+
})(TaskState || (exports.TaskState = TaskState = {}));
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Queue Key Encoding
|
|
48
|
+
// ============================================================================
|
|
49
|
+
/**
|
|
50
|
+
* Encode u64 as big-endian for lexicographic ordering
|
|
51
|
+
*/
|
|
52
|
+
function encodeU64BE(value) {
|
|
53
|
+
const buf = Buffer.allocUnsafe(8);
|
|
54
|
+
buf.writeBigUInt64BE(BigInt(value));
|
|
55
|
+
return buf;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Decode big-endian u64
|
|
59
|
+
*/
|
|
60
|
+
function decodeU64BE(buf) {
|
|
61
|
+
return Number(buf.readBigUInt64BE(0));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Encode i64 as big-endian preserving order
|
|
65
|
+
*/
|
|
66
|
+
function encodeI64BE(value) {
|
|
67
|
+
// Map i64 to u64 by adding offset
|
|
68
|
+
const mapped = BigInt(value) + (1n << 63n);
|
|
69
|
+
const buf = Buffer.allocUnsafe(8);
|
|
70
|
+
buf.writeBigUInt64BE(mapped);
|
|
71
|
+
return buf;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Decode big-endian i64
|
|
75
|
+
*/
|
|
76
|
+
function decodeI64BE(buf) {
|
|
77
|
+
const mapped = buf.readBigUInt64BE(0);
|
|
78
|
+
return Number(mapped - (1n << 63n));
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Encode queue key to bytes for storage
|
|
82
|
+
*/
|
|
83
|
+
function encodeQueueKey(key) {
|
|
84
|
+
const parts = [
|
|
85
|
+
Buffer.from('queue/'),
|
|
86
|
+
Buffer.from(key.queueId),
|
|
87
|
+
Buffer.from('/'),
|
|
88
|
+
encodeI64BE(key.priority),
|
|
89
|
+
Buffer.from('/'),
|
|
90
|
+
encodeU64BE(key.readyTs),
|
|
91
|
+
Buffer.from('/'),
|
|
92
|
+
encodeU64BE(key.sequence),
|
|
93
|
+
Buffer.from('/'),
|
|
94
|
+
Buffer.from(key.taskId),
|
|
95
|
+
];
|
|
96
|
+
return Buffer.concat(parts);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Decode queue key from bytes
|
|
100
|
+
*/
|
|
101
|
+
function decodeQueueKey(data) {
|
|
102
|
+
const str = data.toString();
|
|
103
|
+
const parts = str.split('/');
|
|
104
|
+
if (parts.length < 6 || parts[0] !== 'queue') {
|
|
105
|
+
throw new errors_1.SochDBError('Invalid queue key format');
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
queueId: parts[1],
|
|
109
|
+
priority: 0, // Would need to decode from bytes
|
|
110
|
+
readyTs: 0,
|
|
111
|
+
sequence: 0,
|
|
112
|
+
taskId: parts[parts.length - 1],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Priority Queue
|
|
117
|
+
// ============================================================================
|
|
118
|
+
class PriorityQueue {
|
|
119
|
+
constructor(db, config) {
|
|
120
|
+
this.db = db;
|
|
121
|
+
this.config = config;
|
|
122
|
+
// Set defaults
|
|
123
|
+
this.config.visibilityTimeout = config.visibilityTimeout || 30000;
|
|
124
|
+
this.config.maxRetries = config.maxRetries || 3;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Create queue from embedded database
|
|
128
|
+
*/
|
|
129
|
+
static fromDatabase(db, name, config) {
|
|
130
|
+
const fullConfig = {
|
|
131
|
+
name,
|
|
132
|
+
...config,
|
|
133
|
+
};
|
|
134
|
+
return new PriorityQueue(db, fullConfig);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create queue from gRPC client
|
|
138
|
+
*/
|
|
139
|
+
static fromClient(client, name, config) {
|
|
140
|
+
const fullConfig = {
|
|
141
|
+
name,
|
|
142
|
+
...config,
|
|
143
|
+
};
|
|
144
|
+
return new PriorityQueue(client, fullConfig);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Enqueue a task with priority
|
|
148
|
+
* Lower priority number = higher urgency
|
|
149
|
+
*/
|
|
150
|
+
async enqueue(priority, payload, metadata) {
|
|
151
|
+
const taskId = this.generateTaskId();
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
const key = {
|
|
154
|
+
queueId: this.config.name,
|
|
155
|
+
priority,
|
|
156
|
+
readyTs: now,
|
|
157
|
+
sequence: PriorityQueue.sequenceCounter++,
|
|
158
|
+
taskId,
|
|
159
|
+
};
|
|
160
|
+
const task = {
|
|
161
|
+
taskId,
|
|
162
|
+
priority,
|
|
163
|
+
payload,
|
|
164
|
+
state: TaskState.PENDING,
|
|
165
|
+
enqueuedAt: now,
|
|
166
|
+
retries: 0,
|
|
167
|
+
metadata,
|
|
168
|
+
};
|
|
169
|
+
const keyBuf = encodeQueueKey(key);
|
|
170
|
+
const valueBuf = Buffer.from(JSON.stringify(task));
|
|
171
|
+
await this.db.put(keyBuf, valueBuf);
|
|
172
|
+
// Update stats
|
|
173
|
+
await this.incrementStat('totalEnqueued');
|
|
174
|
+
await this.incrementStat('pending');
|
|
175
|
+
return taskId;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Dequeue the highest priority task
|
|
179
|
+
* Returns null if no tasks available
|
|
180
|
+
*/
|
|
181
|
+
async dequeue(workerId) {
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const prefix = `queue/${this.config.name}/`;
|
|
184
|
+
// TODO: Implement range scan to find first ready task
|
|
185
|
+
// For now, this is a placeholder
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Acknowledge task completion
|
|
190
|
+
*/
|
|
191
|
+
async ack(taskId) {
|
|
192
|
+
// Find and update task state
|
|
193
|
+
const task = await this.getTask(taskId);
|
|
194
|
+
if (!task) {
|
|
195
|
+
throw new errors_1.SochDBError(`Task not found: ${taskId}`);
|
|
196
|
+
}
|
|
197
|
+
if (task.state !== TaskState.CLAIMED) {
|
|
198
|
+
throw new errors_1.SochDBError(`Task not in claimed state: ${taskId}`);
|
|
199
|
+
}
|
|
200
|
+
// Update task state
|
|
201
|
+
task.state = TaskState.COMPLETED;
|
|
202
|
+
task.completedAt = Date.now();
|
|
203
|
+
await this.updateTask(task);
|
|
204
|
+
// Update stats
|
|
205
|
+
await this.decrementStat('claimed');
|
|
206
|
+
await this.incrementStat('completed');
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Negative acknowledge - return task to queue
|
|
210
|
+
*/
|
|
211
|
+
async nack(taskId) {
|
|
212
|
+
const task = await this.getTask(taskId);
|
|
213
|
+
if (!task) {
|
|
214
|
+
throw new errors_1.SochDBError(`Task not found: ${taskId}`);
|
|
215
|
+
}
|
|
216
|
+
task.retries++;
|
|
217
|
+
if (task.retries >= (this.config.maxRetries || 3)) {
|
|
218
|
+
// Move to dead letter queue
|
|
219
|
+
task.state = TaskState.DEAD_LETTERED;
|
|
220
|
+
await this.updateTask(task);
|
|
221
|
+
await this.decrementStat('claimed');
|
|
222
|
+
await this.incrementStat('deadLettered');
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// Return to pending
|
|
226
|
+
task.state = TaskState.PENDING;
|
|
227
|
+
task.claimedAt = undefined;
|
|
228
|
+
task.claimedBy = undefined;
|
|
229
|
+
await this.updateTask(task);
|
|
230
|
+
await this.decrementStat('claimed');
|
|
231
|
+
await this.incrementStat('pending');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get queue statistics
|
|
236
|
+
*/
|
|
237
|
+
async stats() {
|
|
238
|
+
return {
|
|
239
|
+
pending: await this.getStat('pending'),
|
|
240
|
+
claimed: await this.getStat('claimed'),
|
|
241
|
+
completed: await this.getStat('completed'),
|
|
242
|
+
deadLettered: await this.getStat('deadLettered'),
|
|
243
|
+
totalEnqueued: await this.getStat('totalEnqueued'),
|
|
244
|
+
totalDequeued: await this.getStat('totalDequeued'),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Purge completed tasks
|
|
249
|
+
*/
|
|
250
|
+
async purge() {
|
|
251
|
+
// TODO: Implement purging of completed tasks
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
// Helper methods
|
|
255
|
+
generateTaskId() {
|
|
256
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
257
|
+
}
|
|
258
|
+
async getTask(taskId) {
|
|
259
|
+
// TODO: Implement task lookup
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
async updateTask(task) {
|
|
263
|
+
// TODO: Implement task update
|
|
264
|
+
}
|
|
265
|
+
async getStat(name) {
|
|
266
|
+
const key = `_queue_stats/${this.config.name}/${name}`;
|
|
267
|
+
const value = await this.db.get(Buffer.from(key));
|
|
268
|
+
return value ? parseInt(value.toString()) : 0;
|
|
269
|
+
}
|
|
270
|
+
async incrementStat(name) {
|
|
271
|
+
const current = await this.getStat(name);
|
|
272
|
+
const key = `_queue_stats/${this.config.name}/${name}`;
|
|
273
|
+
await this.db.put(Buffer.from(key), Buffer.from((current + 1).toString()));
|
|
274
|
+
}
|
|
275
|
+
async decrementStat(name) {
|
|
276
|
+
const current = await this.getStat(name);
|
|
277
|
+
const key = `_queue_stats/${this.config.name}/${name}`;
|
|
278
|
+
await this.db.put(Buffer.from(key), Buffer.from(Math.max(0, current - 1).toString()));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
exports.PriorityQueue = PriorityQueue;
|
|
282
|
+
PriorityQueue.sequenceCounter = 0;
|
|
283
|
+
/**
|
|
284
|
+
* Create a queue instance
|
|
285
|
+
*/
|
|
286
|
+
function createQueue(db, name, config) {
|
|
287
|
+
return PriorityQueue.fromDatabase(db, name, config);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVldWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcXVldWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRzs7O0FBZ1dILGtDQU1DO0FBcFdELHFDQUF1QztBQUV2QywrRUFBK0U7QUFDL0UsYUFBYTtBQUNiLCtFQUErRTtBQUUvRSxJQUFZLFNBS1g7QUFMRCxXQUFZLFNBQVM7SUFDbkIsZ0NBQW1CLENBQUE7SUFDbkIsZ0NBQW1CLENBQUE7SUFDbkIsb0NBQXVCLENBQUE7SUFDdkIsNENBQStCLENBQUE7QUFDakMsQ0FBQyxFQUxXLFNBQVMseUJBQVQsU0FBUyxRQUtwQjtBQWFELCtFQUErRTtBQUMvRSxxQkFBcUI7QUFDckIsK0VBQStFO0FBRS9FOztHQUVHO0FBQ0gsU0FBUyxXQUFXLENBQUMsS0FBYTtJQUNoQyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwQyxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsV0FBVyxDQUFDLEdBQVc7SUFDOUIsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsV0FBVyxDQUFDLEtBQWE7SUFDaEMsa0NBQWtDO0lBQ2xDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJ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QUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRU8sS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFZO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QyxNQUFNLEdBQUcsR0FBRyxnQkFBZ0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkQsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RixDQUFDOztBQW5NSCxzQ0FvTUM7QUFuTWdCLDZCQUFlLEdBQUcsQ0FBQyxDQUFDO0FBcU1yQzs7R0FFRztBQUNILFNBQWdCLFdBQVcsQ0FDekIsRUFBTyxFQUNQLElBQVksRUFDWixNQUE2QjtJQUU3QixPQUFPLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztBQUN0RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTb2NoREIgUHJpb3JpdHkgUXVldWVcbiAqIFxuICogRmlyc3QtY2xhc3MgcXVldWUgQVBJIHdpdGggb3JkZXJlZC1rZXkgdGFzayBlbnRyaWVzLCBwcm92aWRpbmcgZWZmaWNpZW50XG4gKiBwcmlvcml0eSBxdWV1ZSBvcGVyYXRpb25zIHdpdGhvdXQgdGhlIE8oTikgYmxvYiByZXdyaXRlIGFudGktcGF0dGVybi5cbiAqIFxuICogRmVhdHVyZXM6XG4gKiAtIE9yZGVyZWQta2V5IHJlcHJlc2VudGF0aW9uOiBFYWNoIHRhc2sgaGFzIGl0cyBvd24ga2V5LCBubyBibG9iIHBhcnNpbmdcbiAqIC0gTyhsb2cgTikgZW5xdWV1ZS9kZXF1ZXVlIHdpdGggb3JkZXJlZCBzY2Fuc1xuICogLSBBdG9taWMgY2xhaW0gcHJvdG9jb2wgZm9yIGNvbmN1cnJlbnQgd29ya2Vyc1xuICogLSBWaXNpYmlsaXR5IHRpbWVvdXQgZm9yIGNyYXNoIHJlY292ZXJ5XG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBEYXRhYmFzZSwgUHJpb3JpdHlRdWV1ZSB9IGZyb20gJ0Bzb2NoZGIvc29jaGRiJztcbiAqIFxuICogY29uc3QgZGIgPSBhd2FpdCBEYXRhYmFzZS5vcGVuKCcuL3F1ZXVlX2RiJyk7XG4gKiBjb25zdCBxdWV1ZSA9IFByaW9yaXR5UXVldWUuZnJvbURhdGFiYXNlKGRiLCAndGFza3MnKTtcbiAqIFxuICogLy8gRW5xdWV1ZSB0YXNrXG4gKiBhd2FpdCBxdWV1ZS5lbnF1ZXVlKDEsIEJ1ZmZlci5mcm9tKCdoaWdoIHByaW9yaXR5IHRhc2snKSk7XG4gKiBcbiAqIC8vIERlcXVldWUgYW5kIHByb2Nlc3NcbiAqIGNvbnN0IHRhc2sgPSBhd2FpdCBxdWV1ZS5kZXF1ZXVlKCd3b3JrZXItMScpO1xuICogaWYgKHRhc2spIHtcbiAqICAgLy8gUHJvY2VzcyB0YXNrLi4uXG4gKiAgIGF3YWl0IHF1ZXVlLmFjayh0YXNrLnRhc2tJZCk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBTb2NoREJFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVGFzayBTdGF0ZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgZW51bSBUYXNrU3RhdGUge1xuICBQRU5ESU5HID0gJ3BlbmRpbmcnLFxuICBDTEFJTUVEID0gJ2NsYWltZWQnLFxuICBDT01QTEVURUQgPSAnY29tcGxldGVkJyxcbiAgREVBRF9MRVRURVJFRCA9ICdkZWFkX2xldHRlcmVkJyxcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUXVldWUgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXVlQ29uZmlnIHtcbiAgbmFtZTogc3RyaW5nO1xuICB2aXNpYmlsaXR5VGltZW91dD86IG51bWJlcjsgLy8gbWlsbGlzZWNvbmRzLCBkZWZhdWx0IDMwMDAwXG4gIG1heFJldHJpZXM/OiBudW1iZXI7IC8vIGRlZmF1bHQgM1xuICBkZWFkTGV0dGVyUXVldWU/OiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFF1ZXVlIEtleSBFbmNvZGluZ1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEVuY29kZSB1NjQgYXMgYmlnLWVuZGlhbiBmb3IgbGV4aWNvZ3JhcGhpYyBvcmRlcmluZ1xuICovXG5mdW5jdGlvbiBlbmNvZGVVNjRCRSh2YWx1ZTogbnVtYmVyKTogQnVmZmVyIHtcbiAgY29uc3QgYnVmID0gQnVmZmVyLmFsbG9jVW5zYWZlKDgpO1xuICBidWYud3JpdGVCaWdVSW50NjRCRShCaWdJbnQodmFsdWUpKTtcbiAgcmV0dXJuIGJ1Zjtcbn1cblxuLyoqXG4gKiBEZWNvZGUgYmlnLWVuZGlhbiB1NjRcbiAqL1xuZnVuY3Rpb24gZGVjb2RlVTY0QkUoYnVmOiBCdWZmZXIpOiBudW1iZXIge1xuICByZXR1cm4gTnVtYmVyKGJ1Zi5yZWFkQmlnVUludDY0QkUoMCkpO1xufVxuXG4vKipcbiAqIEVuY29kZSBpNjQgYXMgYmlnLWVuZGlhbiBwcmVzZXJ2aW5nIG9yZGVyXG4gKi9cbmZ1bmN0aW9uIGVuY29kZUk2NEJFKHZhbHVlOiBudW1iZXIpOiBCdWZmZXIge1xuICAvLyBNYXAgaTY0IHRvIHU2NCBieSBhZGRpbmcgb2Zmc2V0XG4gIGNvbnN0IG1hcHBlZCA9IEJpZ0ludCh2YWx1ZSkgKyAoMW4gPDwgNjNuKTtcbiAgY29uc3QgYnVmID0gQnVmZmVyLmFsbG9jVW5zYWZlKDgpO1xuICBidWYud3JpdGVCaWdVSW50NjRCRShtYXBwZWQpO1xuICByZXR1cm4gYnVmO1xufVxuXG4vKipcbiAqIERlY29kZSBiaWctZW5kaWFuIGk2NFxuICovXG5mdW5jdGlvbiBkZWNvZGVJNjRCRShidWY6IEJ1ZmZlcik6IG51bWJlciB7XG4gIGNvbnN0IG1hcHBlZCA9IGJ1Zi5yZWFkQmlnVUludDY0QkUoMCk7XG4gIHJldHVybiBOdW1iZXIobWFwcGVkIC0gKDFuIDw8IDYzbikpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBRdWV1ZSBLZXlcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdWV1ZUtleSB7XG4gIHF1ZXVlSWQ6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgcmVhZHlUczogbnVtYmVyOyAvLyB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzXG4gIHNlcXVlbmNlOiBudW1iZXI7XG4gIHRhc2tJZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEVuY29kZSBxdWV1ZSBrZXkgdG8gYnl0ZXMgZm9yIHN0b3JhZ2VcbiAqL1xuZnVuY3Rpb24gZW5jb2RlUXVldWVLZXkoa2V5OiBRdWV1ZUtleSk6IEJ1ZmZlciB7XG4gIGNvbnN0IHBhcnRzID0gW1xuICAgIEJ1ZmZlci5mcm9tKCdxdWV1ZS8nKSxcbiAgICBCdWZmZXIuZnJvbShrZXkucXVldWVJZCksXG4gICAgQnVmZmVyLmZyb20oJy8nKSxcbiAgICBlbmNvZGVJNjRCRShrZXkucHJpb3JpdHkpLFxuICAgIEJ1ZmZlci5mcm9tKCcvJyksXG4gICAgZW5jb2RlVTY0QkUoa2V5LnJlYWR5VHMpLFxuICAgIEJ1ZmZlci5mcm9tKCcvJyksXG4gICAgZW5jb2RlVTY0QkUoa2V5LnNlcXVlbmNlKSxcbiAgICBCdWZmZXIuZnJvbSgnLycpLFxuICAgIEJ1ZmZlci5mcm9tKGtleS50YXNrSWQpLFxuICBdO1xuICBcbiAgcmV0dXJuIEJ1ZmZlci5jb25jYXQocGFydHMpO1xufVxuXG4vKipcbiAqIERlY29kZSBxdWV1ZSBrZXkgZnJvbSBieXRlc1xuICovXG5mdW5jdGlvbiBkZWNvZGVRdWV1ZUtleShkYXRhOiBCdWZmZXIpOiBRdWV1ZUtleSB7XG4gIGNvbnN0IHN0ciA9IGRhdGEudG9TdHJpbmcoKTtcbiAgY29uc3QgcGFydHMgPSBzdHIuc3BsaXQoJy8nKTtcbiAgXG4gIGlmIChwYXJ0cy5sZW5ndGggPCA2IHx8IHBhcnRzWzBdICE9PSAncXVldWUnKSB7XG4gICAgdGhyb3cgbmV3IFNvY2hEQkVycm9yKCdJbnZhbGlkIHF1ZXVlIGtleSBmb3JtYXQnKTtcbiAgfVxuICBcbiAgcmV0dXJuIHtcbiAgICBxdWV1ZUlkOiBwYXJ0c1sxXSxcbiAgICBwcmlvcml0eTogMCwgLy8gV291bGQgbmVlZCB0byBkZWNvZGUgZnJvbSBieXRlc1xuICAgIHJlYWR5VHM6IDAsXG4gICAgc2VxdWVuY2U6IDAsXG4gICAgdGFza0lkOiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSxcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVGFza1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFRhc2sge1xuICB0YXNrSWQ6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgcGF5bG9hZDogQnVmZmVyO1xuICBzdGF0ZTogVGFza1N0YXRlO1xuICBlbnF1ZXVlZEF0OiBudW1iZXI7XG4gIGNsYWltZWRBdD86IG51bWJlcjtcbiAgY2xhaW1lZEJ5Pzogc3RyaW5nO1xuICBjb21wbGV0ZWRBdD86IG51bWJlcjtcbiAgcmV0cmllczogbnVtYmVyO1xuICBtZXRhZGF0YT86IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFF1ZXVlIFN0YXRpc3RpY3Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdWV1ZVN0YXRzIHtcbiAgcGVuZGluZzogbnVtYmVyO1xuICBjbGFpbWVkOiBudW1iZXI7XG4gIGNvbXBsZXRlZDogbnVtYmVyO1xuICBkZWFkTGV0dGVyZWQ6IG51bWJlcjtcbiAgdG90YWxFbnF1ZXVlZDogbnVtYmVyO1xuICB0b3RhbERlcXVldWVkOiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFByaW9yaXR5IFF1ZXVlXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBQcmlvcml0eVF1ZXVlIHtcbiAgcHJpdmF0ZSBzdGF0aWMgc2VxdWVuY2VDb3VudGVyID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGRiOiBhbnksXG4gICAgcHJpdmF0ZSBjb25maWc6IFF1ZXVlQ29uZmlnXG4gICkge1xuICAgIC8vIFNldCBkZWZhdWx0c1xuICAgIHRoaXMuY29uZmlnLnZpc2liaWxpdHlUaW1lb3V0ID0gY29uZmlnLnZpc2liaWxpdHlUaW1lb3V0IHx8IDMwMDAwO1xuICAgIHRoaXMuY29uZmlnLm1heFJldHJpZXMgPSBjb25maWcubWF4UmV0cmllcyB8fCAzO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBxdWV1ZSBmcm9tIGVtYmVkZGVkIGRhdGFiYXNlXG4gICAqL1xuICBzdGF0aWMgZnJvbURhdGFiYXNlKGRiOiBhbnksIG5hbWU6IHN0cmluZywgY29uZmlnPzogUGFydGlhbDxRdWV1ZUNvbmZpZz4pOiBQcmlvcml0eVF1ZXVlIHtcbiAgICBjb25zdCBmdWxsQ29uZmlnOiBRdWV1ZUNvbmZpZyA9IHtcbiAgICAgIG5hbWUsXG4gICAgICAuLi5jb25maWcsXG4gICAgfTtcbiAgICByZXR1cm4gbmV3IFByaW9yaXR5UXVldWUoZGIsIGZ1bGxDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBxdWV1ZSBmcm9tIGdSUEMgY2xpZW50XG4gICAqL1xuICBzdGF0aWMgZnJvbUNsaWVudChjbGllbnQ6IGFueSwgbmFtZTogc3RyaW5nLCBjb25maWc/OiBQYXJ0aWFsPFF1ZXVlQ29uZmlnPik6IFByaW9yaXR5UXVldWUge1xuICAgIGNvbnN0IGZ1bGxDb25maWc6IFF1ZXVlQ29uZmlnID0ge1xuICAgICAgbmFtZSxcbiAgICAgIC4uLmNvbmZpZyxcbiAgICB9O1xuICAgIHJldHVybiBuZXcgUHJpb3JpdHlRdWV1ZShjbGllbnQsIGZ1bGxDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVucXVldWUgYSB0YXNrIHdpdGggcHJpb3JpdHlcbiAgICogTG93ZXIgcHJpb3JpdHkgbnVtYmVyID0gaGlnaGVyIHVyZ2VuY3lcbiAgICovXG4gIGFzeW5jIGVucXVldWUoXG4gICAgcHJpb3JpdHk6IG51bWJlcixcbiAgICBwYXlsb2FkOiBCdWZmZXIsXG4gICAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgdGFza0lkID0gdGhpcy5nZW5lcmF0ZVRhc2tJZCgpO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgXG4gICAgY29uc3Qga2V5OiBRdWV1ZUtleSA9IHtcbiAgICAgIHF1ZXVlSWQ6IHRoaXMuY29uZmlnLm5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIHJlYWR5VHM6IG5vdyxcbiAgICAgIHNlcXVlbmNlOiBQcmlvcml0eVF1ZXVlLnNlcXVlbmNlQ291bnRlcisrLFxuICAgICAgdGFza0lkLFxuICAgIH07XG5cbiAgICBjb25zdCB0YXNrOiBUYXNrID0ge1xuICAgICAgdGFza0lkLFxuICAgICAgcHJpb3JpdHksXG4gICAgICBwYXlsb2FkLFxuICAgICAgc3RhdGU6IFRhc2tTdGF0ZS5QRU5ESU5HLFxuICAgICAgZW5xdWV1ZWRBdDogbm93LFxuICAgICAgcmV0cmllczogMCxcbiAgICAgIG1ldGFkYXRhLFxuICAgIH07XG5cbiAgICBjb25zdCBrZXlCdWYgPSBlbmNvZGVRdWV1ZUtleShrZXkpO1xuICAgIGNvbnN0IHZhbHVlQnVmID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkodGFzaykpO1xuICAgIFxuICAgIGF3YWl0IHRoaXMuZGIucHV0KGtleUJ1ZiwgdmFsdWVCdWYpO1xuICAgIFxuICAgIC8vIFVwZGF0ZSBzdGF0c1xuICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgndG90YWxFbnF1ZXVlZCcpO1xuICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgncGVuZGluZycpO1xuICAgIFxuICAgIHJldHVybiB0YXNrSWQ7XG4gIH1cblxuICAvKipcbiAgICogRGVxdWV1ZSB0aGUgaGlnaGVzdCBwcmlvcml0eSB0YXNrXG4gICAqIFJldHVybnMgbnVsbCBpZiBubyB0YXNrcyBhdmFpbGFibGVcbiAgICovXG4gIGFzeW5jIGRlcXVldWUod29ya2VySWQ6IHN0cmluZyk6IFByb21pc2U8VGFzayB8IG51bGw+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHByZWZpeCA9IGBxdWV1ZS8ke3RoaXMuY29uZmlnLm5hbWV9L2A7XG4gICAgXG4gICAgLy8gVE9ETzogSW1wbGVtZW50IHJhbmdlIHNjYW4gdG8gZmluZCBmaXJzdCByZWFkeSB0YXNrXG4gICAgLy8gRm9yIG5vdywgdGhpcyBpcyBhIHBsYWNlaG9sZGVyXG4gICAgXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQWNrbm93bGVkZ2UgdGFzayBjb21wbGV0aW9uXG4gICAqL1xuICBhc3luYyBhY2sodGFza0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBGaW5kIGFuZCB1cGRhdGUgdGFzayBzdGF0ZVxuICAgIGNvbnN0IHRhc2sgPSBhd2FpdCB0aGlzLmdldFRhc2sodGFza0lkKTtcbiAgICBpZiAoIXRhc2spIHtcbiAgICAgIHRocm93IG5ldyBTb2NoREJFcnJvcihgVGFzayBub3QgZm91bmQ6ICR7dGFza0lkfWApO1xuICAgIH1cblxuICAgIGlmICh0YXNrLnN0YXRlICE9PSBUYXNrU3RhdGUuQ0xBSU1FRCkge1xuICAgICAgdGhyb3cgbmV3IFNvY2hEQkVycm9yKGBUYXNrIG5vdCBpbiBjbGFpbWVkIHN0YXRlOiAke3Rhc2tJZH1gKTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgdGFzayBzdGF0ZVxuICAgIHRhc2suc3RhdGUgPSBUYXNrU3RhdGUuQ09NUExFVEVEO1xuICAgIHRhc2suY29tcGxldGVkQXQgPSBEYXRlLm5vdygpO1xuICAgIFxuICAgIGF3YWl0IHRoaXMudXBkYXRlVGFzayh0YXNrKTtcbiAgICBcbiAgICAvLyBVcGRhdGUgc3RhdHNcbiAgICBhd2FpdCB0aGlzLmRlY3JlbWVudFN0YXQoJ2NsYWltZWQnKTtcbiAgICBhd2FpdCB0aGlzLmluY3JlbWVudFN0YXQoJ2NvbXBsZXRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5lZ2F0aXZlIGFja25vd2xlZGdlIC0gcmV0dXJuIHRhc2sgdG8gcXVldWVcbiAgICovXG4gIGFzeW5jIG5hY2sodGFza0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0YXNrID0gYXdhaXQgdGhpcy5nZXRUYXNrKHRhc2tJZCk7XG4gICAgaWYgKCF0YXNrKSB7XG4gICAgICB0aHJvdyBuZXcgU29jaERCRXJyb3IoYFRhc2sgbm90IGZvdW5kOiAke3Rhc2tJZH1gKTtcbiAgICB9XG5cbiAgICB0YXNrLnJldHJpZXMrKztcbiAgICBcbiAgICBpZiAodGFzay5yZXRyaWVzID49ICh0aGlzLmNvbmZpZy5tYXhSZXRyaWVzIHx8IDMpKSB7XG4gICAgICAvLyBNb3ZlIHRvIGRlYWQgbGV0dGVyIHF1ZXVlXG4gICAgICB0YXNrLnN0YXRlID0gVGFza1N0YXRlLkRFQURfTEVUVEVSRUQ7XG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZVRhc2sodGFzayk7XG4gICAgICBhd2FpdCB0aGlzLmRlY3JlbWVudFN0YXQoJ2NsYWltZWQnKTtcbiAgICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgnZGVhZExldHRlcmVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJldHVybiB0byBwZW5kaW5nXG4gICAgICB0YXNrLnN0YXRlID0gVGFza1N0YXRlLlBFTkRJTkc7XG4gICAgICB0YXNrLmNsYWltZWRBdCA9IHVuZGVmaW5lZDtcbiAgICAgIHRhc2suY2xhaW1lZEJ5ID0gdW5kZWZpbmVkO1xuICAgICAgYXdhaXQgdGhpcy51cGRhdGVUYXNrKHRhc2spO1xuICAgICAgYXdhaXQgdGhpcy5kZWNyZW1lbnRTdGF0KCdjbGFpbWVkJyk7XG4gICAgICBhd2FpdCB0aGlzLmluY3JlbWVudFN0YXQoJ3BlbmRpbmcnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHF1ZXVlIHN0YXRpc3RpY3NcbiAgICovXG4gIGFzeW5jIHN0YXRzKCk6IFByb21pc2U8UXVldWVTdGF0cz4ge1xuICAgIHJldHVybiB7XG4gICAgICBwZW5kaW5nOiBhd2FpdCB0aGlzLmdldFN0YXQoJ3BlbmRpbmcnKSxcbiAgICAgIGNsYWltZWQ6IGF3YWl0IHRoaXMuZ2V0U3RhdCgnY2xhaW1lZCcpLFxuICAgICAgY29tcGxldGVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ2NvbXBsZXRlZCcpLFxuICAgICAgZGVhZExldHRlcmVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ2RlYWRMZXR0ZXJlZCcpLFxuICAgICAgdG90YWxFbnF1ZXVlZDogYXdhaXQgdGhpcy5nZXRTdGF0KCd0b3RhbEVucXVldWVkJyksXG4gICAgICB0b3RhbERlcXVldWVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ3RvdGFsRGVxdWV1ZWQnKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFB1cmdlIGNvbXBsZXRlZCB0YXNrc1xuICAgKi9cbiAgYXN5bmMgcHVyZ2UoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgcHVyZ2luZyBvZiBjb21wbGV0ZWQgdGFza3NcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8vIEhlbHBlciBtZXRob2RzXG4gIHByaXZhdGUgZ2VuZXJhdGVUYXNrSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0VGFzayh0YXNrSWQ6IHN0cmluZyk6IFByb21pc2U8VGFzayB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdGFzayBsb29rdXBcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBkYXRlVGFzayh0YXNrOiBUYXNrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gVE9ETzogSW1wbGVtZW50IHRhc2sgdXBkYXRlXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0aGlzLmRiLmdldChCdWZmZXIuZnJvbShrZXkpKTtcbiAgICByZXR1cm4gdmFsdWUgPyBwYXJzZUludCh2YWx1ZS50b1N0cmluZygpKSA6IDA7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluY3JlbWVudFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0U3RhdChuYW1lKTtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgYXdhaXQgdGhpcy5kYi5wdXQoQnVmZmVyLmZyb20oa2V5KSwgQnVmZmVyLmZyb20oKGN1cnJlbnQgKyAxKS50b1N0cmluZygpKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlY3JlbWVudFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0U3RhdChuYW1lKTtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgYXdhaXQgdGhpcy5kYi5wdXQoQnVmZmVyLmZyb20oa2V5KSwgQnVmZmVyLmZyb20oTWF0aC5tYXgoMCwgY3VycmVudCAtIDEpLnRvU3RyaW5nKCkpKTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZSBhIHF1ZXVlIGluc3RhbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVRdWV1ZShcbiAgZGI6IGFueSxcbiAgbmFtZTogc3RyaW5nLFxuICBjb25maWc/OiBQYXJ0aWFsPFF1ZXVlQ29uZmlnPlxuKTogUHJpb3JpdHlRdWV1ZSB7XG4gIHJldHVybiBQcmlvcml0eVF1ZXVlLmZyb21EYXRhYmFzZShkYiwgbmFtZSwgY29uZmlnKTtcbn1cbiJdfQ==
|