@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,262 @@
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
+ db;
63
+ namespace;
64
+ name;
65
+ config;
66
+ constructor(db, namespace, name, config) {
67
+ this.db = db;
68
+ this.namespace = namespace;
69
+ this.name = name;
70
+ this.config = config;
71
+ }
72
+ /**
73
+ * Insert a vector with optional metadata
74
+ */
75
+ async insert(vector, metadata, id) {
76
+ if (this.config.dimension && vector.length !== this.config.dimension) {
77
+ throw new errors_1.DatabaseError(`Vector dimension mismatch: expected ${this.config.dimension}, got ${vector.length}`);
78
+ }
79
+ const vectorId = id || this.generateId();
80
+ const key = this.vectorKey(vectorId);
81
+ const data = {
82
+ vector,
83
+ metadata: metadata || {},
84
+ timestamp: Date.now(),
85
+ };
86
+ await this.db.put(Buffer.from(key), Buffer.from(JSON.stringify(data)));
87
+ return vectorId;
88
+ }
89
+ /**
90
+ * Insert multiple vectors
91
+ */
92
+ async insertMany(vectors, metadatas, ids) {
93
+ const resultIds = [];
94
+ for (let i = 0; i < vectors.length; i++) {
95
+ const id = ids ? ids[i] : undefined;
96
+ const metadata = metadatas ? metadatas[i] : undefined;
97
+ const resultId = await this.insert(vectors[i], metadata, id);
98
+ resultIds.push(resultId);
99
+ }
100
+ return resultIds;
101
+ }
102
+ /**
103
+ * Search for similar vectors
104
+ */
105
+ async search(request) {
106
+ // For now, implement basic linear search
107
+ // In production, this would use HNSW index
108
+ const results = [];
109
+ const prefix = this.vectorKeyPrefix();
110
+ // Scan all vectors in collection
111
+ const allVectors = [];
112
+ // TODO: Implement efficient scanning with range queries
113
+ // For now, this is a placeholder that shows the API structure
114
+ // Sort by similarity score
115
+ allVectors.sort((a, b) => b.score - a.score);
116
+ // Return top-k results
117
+ return allVectors.slice(0, request.k).map(v => ({
118
+ id: v.id,
119
+ score: v.score,
120
+ vector: request.includeMetadata ? v.vector : undefined,
121
+ metadata: request.includeMetadata ? v.metadata : undefined,
122
+ }));
123
+ }
124
+ /**
125
+ * Get a vector by ID
126
+ */
127
+ async get(id) {
128
+ const key = this.vectorKey(id);
129
+ const value = await this.db.get(Buffer.from(key));
130
+ if (!value) {
131
+ return null;
132
+ }
133
+ const data = JSON.parse(value.toString());
134
+ return {
135
+ vector: data.vector,
136
+ metadata: data.metadata,
137
+ };
138
+ }
139
+ /**
140
+ * Delete a vector by ID
141
+ */
142
+ async delete(id) {
143
+ const key = this.vectorKey(id);
144
+ await this.db.delete(Buffer.from(key));
145
+ return true;
146
+ }
147
+ /**
148
+ * Count vectors in collection
149
+ */
150
+ async count() {
151
+ // TODO: Implement efficient counting
152
+ return 0;
153
+ }
154
+ // Helper methods
155
+ vectorKey(id) {
156
+ return `_collection/${this.namespace}/${this.name}/vectors/${id}`;
157
+ }
158
+ vectorKeyPrefix() {
159
+ return `_collection/${this.namespace}/${this.name}/vectors/`;
160
+ }
161
+ metadataKey() {
162
+ return `_collection/${this.namespace}/${this.name}/metadata`;
163
+ }
164
+ generateId() {
165
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
166
+ }
167
+ // Calculate cosine similarity
168
+ cosineSimilarity(a, b) {
169
+ let dotProduct = 0;
170
+ let normA = 0;
171
+ let normB = 0;
172
+ for (let i = 0; i < a.length; i++) {
173
+ dotProduct += a[i] * b[i];
174
+ normA += a[i] * a[i];
175
+ normB += b[i] * b[i];
176
+ }
177
+ return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
178
+ }
179
+ }
180
+ exports.Collection = Collection;
181
+ // ============================================================================
182
+ // Namespace Handle
183
+ // ============================================================================
184
+ class Namespace {
185
+ db;
186
+ name;
187
+ config;
188
+ constructor(db, name, config) {
189
+ this.db = db;
190
+ this.name = name;
191
+ this.config = config;
192
+ }
193
+ /**
194
+ * Create a new collection in this namespace
195
+ */
196
+ async createCollection(config) {
197
+ const metadataKey = `_collection/${this.name}/${config.name}/metadata`;
198
+ // Check if collection already exists
199
+ const existing = await this.db.get(Buffer.from(metadataKey));
200
+ if (existing) {
201
+ throw new CollectionExistsError(config.name);
202
+ }
203
+ // Store collection metadata
204
+ const metadata = {
205
+ ...config,
206
+ createdAt: Date.now(),
207
+ };
208
+ await this.db.put(Buffer.from(metadataKey), Buffer.from(JSON.stringify(metadata)));
209
+ return new Collection(this.db, this.name, config.name, config);
210
+ }
211
+ /**
212
+ * Get an existing collection
213
+ */
214
+ async collection(name) {
215
+ const metadataKey = `_collection/${this.name}/${name}/metadata`;
216
+ const metadata = await this.db.get(Buffer.from(metadataKey));
217
+ if (!metadata) {
218
+ throw new CollectionNotFoundError(name);
219
+ }
220
+ const config = JSON.parse(metadata.toString());
221
+ return new Collection(this.db, this.name, name, config);
222
+ }
223
+ /**
224
+ * Get or create a collection
225
+ */
226
+ async getOrCreateCollection(config) {
227
+ try {
228
+ return await this.collection(config.name);
229
+ }
230
+ catch (error) {
231
+ if (error instanceof CollectionNotFoundError) {
232
+ return await this.createCollection(config);
233
+ }
234
+ throw error;
235
+ }
236
+ }
237
+ /**
238
+ * Delete a collection
239
+ */
240
+ async deleteCollection(name) {
241
+ const metadataKey = `_collection/${this.name}/${name}/metadata`;
242
+ const prefix = `_collection/${this.name}/${name}/`;
243
+ // TODO: Delete all keys with prefix
244
+ await this.db.delete(Buffer.from(metadataKey));
245
+ return true;
246
+ }
247
+ /**
248
+ * List all collections in this namespace
249
+ */
250
+ async listCollections() {
251
+ // TODO: Implement efficient listing with range queries
252
+ return [];
253
+ }
254
+ getName() {
255
+ return this.name;
256
+ }
257
+ getConfig() {
258
+ return { ...this.config };
259
+ }
260
+ }
261
+ exports.Namespace = Namespace;
262
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtZXNwYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25hbWVzcGFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHOzs7QUFFSCxxQ0FBc0Q7QUFhdEQsTUFBYSxzQkFBdUIsU0FBUSxvQkFBVztJQUNyRCxZQUFZLFNBQWlCO1FBQzNCLEtBQUssQ0FBQyx3QkFBd0IsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUMzQyxJQUFJLENBQUMsSUFBSSxHQUFHLHdCQUF3QixDQUFDO0lBQ3ZDLENBQUM7Q0FDRjtBQUxELHdEQUtDO0FBRUQsTUFBYSxvQkFBcUIsU0FBUSxvQkFBVztJQUNuRCxZQUFZLFNBQWlCO1FBQzNCLEtBQUssQ0FBQyw2QkFBNkIsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLHNCQUFzQixDQUFDO0lBQ3JDLENBQUM7Q0FDRjtBQUxELG9EQUtDO0FBRUQsTUFBYSx1QkFBd0IsU0FBUSxvQkFBVztJQUN0RCxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyx5QkFBeUIsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsSUFBSSxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLENBQUM7Q0FDRjtBQUxELDBEQUtDO0FBRUQsTUFBYSxxQkFBc0IsU0FBUSxvQkFBVztJQUNwRCxZQUFZLFVBQWtCO1FBQzVCLEtBQUssQ0FBQyw4QkFBOEIsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsSUFBSSxHQUFHLHVCQUF1QixDQUFDO0lBQ3RDLENBQUM7Q0FDRjtBQUxELHNEQUtDO0FBRUQsK0VBQStFO0FBQy9FLDJCQUEyQjtBQUMzQiwrRUFBK0U7QUFFL0UsSUFBWSxjQUlYO0FBSkQsV0FBWSxjQUFjO0lBQ3hCLG1DQUFpQixDQUFBO0lBQ2pCLHlDQUF1QixDQUFBO0lBQ3ZCLG9DQUFrQixDQUFBO0FBQ3BCLENBQUMsRUFK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N0MsQ0FBQztZQUNELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFZO1FBQ2pDLE1BQU0sV0FBVyxHQUFHLGVBQWUsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLFdBQVcsQ0FBQztRQUNoRSxNQUFNLE1BQU0sR0FBRyxlQUFlLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxHQUFHLENBQUM7UUFFbkQsb0NBQW9DO1FBQ3BDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBRS9DLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGVBQWU7UUFDbkIsdURBQXVEO1FBQ3ZELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUVELFNBQVM7UUFDUCxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBMUZELDhCQTBGQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU29jaERCIE5hbWVzcGFjZSBBUElcbiAqIFxuICogUHJvdmlkZXMgdHlwZS1zYWZlIG5hbWVzcGFjZSBpc29sYXRpb24gd2l0aCBmaXJzdC1jbGFzcyBuYW1lc3BhY2UgaGFuZGxlcy5cbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IERhdGFiYXNlIH0gZnJvbSAnQHNvY2hkYi9zb2NoZGInO1xuICogXG4gKiBjb25zdCBkYiA9IGF3YWl0IERhdGFiYXNlLm9wZW4oJy4vbXlkYicpO1xuICogY29uc3QgbnMgPSBhd2FpdCBkYi5jcmVhdGVOYW1lc3BhY2UoJ3RlbmFudF8xMjMnKTtcbiAqIGNvbnN0IGNvbGxlY3Rpb24gPSBhd2FpdCBucy5jcmVhdGVDb2xsZWN0aW9uKCdkb2N1bWVudHMnLCB7IGRpbWVuc2lvbjogMzg0IH0pO1xuICogYXdhaXQgY29sbGVjdGlvbi5pbnNlcnQoWzEuMCwgMi4wLCAuLi5dLCB7IHNvdXJjZTogJ3dlYicgfSk7XG4gKiBjb25zdCByZXN1bHRzID0gYXdhaXQgY29sbGVjdGlvbi5zZWFyY2gocXVlcnlWZWN0b3IsIDEwKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB7IFNvY2hEQkVycm9yLCBEYXRhYmFzZUVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBOYW1lc3BhY2UgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIE5hbWVzcGFjZUNvbmZpZyB7XG4gIG5hbWU6IHN0cmluZztcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG4gIGxhYmVscz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIHJlYWRPbmx5PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIE5hbWVzcGFjZU5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG5hbWVzcGFjZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoYE5hbWVzcGFjZSBub3QgZm91bmQ6ICR7bmFtZXNwYWNlfWApO1xuICAgIHRoaXMubmFtZSA9ICdOYW1lc3BhY2VOb3RGb3VuZEVycm9yJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTmFtZXNwYWNlRXhpc3RzRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG5hbWVzcGFjZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoYE5hbWVzcGFjZSBhbHJlYWR5IGV4aXN0czogJHtuYW1lc3BhY2V9YCk7XG4gICAgdGhpcy5uYW1lID0gJ05hbWVzcGFjZUV4aXN0c0Vycm9yJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbk5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBTb2NoREJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGNvbGxlY3Rpb246IHN0cmluZykge1xuICAgIHN1cGVyKGBDb2xsZWN0aW9uIG5vdCBmb3VuZDogJHtjb2xsZWN0aW9ufWApO1xuICAgIHRoaXMubmFtZSA9ICdDb2xsZWN0aW9uTm90Rm91bmRFcnJvcic7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENvbGxlY3Rpb25FeGlzdHNFcnJvciBleHRlbmRzIFNvY2hEQkVycm9yIHtcbiAgY29uc3RydWN0b3IoY29sbGVjdGlvbjogc3RyaW5nKSB7XG4gICAgc3VwZXIoYENvbGxlY3Rpb24gYWxyZWFkeSBleGlzdHM6ICR7Y29sbGVjdGlvbn1gKTtcbiAgICB0aGlzLm5hbWUgPSAnQ29sbGVjdGlvbkV4aXN0c0Vycm9yJztcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb2xsZWN0aW9uIENvbmZpZ3VyYXRpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGVudW0gRGlzdGFuY2VNZXRyaWMge1xuICBDb3NpbmUgPSAnY29zaW5lJyxcbiAgRXVjbGlkZWFuID0gJ2V1Y2xpZGVhbicsXG4gIERvdFByb2R1Y3QgPSAnZG90Jyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uQ29uZmlnIHtcbiAgbmFtZTogc3RyaW5nO1xuICBkaW1lbnNpb24/OiBudW1iZXI7XG4gIG1ldHJpYz86IERpc3RhbmNlTWV0cmljO1xuICBpbmRleGVkPzogYm9vbGVhbjtcbiAgaG5zd00/OiBudW1iZXI7XG4gIGhuc3dFZkNvbnN0cnVjdGlvbj86IG51bWJlcjtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlYXJjaFJlcXVlc3Qge1xuICBxdWVyeVZlY3RvcjogbnVtYmVyW107XG4gIGs6IG51bWJlcjtcbiAgZmlsdGVyPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgaW5jbHVkZU1ldGFkYXRhPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWFyY2hSZXN1bHQge1xuICBpZDogc3RyaW5nO1xuICBzY29yZTogbnVtYmVyO1xuICB2ZWN0b3I/OiBudW1iZXJbXTtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDb2xsZWN0aW9uIEhhbmRsZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZGI6IGFueSxcbiAgICBwcml2YXRlIG5hbWVzcGFjZTogc3RyaW5nLFxuICAgIHByaXZhdGUgbmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgY29uZmlnOiBDb2xsZWN0aW9uQ29uZmlnXG4gICkge31cblxuICAvKipcbiAgICogSW5zZXJ0IGEgdmVjdG9yIHdpdGggb3B0aW9uYWwgbWV0YWRhdGFcbiAgICovXG4gIGFzeW5jIGluc2VydChcbiAgICB2ZWN0b3I6IG51bWJlcltdLFxuICAgIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBpZD86IHN0cmluZ1xuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICh0aGlzLmNvbmZpZy5kaW1lbnNpb24gJiYgdmVjdG9yLmxlbmd0aCAhPT0gdGhpcy5jb25maWcuZGltZW5zaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcihcbiAgICAgICAgYFZlY3RvciBkaW1lbnNpb24gbWlzbWF0Y2g6IGV4cGVjdGVkICR7dGhpcy5jb25maWcuZGltZW5zaW9ufSwgZ290ICR7dmVjdG9yLmxlbmd0aH1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHZlY3RvcklkID0gaWQgfHwgdGhpcy5nZW5lcmF0ZUlkKCk7XG4gICAgY29uc3Qga2V5ID0gdGhpcy52ZWN0b3JLZXkodmVjdG9ySWQpO1xuICAgIFxuICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICB2ZWN0b3IsXG4gICAgICBtZXRhZGF0YTogbWV0YWRhdGEgfHwge30sXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgfTtcblxuICAgIGF3YWl0IHRoaXMuZGIucHV0KEJ1ZmZlci5mcm9tKGtleSksIEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KGRhdGEpKSk7XG4gICAgcmV0dXJuIHZlY3RvcklkO1xuICB9XG5cbiAgLyoqXG4gICAqIEluc2VydCBtdWx0aXBsZSB2ZWN0b3JzXG4gICAqL1xuICBhc3luYyBpbnNlcnRNYW55KFxuICAgIHZlY3RvcnM6IG51bWJlcltdW10sXG4gICAgbWV0YWRhdGFzPzogUmVjb3JkPHN0cmluZywgYW55PltdLFxuICAgIGlkcz86IHN0cmluZ1tdXG4gICk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCByZXN1bHRJZHM6IHN0cmluZ1tdID0gW107XG4gICAgXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpZCA9IGlkcyA/IGlkc1tpXSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gbWV0YWRhdGFzID8gbWV0YWRhdGFzW2ldIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcmVzdWx0SWQgPSBhd2FpdCB0aGlzLmluc2VydCh2ZWN0b3JzW2ldLCBtZXRhZGF0YSwgaWQpO1xuICAgICAgcmVzdWx0SWRzLnB1c2gocmVzdWx0SWQpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gcmVzdWx0SWRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlYXJjaCBmb3Igc2ltaWxhciB2ZWN0b3JzXG4gICAqL1xuICBhc3luYyBzZWFyY2gocmVxdWVzdDogU2VhcmNoUmVxdWVzdCk6IFByb21pc2U8U2VhcmNoUmVzdWx0W10+IHtcbiAgICAvLyBGb3Igbm93LCBpbXBsZW1lbnQgYmFzaWMgbGluZWFyIHNlYXJjaFxuICAgIC8vIEluIHByb2R1Y3Rpb24sIHRoaXMgd291bGQgdXNlIEhOU1cgaW5kZXhcbiAgICBjb25zdCByZXN1bHRzOiBTZWFyY2hSZXN1bHRbXSA9IFtdO1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMudmVjdG9yS2V5UHJlZml4KCk7XG4gICAgXG4gICAgLy8gU2NhbiBhbGwgdmVjdG9ycyBpbiBjb2xsZWN0aW9uXG4gICAgY29uc3QgYWxsVmVjdG9yczogQXJyYXk8eyBpZDogc3RyaW5nOyB2ZWN0b3I6IG51bWJlcltdOyBtZXRhZGF0YT86IGFueTsgc2NvcmU6IG51bWJlciB9PiA9IFtdO1xuICAgIFxuICAgIC8vIFRPRE86IEltcGxlbWVudCBlZmZpY2llbnQgc2Nhbm5pbmcgd2l0aCByYW5nZSBxdWVyaWVzXG4gICAgLy8gRm9yIG5vdywgdGhpcyBpcyBhIHBsYWNlaG9sZGVyIHRoYXQgc2hvd3MgdGhlIEFQSSBzdHJ1Y3R1cmVcbiAgICBcbiAgICAvLyBTb3J0IGJ5IHNpbWlsYXJpdHkgc2NvcmVcbiAgICBhbGxWZWN0b3JzLnNvcnQoKGEsIGIpID0+IGIuc2NvcmUgLSBhLnNjb3JlKTtcbiAgICBcbiAgICAvLyBSZXR1cm4gdG9wLWsgcmVzdWx0c1xuICAgIHJldHVybiBhbGxWZWN0b3JzLnNsaWNlKDAsIHJlcXVlc3QuaykubWFwKHYgPT4gKHtcbiAgICAgIGlkOiB2LmlkLFxuICAgICAgc2NvcmU6IHYuc2NvcmUsXG4gICAgICB2ZWN0b3I6IHJlcXVlc3QuaW5jbHVkZU1ldGFkYXRhID8gdi52ZWN0b3IgOiB1bmRlZmluZWQsXG4gICAgICBtZXRhZGF0YTogcmVxdWVzdC5pbmNsdWRlTWV0YWRhdGEgPyB2Lm1ldGFkYXRhIDogdW5kZWZpbmVkLFxuICAgIH0pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSB2ZWN0b3IgYnkgSURcbiAgICovXG4gIGFzeW5jIGdldChpZDogc3RyaW5nKTogUHJvbWlzZTx7IHZlY3RvcjogbnVtYmVyW107IG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PiB9IHwgbnVsbD4ge1xuICAgIGNvbnN0IGtleSA9IHRoaXMudmVjdG9yS2V5KGlkKTtcbiAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHRoaXMuZGIuZ2V0KEJ1ZmZlci5mcm9tKGtleSkpO1xuICAgIFxuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZSh2YWx1ZS50b1N0cmluZygpKTtcbiAgICByZXR1cm4ge1xuICAgICAgdmVjdG9yOiBkYXRhLnZlY3RvcixcbiAgICAgIG1ldGFkYXRhOiBkYXRhLm1ldGFkYXRhLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlIGEgdmVjdG9yIGJ5IElEXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGtleSA9IHRoaXMudmVjdG9yS2V5KGlkKTtcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShCdWZmZXIuZnJvbShrZXkpKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3VudCB2ZWN0b3JzIGluIGNvbGxlY3Rpb25cbiAgICovXG4gIGFzeW5jIGNvdW50KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgLy8gVE9ETzogSW1wbGVtZW50IGVmZmljaWVudCBjb3VudGluZ1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgLy8gSGVscGVyIG1ldGhvZHNcbiAgcHJpdmF0ZSB2ZWN0b3JLZXkoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBfY29sbGVjdGlvbi8ke3RoaXMubmFtZXNwYWNlfS8ke3RoaXMubmFtZX0vdmVjdG9ycy8ke2lkfWA7XG4gIH1cblxuICBwcml2YXRlIHZlY3RvcktleVByZWZpeCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgX2NvbGxlY3Rpb24vJHt0aGlzLm5hbWVzcGFjZX0vJHt0aGlzLm5hbWV9L3ZlY3RvcnMvYDtcbiAgfVxuXG4gIHByaXZhdGUgbWV0YWRhdGFLZXkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lc3BhY2V9LyR7dGhpcy5uYW1lfS9tZXRhZGF0YWA7XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcbiAgfVxuXG4gIC8vIENhbGN1bGF0ZSBjb3NpbmUgc2ltaWxhcml0eVxuICBwcml2YXRlIGNvc2luZVNpbWlsYXJpdHkoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBsZXQgZG90UHJvZHVjdCA9IDA7XG4gICAgbGV0IG5vcm1BID0gMDtcbiAgICBsZXQgbm9ybUIgPSAwO1xuICAgIFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgZG90UHJvZHVjdCArPSBhW2ldICogYltpXTtcbiAgICAgIG5vcm1BICs9IGFbaV0gKiBhW2ldO1xuICAgICAgbm9ybUIgKz0gYltpXSAqIGJbaV07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBkb3RQcm9kdWN0IC8gKE1hdGguc3FydChub3JtQSkgKiBNYXRoLnNxcnQobm9ybUIpKTtcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBOYW1lc3BhY2UgSGFuZGxlXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBOYW1lc3BhY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGRiOiBhbnksXG4gICAgcHJpdmF0ZSBuYW1lOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSBjb25maWc6IE5hbWVzcGFjZUNvbmZpZ1xuICApIHt9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBjb2xsZWN0aW9uIGluIHRoaXMgbmFtZXNwYWNlXG4gICAqL1xuICBhc3luYyBjcmVhdGVDb2xsZWN0aW9uKGNvbmZpZzogQ29sbGVjdGlvbkNvbmZpZyk6IFByb21pc2U8Q29sbGVjdGlvbj4ge1xuICAgIGNvbnN0IG1ldGFkYXRhS2V5ID0gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lfS8ke2NvbmZpZy5uYW1lfS9tZXRhZGF0YWA7XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgY29sbGVjdGlvbiBhbHJlYWR5IGV4aXN0c1xuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy5kYi5nZXQoQnVmZmVyLmZyb20obWV0YWRhdGFLZXkpKTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRocm93IG5ldyBDb2xsZWN0aW9uRXhpc3RzRXJyb3IoY29uZmlnLm5hbWUpO1xuICAgIH1cblxuICAgIC8vIFN0b3JlIGNvbGxlY3Rpb24gbWV0YWRhdGFcbiAgICBjb25zdCBtZXRhZGF0YSA9IHtcbiAgICAgIC4uLmNvbmZpZyxcbiAgICAgIGNyZWF0ZWRBdDogRGF0ZS5ub3coKSxcbiAgICB9O1xuICAgIFxuICAgIGF3YWl0IHRoaXMuZGIucHV0KFxuICAgICAgQnVmZmVyLmZyb20obWV0YWRhdGFLZXkpLFxuICAgICAgQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpKVxuICAgICk7XG5cbiAgICByZXR1cm4gbmV3IENvbGxlY3Rpb24odGhpcy5kYiwgdGhpcy5uYW1lLCBjb25maWcubmFtZSwgY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYW4gZXhpc3RpbmcgY29sbGVjdGlvblxuICAgKi9cbiAgYXN5bmMgY29sbGVjdGlvbihuYW1lOiBzdHJpbmcpOiBQcm9taXNlPENvbGxlY3Rpb24+IHtcbiAgICBjb25zdCBtZXRhZGF0YUtleSA9IGBfY29sbGVjdGlvbi8ke3RoaXMubmFtZX0vJHtuYW1lfS9tZXRhZGF0YWA7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBhd2FpdCB0aGlzLmRiLmdldChCdWZmZXIuZnJvbShtZXRhZGF0YUtleSkpO1xuICAgIFxuICAgIGlmICghbWV0YWRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBDb2xsZWN0aW9uTm90Rm91bmRFcnJvcihuYW1lKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWcgPSBKU09OLnBhcnNlKG1ldGFkYXRhLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiBuZXcgQ29sbGVjdGlvbih0aGlzLmRiLCB0aGlzLm5hbWUsIG5hbWUsIGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IG9yIGNyZWF0ZSBhIGNvbGxlY3Rpb25cbiAgICovXG4gIGFzeW5jIGdldE9yQ3JlYXRlQ29sbGVjdGlvbihjb25maWc6IENvbGxlY3Rpb25Db25maWcpOiBQcm9taXNlPENvbGxlY3Rpb24+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29sbGVjdGlvbihjb25maWcubmFtZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIENvbGxlY3Rpb25Ob3RGb3VuZEVycm9yKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNyZWF0ZUNvbGxlY3Rpb24oY29uZmlnKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBjb2xsZWN0aW9uXG4gICAqL1xuICBhc3luYyBkZWxldGVDb2xsZWN0aW9uKG5hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IG1ldGFkYXRhS2V5ID0gYF9jb2xsZWN0aW9uLyR7dGhpcy5uYW1lfS8ke25hbWV9L21ldGFkYXRhYDtcbiAgICBjb25zdCBwcmVmaXggPSBgX2NvbGxlY3Rpb24vJHt0aGlzLm5hbWV9LyR7bmFtZX0vYDtcbiAgICBcbiAgICAvLyBUT0RPOiBEZWxldGUgYWxsIGtleXMgd2l0aCBwcmVmaXhcbiAgICBhd2FpdCB0aGlzLmRiLmRlbGV0ZShCdWZmZXIuZnJvbShtZXRhZGF0YUtleSkpO1xuICAgIFxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgYWxsIGNvbGxlY3Rpb25zIGluIHRoaXMgbmFtZXNwYWNlXG4gICAqL1xuICBhc3luYyBsaXN0Q29sbGVjdGlvbnMoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIC8vIFRPRE86IEltcGxlbWVudCBlZmZpY2llbnQgbGlzdGluZyB3aXRoIHJhbmdlIHF1ZXJpZXNcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgfVxuXG4gIGdldENvbmZpZygpOiBOYW1lc3BhY2VDb25maWcge1xuICAgIHJldHVybiB7IC4uLnRoaXMuY29uZmlnIH07XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,291 @@
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
+ db;
120
+ config;
121
+ static sequenceCounter = 0;
122
+ constructor(db, config) {
123
+ this.db = db;
124
+ this.config = config;
125
+ // Set defaults
126
+ this.config.visibilityTimeout = config.visibilityTimeout || 30000;
127
+ this.config.maxRetries = config.maxRetries || 3;
128
+ }
129
+ /**
130
+ * Create queue from embedded database
131
+ */
132
+ static fromDatabase(db, name, config) {
133
+ const fullConfig = {
134
+ name,
135
+ ...config,
136
+ };
137
+ return new PriorityQueue(db, fullConfig);
138
+ }
139
+ /**
140
+ * Create queue from gRPC client
141
+ */
142
+ static fromClient(client, name, config) {
143
+ const fullConfig = {
144
+ name,
145
+ ...config,
146
+ };
147
+ return new PriorityQueue(client, fullConfig);
148
+ }
149
+ /**
150
+ * Enqueue a task with priority
151
+ * Lower priority number = higher urgency
152
+ */
153
+ async enqueue(priority, payload, metadata) {
154
+ const taskId = this.generateTaskId();
155
+ const now = Date.now();
156
+ const key = {
157
+ queueId: this.config.name,
158
+ priority,
159
+ readyTs: now,
160
+ sequence: PriorityQueue.sequenceCounter++,
161
+ taskId,
162
+ };
163
+ const task = {
164
+ taskId,
165
+ priority,
166
+ payload,
167
+ state: TaskState.PENDING,
168
+ enqueuedAt: now,
169
+ retries: 0,
170
+ metadata,
171
+ };
172
+ const keyBuf = encodeQueueKey(key);
173
+ const valueBuf = Buffer.from(JSON.stringify(task));
174
+ await this.db.put(keyBuf, valueBuf);
175
+ // Update stats
176
+ await this.incrementStat('totalEnqueued');
177
+ await this.incrementStat('pending');
178
+ return taskId;
179
+ }
180
+ /**
181
+ * Dequeue the highest priority task
182
+ * Returns null if no tasks available
183
+ */
184
+ async dequeue(workerId) {
185
+ const now = Date.now();
186
+ const prefix = `queue/${this.config.name}/`;
187
+ // TODO: Implement range scan to find first ready task
188
+ // For now, this is a placeholder
189
+ return null;
190
+ }
191
+ /**
192
+ * Acknowledge task completion
193
+ */
194
+ async ack(taskId) {
195
+ // Find and update task state
196
+ const task = await this.getTask(taskId);
197
+ if (!task) {
198
+ throw new errors_1.SochDBError(`Task not found: ${taskId}`);
199
+ }
200
+ if (task.state !== TaskState.CLAIMED) {
201
+ throw new errors_1.SochDBError(`Task not in claimed state: ${taskId}`);
202
+ }
203
+ // Update task state
204
+ task.state = TaskState.COMPLETED;
205
+ task.completedAt = Date.now();
206
+ await this.updateTask(task);
207
+ // Update stats
208
+ await this.decrementStat('claimed');
209
+ await this.incrementStat('completed');
210
+ }
211
+ /**
212
+ * Negative acknowledge - return task to queue
213
+ */
214
+ async nack(taskId) {
215
+ const task = await this.getTask(taskId);
216
+ if (!task) {
217
+ throw new errors_1.SochDBError(`Task not found: ${taskId}`);
218
+ }
219
+ task.retries++;
220
+ if (task.retries >= (this.config.maxRetries || 3)) {
221
+ // Move to dead letter queue
222
+ task.state = TaskState.DEAD_LETTERED;
223
+ await this.updateTask(task);
224
+ await this.decrementStat('claimed');
225
+ await this.incrementStat('deadLettered');
226
+ }
227
+ else {
228
+ // Return to pending
229
+ task.state = TaskState.PENDING;
230
+ task.claimedAt = undefined;
231
+ task.claimedBy = undefined;
232
+ await this.updateTask(task);
233
+ await this.decrementStat('claimed');
234
+ await this.incrementStat('pending');
235
+ }
236
+ }
237
+ /**
238
+ * Get queue statistics
239
+ */
240
+ async stats() {
241
+ return {
242
+ pending: await this.getStat('pending'),
243
+ claimed: await this.getStat('claimed'),
244
+ completed: await this.getStat('completed'),
245
+ deadLettered: await this.getStat('deadLettered'),
246
+ totalEnqueued: await this.getStat('totalEnqueued'),
247
+ totalDequeued: await this.getStat('totalDequeued'),
248
+ };
249
+ }
250
+ /**
251
+ * Purge completed tasks
252
+ */
253
+ async purge() {
254
+ // TODO: Implement purging of completed tasks
255
+ return 0;
256
+ }
257
+ // Helper methods
258
+ generateTaskId() {
259
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
260
+ }
261
+ async getTask(taskId) {
262
+ // TODO: Implement task lookup
263
+ return null;
264
+ }
265
+ async updateTask(task) {
266
+ // TODO: Implement task update
267
+ }
268
+ async getStat(name) {
269
+ const key = `_queue_stats/${this.config.name}/${name}`;
270
+ const value = await this.db.get(Buffer.from(key));
271
+ return value ? parseInt(value.toString()) : 0;
272
+ }
273
+ async incrementStat(name) {
274
+ const current = await this.getStat(name);
275
+ const key = `_queue_stats/${this.config.name}/${name}`;
276
+ await this.db.put(Buffer.from(key), Buffer.from((current + 1).toString()));
277
+ }
278
+ async decrementStat(name) {
279
+ const current = await this.getStat(name);
280
+ const key = `_queue_stats/${this.config.name}/${name}`;
281
+ await this.db.put(Buffer.from(key), Buffer.from(Math.max(0, current - 1).toString()));
282
+ }
283
+ }
284
+ exports.PriorityQueue = PriorityQueue;
285
+ /**
286
+ * Create a queue instance
287
+ */
288
+ function createQueue(db, name, config) {
289
+ return PriorityQueue.fromDatabase(db, name, config);
290
+ }
291
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVldWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcXVldWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRzs7O0FBZ1dILGtDQU1DO0FBcFdELHFDQUF1QztBQUV2QywrRUFBK0U7QUFDL0UsYUFBYTtBQUNiLCtFQUErRTtBQUUvRSxJQUFZLFNBS1g7QUFMRCxXQUFZLFNBQVM7SUFDbkIsZ0NBQW1CLENBQUE7SUFDbkIsZ0NBQW1CLENBQUE7SUFDbkIsb0NBQXVCLENBQUE7SUFDdkIsNENBQStCLENBQUE7QUFDakMsQ0FBQyxFQUxXLFNBQVMseUJBQVQsU0FBUyxRQUtwQjtBQWFELCtFQUErRTtBQUMvRSxxQkFBcUI7QUFDckIsK0VBQStFO0FBRS9FOztHQUVHO0FBQ0gsU0FBUyxXQUFXLENBQUMsS0FBYTtJQUNoQyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwQyxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsV0FBVyxDQUFDLEdBQVc7SUFDOUIsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsV0FBVyxDQUFDLEtBQWE7SUFDaEMsa0NBQWtDO0lBQ2xDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJ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TSxHQUFHLEdBQUcsZ0JBQWdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZELE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRU8sS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFZO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QyxNQUFNLEdBQUcsR0FBRyxnQkFBZ0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkQsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RixDQUFDOztBQW5NSCxzQ0FvTUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFdBQVcsQ0FDekIsRUFBTyxFQUNQLElBQVksRUFDWixNQUE2QjtJQUU3QixPQUFPLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztBQUN0RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTb2NoREIgUHJpb3JpdHkgUXVldWVcbiAqIFxuICogRmlyc3QtY2xhc3MgcXVldWUgQVBJIHdpdGggb3JkZXJlZC1rZXkgdGFzayBlbnRyaWVzLCBwcm92aWRpbmcgZWZmaWNpZW50XG4gKiBwcmlvcml0eSBxdWV1ZSBvcGVyYXRpb25zIHdpdGhvdXQgdGhlIE8oTikgYmxvYiByZXdyaXRlIGFudGktcGF0dGVybi5cbiAqIFxuICogRmVhdHVyZXM6XG4gKiAtIE9yZGVyZWQta2V5IHJlcHJlc2VudGF0aW9uOiBFYWNoIHRhc2sgaGFzIGl0cyBvd24ga2V5LCBubyBibG9iIHBhcnNpbmdcbiAqIC0gTyhsb2cgTikgZW5xdWV1ZS9kZXF1ZXVlIHdpdGggb3JkZXJlZCBzY2Fuc1xuICogLSBBdG9taWMgY2xhaW0gcHJvdG9jb2wgZm9yIGNvbmN1cnJlbnQgd29ya2Vyc1xuICogLSBWaXNpYmlsaXR5IHRpbWVvdXQgZm9yIGNyYXNoIHJlY292ZXJ5XG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBEYXRhYmFzZSwgUHJpb3JpdHlRdWV1ZSB9IGZyb20gJ0Bzb2NoZGIvc29jaGRiJztcbiAqIFxuICogY29uc3QgZGIgPSBhd2FpdCBEYXRhYmFzZS5vcGVuKCcuL3F1ZXVlX2RiJyk7XG4gKiBjb25zdCBxdWV1ZSA9IFByaW9yaXR5UXVldWUuZnJvbURhdGFiYXNlKGRiLCAndGFza3MnKTtcbiAqIFxuICogLy8gRW5xdWV1ZSB0YXNrXG4gKiBhd2FpdCBxdWV1ZS5lbnF1ZXVlKDEsIEJ1ZmZlci5mcm9tKCdoaWdoIHByaW9yaXR5IHRhc2snKSk7XG4gKiBcbiAqIC8vIERlcXVldWUgYW5kIHByb2Nlc3NcbiAqIGNvbnN0IHRhc2sgPSBhd2FpdCBxdWV1ZS5kZXF1ZXVlKCd3b3JrZXItMScpO1xuICogaWYgKHRhc2spIHtcbiAqICAgLy8gUHJvY2VzcyB0YXNrLi4uXG4gKiAgIGF3YWl0IHF1ZXVlLmFjayh0YXNrLnRhc2tJZCk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBTb2NoREJFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVGFzayBTdGF0ZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgZW51bSBUYXNrU3RhdGUge1xuICBQRU5ESU5HID0gJ3BlbmRpbmcnLFxuICBDTEFJTUVEID0gJ2NsYWltZWQnLFxuICBDT01QTEVURUQgPSAnY29tcGxldGVkJyxcbiAgREVBRF9MRVRURVJFRCA9ICdkZWFkX2xldHRlcmVkJyxcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUXVldWUgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXVlQ29uZmlnIHtcbiAgbmFtZTogc3RyaW5nO1xuICB2aXNpYmlsaXR5VGltZW91dD86IG51bWJlcjsgLy8gbWlsbGlzZWNvbmRzLCBkZWZhdWx0IDMwMDAwXG4gIG1heFJldHJpZXM/OiBudW1iZXI7IC8vIGRlZmF1bHQgM1xuICBkZWFkTGV0dGVyUXVldWU/OiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFF1ZXVlIEtleSBFbmNvZGluZ1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEVuY29kZSB1NjQgYXMgYmlnLWVuZGlhbiBmb3IgbGV4aWNvZ3JhcGhpYyBvcmRlcmluZ1xuICovXG5mdW5jdGlvbiBlbmNvZGVVNjRCRSh2YWx1ZTogbnVtYmVyKTogQnVmZmVyIHtcbiAgY29uc3QgYnVmID0gQnVmZmVyLmFsbG9jVW5zYWZlKDgpO1xuICBidWYud3JpdGVCaWdVSW50NjRCRShCaWdJbnQodmFsdWUpKTtcbiAgcmV0dXJuIGJ1Zjtcbn1cblxuLyoqXG4gKiBEZWNvZGUgYmlnLWVuZGlhbiB1NjRcbiAqL1xuZnVuY3Rpb24gZGVjb2RlVTY0QkUoYnVmOiBCdWZmZXIpOiBudW1iZXIge1xuICByZXR1cm4gTnVtYmVyKGJ1Zi5yZWFkQmlnVUludDY0QkUoMCkpO1xufVxuXG4vKipcbiAqIEVuY29kZSBpNjQgYXMgYmlnLWVuZGlhbiBwcmVzZXJ2aW5nIG9yZGVyXG4gKi9cbmZ1bmN0aW9uIGVuY29kZUk2NEJFKHZhbHVlOiBudW1iZXIpOiBCdWZmZXIge1xuICAvLyBNYXAgaTY0IHRvIHU2NCBieSBhZGRpbmcgb2Zmc2V0XG4gIGNvbnN0IG1hcHBlZCA9IEJpZ0ludCh2YWx1ZSkgKyAoMW4gPDwgNjNuKTtcbiAgY29uc3QgYnVmID0gQnVmZmVyLmFsbG9jVW5zYWZlKDgpO1xuICBidWYud3JpdGVCaWdVSW50NjRCRShtYXBwZWQpO1xuICByZXR1cm4gYnVmO1xufVxuXG4vKipcbiAqIERlY29kZSBiaWctZW5kaWFuIGk2NFxuICovXG5mdW5jdGlvbiBkZWNvZGVJNjRCRShidWY6IEJ1ZmZlcik6IG51bWJlciB7XG4gIGNvbnN0IG1hcHBlZCA9IGJ1Zi5yZWFkQmlnVUludDY0QkUoMCk7XG4gIHJldHVybiBOdW1iZXIobWFwcGVkIC0gKDFuIDw8IDYzbikpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBRdWV1ZSBLZXlcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdWV1ZUtleSB7XG4gIHF1ZXVlSWQ6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgcmVhZHlUczogbnVtYmVyOyAvLyB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzXG4gIHNlcXVlbmNlOiBudW1iZXI7XG4gIHRhc2tJZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEVuY29kZSBxdWV1ZSBrZXkgdG8gYnl0ZXMgZm9yIHN0b3JhZ2VcbiAqL1xuZnVuY3Rpb24gZW5jb2RlUXVldWVLZXkoa2V5OiBRdWV1ZUtleSk6IEJ1ZmZlciB7XG4gIGNvbnN0IHBhcnRzID0gW1xuICAgIEJ1ZmZlci5mcm9tKCdxdWV1ZS8nKSxcbiAgICBCdWZmZXIuZnJvbShrZXkucXVldWVJZCksXG4gICAgQnVmZmVyLmZyb20oJy8nKSxcbiAgICBlbmNvZGVJNjRCRShrZXkucHJpb3JpdHkpLFxuICAgIEJ1ZmZlci5mcm9tKCcvJyksXG4gICAgZW5jb2RlVTY0QkUoa2V5LnJlYWR5VHMpLFxuICAgIEJ1ZmZlci5mcm9tKCcvJyksXG4gICAgZW5jb2RlVTY0QkUoa2V5LnNlcXVlbmNlKSxcbiAgICBCdWZmZXIuZnJvbSgnLycpLFxuICAgIEJ1ZmZlci5mcm9tKGtleS50YXNrSWQpLFxuICBdO1xuICBcbiAgcmV0dXJuIEJ1ZmZlci5jb25jYXQocGFydHMpO1xufVxuXG4vKipcbiAqIERlY29kZSBxdWV1ZSBrZXkgZnJvbSBieXRlc1xuICovXG5mdW5jdGlvbiBkZWNvZGVRdWV1ZUtleShkYXRhOiBCdWZmZXIpOiBRdWV1ZUtleSB7XG4gIGNvbnN0IHN0ciA9IGRhdGEudG9TdHJpbmcoKTtcbiAgY29uc3QgcGFydHMgPSBzdHIuc3BsaXQoJy8nKTtcbiAgXG4gIGlmIChwYXJ0cy5sZW5ndGggPCA2IHx8IHBhcnRzWzBdICE9PSAncXVldWUnKSB7XG4gICAgdGhyb3cgbmV3IFNvY2hEQkVycm9yKCdJbnZhbGlkIHF1ZXVlIGtleSBmb3JtYXQnKTtcbiAgfVxuICBcbiAgcmV0dXJuIHtcbiAgICBxdWV1ZUlkOiBwYXJ0c1sxXSxcbiAgICBwcmlvcml0eTogMCwgLy8gV291bGQgbmVlZCB0byBkZWNvZGUgZnJvbSBieXRlc1xuICAgIHJlYWR5VHM6IDAsXG4gICAgc2VxdWVuY2U6IDAsXG4gICAgdGFza0lkOiBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSxcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVGFza1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFRhc2sge1xuICB0YXNrSWQ6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgcGF5bG9hZDogQnVmZmVyO1xuICBzdGF0ZTogVGFza1N0YXRlO1xuICBlbnF1ZXVlZEF0OiBudW1iZXI7XG4gIGNsYWltZWRBdD86IG51bWJlcjtcbiAgY2xhaW1lZEJ5Pzogc3RyaW5nO1xuICBjb21wbGV0ZWRBdD86IG51bWJlcjtcbiAgcmV0cmllczogbnVtYmVyO1xuICBtZXRhZGF0YT86IFJlY29yZDxzdHJpbmcsIGFueT47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFF1ZXVlIFN0YXRpc3RpY3Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBRdWV1ZVN0YXRzIHtcbiAgcGVuZGluZzogbnVtYmVyO1xuICBjbGFpbWVkOiBudW1iZXI7XG4gIGNvbXBsZXRlZDogbnVtYmVyO1xuICBkZWFkTGV0dGVyZWQ6IG51bWJlcjtcbiAgdG90YWxFbnF1ZXVlZDogbnVtYmVyO1xuICB0b3RhbERlcXVldWVkOiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFByaW9yaXR5IFF1ZXVlXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBjbGFzcyBQcmlvcml0eVF1ZXVlIHtcbiAgcHJpdmF0ZSBzdGF0aWMgc2VxdWVuY2VDb3VudGVyID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGRiOiBhbnksXG4gICAgcHJpdmF0ZSBjb25maWc6IFF1ZXVlQ29uZmlnXG4gICkge1xuICAgIC8vIFNldCBkZWZhdWx0c1xuICAgIHRoaXMuY29uZmlnLnZpc2liaWxpdHlUaW1lb3V0ID0gY29uZmlnLnZpc2liaWxpdHlUaW1lb3V0IHx8IDMwMDAwO1xuICAgIHRoaXMuY29uZmlnLm1heFJldHJpZXMgPSBjb25maWcubWF4UmV0cmllcyB8fCAzO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBxdWV1ZSBmcm9tIGVtYmVkZGVkIGRhdGFiYXNlXG4gICAqL1xuICBzdGF0aWMgZnJvbURhdGFiYXNlKGRiOiBhbnksIG5hbWU6IHN0cmluZywgY29uZmlnPzogUGFydGlhbDxRdWV1ZUNvbmZpZz4pOiBQcmlvcml0eVF1ZXVlIHtcbiAgICBjb25zdCBmdWxsQ29uZmlnOiBRdWV1ZUNvbmZpZyA9IHtcbiAgICAgIG5hbWUsXG4gICAgICAuLi5jb25maWcsXG4gICAgfTtcbiAgICByZXR1cm4gbmV3IFByaW9yaXR5UXVldWUoZGIsIGZ1bGxDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBxdWV1ZSBmcm9tIGdSUEMgY2xpZW50XG4gICAqL1xuICBzdGF0aWMgZnJvbUNsaWVudChjbGllbnQ6IGFueSwgbmFtZTogc3RyaW5nLCBjb25maWc/OiBQYXJ0aWFsPFF1ZXVlQ29uZmlnPik6IFByaW9yaXR5UXVldWUge1xuICAgIGNvbnN0IGZ1bGxDb25maWc6IFF1ZXVlQ29uZmlnID0ge1xuICAgICAgbmFtZSxcbiAgICAgIC4uLmNvbmZpZyxcbiAgICB9O1xuICAgIHJldHVybiBuZXcgUHJpb3JpdHlRdWV1ZShjbGllbnQsIGZ1bGxDb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVucXVldWUgYSB0YXNrIHdpdGggcHJpb3JpdHlcbiAgICogTG93ZXIgcHJpb3JpdHkgbnVtYmVyID0gaGlnaGVyIHVyZ2VuY3lcbiAgICovXG4gIGFzeW5jIGVucXVldWUoXG4gICAgcHJpb3JpdHk6IG51bWJlcixcbiAgICBwYXlsb2FkOiBCdWZmZXIsXG4gICAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgdGFza0lkID0gdGhpcy5nZW5lcmF0ZVRhc2tJZCgpO1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgXG4gICAgY29uc3Qga2V5OiBRdWV1ZUtleSA9IHtcbiAgICAgIHF1ZXVlSWQ6IHRoaXMuY29uZmlnLm5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIHJlYWR5VHM6IG5vdyxcbiAgICAgIHNlcXVlbmNlOiBQcmlvcml0eVF1ZXVlLnNlcXVlbmNlQ291bnRlcisrLFxuICAgICAgdGFza0lkLFxuICAgIH07XG5cbiAgICBjb25zdCB0YXNrOiBUYXNrID0ge1xuICAgICAgdGFza0lkLFxuICAgICAgcHJpb3JpdHksXG4gICAgICBwYXlsb2FkLFxuICAgICAgc3RhdGU6IFRhc2tTdGF0ZS5QRU5ESU5HLFxuICAgICAgZW5xdWV1ZWRBdDogbm93LFxuICAgICAgcmV0cmllczogMCxcbiAgICAgIG1ldGFkYXRhLFxuICAgIH07XG5cbiAgICBjb25zdCBrZXlCdWYgPSBlbmNvZGVRdWV1ZUtleShrZXkpO1xuICAgIGNvbnN0IHZhbHVlQnVmID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkodGFzaykpO1xuICAgIFxuICAgIGF3YWl0IHRoaXMuZGIucHV0KGtleUJ1ZiwgdmFsdWVCdWYpO1xuICAgIFxuICAgIC8vIFVwZGF0ZSBzdGF0c1xuICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgndG90YWxFbnF1ZXVlZCcpO1xuICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgncGVuZGluZycpO1xuICAgIFxuICAgIHJldHVybiB0YXNrSWQ7XG4gIH1cblxuICAvKipcbiAgICogRGVxdWV1ZSB0aGUgaGlnaGVzdCBwcmlvcml0eSB0YXNrXG4gICAqIFJldHVybnMgbnVsbCBpZiBubyB0YXNrcyBhdmFpbGFibGVcbiAgICovXG4gIGFzeW5jIGRlcXVldWUod29ya2VySWQ6IHN0cmluZyk6IFByb21pc2U8VGFzayB8IG51bGw+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHByZWZpeCA9IGBxdWV1ZS8ke3RoaXMuY29uZmlnLm5hbWV9L2A7XG4gICAgXG4gICAgLy8gVE9ETzogSW1wbGVtZW50IHJhbmdlIHNjYW4gdG8gZmluZCBmaXJzdCByZWFkeSB0YXNrXG4gICAgLy8gRm9yIG5vdywgdGhpcyBpcyBhIHBsYWNlaG9sZGVyXG4gICAgXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQWNrbm93bGVkZ2UgdGFzayBjb21wbGV0aW9uXG4gICAqL1xuICBhc3luYyBhY2sodGFza0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBGaW5kIGFuZCB1cGRhdGUgdGFzayBzdGF0ZVxuICAgIGNvbnN0IHRhc2sgPSBhd2FpdCB0aGlzLmdldFRhc2sodGFza0lkKTtcbiAgICBpZiAoIXRhc2spIHtcbiAgICAgIHRocm93IG5ldyBTb2NoREJFcnJvcihgVGFzayBub3QgZm91bmQ6ICR7dGFza0lkfWApO1xuICAgIH1cblxuICAgIGlmICh0YXNrLnN0YXRlICE9PSBUYXNrU3RhdGUuQ0xBSU1FRCkge1xuICAgICAgdGhyb3cgbmV3IFNvY2hEQkVycm9yKGBUYXNrIG5vdCBpbiBjbGFpbWVkIHN0YXRlOiAke3Rhc2tJZH1gKTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgdGFzayBzdGF0ZVxuICAgIHRhc2suc3RhdGUgPSBUYXNrU3RhdGUuQ09NUExFVEVEO1xuICAgIHRhc2suY29tcGxldGVkQXQgPSBEYXRlLm5vdygpO1xuICAgIFxuICAgIGF3YWl0IHRoaXMudXBkYXRlVGFzayh0YXNrKTtcbiAgICBcbiAgICAvLyBVcGRhdGUgc3RhdHNcbiAgICBhd2FpdCB0aGlzLmRlY3JlbWVudFN0YXQoJ2NsYWltZWQnKTtcbiAgICBhd2FpdCB0aGlzLmluY3JlbWVudFN0YXQoJ2NvbXBsZXRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5lZ2F0aXZlIGFja25vd2xlZGdlIC0gcmV0dXJuIHRhc2sgdG8gcXVldWVcbiAgICovXG4gIGFzeW5jIG5hY2sodGFza0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0YXNrID0gYXdhaXQgdGhpcy5nZXRUYXNrKHRhc2tJZCk7XG4gICAgaWYgKCF0YXNrKSB7XG4gICAgICB0aHJvdyBuZXcgU29jaERCRXJyb3IoYFRhc2sgbm90IGZvdW5kOiAke3Rhc2tJZH1gKTtcbiAgICB9XG5cbiAgICB0YXNrLnJldHJpZXMrKztcbiAgICBcbiAgICBpZiAodGFzay5yZXRyaWVzID49ICh0aGlzLmNvbmZpZy5tYXhSZXRyaWVzIHx8IDMpKSB7XG4gICAgICAvLyBNb3ZlIHRvIGRlYWQgbGV0dGVyIHF1ZXVlXG4gICAgICB0YXNrLnN0YXRlID0gVGFza1N0YXRlLkRFQURfTEVUVEVSRUQ7XG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZVRhc2sodGFzayk7XG4gICAgICBhd2FpdCB0aGlzLmRlY3JlbWVudFN0YXQoJ2NsYWltZWQnKTtcbiAgICAgIGF3YWl0IHRoaXMuaW5jcmVtZW50U3RhdCgnZGVhZExldHRlcmVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJldHVybiB0byBwZW5kaW5nXG4gICAgICB0YXNrLnN0YXRlID0gVGFza1N0YXRlLlBFTkRJTkc7XG4gICAgICB0YXNrLmNsYWltZWRBdCA9IHVuZGVmaW5lZDtcbiAgICAgIHRhc2suY2xhaW1lZEJ5ID0gdW5kZWZpbmVkO1xuICAgICAgYXdhaXQgdGhpcy51cGRhdGVUYXNrKHRhc2spO1xuICAgICAgYXdhaXQgdGhpcy5kZWNyZW1lbnRTdGF0KCdjbGFpbWVkJyk7XG4gICAgICBhd2FpdCB0aGlzLmluY3JlbWVudFN0YXQoJ3BlbmRpbmcnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHF1ZXVlIHN0YXRpc3RpY3NcbiAgICovXG4gIGFzeW5jIHN0YXRzKCk6IFByb21pc2U8UXVldWVTdGF0cz4ge1xuICAgIHJldHVybiB7XG4gICAgICBwZW5kaW5nOiBhd2FpdCB0aGlzLmdldFN0YXQoJ3BlbmRpbmcnKSxcbiAgICAgIGNsYWltZWQ6IGF3YWl0IHRoaXMuZ2V0U3RhdCgnY2xhaW1lZCcpLFxuICAgICAgY29tcGxldGVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ2NvbXBsZXRlZCcpLFxuICAgICAgZGVhZExldHRlcmVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ2RlYWRMZXR0ZXJlZCcpLFxuICAgICAgdG90YWxFbnF1ZXVlZDogYXdhaXQgdGhpcy5nZXRTdGF0KCd0b3RhbEVucXVldWVkJyksXG4gICAgICB0b3RhbERlcXVldWVkOiBhd2FpdCB0aGlzLmdldFN0YXQoJ3RvdGFsRGVxdWV1ZWQnKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFB1cmdlIGNvbXBsZXRlZCB0YXNrc1xuICAgKi9cbiAgYXN5bmMgcHVyZ2UoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgcHVyZ2luZyBvZiBjb21wbGV0ZWQgdGFza3NcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8vIEhlbHBlciBtZXRob2RzXG4gIHByaXZhdGUgZ2VuZXJhdGVUYXNrSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0VGFzayh0YXNrSWQ6IHN0cmluZyk6IFByb21pc2U8VGFzayB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdGFzayBsb29rdXBcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBkYXRlVGFzayh0YXNrOiBUYXNrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gVE9ETzogSW1wbGVtZW50IHRhc2sgdXBkYXRlXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0aGlzLmRiLmdldChCdWZmZXIuZnJvbShrZXkpKTtcbiAgICByZXR1cm4gdmFsdWUgPyBwYXJzZUludCh2YWx1ZS50b1N0cmluZygpKSA6IDA7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluY3JlbWVudFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0U3RhdChuYW1lKTtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgYXdhaXQgdGhpcy5kYi5wdXQoQnVmZmVyLmZyb20oa2V5KSwgQnVmZmVyLmZyb20oKGN1cnJlbnQgKyAxKS50b1N0cmluZygpKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlY3JlbWVudFN0YXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IHRoaXMuZ2V0U3RhdChuYW1lKTtcbiAgICBjb25zdCBrZXkgPSBgX3F1ZXVlX3N0YXRzLyR7dGhpcy5jb25maWcubmFtZX0vJHtuYW1lfWA7XG4gICAgYXdhaXQgdGhpcy5kYi5wdXQoQnVmZmVyLmZyb20oa2V5KSwgQnVmZmVyLmZyb20oTWF0aC5tYXgoMCwgY3VycmVudCAtIDEpLnRvU3RyaW5nKCkpKTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZSBhIHF1ZXVlIGluc3RhbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVRdWV1ZShcbiAgZGI6IGFueSxcbiAgbmFtZTogc3RyaW5nLFxuICBjb25maWc/OiBQYXJ0aWFsPFF1ZXVlQ29uZmlnPlxuKTogUHJpb3JpdHlRdWV1ZSB7XG4gIHJldHVybiBQcmlvcml0eVF1ZXVlLmZyb21EYXRhYmFzZShkYiwgbmFtZSwgY29uZmlnKTtcbn1cbiJdfQ==