@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.
Files changed (69) hide show
  1. package/README.md +220 -33
  2. package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
  3. package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
  4. package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
  5. package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
  6. package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
  7. package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
  8. package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
  9. package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
  10. package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
  11. package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
  12. package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
  13. package/bin/sochdb-bulk.js +1 -1
  14. package/bin/sochdb-grpc-server.js +1 -1
  15. package/bin/sochdb-server.js +1 -1
  16. package/dist/cjs/context-builder.js +280 -0
  17. package/dist/cjs/database.js +2 -2
  18. package/dist/cjs/embedded/database.js +2 -2
  19. package/dist/cjs/errors.js +99 -7
  20. package/dist/cjs/index.js +40 -3
  21. package/dist/cjs/ipc-client.js +2 -2
  22. package/dist/cjs/memory/consolidation.js +202 -0
  23. package/dist/cjs/memory/extraction.js +181 -0
  24. package/dist/cjs/memory/index.js +26 -0
  25. package/dist/cjs/memory/retrieval.js +232 -0
  26. package/dist/cjs/memory/types.js +69 -0
  27. package/dist/cjs/namespace.js +255 -0
  28. package/dist/cjs/queue.js +289 -0
  29. package/dist/cjs/semantic-cache.js +220 -0
  30. package/dist/esm/context-builder.js +280 -0
  31. package/dist/esm/database.js +2 -2
  32. package/dist/esm/embedded/database.js +2 -2
  33. package/dist/esm/errors.js +107 -7
  34. package/dist/esm/index.js +40 -3
  35. package/dist/esm/ipc-client.js +2 -2
  36. package/dist/esm/memory/consolidation.js +206 -0
  37. package/dist/esm/memory/extraction.js +185 -0
  38. package/dist/esm/memory/index.js +26 -0
  39. package/dist/esm/memory/retrieval.js +243 -0
  40. package/dist/esm/memory/types.js +72 -0
  41. package/dist/esm/namespace.js +262 -0
  42. package/dist/esm/queue.js +291 -0
  43. package/dist/esm/semantic-cache.js +223 -0
  44. package/dist/types/context-builder.d.ts +97 -0
  45. package/dist/types/context-builder.d.ts.map +1 -0
  46. package/dist/types/database.d.ts +1 -1
  47. package/dist/types/embedded/database.d.ts +1 -1
  48. package/dist/types/errors.d.ts +57 -1
  49. package/dist/types/errors.d.ts.map +1 -1
  50. package/dist/types/index.d.ts +12 -2
  51. package/dist/types/index.d.ts.map +1 -1
  52. package/dist/types/ipc-client.d.ts +1 -1
  53. package/dist/types/memory/consolidation.d.ts +66 -0
  54. package/dist/types/memory/consolidation.d.ts.map +1 -0
  55. package/dist/types/memory/extraction.d.ts +82 -0
  56. package/dist/types/memory/extraction.d.ts.map +1 -0
  57. package/dist/types/memory/index.d.ts +10 -0
  58. package/dist/types/memory/index.d.ts.map +1 -0
  59. package/dist/types/memory/retrieval.d.ts +46 -0
  60. package/dist/types/memory/retrieval.d.ts.map +1 -0
  61. package/dist/types/memory/types.d.ts +147 -0
  62. package/dist/types/memory/types.d.ts.map +1 -0
  63. package/dist/types/namespace.d.ts +129 -0
  64. package/dist/types/namespace.d.ts.map +1 -0
  65. package/dist/types/queue.d.ts +120 -0
  66. package/dist/types/queue.d.ts.map +1 -0
  67. package/dist/types/semantic-cache.d.ts +84 -0
  68. package/dist/types/semantic-cache.d.ts.map +1 -0
  69. 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==