@sochdb/sochdb 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +356 -14
- package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
- package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
- package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
- package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
- package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
- package/dist/cjs/embedded/database.js +98 -4
- package/dist/cjs/embedded/ffi/bindings.js +46 -8
- package/dist/cjs/index.js +28 -6
- package/dist/cjs/mcp/client.js +115 -0
- package/dist/cjs/mcp/index.js +28 -0
- package/dist/cjs/mcp/server.js +242 -0
- package/dist/cjs/mcp/types.js +32 -0
- package/dist/cjs/namespace.js +147 -19
- package/dist/cjs/policy/index.js +26 -0
- package/dist/cjs/policy/service.js +394 -0
- package/dist/cjs/policy/types.js +8 -0
- package/dist/esm/embedded/database.js +98 -4
- package/dist/esm/embedded/ffi/bindings.js +48 -8
- package/dist/esm/index.js +28 -6
- package/dist/esm/mcp/client.js +116 -0
- package/dist/esm/mcp/index.js +28 -0
- package/dist/esm/mcp/server.js +244 -0
- package/dist/esm/mcp/types.js +34 -0
- package/dist/esm/namespace.js +150 -19
- package/dist/esm/policy/index.js +26 -0
- package/dist/esm/policy/service.js +396 -0
- package/dist/esm/policy/types.js +8 -0
- package/dist/types/embedded/database.d.ts +66 -1
- package/dist/types/embedded/database.d.ts.map +1 -1
- package/dist/types/embedded/ffi/bindings.d.ts +7 -0
- package/dist/types/embedded/ffi/bindings.d.ts.map +1 -1
- package/dist/types/index.d.ts +23 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/mcp/client.d.ts +69 -0
- package/dist/types/mcp/client.d.ts.map +1 -0
- package/dist/types/mcp/index.d.ts +9 -0
- package/dist/types/mcp/index.d.ts.map +1 -0
- package/dist/types/mcp/server.d.ts +87 -0
- package/dist/types/mcp/server.d.ts.map +1 -0
- package/dist/types/mcp/types.d.ts +124 -0
- package/dist/types/mcp/types.d.ts.map +1 -0
- package/dist/types/namespace.d.ts +13 -0
- package/dist/types/namespace.d.ts.map +1 -1
- package/dist/types/policy/index.d.ts +8 -0
- package/dist/types/policy/index.d.ts.map +1 -0
- package/dist/types/policy/service.d.ts +115 -0
- package/dist/types/policy/service.d.ts.map +1 -0
- package/dist/types/policy/types.d.ts +102 -0
- package/dist/types/policy/types.d.ts.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,212 @@
|
|
|
1
1
|
# SochDB Node.js SDK
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**LLM-Optimized Embedded Database with Native Vector Search**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @sochdb/sochdb
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or from source:
|
|
14
|
+
```bash
|
|
15
|
+
cd sochdb-typescript-sdk
|
|
16
|
+
npm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Architecture: Flexible Deployment
|
|
22
|
+
|
|
23
|
+
**Tri-mode architecture: Embedded + Concurrent + Server (gRPC/IPC)**
|
|
4
24
|
Choose the deployment mode that fits your needs.
|
|
5
25
|
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# SochDB Node.js SDK Documentation
|
|
29
|
+
|
|
30
|
+
**LLM-Optimized Embedded Database with Native Vector Search**
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Table of Contents
|
|
35
|
+
|
|
36
|
+
1. [Quick Start](#1-quick-start)
|
|
37
|
+
2. [Installation](#2-installation)
|
|
38
|
+
3. [Features](#3-features)
|
|
39
|
+
- [Namespace API](#namespace-api---multi-tenant-isolation)
|
|
40
|
+
- [Priority Queue API](#priority-queue-api---task-processing)
|
|
41
|
+
4. [Architecture Overview](#4-architecture-overview)
|
|
42
|
+
5. [Core Key-Value Operations](#5-core-key-value-operations)
|
|
43
|
+
6. [Transactions (ACID with SSI)](#6-transactions-acid-with-ssi)
|
|
44
|
+
7. [Query Builder](#7-query-builder)
|
|
45
|
+
8. [Prefix Scanning](#8-prefix-scanning)
|
|
46
|
+
9. [SQL Operations](#9-sql-operations)
|
|
47
|
+
10. [Table Management & Index Policies](#10-table-management--index-policies)
|
|
48
|
+
11. [Namespaces & Collections](#11-namespaces--collections)
|
|
49
|
+
12. [Priority Queues](#12-priority-queues)
|
|
50
|
+
13. [Vector Search](#13-vector-search)
|
|
51
|
+
14. [Hybrid Search (Vector + BM25)](#14-hybrid-search-vector--bm25)
|
|
52
|
+
15. [Graph Operations](#15-graph-operations)
|
|
53
|
+
16. [Temporal Graph (Time-Travel)](#16-temporal-graph-time-travel)
|
|
54
|
+
17. [Semantic Cache](#17-semantic-cache)
|
|
55
|
+
18. [Memory System](#18-memory-system)
|
|
56
|
+
19. [Session Management](#19-session-management)
|
|
57
|
+
20. [Context Query Builder (LLM Optimization)](#20-context-query-builder-llm-optimization)
|
|
58
|
+
21. [Atomic Multi-Index Writes](#21-atomic-multi-index-writes)
|
|
59
|
+
22. [Recovery & WAL Management](#22-recovery--wal-management)
|
|
60
|
+
23. [Checkpoints & Snapshots](#23-checkpoints--snapshots)
|
|
61
|
+
24. [Compression & Storage](#24-compression--storage)
|
|
62
|
+
25. [Statistics & Monitoring](#25-statistics--monitoring)
|
|
63
|
+
26. [Distributed Tracing](#26-distributed-tracing)
|
|
64
|
+
27. [Workflow & Run Tracking](#27-workflow--run-tracking)
|
|
65
|
+
28. [Server Mode (gRPC Client)](#28-server-mode-grpc-client)
|
|
66
|
+
29. [IPC Client (Unix Sockets)](#29-ipc-client-unix-sockets)
|
|
67
|
+
30. [Standalone VectorIndex](#30-standalone-vectorindex)
|
|
68
|
+
31. [Vector Utilities](#31-vector-utilities)
|
|
69
|
+
32. [Data Formats (TOON/JSON/Columnar)](#32-data-formats-toonjsoncolumnar)
|
|
70
|
+
33. [Policy Service](#33-policy-service)
|
|
71
|
+
34. [MCP (Model Context Protocol)](#34-mcp-model-context-protocol)
|
|
72
|
+
35. [Configuration Reference](#35-configuration-reference)
|
|
73
|
+
36. [Error Handling](#36-error-handling)
|
|
74
|
+
37. [Async Support](#37-async-support)
|
|
75
|
+
38. [Building & Development](#38-building--development)
|
|
76
|
+
39. [Complete Examples](#39-complete-examples)
|
|
77
|
+
40. [Migration Guide](#40-migration-guide)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 1. Quick Start
|
|
82
|
+
|
|
83
|
+
### Concurrent Embedded Mode
|
|
84
|
+
|
|
85
|
+
For web applications with multiple Node.js processes (PM2 cluster, multiple workers):
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { EmbeddedDatabase } from '@sochdb/sochdb';
|
|
89
|
+
import express from 'express';
|
|
90
|
+
|
|
91
|
+
// Open in concurrent mode - multiple processes can access simultaneously
|
|
92
|
+
const db = EmbeddedDatabase.openConcurrent('./web_db');
|
|
93
|
+
|
|
94
|
+
const app = express();
|
|
95
|
+
|
|
96
|
+
app.get('/user/:id', async (req, res) => {
|
|
97
|
+
// Multiple concurrent requests can read simultaneously (~100ns)
|
|
98
|
+
const data = await db.get(Buffer.from(`user:${req.params.id}`));
|
|
99
|
+
if (!data) {
|
|
100
|
+
res.status(404).json({ error: 'not found' });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
res.send(data);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
app.post('/user/:id', async (req, res) => {
|
|
107
|
+
// Writes are automatically coordinated (~60µs amortized)
|
|
108
|
+
await db.put(Buffer.from(`user:${req.params.id}`), req.body);
|
|
109
|
+
res.json({ status: 'ok' });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Check concurrent mode status
|
|
113
|
+
console.log(`Concurrent mode: ${db.isConcurrent}`); // true
|
|
114
|
+
|
|
115
|
+
// Start with PM2 cluster mode (multiple workers can access DB)
|
|
116
|
+
// pm2 start app.js -i max
|
|
117
|
+
app.listen(3000);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Performance
|
|
121
|
+
|
|
122
|
+
| Operation | Standard Mode | Concurrent Mode |
|
|
123
|
+
|-----------|---------------|-----------------|
|
|
124
|
+
| Read (single process) | ~100ns | ~100ns |
|
|
125
|
+
| Read (multi-process) | **Blocked** ❌ | ~100ns ✅ |
|
|
126
|
+
| Write | ~5ms (fsync) | ~60µs (amortized) |
|
|
127
|
+
| Max concurrent readers | 1 | 1024 |
|
|
128
|
+
|
|
129
|
+
### PM2 Cluster Example
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Install PM2
|
|
133
|
+
npm install -g pm2
|
|
134
|
+
|
|
135
|
+
# Start with automatic worker scaling
|
|
136
|
+
pm2 start server.js -i max
|
|
137
|
+
|
|
138
|
+
# All workers can access the same database concurrently!
|
|
139
|
+
pm2 logs
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### PM2 Ecosystem File
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// ecosystem.config.js
|
|
146
|
+
module.exports = {
|
|
147
|
+
apps: [{
|
|
148
|
+
name: 'api-server',
|
|
149
|
+
script: './server.js',
|
|
150
|
+
instances: 'max', // Scale across all CPU cores
|
|
151
|
+
exec_mode: 'cluster',
|
|
152
|
+
env: {
|
|
153
|
+
NODE_ENV: 'production',
|
|
154
|
+
DB_PATH: './shared_db' // All workers use same DB
|
|
155
|
+
}
|
|
156
|
+
}]
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Deploy with ecosystem file
|
|
162
|
+
pm2 start ecosystem.config.js
|
|
163
|
+
|
|
164
|
+
# Monitor all workers
|
|
165
|
+
pm2 monit
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Docker Compose with PM2
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
version: '3.8'
|
|
172
|
+
services:
|
|
173
|
+
app:
|
|
174
|
+
build: .
|
|
175
|
+
environment:
|
|
176
|
+
- NODE_ENV=production
|
|
177
|
+
- INSTANCES=4 # 4 PM2 workers
|
|
178
|
+
volumes:
|
|
179
|
+
- ./data:/app/data # Shared database volume
|
|
180
|
+
ports:
|
|
181
|
+
- "3000:3000"
|
|
182
|
+
command: pm2-runtime start ecosystem.config.js
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Kubernetes Deployment
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
apiVersion: apps/v1
|
|
189
|
+
kind: Deployment
|
|
190
|
+
metadata:
|
|
191
|
+
name: sochdb-app
|
|
192
|
+
spec:
|
|
193
|
+
replicas: 4 # 4 pods share the database
|
|
194
|
+
template:
|
|
195
|
+
spec:
|
|
196
|
+
containers:
|
|
197
|
+
- name: app
|
|
198
|
+
image: myapp:latest
|
|
199
|
+
volumeMounts:
|
|
200
|
+
- name: db-storage
|
|
201
|
+
mountPath: /app/data
|
|
202
|
+
volumes:
|
|
203
|
+
- name: db-storage
|
|
204
|
+
persistentVolumeClaim:
|
|
205
|
+
claimName: sochdb-pvc # Shared PVC with ReadWriteMany
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
6
210
|
## Features
|
|
7
211
|
|
|
8
212
|
### Memory System - LLM-Native Memory for AI Agents
|
|
@@ -239,21 +443,161 @@ console.log(`Pending: ${stats.pending}, Completed: ${stats.completed}`);
|
|
|
239
443
|
|
|
240
444
|
---
|
|
241
445
|
|
|
242
|
-
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## System Requirements
|
|
449
|
+
|
|
450
|
+
### For Concurrent Mode
|
|
451
|
+
|
|
452
|
+
- **SochDB Core**: Latest version
|
|
453
|
+
- **Node.js**: 14.0+ (18.0+ recommended)
|
|
454
|
+
- **Native Library**: `libsochdb_storage.{dylib,so}`
|
|
455
|
+
- **FFI**: Koffi (automatically installed)
|
|
456
|
+
|
|
457
|
+
**Operating Systems:**
|
|
458
|
+
- ✅ Linux (Ubuntu 20.04+, RHEL 8+)
|
|
459
|
+
- ✅ macOS (10.15+, both Intel and Apple Silicon)
|
|
460
|
+
- ⚠️ Windows (requires native builds)
|
|
461
|
+
|
|
462
|
+
**File Descriptors:**
|
|
463
|
+
- Default limit: 1024 (sufficient for most workloads)
|
|
464
|
+
- For high concurrency with PM2: `ulimit -n 4096`
|
|
465
|
+
|
|
466
|
+
**Memory:**
|
|
467
|
+
- Standard mode: ~50MB base + data
|
|
468
|
+
- Concurrent mode: +4KB per concurrent reader slot (1024 slots = ~4MB overhead)
|
|
469
|
+
- PM2 cluster: Each worker has independent memory
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Troubleshooting
|
|
474
|
+
|
|
475
|
+
### "Database is locked" Error (Standard Mode)
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
Error: SQLITE_BUSY: database is locked
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Solution**: Use concurrent mode for multi-process access:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
// ❌ Standard mode - PM2 cluster will fail
|
|
485
|
+
const db = new EmbeddedDatabase('./data.db');
|
|
243
486
|
|
|
487
|
+
// ✅ Concurrent mode - PM2 cluster works!
|
|
488
|
+
const db = EmbeddedDatabase.openConcurrent('./data.db');
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Library Not Found Error
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
Error: Dynamic library 'libsochdb_storage.dylib' not found
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**macOS**:
|
|
244
498
|
```bash
|
|
245
|
-
|
|
499
|
+
# Build and install library
|
|
500
|
+
cd /path/to/sochdb
|
|
501
|
+
cargo build --release
|
|
502
|
+
sudo cp target/release/libsochdb_storage.dylib /usr/local/lib/
|
|
246
503
|
```
|
|
247
504
|
|
|
248
|
-
|
|
505
|
+
**Linux**:
|
|
249
506
|
```bash
|
|
250
|
-
cd sochdb
|
|
251
|
-
|
|
507
|
+
cd /path/to/sochdb
|
|
508
|
+
cargo build --release
|
|
509
|
+
sudo cp target/release/libsochdb_storage.so /usr/local/lib/
|
|
510
|
+
sudo ldconfig
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**Development Mode** (no install):
|
|
514
|
+
```bash
|
|
515
|
+
export DYLD_LIBRARY_PATH=/path/to/sochdb/target/release # macOS
|
|
516
|
+
export LD_LIBRARY_PATH=/path/to/sochdb/target/release # Linux
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### PM2 Cluster Issues
|
|
520
|
+
|
|
521
|
+
**Symptom**: Workers crash with "database locked"
|
|
522
|
+
|
|
523
|
+
**Solution**: Ensure concurrent mode is used:
|
|
524
|
+
```javascript
|
|
525
|
+
// ecosystem.config.js
|
|
526
|
+
module.exports = {
|
|
527
|
+
apps: [{
|
|
528
|
+
name: 'api',
|
|
529
|
+
script: './server.js',
|
|
530
|
+
instances: 4,
|
|
531
|
+
exec_mode: 'cluster',
|
|
532
|
+
env: {
|
|
533
|
+
USE_CONCURRENT_MODE: 'true' // Flag to use openConcurrent()
|
|
534
|
+
}
|
|
535
|
+
}]
|
|
536
|
+
};
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
// server.ts
|
|
541
|
+
const db = process.env.USE_CONCURRENT_MODE
|
|
542
|
+
? EmbeddedDatabase.openConcurrent('./db')
|
|
543
|
+
: new EmbeddedDatabase('./db');
|
|
544
|
+
|
|
545
|
+
console.log('Concurrent mode:', db.isConcurrent); // Should be true
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Docker Volume Permissions
|
|
549
|
+
|
|
550
|
+
**Symptom**: `EACCES: permission denied` when opening database
|
|
551
|
+
|
|
552
|
+
**Solution**: Fix volume ownership:
|
|
553
|
+
```dockerfile
|
|
554
|
+
FROM node:18
|
|
555
|
+
WORKDIR /app
|
|
556
|
+
|
|
557
|
+
# Create data directory with correct permissions
|
|
558
|
+
RUN mkdir -p /app/data && chown -R node:node /app
|
|
559
|
+
|
|
560
|
+
# Switch to non-root user
|
|
561
|
+
USER node
|
|
562
|
+
|
|
563
|
+
COPY --chown=node:node . .
|
|
564
|
+
RUN npm install
|
|
565
|
+
|
|
566
|
+
CMD ["npm", "start"]
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Performance Issues
|
|
570
|
+
|
|
571
|
+
**Symptom**: Concurrent reads slower than expected
|
|
572
|
+
|
|
573
|
+
**Check 1** - Verify concurrent mode:
|
|
574
|
+
```typescript
|
|
575
|
+
if (!db.isConcurrent) {
|
|
576
|
+
console.error('Database is not in concurrent mode!');
|
|
577
|
+
process.exit(1);
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Check 2** - Monitor PM2 workers:
|
|
582
|
+
```bash
|
|
583
|
+
pm2 monit # Real-time monitoring
|
|
584
|
+
pm2 logs --lines 200 # Check for errors
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Check 3** - Batch writes:
|
|
588
|
+
```typescript
|
|
589
|
+
// ❌ Slow - individual writes
|
|
590
|
+
for (const item of items) {
|
|
591
|
+
await collection.insert(item);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ✅ Fast - batch write
|
|
595
|
+
await collection.insertBatch(items);
|
|
252
596
|
```
|
|
253
597
|
|
|
254
598
|
---
|
|
255
599
|
|
|
256
|
-
## 🆕 Vector Search - Native HNSW
|
|
600
|
+
## 🆕 Vector Search - Native HNSW
|
|
257
601
|
|
|
258
602
|
SochDB now includes **native HNSW (Hierarchical Navigable Small World)** vector search for sub-millisecond similarity search across millions of vectors.
|
|
259
603
|
|
|
@@ -337,8 +681,6 @@ const results = await collection.search({ queryVector: [...], k: 10 });
|
|
|
337
681
|
- Direct HNSW API (above), OR
|
|
338
682
|
- gRPC Server Mode (see below)
|
|
339
683
|
|
|
340
|
-
**✅ Coming in v0.4.3:** Collection API will automatically use native HNSW
|
|
341
|
-
|
|
342
684
|
#### 3. gRPC Server Mode (Production-Ready)
|
|
343
685
|
|
|
344
686
|
For distributed systems, multi-language support:
|
|
@@ -440,15 +782,15 @@ class HnswIndex {
|
|
|
440
782
|
|
|
441
783
|
### Roadmap
|
|
442
784
|
|
|
443
|
-
- **
|
|
444
|
-
- **
|
|
445
|
-
- **
|
|
785
|
+
- **Current**: Direct HNSW FFI bindings
|
|
786
|
+
- **Next**: Collection API auto-uses HNSW in embedded mode
|
|
787
|
+
- **Future**: Persistent HNSW indexes with disk storage
|
|
446
788
|
|
|
447
789
|
---
|
|
448
790
|
|
|
449
791
|
# SochDB Node.js SDK Documentation
|
|
450
792
|
|
|
451
|
-
**
|
|
793
|
+
**LLM-Optimized Embedded Database with Native Vector Search**
|
|
452
794
|
|
|
453
795
|
---
|
|
454
796
|
|
|
@@ -3679,7 +4021,7 @@ A:
|
|
|
3679
4021
|
A: Yes! Both modes have the same API. Change `Database.open()` to `SochDBClient()` and vice versa.
|
|
3680
4022
|
|
|
3681
4023
|
**Q: Do temporal graphs work in embedded mode?**
|
|
3682
|
-
A: Yes!
|
|
4024
|
+
A: Yes! Temporal graphs work in both embedded and server modes with identical APIs.
|
|
3683
4025
|
|
|
3684
4026
|
**Q: Is embedded mode slower than server mode?**
|
|
3685
4027
|
A: Embedded mode is faster for single-process use (no network overhead). Server mode is better for distributed deployments.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -24,14 +24,20 @@ const transaction_1 = require("./transaction");
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
class EmbeddedDatabase {
|
|
27
|
-
constructor(path, handle) {
|
|
27
|
+
constructor(path, handle, concurrent = false, fallback = false) {
|
|
28
28
|
this.closed = false;
|
|
29
|
+
this.concurrent = false;
|
|
30
|
+
this._concurrentModeFallback = false;
|
|
29
31
|
this.path = path;
|
|
30
32
|
this.handle = handle;
|
|
33
|
+
this.concurrent = concurrent;
|
|
34
|
+
this._concurrentModeFallback = fallback;
|
|
31
35
|
this.bindings = bindings_1.NativeBindings.getInstance();
|
|
32
36
|
}
|
|
33
37
|
/**
|
|
34
|
-
* Open a database at the specified path
|
|
38
|
+
* Open a database at the specified path in standard mode
|
|
39
|
+
*
|
|
40
|
+
* For web applications with multiple processes, use `openConcurrent()` instead.
|
|
35
41
|
*
|
|
36
42
|
* @param path - Path to database directory
|
|
37
43
|
* @param config - Optional configuration
|
|
@@ -60,7 +66,95 @@ class EmbeddedDatabase {
|
|
|
60
66
|
if (!handle) {
|
|
61
67
|
throw new errors_1.DatabaseError(`Failed to open database at ${path}`);
|
|
62
68
|
}
|
|
63
|
-
return new EmbeddedDatabase(path, handle);
|
|
69
|
+
return new EmbeddedDatabase(path, handle, false);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Open a database in concurrent mode for multi-process web applications
|
|
73
|
+
*
|
|
74
|
+
* This mode allows multiple Node.js processes (e.g., PM2 cluster workers,
|
|
75
|
+
* multiple Express instances) to access the database simultaneously.
|
|
76
|
+
*
|
|
77
|
+
* Features:
|
|
78
|
+
* - Lock-free reads with ~100ns latency
|
|
79
|
+
* - Multi-reader, single-writer coordination
|
|
80
|
+
* - Automatic write serialization
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* import { EmbeddedDatabase } from '@sochdb/sochdb';
|
|
85
|
+
* import express from 'express';
|
|
86
|
+
*
|
|
87
|
+
* // Open in concurrent mode - multiple workers can access
|
|
88
|
+
* const db = EmbeddedDatabase.openConcurrent('./web_db');
|
|
89
|
+
*
|
|
90
|
+
* const app = express();
|
|
91
|
+
*
|
|
92
|
+
* app.get('/user/:id', async (req, res) => {
|
|
93
|
+
* // Multiple concurrent requests can read simultaneously
|
|
94
|
+
* const data = await db.get(Buffer.from(`user:${req.params.id}`));
|
|
95
|
+
* if (!data) {
|
|
96
|
+
* res.status(404).json({ error: 'not found' });
|
|
97
|
+
* return;
|
|
98
|
+
* }
|
|
99
|
+
* res.send(data);
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* app.post('/user/:id', async (req, res) => {
|
|
103
|
+
* // Writes are serialized automatically
|
|
104
|
+
* await db.put(Buffer.from(`user:${req.params.id}`), req.body);
|
|
105
|
+
* res.json({ status: 'ok' });
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* // Start with PM2 cluster mode:
|
|
109
|
+
* // pm2 start app.js -i max
|
|
110
|
+
* app.listen(3000);
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @param path - Path to database directory
|
|
114
|
+
* @param options - Optional configuration for concurrent mode
|
|
115
|
+
* @returns EmbeddedDatabase instance in concurrent mode
|
|
116
|
+
*/
|
|
117
|
+
static openConcurrent(path, options) {
|
|
118
|
+
const bindings = bindings_1.NativeBindings.getInstance();
|
|
119
|
+
const fallbackToStandard = options?.fallbackToStandard ?? false;
|
|
120
|
+
if (!bindings.isConcurrentModeAvailable()) {
|
|
121
|
+
if (fallbackToStandard) {
|
|
122
|
+
console.warn('[SochDB] Concurrent mode not available in native library (requires v0.4.8+). ' +
|
|
123
|
+
'Falling back to standard mode. For production multi-process deployments, ' +
|
|
124
|
+
'please upgrade the SochDB native library.');
|
|
125
|
+
const handle = bindings.sochdb_open(path);
|
|
126
|
+
if (!handle) {
|
|
127
|
+
throw new errors_1.DatabaseError(`Failed to open database at ${path}`);
|
|
128
|
+
}
|
|
129
|
+
return new EmbeddedDatabase(path, handle, false, true);
|
|
130
|
+
}
|
|
131
|
+
throw new errors_1.DatabaseError('Concurrent mode not supported. Please upgrade the SochDB native library to v0.4.8+ ' +
|
|
132
|
+
'or use openConcurrent(path, { fallbackToStandard: true }) to fall back to standard mode.');
|
|
133
|
+
}
|
|
134
|
+
const handle = bindings.sochdb_open_concurrent(path);
|
|
135
|
+
if (!handle) {
|
|
136
|
+
throw new errors_1.DatabaseError(`Failed to open database in concurrent mode at ${path}`);
|
|
137
|
+
}
|
|
138
|
+
const isConcurrent = bindings.sochdb_is_concurrent?.(handle) === 1;
|
|
139
|
+
return new EmbeddedDatabase(path, handle, isConcurrent, false);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if database is opened in concurrent mode
|
|
143
|
+
*/
|
|
144
|
+
get isConcurrent() {
|
|
145
|
+
return this.concurrent;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if concurrent mode fell back to standard mode
|
|
149
|
+
*/
|
|
150
|
+
get isConcurrentFallback() {
|
|
151
|
+
return this._concurrentModeFallback;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Check if concurrent mode is available in the native library
|
|
155
|
+
*/
|
|
156
|
+
static isConcurrentModeAvailable() {
|
|
157
|
+
return bindings_1.NativeBindings.getInstance().isConcurrentModeAvailable();
|
|
64
158
|
}
|
|
65
159
|
/**
|
|
66
160
|
* Put a key-value pair (auto-transaction)
|
|
@@ -233,4 +327,4 @@ class EmbeddedDatabase {
|
|
|
233
327
|
}
|
|
234
328
|
}
|
|
235
329
|
exports.EmbeddedDatabase = EmbeddedDatabase;
|
|
236
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZW1iZWRkZWQvZGF0YWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFFSCxzQ0FBMEM7QUFDMUMsNkNBQWdEO0FBQ2hELCtDQUFvRDtBQVdwRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFhLGdCQUFnQjtJQU16QixZQUFvQixJQUFZLEVBQUUsTUFBVztRQUhyQyxXQUFNLEdBQUcsS0FBSyxDQUFDO1FBSW5CLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcseUJBQWMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFZLEVBQUUsTUFBK0I7UUFDckQsTUFBTSxRQUFRLEdBQUcseUJBQWMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM5QyxJQUFJLE1BQU0sQ0FBQztRQUVYLElBQUksTUFBTSxFQUFFLENBQUM7WUFDVCxNQUFNLE9BQU8sR0FBRztnQkFDWixXQUFXLEVBQUUsTUFBTSxDQUFDLFVBQVUsSUFBSSxLQUFLO2dCQUN2QyxlQUFlLEVBQUUsTUFBTSxDQUFDLFVBQVUsS0FBSyxTQUFTO2dCQUNoRCxTQUFTLEVBQUUsTUFBTSxDQUFDLFFBQVEsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xGLGFBQWEsRUFBRSxNQUFNLENBQUMsUUFBUSxLQUFLLFNBQVM7Z0JBQzVDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLElBQUks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QUFDO1lBQzFDLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxtQkFBbUI7WUFDN0MsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQztZQUNwRCxpQkFBaUIsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDO1NBQ3ZELENBQUM7UUFFRixPQUFPLE1BQU0sQ0FBQztJQUNsQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUN2QixDQUFDO0lBQ0wsQ0FBQztJQUVPLFVBQVU7UUFDZCxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNkLE1BQU0sSUFBSSxzQkFBYSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDbEQsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTO1FBQ0wsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXO1FBQ1AsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3pCLENBQUM7Q0FDSjtBQTlPRCw0Q0E4T0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEVtYmVkZGVkIERhdGFiYXNlIC0gRkZJIE1vZGVcbiAqIFxuICogRGlyZWN0IEZGSSBhY2Nlc3MgdG8gU29jaERCIG5hdGl2ZSBsaWJyYXJ5LlxuICogTm8gc2VydmVyIHJlcXVpcmVkIC0gc2ltaWxhciB0byBQeXRob24gU0RLJ3MgRGF0YWJhc2UgY2xhc3MuXG4gKi9cblxuaW1wb3J0IHsgRGF0YWJhc2VFcnJvciB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBOYXRpdmVCaW5kaW5ncyB9IGZyb20gJy4vZmZpL2JpbmRpbmdzJztcbmltcG9ydCB7IEVtYmVkZGVkVHJhbnNhY3Rpb24gfSBmcm9tICcuL3RyYW5zYWN0aW9uJztcbmltcG9ydCAqIGFzIGtvZmZpIGZyb20gJ2tvZmZpJztcblxuZXhwb3J0IGludGVyZmFjZSBFbWJlZGRlZERhdGFiYXNlQ29uZmlnIHtcbiAgICB3YWxFbmFibGVkPzogYm9vbGVhbjtcbiAgICBzeW5jTW9kZT86ICdmdWxsJyB8ICdub3JtYWwnIHwgJ29mZic7XG4gICAgbWVtdGFibGVTaXplQnl0ZXM/OiBudW1iZXI7XG4gICAgZ3JvdXBDb21taXQ/OiBib29sZWFuO1xuICAgIGluZGV4UG9saWN5PzogJ3dyaXRlX29wdGltaXplZCcgfCAnYmFsYW5jZWQnIHwgJ3NjYW5fb3B0aW1pemVkJyB8ICdhcHBlbmRfb25seSc7XG59XG5cbi8qKlxuICogRW1iZWRkZWQgRGF0YWJhc2UgdXNpbmcgZGlyZWN0IEZGSVxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgRW1iZWRkZWREYXRhYmFzZSB9IGZyb20gJ0Bzb2NoZGIvc29jaGRiJztcbiAqIFxuICogY29uc3QgZGIgPSBhd2FpdCBFbWJlZGRlZERhdGFiYXNlLm9wZW4oJy4vbXlkYicpO1xuICogYXdhaXQgZGIucHV0KEJ1ZmZlci5mcm9tKCdrZXknKSwgQnVmZmVyLmZyb20oJ3ZhbHVlJykpO1xuICogY29uc3QgdmFsdWUgPSBhd2FpdCBkYi5nZXQoQnVmZmVyLmZyb20oJ2tleScpKTtcbiAqIGF3YWl0IGRiLmNsb3NlKCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIEVtYmVkZGVkRGF0YWJhc2Uge1xuICAgIHByaXZhdGUgaGFuZGxlOiBhbnk7XG4gICAgcHJpdmF0ZSBiaW5kaW5nczogTmF0aXZlQmluZGluZ3M7XG4gICAgcHJpdmF0ZSBjbG9zZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHBhdGg6IHN0cmluZztcblxuICAgIHByaXZhdGUgY29uc3RydWN0b3IocGF0aDogc3RyaW5nLCBoYW5kbGU6IGFueSkge1xuICAgICAgICB0aGlzLnBhdGggPSBwYXRoO1xuICAgICAgICB0aGlzLmhhbmRsZSA9IGhhbmRsZTtcbiAgICAgICAgdGhpcy5iaW5kaW5ncyA9IE5hdGl2ZUJpbmRpbmdzLmdldEluc3RhbmNlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbiBhIGRhdGFiYXNlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aFxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXRoIC0gUGF0aCB0byBkYXRhYmFzZSBkaXJlY3RvcnlcbiAgICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIEVtYmVkZGVkRGF0YWJhc2UgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBzdGF0aWMgb3BlbihwYXRoOiBzdHJpbmcsIGNvbmZpZz86IEVtYmVkZGVkRGF0YWJhc2VDb25maWcpOiBFbWJlZGRlZERhdGFiYXNlIHtcbiAgICAgICAgY29uc3QgYmluZGluZ3MgPSBOYXRpdmVCaW5kaW5ncy5nZXRJbnN0YW5jZSgpO1xuICAgICAgICBsZXQgaGFuZGxlO1xuXG4gICAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgICAgIGNvbnN0IGNDb25maWcgPSB7XG4gICAgICAgICAgICAgICAgd2FsX2VuYWJsZWQ6IGNvbmZpZy53YWxFbmFibGVkID8/IGZhbHNlLFxuICAgICAgICAgICAgICAgIHdhbF9lbmFibGVkX3NldDogY29uZmlnLndhbEVuYWJsZWQgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBzeW5jX21vZGU6IGNvbmZpZy5zeW5jTW9kZSA9PT0gJ2Z1bGwnID8gMiA6IChjb25maWcuc3luY01vZGUgPT09ICdub3JtYWwnID8gMSA6IDApLFxuICAgICAgICAgICAgICAgIHN5bmNfbW9kZV9zZXQ6IGNvbmZpZy5zeW5jTW9kZSAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIG1lbXRhYmxlX3NpemVfYnl0ZXM6IEJpZ0ludChjb25maWcubWVtdGFibGVTaXplQnl0ZXMgPz8gMCksXG4gICAgICAgICAgICAgICAgZ3JvdXBfY29tbWl0OiBjb25maWcuZ3JvdXBDb21taXQgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgZ3JvdXBfY29tbWl0X3NldDogY29uZmlnLmdyb3VwQ29tbWl0ICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgZGVmYXVsdF9pbmRleF9wb2xpY3k6IDEsIC8vIERlZmF1bHQgdG8gQmFsYW5jZWRcbiAgICAgICAgICAgICAgICBkZWZhdWx0X2luZGV4X3BvbGljeV9zZXQ6IGZhbHNlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaGFuZGxlID0gYmluZGluZ3Muc29jaGRiX29wZW5fd2l0aF9jb25maWcocGF0aCwgY0NvbmZpZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGUgPSBiaW5kaW5ncy5zb2NoZGJfb3BlbihwYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaGFuZGxlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcihgRmFpbGVkIHRvIG9wZW4gZGF0YWJhc2UgYXQgJHtwYXRofWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBFbWJlZGRlZERhdGFiYXNlKHBhdGgsIGhhbmRsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHV0IGEga2V5LXZhbHVlIHBhaXIgKGF1dG8tdHJhbnNhY3Rpb24pXG4gICAgICovXG4gICAgYXN5bmMgcHV0KGtleTogQnVmZmVyLCB2YWx1ZTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuXG4gICAgICAgIGNvbnN0IHR4biA9IHRoaXMudHJhbnNhY3Rpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5wdXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGEgdmFsdWUgYnkga2V5IChhdXRvLXRyYW5zYWN0aW9uKVxuICAgICAqL1xuICAgIGFzeW5jIGdldChrZXk6IEJ1ZmZlcik6IFByb21pc2U8QnVmZmVyIHwgbnVsbD4ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcblxuICAgICAgICBjb25zdCB0eG4gPSB0aGlzLnRyYW5zYWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHR4bi5nZXQoa2V5KTtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5jb21taXQoKTtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5hYm9ydCgpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGUgYSBrZXkgKGF1dG8tdHJhbnNhY3Rpb24pXG4gICAgICovXG4gICAgYXN5bmMgZGVsZXRlKGtleTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuXG4gICAgICAgIGNvbnN0IHR4biA9IHRoaXMudHJhbnNhY3Rpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5jb21taXQoKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5hYm9ydCgpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQdXQgdmFsdWUgYXQgcGF0aCAoYXV0by10cmFuc2FjdGlvbilcbiAgICAgKi9cbiAgICBhc3luYyBwdXRQYXRoKHBhdGg6IHN0cmluZywgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcblxuICAgICAgICBjb25zdCB0eG4gPSB0aGlzLnRyYW5zYWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4ucHV0UGF0aChwYXRoLCB2YWx1ZSk7XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHZhbHVlIGF0IHBhdGggKGF1dG8tdHJhbnNhY3Rpb24pXG4gICAgICovXG4gICAgYXN5bmMgZ2V0UGF0aChwYXRoOiBzdHJpbmcpOiBQcm9taXNlPEJ1ZmZlciB8IG51bGw+IHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgY29uc3QgdHhuID0gdGhpcy50cmFuc2FjdGlvbigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0eG4uZ2V0UGF0aChwYXRoKTtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5jb21taXQoKTtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5hYm9ydCgpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY2FuIGtleXMgd2l0aCBwcmVmaXhcbiAgICAgKi9cbiAgICBhc3luYyAqc2NhblByZWZpeChwcmVmaXg6IEJ1ZmZlcik6IEFzeW5jR2VuZXJhdG9yPFtCdWZmZXIsIEJ1ZmZlcl0+IHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgY29uc3QgdHhuID0gdGhpcy50cmFuc2FjdGlvbigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBlbnRyeSBvZiB0eG4uc2NhblByZWZpeChwcmVmaXgpKSB7XG4gICAgICAgICAgICAgICAgeWllbGQgZW50cnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQmVnaW4gYSB0cmFuc2FjdGlvblxuICAgICAqL1xuICAgIHRyYW5zYWN0aW9uKCk6IEVtYmVkZGVkVHJhbnNhY3Rpb24ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcblxuICAgICAgICBjb25zdCB0eG5IYW5kbGUgPSB0aGlzLmJpbmRpbmdzLnNvY2hkYl9iZWdpbl90eG4odGhpcy5oYW5kbGUpO1xuICAgICAgICByZXR1cm4gbmV3IEVtYmVkZGVkVHJhbnNhY3Rpb24odGhpcywgdGhpcy5oYW5kbGUsIHR4bkhhbmRsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSBvcGVyYXRpb25zIHdpdGhpbiBhIHRyYW5zYWN0aW9uICh3aXRoIGF1dG8tY29tbWl0L2Fib3J0KVxuICAgICAqL1xuICAgIGFzeW5jIHdpdGhUcmFuc2FjdGlvbjxUPihmbjogKHR4bjogRW1iZWRkZWRUcmFuc2FjdGlvbikgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICAgICAgICBjb25zdCB0eG4gPSB0aGlzLnRyYW5zYWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbih0eG4pO1xuICAgICAgICAgICAgYXdhaXQgdHhuLmNvbW1pdCgpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5hYm9ydCgpO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZSBhIGNoZWNrcG9pbnRcbiAgICAgKi9cbiAgICBhc3luYyBjaGVja3BvaW50KCk6IFByb21pc2U8YmlnaW50PiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuICAgICAgICBjb25zdCBsc24gPSB0aGlzLmJpbmRpbmdzLnNvY2hkYl9jaGVja3BvaW50KHRoaXMuaGFuZGxlKTtcbiAgICAgICAgcmV0dXJuIEJpZ0ludChsc24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBzdG9yYWdlIHN0YXRpc3RpY3NcbiAgICAgKi9cbiAgICBhc3luYyBzdGF0cygpOiBQcm9taXNlPHtcbiAgICAgICAgbWVtdGFibGVTaXplQnl0ZXM6IGJpZ2ludDtcbiAgICAgICAgd2FsU2l6ZUJ5dGVzOiBiaWdpbnQ7XG4gICAgICAgIGFjdGl2ZVRyYW5zYWN0aW9uczogbnVtYmVyO1xuICAgICAgICBtaW5BY3RpdmVTbmFwc2hvdDogYmlnaW50O1xuICAgICAgICBsYXN0Q2hlY2twb2ludExzbjogYmlnaW50O1xuICAgIH0+IHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgLy8gUmV0dXJucyBzdHJ1Y3QgYnkgdmFsdWUgKGF1dG9tYXRpY2FsbHkgZGVjb2RlZClcbiAgICAgICAgY29uc3Qgc3RhdHMgPSB0aGlzLmJpbmRpbmdzLnNvY2hkYl9zdGF0cyh0aGlzLmhhbmRsZSk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge1xuICAgICAgICAgICAgbWVtdGFibGVTaXplQnl0ZXM6IEJpZ0ludChzdGF0cy5tZW10YWJsZV9zaXplX2J5dGVzKSxcbiAgICAgICAgICAgIHdhbFNpemVCeXRlczogQmlnSW50KHN0YXRzLndhbF9zaXplX2J5dGVzKSxcbiAgICAgICAgICAgIGFjdGl2ZVRyYW5zYWN0aW9uczogc3RhdHMuYWN0aXZlX3RyYW5zYWN0aW9ucyxcbiAgICAgICAgICAgIG1pbkFjdGl2ZVNuYXBzaG90OiBCaWdJbnQoc3RhdHMubWluX2FjdGl2ZV9zbmFwc2hvdCksXG4gICAgICAgICAgICBsYXN0Q2hlY2twb2ludExzbjogQmlnSW50KHN0YXRzLmxhc3RfY2hlY2twb2ludF9sc24pLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xvc2UgdGhlIGRhdGFiYXNlXG4gICAgICovXG4gICAgY2xvc2UoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5jbG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYmluZGluZ3Muc29jaGRiX2Nsb3NlKHRoaXMuaGFuZGxlKTtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZW5zdXJlT3BlbigpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcignRGF0YWJhc2UgaXMgY2xvc2VkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgaW50ZXJuYWwgaGFuZGxlIChmb3IgdHJhbnNhY3Rpb25zKVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGdldEhhbmRsZSgpOiBhbnkge1xuICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGJpbmRpbmdzIGluc3RhbmNlIChmb3IgdHJhbnNhY3Rpb25zKVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGdldEJpbmRpbmdzKCk6IE5hdGl2ZUJpbmRpbmdzIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmluZGluZ3M7XG4gICAgfVxufVxuIl19
|
|
330
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZW1iZWRkZWQvZGF0YWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFFSCxzQ0FBMEM7QUFDMUMsNkNBQWdEO0FBQ2hELCtDQUFvRDtBQVdwRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFhLGdCQUFnQjtJQVF6QixZQUFvQixJQUFZLEVBQUUsTUFBVyxFQUFFLFVBQVUsR0FBRyxLQUFLLEVBQUUsUUFBUSxHQUFHLEtBQUs7UUFMM0UsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUVmLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbkIsNEJBQXVCLEdBQUcsS0FBSyxDQUFDO1FBR3BDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxRQUFRLENBQUM7UUFDeEMsSUFBSSxDQUFDLFFBQVEsR0FBRyx5QkFBYyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2pELENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBWSxFQUFFLE1BQStCO1FBQ3JELE1BQU0sUUFBUSxHQUFHLHlCQUFjLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDOUMsSUFBSSxNQUFNLENBQUM7UUFFWCxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1QsTUFBTSxPQUFPLEdBQUc7Z0JBQ1osV0FBVyxFQUFFLE1BQU0sQ0FBQyxVQUFVLElBQUksS0FBSztnQkFDdkMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEtBQUssU0FBUztnQkFDaEQsU0FBUyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFD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QWEsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2xELENBQUM7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBUztRQUNMLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVztRQUNQLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDO0NBQ0o7QUF2VkQsNENBdVZDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBFbWJlZGRlZCBEYXRhYmFzZSAtIEZGSSBNb2RlXG4gKiBcbiAqIERpcmVjdCBGRkkgYWNjZXNzIHRvIFNvY2hEQiBuYXRpdmUgbGlicmFyeS5cbiAqIE5vIHNlcnZlciByZXF1aXJlZCAtIHNpbWlsYXIgdG8gUHl0aG9uIFNESydzIERhdGFiYXNlIGNsYXNzLlxuICovXG5cbmltcG9ydCB7IERhdGFiYXNlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgTmF0aXZlQmluZGluZ3MgfSBmcm9tICcuL2ZmaS9iaW5kaW5ncyc7XG5pbXBvcnQgeyBFbWJlZGRlZFRyYW5zYWN0aW9uIH0gZnJvbSAnLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgKiBhcyBrb2ZmaSBmcm9tICdrb2ZmaSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW1iZWRkZWREYXRhYmFzZUNvbmZpZyB7XG4gICAgd2FsRW5hYmxlZD86IGJvb2xlYW47XG4gICAgc3luY01vZGU/OiAnZnVsbCcgfCAnbm9ybWFsJyB8ICdvZmYnO1xuICAgIG1lbXRhYmxlU2l6ZUJ5dGVzPzogbnVtYmVyO1xuICAgIGdyb3VwQ29tbWl0PzogYm9vbGVhbjtcbiAgICBpbmRleFBvbGljeT86ICd3cml0ZV9vcHRpbWl6ZWQnIHwgJ2JhbGFuY2VkJyB8ICdzY2FuX29wdGltaXplZCcgfCAnYXBwZW5kX29ubHknO1xufVxuXG4vKipcbiAqIEVtYmVkZGVkIERhdGFiYXNlIHVzaW5nIGRpcmVjdCBGRklcbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IEVtYmVkZGVkRGF0YWJhc2UgfSBmcm9tICdAc29jaGRiL3NvY2hkYic7XG4gKiBcbiAqIGNvbnN0IGRiID0gYXdhaXQgRW1iZWRkZWREYXRhYmFzZS5vcGVuKCcuL215ZGInKTtcbiAqIGF3YWl0IGRiLnB1dChCdWZmZXIuZnJvbSgna2V5JyksIEJ1ZmZlci5mcm9tKCd2YWx1ZScpKTtcbiAqIGNvbnN0IHZhbHVlID0gYXdhaXQgZGIuZ2V0KEJ1ZmZlci5mcm9tKCdrZXknKSk7XG4gKiBhd2FpdCBkYi5jbG9zZSgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBFbWJlZGRlZERhdGFiYXNlIHtcbiAgICBwcml2YXRlIGhhbmRsZTogYW55O1xuICAgIHByaXZhdGUgYmluZGluZ3M6IE5hdGl2ZUJpbmRpbmdzO1xuICAgIHByaXZhdGUgY2xvc2VkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBwYXRoOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBjb25jdXJyZW50ID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfY29uY3VycmVudE1vZGVGYWxsYmFjayA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihwYXRoOiBzdHJpbmcsIGhhbmRsZTogYW55LCBjb25jdXJyZW50ID0gZmFsc2UsIGZhbGxiYWNrID0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5wYXRoID0gcGF0aDtcbiAgICAgICAgdGhpcy5oYW5kbGUgPSBoYW5kbGU7XG4gICAgICAgIHRoaXMuY29uY3VycmVudCA9IGNvbmN1cnJlbnQ7XG4gICAgICAgIHRoaXMuX2NvbmN1cnJlbnRNb2RlRmFsbGJhY2sgPSBmYWxsYmFjaztcbiAgICAgICAgdGhpcy5iaW5kaW5ncyA9IE5hdGl2ZUJpbmRpbmdzLmdldEluc3RhbmNlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3BlbiBhIGRhdGFiYXNlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aCBpbiBzdGFuZGFyZCBtb2RlXG4gICAgICogXG4gICAgICogRm9yIHdlYiBhcHBsaWNhdGlvbnMgd2l0aCBtdWx0aXBsZSBwcm9jZXNzZXMsIHVzZSBgb3BlbkNvbmN1cnJlbnQoKWAgaW5zdGVhZC5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gcGF0aCAtIFBhdGggdG8gZGF0YWJhc2UgZGlyZWN0b3J5XG4gICAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAcmV0dXJucyBFbWJlZGRlZERhdGFiYXNlIGluc3RhbmNlXG4gICAgICovXG4gICAgc3RhdGljIG9wZW4ocGF0aDogc3RyaW5nLCBjb25maWc/OiBFbWJlZGRlZERhdGFiYXNlQ29uZmlnKTogRW1iZWRkZWREYXRhYmFzZSB7XG4gICAgICAgIGNvbnN0IGJpbmRpbmdzID0gTmF0aXZlQmluZGluZ3MuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgbGV0IGhhbmRsZTtcblxuICAgICAgICBpZiAoY29uZmlnKSB7XG4gICAgICAgICAgICBjb25zdCBjQ29uZmlnID0ge1xuICAgICAgICAgICAgICAgIHdhbF9lbmFibGVkOiBjb25maWcud2FsRW5hYmxlZCA/PyBmYWxzZSxcbiAgICAgICAgICAgICAgICB3YWxfZW5hYmxlZF9zZXQ6IGNvbmZpZy53YWxFbmFibGVkICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgc3luY19tb2RlOiBjb25maWcuc3luY01vZGUgPT09ICdmdWxsJyA/IDIgOiAoY29uZmlnLnN5bmNNb2RlID09PSAnbm9ybWFsJyA/IDEgOiAwKSxcbiAgICAgICAgICAgICAgICBzeW5jX21vZGVfc2V0OiBjb25maWcuc3luY01vZGUgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBtZW10YWJsZV9zaXplX2J5dGVzOiBCaWdJbnQoY29uZmlnLm1lbXRhYmxlU2l6ZUJ5dGVzID8/IDApLFxuICAgICAgICAgICAgICAgIGdyb3VwX2NvbW1pdDogY29uZmlnLmdyb3VwQ29tbWl0ID8/IGZhbHNlLFxuICAgICAgICAgICAgICAgIGdyb3VwX2NvbW1pdF9zZXQ6IGNvbmZpZy5ncm91cENvbW1pdCAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGRlZmF1bHRfaW5kZXhfcG9saWN5OiAxLCAvLyBEZWZhdWx0IHRvIEJhbGFuY2VkXG4gICAgICAgICAgICAgICAgZGVmYXVsdF9pbmRleF9wb2xpY3lfc2V0OiBmYWxzZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGhhbmRsZSA9IGJpbmRpbmdzLnNvY2hkYl9vcGVuX3dpdGhfY29uZmlnKHBhdGgsIGNDb25maWcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlID0gYmluZGluZ3Muc29jaGRiX29wZW4ocGF0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhhbmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IERhdGFiYXNlRXJyb3IoYEZhaWxlZCB0byBvcGVuIGRhdGFiYXNlIGF0ICR7cGF0aH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgRW1iZWRkZWREYXRhYmFzZShwYXRoLCBoYW5kbGUsIGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPcGVuIGEgZGF0YWJhc2UgaW4gY29uY3VycmVudCBtb2RlIGZvciBtdWx0aS1wcm9jZXNzIHdlYiBhcHBsaWNhdGlvbnNcbiAgICAgKiBcbiAgICAgKiBUaGlzIG1vZGUgYWxsb3dzIG11bHRpcGxlIE5vZGUuanMgcHJvY2Vzc2VzIChlLmcuLCBQTTIgY2x1c3RlciB3b3JrZXJzLFxuICAgICAqIG11bHRpcGxlIEV4cHJlc3MgaW5zdGFuY2VzKSB0byBhY2Nlc3MgdGhlIGRhdGFiYXNlIHNpbXVsdGFuZW91c2x5LlxuICAgICAqIFxuICAgICAqIEZlYXR1cmVzOlxuICAgICAqIC0gTG9jay1mcmVlIHJlYWRzIHdpdGggfjEwMG5zIGxhdGVuY3lcbiAgICAgKiAtIE11bHRpLXJlYWRlciwgc2luZ2xlLXdyaXRlciBjb29yZGluYXRpb25cbiAgICAgKiAtIEF1dG9tYXRpYyB3cml0ZSBzZXJpYWxpemF0aW9uXG4gICAgICogXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogaW1wb3J0IHsgRW1iZWRkZWREYXRhYmFzZSB9IGZyb20gJ0Bzb2NoZGIvc29jaGRiJztcbiAgICAgKiBpbXBvcnQgZXhwcmVzcyBmcm9tICdleHByZXNzJztcbiAgICAgKiBcbiAgICAgKiAvLyBPcGVuIGluIGNvbmN1cnJlbnQgbW9kZSAtIG11bHRpcGxlIHdvcmtlcnMgY2FuIGFjY2Vzc1xuICAgICAqIGNvbnN0IGRiID0gRW1iZWRkZWREYXRhYmFzZS5vcGVuQ29uY3VycmVudCgnLi93ZWJfZGInKTtcbiAgICAgKiBcbiAgICAgKiBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gICAgICogXG4gICAgICogYXBwLmdldCgnL3VzZXIvOmlkJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgICogICAvLyBNdWx0aXBsZSBjb25jdXJyZW50IHJlcXVlc3RzIGNhbiByZWFkIHNpbXVsdGFuZW91c2x5XG4gICAgICogICBjb25zdCBkYXRhID0gYXdhaXQgZGIuZ2V0KEJ1ZmZlci5mcm9tKGB1c2VyOiR7cmVxLnBhcmFtcy5pZH1gKSk7XG4gICAgICogICBpZiAoIWRhdGEpIHtcbiAgICAgKiAgICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oeyBlcnJvcjogJ25vdCBmb3VuZCcgfSk7XG4gICAgICogICAgIHJldHVybjtcbiAgICAgKiAgIH1cbiAgICAgKiAgIHJlcy5zZW5kKGRhdGEpO1xuICAgICAqIH0pO1xuICAgICAqIFxuICAgICAqIGFwcC5wb3N0KCcvdXNlci86aWQnLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICAgKiAgIC8vIFdyaXRlcyBhcmUgc2VyaWFsaXplZCBhdXRvbWF0aWNhbGx5XG4gICAgICogICBhd2FpdCBkYi5wdXQoQnVmZmVyLmZyb20oYHVzZXI6JHtyZXEucGFyYW1zLmlkfWApLCByZXEuYm9keSk7XG4gICAgICogICByZXMuanNvbih7IHN0YXR1czogJ29rJyB9KTtcbiAgICAgKiB9KTtcbiAgICAgKiBcbiAgICAgKiAvLyBTdGFydCB3aXRoIFBNMiBjbHVzdGVyIG1vZGU6XG4gICAgICogLy8gcG0yIHN0YXJ0IGFwcC5qcyAtaSBtYXhcbiAgICAgKiBhcHAubGlzdGVuKDMwMDApO1xuICAgICAqIGBgYFxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXRoIC0gUGF0aCB0byBkYXRhYmFzZSBkaXJlY3RvcnlcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24gZm9yIGNvbmN1cnJlbnQgbW9kZVxuICAgICAqIEByZXR1cm5zIEVtYmVkZGVkRGF0YWJhc2UgaW5zdGFuY2UgaW4gY29uY3VycmVudCBtb2RlXG4gICAgICovXG4gICAgc3RhdGljIG9wZW5Db25jdXJyZW50KHBhdGg6IHN0cmluZywgb3B0aW9ucz86IHsgZmFsbGJhY2tUb1N0YW5kYXJkPzogYm9vbGVhbiB9KTogRW1iZWRkZWREYXRhYmFzZSB7XG4gICAgICAgIGNvbnN0IGJpbmRpbmdzID0gTmF0aXZlQmluZGluZ3MuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgY29uc3QgZmFsbGJhY2tUb1N0YW5kYXJkID0gb3B0aW9ucz8uZmFsbGJhY2tUb1N0YW5kYXJkID8/IGZhbHNlO1xuICAgICAgICBcbiAgICAgICAgaWYgKCFiaW5kaW5ncy5pc0NvbmN1cnJlbnRNb2RlQXZhaWxhYmxlKCkpIHtcbiAgICAgICAgICAgIGlmIChmYWxsYmFja1RvU3RhbmRhcmQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgICAgICdbU29jaERCXSBDb25jdXJyZW50IG1vZGUgbm90IGF2YWlsYWJsZSBpbiBuYXRpdmUgbGlicmFyeSAocmVxdWlyZXMgdjAuNC44KykuICcgK1xuICAgICAgICAgICAgICAgICAgICAnRmFsbGluZyBiYWNrIHRvIHN0YW5kYXJkIG1vZGUuIEZvciBwcm9kdWN0aW9uIG11bHRpLXByb2Nlc3MgZGVwbG95bWVudHMsICcgK1xuICAgICAgICAgICAgICAgICAgICAncGxlYXNlIHVwZ3JhZGUgdGhlIFNvY2hEQiBuYXRpdmUgbGlicmFyeS4nXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGUgPSBiaW5kaW5ncy5zb2NoZGJfb3BlbihwYXRoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWhhbmRsZSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcihgRmFpbGVkIHRvIG9wZW4gZGF0YWJhc2UgYXQgJHtwYXRofWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEVtYmVkZGVkRGF0YWJhc2UocGF0aCwgaGFuZGxlLCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRGF0YWJhc2VFcnJvcihcbiAgICAgICAgICAgICAgICAnQ29uY3VycmVudCBtb2RlIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSB1cGdyYWRlIHRoZSBTb2NoREIgbmF0aXZlIGxpYnJhcnkgdG8gdjAuNC44KyAnICtcbiAgICAgICAgICAgICAgICAnb3IgdXNlIG9wZW5Db25jdXJyZW50KHBhdGgsIHsgZmFsbGJhY2tUb1N0YW5kYXJkOiB0cnVlIH0pIHRvIGZhbGwgYmFjayB0byBzdGFuZGFyZCBtb2RlLidcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBoYW5kbGUgPSBiaW5kaW5ncy5zb2NoZGJfb3Blbl9jb25jdXJyZW50KHBhdGgpO1xuICAgICAgICBpZiAoIWhhbmRsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IERhdGFiYXNlRXJyb3IoYEZhaWxlZCB0byBvcGVuIGRhdGFiYXNlIGluIGNvbmN1cnJlbnQgbW9kZSBhdCAke3BhdGh9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc0NvbmN1cnJlbnQgPSBiaW5kaW5ncy5zb2NoZGJfaXNfY29uY3VycmVudD8uKGhhbmRsZSkgPT09IDE7XG4gICAgICAgIHJldHVybiBuZXcgRW1iZWRkZWREYXRhYmFzZShwYXRoLCBoYW5kbGUsIGlzQ29uY3VycmVudCwgZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGRhdGFiYXNlIGlzIG9wZW5lZCBpbiBjb25jdXJyZW50IG1vZGVcbiAgICAgKi9cbiAgICBnZXQgaXNDb25jdXJyZW50KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25jdXJyZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGNvbmN1cnJlbnQgbW9kZSBmZWxsIGJhY2sgdG8gc3RhbmRhcmQgbW9kZVxuICAgICAqL1xuICAgIGdldCBpc0NvbmN1cnJlbnRGYWxsYmFjaygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbmN1cnJlbnRNb2RlRmFsbGJhY2s7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgY29uY3VycmVudCBtb2RlIGlzIGF2YWlsYWJsZSBpbiB0aGUgbmF0aXZlIGxpYnJhcnlcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNDb25jdXJyZW50TW9kZUF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIE5hdGl2ZUJpbmRpbmdzLmdldEluc3RhbmNlKCkuaXNDb25jdXJyZW50TW9kZUF2YWlsYWJsZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFB1dCBhIGtleS12YWx1ZSBwYWlyIChhdXRvLXRyYW5zYWN0aW9uKVxuICAgICAqL1xuICAgIGFzeW5jIHB1dChrZXk6IEJ1ZmZlciwgdmFsdWU6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcblxuICAgICAgICBjb25zdCB0eG4gPSB0aGlzLnRyYW5zYWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4ucHV0KGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgYXdhaXQgdHhuLmNvbW1pdCgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgYXdhaXQgdHhuLmFib3J0KCk7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIHZhbHVlIGJ5IGtleSAoYXV0by10cmFuc2FjdGlvbilcbiAgICAgKi9cbiAgICBhc3luYyBnZXQoa2V5OiBCdWZmZXIpOiBQcm9taXNlPEJ1ZmZlciB8IG51bGw+IHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgY29uc3QgdHhuID0gdGhpcy50cmFuc2FjdGlvbigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCB0eG4uZ2V0KGtleSk7XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVsZXRlIGEga2V5IChhdXRvLXRyYW5zYWN0aW9uKVxuICAgICAqL1xuICAgIGFzeW5jIGRlbGV0ZShrZXk6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcblxuICAgICAgICBjb25zdCB0eG4gPSB0aGlzLnRyYW5zYWN0aW9uKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uZGVsZXRlKGtleSk7XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHV0IHZhbHVlIGF0IHBhdGggKGF1dG8tdHJhbnNhY3Rpb24pXG4gICAgICovXG4gICAgYXN5bmMgcHV0UGF0aChwYXRoOiBzdHJpbmcsIHZhbHVlOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgY29uc3QgdHhuID0gdGhpcy50cmFuc2FjdGlvbigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdHhuLnB1dFBhdGgocGF0aCwgdmFsdWUpO1xuICAgICAgICAgICAgYXdhaXQgdHhuLmNvbW1pdCgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgYXdhaXQgdHhuLmFib3J0KCk7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB2YWx1ZSBhdCBwYXRoIChhdXRvLXRyYW5zYWN0aW9uKVxuICAgICAqL1xuICAgIGFzeW5jIGdldFBhdGgocGF0aDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuXG4gICAgICAgIGNvbnN0IHR4biA9IHRoaXMudHJhbnNhY3Rpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgdHhuLmdldFBhdGgocGF0aCk7XG4gICAgICAgICAgICBhd2FpdCB0eG4uY29tbWl0KCk7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2NhbiBrZXlzIHdpdGggcHJlZml4XG4gICAgICovXG4gICAgYXN5bmMgKnNjYW5QcmVmaXgocHJlZml4OiBCdWZmZXIpOiBBc3luY0dlbmVyYXRvcjxbQnVmZmVyLCBCdWZmZXJdPiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuXG4gICAgICAgIGNvbnN0IHR4biA9IHRoaXMudHJhbnNhY3Rpb24oKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgZW50cnkgb2YgdHhuLnNjYW5QcmVmaXgocHJlZml4KSkge1xuICAgICAgICAgICAgICAgIHlpZWxkIGVudHJ5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgdHhuLmNvbW1pdCgpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgYXdhaXQgdHhuLmFib3J0KCk7XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJlZ2luIGEgdHJhbnNhY3Rpb25cbiAgICAgKi9cbiAgICB0cmFuc2FjdGlvbigpOiBFbWJlZGRlZFRyYW5zYWN0aW9uIHtcbiAgICAgICAgdGhpcy5lbnN1cmVPcGVuKCk7XG5cbiAgICAgICAgY29uc3QgdHhuSGFuZGxlID0gdGhpcy5iaW5kaW5ncy5zb2NoZGJfYmVnaW5fdHhuKHRoaXMuaGFuZGxlKTtcbiAgICAgICAgcmV0dXJuIG5ldyBFbWJlZGRlZFRyYW5zYWN0aW9uKHRoaXMsIHRoaXMuaGFuZGxlLCB0eG5IYW5kbGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGUgb3BlcmF0aW9ucyB3aXRoaW4gYSB0cmFuc2FjdGlvbiAod2l0aCBhdXRvLWNvbW1pdC9hYm9ydClcbiAgICAgKi9cbiAgICBhc3luYyB3aXRoVHJhbnNhY3Rpb248VD4oZm46ICh0eG46IEVtYmVkZGVkVHJhbnNhY3Rpb24pID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgY29uc3QgdHhuID0gdGhpcy50cmFuc2FjdGlvbigpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4odHhuKTtcbiAgICAgICAgICAgIGF3YWl0IHR4bi5jb21taXQoKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhd2FpdCB0eG4uYWJvcnQoKTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2UgYSBjaGVja3BvaW50XG4gICAgICovXG4gICAgYXN5bmMgY2hlY2twb2ludCgpOiBQcm9taXNlPGJpZ2ludD4ge1xuICAgICAgICB0aGlzLmVuc3VyZU9wZW4oKTtcbiAgICAgICAgY29uc3QgbHNuID0gdGhpcy5iaW5kaW5ncy5zb2NoZGJfY2hlY2twb2ludCh0aGlzLmhhbmRsZSk7XG4gICAgICAgIHJldHVybiBCaWdJbnQobHNuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgc3RvcmFnZSBzdGF0aXN0aWNzXG4gICAgICovXG4gICAgYXN5bmMgc3RhdHMoKTogUHJvbWlzZTx7XG4gICAgICAgIG1lbXRhYmxlU2l6ZUJ5dGVzOiBiaWdpbnQ7XG4gICAgICAgIHdhbFNpemVCeXRlczogYmlnaW50O1xuICAgICAgICBhY3RpdmVUcmFuc2FjdGlvbnM6IG51bWJlcjtcbiAgICAgICAgbWluQWN0aXZlU25hcHNob3Q6IGJpZ2ludDtcbiAgICAgICAgbGFzdENoZWNrcG9pbnRMc246IGJpZ2ludDtcbiAgICB9PiB7XG4gICAgICAgIHRoaXMuZW5zdXJlT3BlbigpO1xuXG4gICAgICAgIC8vIFJldHVybnMgc3RydWN0IGJ5IHZhbHVlIChhdXRvbWF0aWNhbGx5IGRlY29kZWQpXG4gICAgICAgIGNvbnN0IHN0YXRzID0gdGhpcy5iaW5kaW5ncy5zb2NoZGJfc3RhdHModGhpcy5oYW5kbGUpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgICAgICAgIG1lbXRhYmxlU2l6ZUJ5dGVzOiBCaWdJbnQoc3RhdHMubWVtdGFibGVfc2l6ZV9ieXRlcyksXG4gICAgICAgICAgICB3YWxTaXplQnl0ZXM6IEJpZ0ludChzdGF0cy53YWxfc2l6ZV9ieXRlcyksXG4gICAgICAgICAgICBhY3RpdmVUcmFuc2FjdGlvbnM6IHN0YXRzLmFjdGl2ZV90cmFuc2FjdGlvbnMsXG4gICAgICAgICAgICBtaW5BY3RpdmVTbmFwc2hvdDogQmlnSW50KHN0YXRzLm1pbl9hY3RpdmVfc25hcHNob3QpLFxuICAgICAgICAgICAgbGFzdENoZWNrcG9pbnRMc246IEJpZ0ludChzdGF0cy5sYXN0X2NoZWNrcG9pbnRfbHNuKSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlIHRoZSBkYXRhYmFzZVxuICAgICAqL1xuICAgIGNsb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuY2xvc2VkKSB7XG4gICAgICAgICAgICB0aGlzLmJpbmRpbmdzLnNvY2hkYl9jbG9zZSh0aGlzLmhhbmRsZSk7XG4gICAgICAgICAgICB0aGlzLmNsb3NlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGVuc3VyZU9wZW4oKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmNsb3NlZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IERhdGFiYXNlRXJyb3IoJ0RhdGFiYXNlIGlzIGNsb3NlZCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGludGVybmFsIGhhbmRsZSAoZm9yIHRyYW5zYWN0aW9ucylcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBnZXRIYW5kbGUoKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBiaW5kaW5ncyBpbnN0YW5jZSAoZm9yIHRyYW5zYWN0aW9ucylcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBnZXRCaW5kaW5ncygpOiBOYXRpdmVCaW5kaW5ncyB7XG4gICAgICAgIHJldHVybiB0aGlzLmJpbmRpbmdzO1xuICAgIH1cbn1cbiJdfQ==
|