Skip to content

Commit 8e6aa29

Browse files
authored
Merge pull request #290 from underctrl-io/kv
feat: kv api
2 parents ab46d92 + c302d8f commit 8e6aa29

File tree

11 files changed

+2532
-1
lines changed

11 files changed

+2532
-1
lines changed
Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
---
2+
title: "KV"
3+
isDefaultIndex: false
4+
generated: true
5+
---
6+
7+
import MemberInfo from '@site/src/components/MemberInfo';
8+
import GenerationInfo from '@site/src/components/GenerationInfo';
9+
import MemberDescription from '@site/src/components/MemberDescription';
10+
11+
<!-- This file was generated from the CommandKit source. Do not modify. Instead, re-run the "docgen" script -->
12+
13+
14+
## KV
15+
16+
<GenerationInfo sourceFile="packages/commandkit/src/kv/kv.ts" sourceLine="30" packageName="commandkit" />
17+
18+
A key-value store implementation using SQLite
19+
20+
This class provides a simple, persistent key-value storage solution
21+
with support for namespaces, automatic cleanup, iteration, and expiration.
22+
23+
24+
25+
*Example*
26+
27+
```typescript
28+
const kv = new KV('data.db');
29+
kv.set('user:123', JSON.stringify({ name: 'John', age: 30 }));
30+
const user = JSON.parse(kv.get('user:123') || '{}');
31+
32+
// Using namespaces
33+
const userKv = kv.namespace('users');
34+
userKv.set('123', JSON.stringify({ name: 'John' }));
35+
```
36+
37+
```ts title="Signature"
38+
class KV implements Disposable, AsyncDisposable {
39+
constructor(path: string | Buffer | URL | DatabaseSync, options: KvOptions = {
40+
enableWAL: true,
41+
namespace: 'commandkit_kv',
42+
})
43+
isOpen() => boolean;
44+
getDatabase() => DatabaseSync;
45+
close() => void;
46+
[Symbol.dispose]() => ;
47+
[Symbol.asyncDispose]() => ;
48+
get(key: string) => string | undefined;
49+
set(key: string, value: string) => void;
50+
setex(key: string, value: string, ttl: number) => void;
51+
expire(key: string, ttl: number) => boolean;
52+
ttl(key: string) => number;
53+
delete(key: string) => void;
54+
has(key: string) => boolean;
55+
keys() => string[];
56+
values() => string[];
57+
count() => number;
58+
clear() => void;
59+
all() => Record<string, string>;
60+
namespaces() => string[];
61+
getCurrentNamespace() => string;
62+
namespace(namespace: string) => KV;
63+
[Symbol.iterator]() => Iterator<[string, string]>;
64+
transaction(fn: () => T | Promise<T>) => Promise<T>;
65+
}
66+
```
67+
* Implements: <code>Disposable</code>, <code>AsyncDisposable</code>
68+
69+
70+
71+
<div className="members-wrapper">
72+
73+
### constructor
74+
75+
<MemberInfo kind="method" type={`(path: string | Buffer | URL | DatabaseSync, options: <a href='/docs/next/api-reference/commandkit/interfaces/kv-options#kvoptions'>KvOptions</a> = {
76+
enableWAL: true,
77+
namespace: 'commandkit_kv',
78+
}) => KV`} />
79+
80+
Creates a new KV store instance
81+
### isOpen
82+
83+
<MemberInfo kind="method" type={`() => boolean`} />
84+
85+
Checks if the database connection is open
86+
### getDatabase
87+
88+
<MemberInfo kind="method" type={`() => DatabaseSync`} />
89+
90+
Gets the underlying SQLite database instance
91+
### close
92+
93+
<MemberInfo kind="method" type={`() => void`} />
94+
95+
Closes the database connection
96+
### \[Symbol.dispose]
97+
98+
<MemberInfo kind="method" type={`() => `} />
99+
100+
Disposable implementation - closes the database when disposed
101+
### \[Symbol.asyncDispose]
102+
103+
<MemberInfo kind="method" type={`() => `} />
104+
105+
AsyncDisposable implementation - closes the database when disposed
106+
### get
107+
108+
<MemberInfo kind="method" type={`(key: string) => string | undefined`} />
109+
110+
Retrieves a value by key
111+
112+
113+
114+
*Example*
115+
116+
```typescript
117+
const value = kv.get('my-key');
118+
if (value) {
119+
console.log('Found:', value);
120+
}
121+
```
122+
### set
123+
124+
<MemberInfo kind="method" type={`(key: string, value: string) => void`} />
125+
126+
Sets a key-value pair
127+
128+
129+
130+
*Example*
131+
132+
```typescript
133+
kv.set('user:123', JSON.stringify({ name: 'John' }));
134+
kv.set('counter', '42');
135+
```
136+
### setex
137+
138+
<MemberInfo kind="method" type={`(key: string, value: string, ttl: number) => void`} />
139+
140+
Sets a key-value pair with expiration
141+
142+
143+
144+
*Example*
145+
146+
```typescript
147+
// Set with 1 hour expiration
148+
kv.setex('session:123', 'user_data', 60 * 60 * 1000);
149+
150+
// Set with 5 minutes expiration
151+
kv.setex('temp:data', 'cached_value', 5 * 60 * 1000);
152+
```
153+
### expire
154+
155+
<MemberInfo kind="method" type={`(key: string, ttl: number) => boolean`} />
156+
157+
Sets expiration for an existing key
158+
159+
160+
161+
*Example*
162+
163+
```typescript
164+
kv.set('user:123', 'user_data');
165+
166+
// Set 30 minute expiration
167+
if (kv.expire('user:123', 30 * 60 * 1000)) {
168+
console.log('Expiration set successfully');
169+
}
170+
```
171+
### ttl
172+
173+
<MemberInfo kind="method" type={`(key: string) => number`} />
174+
175+
Gets the time to live for a key
176+
177+
178+
179+
*Example*
180+
181+
```typescript
182+
const ttl = kv.ttl('user:123');
183+
if (ttl > 0) {
184+
console.log(`Key expires in ${ttl}ms`);
185+
} else if (ttl === -2) {
186+
console.log('Key has no expiration');
187+
} else {
188+
console.log('Key does not exist');
189+
}
190+
```
191+
### delete
192+
193+
<MemberInfo kind="method" type={`(key: string) => void`} />
194+
195+
Deletes a key-value pair
196+
197+
198+
199+
*Example*
200+
201+
```typescript
202+
kv.delete('user:123');
203+
```
204+
### has
205+
206+
<MemberInfo kind="method" type={`(key: string) => boolean`} />
207+
208+
Checks if a key exists and is not expired
209+
210+
211+
212+
*Example*
213+
214+
```typescript
215+
if (kv.has('user:123')) {
216+
console.log('User exists and is not expired');
217+
}
218+
```
219+
### keys
220+
221+
<MemberInfo kind="method" type={`() => string[]`} />
222+
223+
Gets all keys in the current namespace (excluding expired keys)
224+
225+
226+
227+
*Example*
228+
229+
```typescript
230+
const keys = kv.keys();
231+
console.log('All keys:', keys);
232+
```
233+
### values
234+
235+
<MemberInfo kind="method" type={`() => string[]`} />
236+
237+
Gets all values in the current namespace (excluding expired keys)
238+
239+
240+
241+
*Example*
242+
243+
```typescript
244+
const values = kv.values();
245+
console.log('All values:', values);
246+
```
247+
### count
248+
249+
<MemberInfo kind="method" type={`() => number`} />
250+
251+
Gets the total number of key-value pairs in the current namespace (excluding expired keys)
252+
253+
254+
255+
*Example*
256+
257+
```typescript
258+
const count = kv.count();
259+
console.log(`Total entries: ${count}`);
260+
```
261+
### clear
262+
263+
<MemberInfo kind="method" type={`() => void`} />
264+
265+
Removes all key-value pairs from the current namespace
266+
267+
268+
269+
*Example*
270+
271+
```typescript
272+
kv.clear(); // Removes all entries in current namespace
273+
```
274+
### all
275+
276+
<MemberInfo kind="method" type={`() => Record&#60;string, string&#62;`} />
277+
278+
Gets all key-value pairs as an object (excluding expired keys)
279+
280+
281+
282+
*Example*
283+
284+
```typescript
285+
const all = kv.all();
286+
console.log('All entries:', all);
287+
// Output: { 'key1': 'value1', 'key2': 'value2' }
288+
```
289+
### namespaces
290+
291+
<MemberInfo kind="method" type={`() => string[]`} />
292+
293+
Gets all available namespaces (tables) in the database
294+
295+
296+
297+
*Example*
298+
299+
```typescript
300+
const namespaces = kv.namespaces();
301+
console.log('Available namespaces:', namespaces);
302+
```
303+
### getCurrentNamespace
304+
305+
<MemberInfo kind="method" type={`() => string`} />
306+
307+
Gets the current namespace name
308+
### namespace
309+
310+
<MemberInfo kind="method" type={`(namespace: string) => <a href='/docs/next/api-reference/commandkit/classes/kv#kv'>KV</a>`} />
311+
312+
Creates a new KV instance with a different namespace
313+
314+
315+
316+
*Example*
317+
318+
```typescript
319+
const userKv = kv.namespace('users');
320+
const configKv = kv.namespace('config');
321+
322+
userKv.set('123', 'John Doe');
323+
configKv.set('theme', 'dark');
324+
```
325+
### \[Symbol.iterator]
326+
327+
<MemberInfo kind="method" type={`() => Iterator&#60;[string, string]&#62;`} />
328+
329+
Iterator implementation for iterating over all non-expired key-value pairs
330+
331+
332+
333+
*Example*
334+
335+
```typescript
336+
for (const [key, value] of kv) {
337+
console.log(`${key}: ${value}`);
338+
}
339+
340+
// Or using spread operator
341+
const entries = [...kv];
342+
```
343+
### transaction
344+
345+
<MemberInfo kind="method" type={`(fn: () =&#62; T | Promise&#60;T&#62;) => Promise&#60;T&#62;`} />
346+
347+
Executes a function within a transaction
348+
349+
350+
351+
*Example*
352+
353+
```typescript
354+
// Synchronous transaction
355+
kv.transaction(() => {
356+
kv.set('user:123', JSON.stringify({ name: 'John' }));
357+
kv.set('user:456', JSON.stringify({ name: 'Jane' }));
358+
// If any operation fails, all changes are rolled back
359+
});
360+
361+
// Async transaction
362+
await kv.transaction(async () => {
363+
kv.set('user:123', JSON.stringify({ name: 'John' }));
364+
await someAsyncOperation();
365+
kv.set('user:456', JSON.stringify({ name: 'Jane' }));
366+
// If any operation fails, all changes are rolled back
367+
});
368+
```
369+
370+
371+
</div>

0 commit comments

Comments
 (0)