@stratadb/core 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +125 -0
- package/Cargo.lock +1169 -0
- package/Cargo.toml +25 -0
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/__tests__/strata.test.js +217 -0
- package/build.rs +5 -0
- package/index.d.ts +536 -0
- package/index.js +236 -0
- package/jest.config.js +5 -0
- package/npm/darwin-arm64/README.md +3 -0
- package/npm/darwin-arm64/package.json +41 -0
- package/npm/darwin-x64/README.md +3 -0
- package/npm/darwin-x64/package.json +41 -0
- package/npm/linux-arm64-gnu/README.md +3 -0
- package/npm/linux-arm64-gnu/package.json +44 -0
- package/npm/linux-arm64-musl/README.md +3 -0
- package/npm/linux-arm64-musl/package.json +44 -0
- package/npm/linux-x64-gnu/README.md +3 -0
- package/npm/linux-x64-gnu/package.json +44 -0
- package/npm/linux-x64-musl/README.md +3 -0
- package/npm/linux-x64-musl/package.json +44 -0
- package/npm/win32-x64-msvc/README.md +3 -0
- package/npm/win32-x64-msvc/package.json +41 -0
- package/package.json +67 -0
- package/src/lib.rs +775 -0
package/Cargo.toml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "stratadb-node"
|
|
3
|
+
version = "0.6.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
description = "Node.js bindings for StrataDB"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
repository = "https://github.com/stratadb-labs/strata-node"
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
crate-type = ["cdylib"]
|
|
11
|
+
|
|
12
|
+
[dependencies]
|
|
13
|
+
napi = { version = "2", features = ["napi8", "async", "serde-json"] }
|
|
14
|
+
napi-derive = "2"
|
|
15
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
16
|
+
serde_json = "1.0"
|
|
17
|
+
|
|
18
|
+
# Use git dependency during development
|
|
19
|
+
stratadb = { git = "https://github.com/stratadb-labs/strata-core", branch = "main" }
|
|
20
|
+
|
|
21
|
+
[build-dependencies]
|
|
22
|
+
napi-build = "2"
|
|
23
|
+
|
|
24
|
+
[profile.release]
|
|
25
|
+
lto = true
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Strata
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# strata-node
|
|
2
|
+
|
|
3
|
+
Node.js SDK for [StrataDB](https://github.com/strata-systems/strata-core) - an embedded database for AI agents.
|
|
4
|
+
|
|
5
|
+
NAPI-RS bindings embedding the Rust library directly in a native Node.js addon. No network hop, no serialization overhead beyond the Node/Rust boundary.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### From npm (coming soon)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install stratadb
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### From Source
|
|
16
|
+
|
|
17
|
+
Requires Rust toolchain and Node.js:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/strata-systems/strata-node.git
|
|
21
|
+
cd strata-node
|
|
22
|
+
npm install
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
const { Strata } = require('stratadb');
|
|
30
|
+
|
|
31
|
+
// Open a database (or use Strata.cache() for in-memory)
|
|
32
|
+
const db = Strata.open('/path/to/data');
|
|
33
|
+
|
|
34
|
+
// Key-value storage
|
|
35
|
+
db.kvPut('user:123', 'Alice');
|
|
36
|
+
console.log(db.kvGet('user:123')); // "Alice"
|
|
37
|
+
|
|
38
|
+
// Branch isolation (like git branches)
|
|
39
|
+
db.createBranch('experiment');
|
|
40
|
+
db.setBranch('experiment');
|
|
41
|
+
console.log(db.kvGet('user:123')); // null - isolated
|
|
42
|
+
|
|
43
|
+
// Space organization within branches
|
|
44
|
+
db.setSpace('conversations');
|
|
45
|
+
db.kvPut('msg_001', 'hello');
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
### Six Data Primitives
|
|
51
|
+
|
|
52
|
+
| Primitive | Purpose | Key Methods |
|
|
53
|
+
|-----------|---------|-------------|
|
|
54
|
+
| **KV Store** | Working memory, config | `kvPut`, `kvGet`, `kvDelete`, `kvList` |
|
|
55
|
+
| **Event Log** | Immutable audit trail | `eventAppend`, `eventGet`, `eventList` |
|
|
56
|
+
| **State Cell** | CAS-based coordination | `stateSet`, `stateGet`, `stateCas` |
|
|
57
|
+
| **JSON Store** | Structured documents | `jsonSet`, `jsonGet`, `jsonDelete` |
|
|
58
|
+
| **Vector Store** | Embeddings, similarity search | `vectorUpsert`, `vectorSearch` |
|
|
59
|
+
| **Branch** | Data isolation | `createBranch`, `setBranch`, `forkBranch` |
|
|
60
|
+
|
|
61
|
+
### Vector Operations
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Create a collection
|
|
65
|
+
db.vectorCreateCollection('embeddings', 384, 'cosine');
|
|
66
|
+
|
|
67
|
+
// Upsert with array
|
|
68
|
+
const embedding = new Array(384).fill(0).map(() => Math.random());
|
|
69
|
+
db.vectorUpsert('embeddings', 'doc-1', embedding, { title: 'Hello' });
|
|
70
|
+
|
|
71
|
+
// Search returns matches with scores
|
|
72
|
+
const results = db.vectorSearch('embeddings', embedding, 10);
|
|
73
|
+
for (const match of results) {
|
|
74
|
+
console.log(`${match.key}: ${match.score}`);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Branch Operations
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
// Fork current branch (copies all data)
|
|
82
|
+
db.forkBranch('experiment');
|
|
83
|
+
|
|
84
|
+
// Compare branches
|
|
85
|
+
const diff = db.diffBranches('default', 'experiment');
|
|
86
|
+
console.log(`Added: ${diff.summary.totalAdded}`);
|
|
87
|
+
|
|
88
|
+
// Merge branches
|
|
89
|
+
const result = db.mergeBranches('experiment', 'last_writer_wins');
|
|
90
|
+
console.log(`Keys applied: ${result.keysApplied}`);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Event Log
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
// Append events
|
|
97
|
+
db.eventAppend('tool_call', { tool: 'search', query: 'weather' });
|
|
98
|
+
db.eventAppend('tool_call', { tool: 'calculator', expr: '2+2' });
|
|
99
|
+
|
|
100
|
+
// Get by sequence number
|
|
101
|
+
const event = db.eventGet(0);
|
|
102
|
+
|
|
103
|
+
// List by type
|
|
104
|
+
const toolCalls = db.eventList('tool_call');
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Compare-and-Swap (Version-based)
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
// Initialize if not exists
|
|
111
|
+
db.stateInit('counter', 0);
|
|
112
|
+
|
|
113
|
+
// CAS is version-based - pass expected version, not expected value
|
|
114
|
+
// Get current value and its version via stateSet (returns version)
|
|
115
|
+
const version = db.stateSet('counter', 1);
|
|
116
|
+
|
|
117
|
+
// Update only if version matches
|
|
118
|
+
const newVersion = db.stateCas('counter', 2, version); // (cell, new_value, expected_version)
|
|
119
|
+
if (newVersion === null) {
|
|
120
|
+
console.log('CAS failed - version mismatch');
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API Reference
|
|
125
|
+
|
|
126
|
+
### Strata
|
|
127
|
+
|
|
128
|
+
| Method | Description |
|
|
129
|
+
|--------|-------------|
|
|
130
|
+
| `Strata.open(path)` | Open database at path |
|
|
131
|
+
| `Strata.cache()` | Create in-memory database |
|
|
132
|
+
|
|
133
|
+
### KV Store
|
|
134
|
+
|
|
135
|
+
| Method | Description |
|
|
136
|
+
|--------|-------------|
|
|
137
|
+
| `kvPut(key, value)` | Store a value |
|
|
138
|
+
| `kvGet(key)` | Get a value (returns null if missing) |
|
|
139
|
+
| `kvDelete(key)` | Delete a key |
|
|
140
|
+
| `kvList(prefix?)` | List keys |
|
|
141
|
+
| `kvHistory(key)` | Get version history |
|
|
142
|
+
|
|
143
|
+
### State Cell
|
|
144
|
+
|
|
145
|
+
| Method | Description |
|
|
146
|
+
|--------|-------------|
|
|
147
|
+
| `stateSet(cell, value)` | Set value |
|
|
148
|
+
| `stateGet(cell)` | Get value |
|
|
149
|
+
| `stateInit(cell, value)` | Initialize if not exists |
|
|
150
|
+
| `stateCas(cell, newValue, expectedVersion?)` | Compare-and-swap (version-based) |
|
|
151
|
+
| `stateHistory(cell)` | Get version history |
|
|
152
|
+
|
|
153
|
+
### Event Log
|
|
154
|
+
|
|
155
|
+
| Method | Description |
|
|
156
|
+
|--------|-------------|
|
|
157
|
+
| `eventAppend(type, payload)` | Append event |
|
|
158
|
+
| `eventGet(sequence)` | Get by sequence |
|
|
159
|
+
| `eventList(type)` | List by type |
|
|
160
|
+
| `eventLen()` | Get count |
|
|
161
|
+
|
|
162
|
+
### JSON Store
|
|
163
|
+
|
|
164
|
+
| Method | Description |
|
|
165
|
+
|--------|-------------|
|
|
166
|
+
| `jsonSet(key, path, value)` | Set at JSONPath |
|
|
167
|
+
| `jsonGet(key, path)` | Get at JSONPath |
|
|
168
|
+
| `jsonDelete(key, path)` | Delete |
|
|
169
|
+
| `jsonHistory(key)` | Get version history |
|
|
170
|
+
| `jsonList(limit, prefix?, cursor?)` | List keys |
|
|
171
|
+
|
|
172
|
+
### Vector Store
|
|
173
|
+
|
|
174
|
+
| Method | Description |
|
|
175
|
+
|--------|-------------|
|
|
176
|
+
| `vectorCreateCollection(name, dim, metric?)` | Create collection |
|
|
177
|
+
| `vectorDeleteCollection(name)` | Delete collection |
|
|
178
|
+
| `vectorListCollections()` | List collections |
|
|
179
|
+
| `vectorUpsert(collection, key, vector, metadata?)` | Insert/update |
|
|
180
|
+
| `vectorGet(collection, key)` | Get vector |
|
|
181
|
+
| `vectorDelete(collection, key)` | Delete vector |
|
|
182
|
+
| `vectorSearch(collection, query, k)` | Search |
|
|
183
|
+
| `vectorCollectionStats(collection)` | Get collection statistics |
|
|
184
|
+
| `vectorBatchUpsert(collection, vectors)` | Batch insert/update vectors |
|
|
185
|
+
|
|
186
|
+
### Branches
|
|
187
|
+
|
|
188
|
+
| Method | Description |
|
|
189
|
+
|--------|-------------|
|
|
190
|
+
| `currentBranch()` | Get current branch |
|
|
191
|
+
| `setBranch(name)` | Switch branch |
|
|
192
|
+
| `createBranch(name)` | Create empty branch |
|
|
193
|
+
| `forkBranch(dest)` | Fork with data copy |
|
|
194
|
+
| `listBranches()` | List all branches |
|
|
195
|
+
| `deleteBranch(name)` | Delete branch |
|
|
196
|
+
| `branchExists(name)` | Check if branch exists |
|
|
197
|
+
| `branchGet(name)` | Get branch metadata |
|
|
198
|
+
| `diffBranches(a, b)` | Compare branches |
|
|
199
|
+
| `mergeBranches(source, strategy?)` | Merge into current |
|
|
200
|
+
|
|
201
|
+
### Spaces
|
|
202
|
+
|
|
203
|
+
| Method | Description |
|
|
204
|
+
|--------|-------------|
|
|
205
|
+
| `currentSpace()` | Get current space |
|
|
206
|
+
| `setSpace(name)` | Switch space |
|
|
207
|
+
| `listSpaces()` | List spaces |
|
|
208
|
+
| `deleteSpace(name)` | Delete space |
|
|
209
|
+
| `deleteSpaceForce(name)` | Force delete space |
|
|
210
|
+
|
|
211
|
+
### Database
|
|
212
|
+
|
|
213
|
+
| Method | Description |
|
|
214
|
+
|--------|-------------|
|
|
215
|
+
| `ping()` | Health check |
|
|
216
|
+
| `info()` | Get database info |
|
|
217
|
+
| `flush()` | Flush to disk |
|
|
218
|
+
| `compact()` | Trigger compaction |
|
|
219
|
+
|
|
220
|
+
### Bundle Operations
|
|
221
|
+
|
|
222
|
+
| Method | Description |
|
|
223
|
+
|--------|-------------|
|
|
224
|
+
| `branchExport(branch, path)` | Export branch to bundle file |
|
|
225
|
+
| `branchImport(path)` | Import branch from bundle file |
|
|
226
|
+
| `branchValidateBundle(path)` | Validate bundle file |
|
|
227
|
+
|
|
228
|
+
## TypeScript
|
|
229
|
+
|
|
230
|
+
Full TypeScript definitions are included:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
import { Strata, JsonValue, SearchMatch } from 'stratadb';
|
|
234
|
+
|
|
235
|
+
const db = Strata.cache();
|
|
236
|
+
db.kvPut('key', { count: 42 });
|
|
237
|
+
const value: JsonValue = db.kvGet('key');
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Development
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Install dev dependencies
|
|
244
|
+
npm install
|
|
245
|
+
|
|
246
|
+
# Build native module
|
|
247
|
+
npm run build
|
|
248
|
+
|
|
249
|
+
# Run tests
|
|
250
|
+
npm test
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for the StrataDB Node.js SDK.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { Strata } = require('../index');
|
|
6
|
+
|
|
7
|
+
describe('Strata', () => {
|
|
8
|
+
let db;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
db = Strata.cache();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('KV Store', () => {
|
|
15
|
+
test('put and get', () => {
|
|
16
|
+
db.kvPut('key1', 'value1');
|
|
17
|
+
expect(db.kvGet('key1')).toBe('value1');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('put and get object', () => {
|
|
21
|
+
db.kvPut('config', { theme: 'dark', count: 42 });
|
|
22
|
+
const result = db.kvGet('config');
|
|
23
|
+
expect(result.theme).toBe('dark');
|
|
24
|
+
expect(result.count).toBe(42);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('get missing returns null', () => {
|
|
28
|
+
expect(db.kvGet('nonexistent')).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('delete', () => {
|
|
32
|
+
db.kvPut('to_delete', 'value');
|
|
33
|
+
expect(db.kvDelete('to_delete')).toBe(true);
|
|
34
|
+
expect(db.kvGet('to_delete')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('list', () => {
|
|
38
|
+
db.kvPut('user:1', 'alice');
|
|
39
|
+
db.kvPut('user:2', 'bob');
|
|
40
|
+
db.kvPut('item:1', 'book');
|
|
41
|
+
|
|
42
|
+
const allKeys = db.kvList();
|
|
43
|
+
expect(allKeys.length).toBe(3);
|
|
44
|
+
|
|
45
|
+
const userKeys = db.kvList('user:');
|
|
46
|
+
expect(userKeys.length).toBe(2);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('State Cell', () => {
|
|
51
|
+
test('set and get', () => {
|
|
52
|
+
db.stateSet('counter', 100);
|
|
53
|
+
expect(db.stateGet('counter')).toBe(100);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('init', () => {
|
|
57
|
+
db.stateInit('status', 'pending');
|
|
58
|
+
expect(db.stateGet('status')).toBe('pending');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('cas', () => {
|
|
62
|
+
// CAS is version-based, not value-based
|
|
63
|
+
const version = db.stateSet('value', 1);
|
|
64
|
+
// Try to update with correct version
|
|
65
|
+
const newVersion = db.stateCas('value', 2, version);
|
|
66
|
+
expect(newVersion).not.toBeNull();
|
|
67
|
+
expect(db.stateGet('value')).toBe(2);
|
|
68
|
+
// Try with wrong version - should fail
|
|
69
|
+
const result = db.stateCas('value', 3, 999);
|
|
70
|
+
expect(result).toBeNull(); // CAS failed
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('Event Log', () => {
|
|
75
|
+
test('append and get', () => {
|
|
76
|
+
db.eventAppend('user_action', { action: 'click', target: 'button' });
|
|
77
|
+
expect(db.eventLen()).toBe(1);
|
|
78
|
+
|
|
79
|
+
const event = db.eventGet(0);
|
|
80
|
+
expect(event).not.toBeNull();
|
|
81
|
+
expect(event.value.action).toBe('click');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('list by type', () => {
|
|
85
|
+
db.eventAppend('click', { x: 10 });
|
|
86
|
+
db.eventAppend('scroll', { y: 100 });
|
|
87
|
+
db.eventAppend('click', { x: 20 });
|
|
88
|
+
|
|
89
|
+
const clicks = db.eventList('click');
|
|
90
|
+
expect(clicks.length).toBe(2);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('JSON Store', () => {
|
|
95
|
+
test('set and get', () => {
|
|
96
|
+
db.jsonSet('config', '$', { theme: 'dark', lang: 'en' });
|
|
97
|
+
const result = db.jsonGet('config', '$');
|
|
98
|
+
expect(result.theme).toBe('dark');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('get path', () => {
|
|
102
|
+
db.jsonSet('config', '$', { theme: 'dark', lang: 'en' });
|
|
103
|
+
const theme = db.jsonGet('config', '$.theme');
|
|
104
|
+
expect(theme).toBe('dark');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('list', () => {
|
|
108
|
+
db.jsonSet('doc1', '$', { a: 1 });
|
|
109
|
+
db.jsonSet('doc2', '$', { b: 2 });
|
|
110
|
+
const result = db.jsonList(100); // limit is required
|
|
111
|
+
expect(result.keys.length).toBe(2);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Vector Store', () => {
|
|
116
|
+
test('create collection', () => {
|
|
117
|
+
db.vectorCreateCollection('embeddings', 4);
|
|
118
|
+
const collections = db.vectorListCollections();
|
|
119
|
+
expect(collections.some((c) => c.name === 'embeddings')).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('upsert and search', () => {
|
|
123
|
+
db.vectorCreateCollection('embeddings', 4);
|
|
124
|
+
|
|
125
|
+
const v1 = [1.0, 0.0, 0.0, 0.0];
|
|
126
|
+
const v2 = [0.0, 1.0, 0.0, 0.0];
|
|
127
|
+
|
|
128
|
+
db.vectorUpsert('embeddings', 'v1', v1);
|
|
129
|
+
db.vectorUpsert('embeddings', 'v2', v2);
|
|
130
|
+
|
|
131
|
+
const results = db.vectorSearch('embeddings', v1, 2);
|
|
132
|
+
expect(results.length).toBe(2);
|
|
133
|
+
expect(results[0].key).toBe('v1'); // Most similar
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('upsert with metadata', () => {
|
|
137
|
+
db.vectorCreateCollection('docs', 4);
|
|
138
|
+
const vec = [1.0, 0.0, 0.0, 0.0];
|
|
139
|
+
db.vectorUpsert('docs', 'doc1', vec, { title: 'Hello' });
|
|
140
|
+
|
|
141
|
+
const result = db.vectorGet('docs', 'doc1');
|
|
142
|
+
expect(result.metadata.title).toBe('Hello');
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('Branches', () => {
|
|
147
|
+
test('create and list', () => {
|
|
148
|
+
db.createBranch('feature');
|
|
149
|
+
const branches = db.listBranches();
|
|
150
|
+
expect(branches).toContain('default');
|
|
151
|
+
expect(branches).toContain('feature');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test('switch', () => {
|
|
155
|
+
db.kvPut('x', 1);
|
|
156
|
+
db.createBranch('feature');
|
|
157
|
+
db.setBranch('feature');
|
|
158
|
+
|
|
159
|
+
// Data isolated in new branch
|
|
160
|
+
expect(db.kvGet('x')).toBeNull();
|
|
161
|
+
|
|
162
|
+
db.kvPut('x', 2);
|
|
163
|
+
db.setBranch('default');
|
|
164
|
+
expect(db.kvGet('x')).toBe(1);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('fork', () => {
|
|
168
|
+
db.kvPut('shared', 'original');
|
|
169
|
+
const result = db.forkBranch('forked');
|
|
170
|
+
expect(result.keysCopied).toBeGreaterThan(0);
|
|
171
|
+
|
|
172
|
+
db.setBranch('forked');
|
|
173
|
+
expect(db.kvGet('shared')).toBe('original');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('current branch', () => {
|
|
177
|
+
expect(db.currentBranch()).toBe('default');
|
|
178
|
+
db.createBranch('test');
|
|
179
|
+
db.setBranch('test');
|
|
180
|
+
expect(db.currentBranch()).toBe('test');
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
describe('Spaces', () => {
|
|
185
|
+
test('list spaces', () => {
|
|
186
|
+
const spaces = db.listSpaces();
|
|
187
|
+
expect(spaces).toContain('default');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('switch space', () => {
|
|
191
|
+
db.kvPut('key', 'value1');
|
|
192
|
+
db.setSpace('other');
|
|
193
|
+
expect(db.kvGet('key')).toBeNull();
|
|
194
|
+
|
|
195
|
+
db.kvPut('key', 'value2');
|
|
196
|
+
db.setSpace('default');
|
|
197
|
+
expect(db.kvGet('key')).toBe('value1');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('current space', () => {
|
|
201
|
+
expect(db.currentSpace()).toBe('default');
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe('Database', () => {
|
|
206
|
+
test('ping', () => {
|
|
207
|
+
const version = db.ping();
|
|
208
|
+
expect(version).toBeTruthy();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test('info', () => {
|
|
212
|
+
const info = db.info();
|
|
213
|
+
expect(info.version).toBeTruthy();
|
|
214
|
+
expect(info.branchCount).toBeGreaterThanOrEqual(1);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|