commandkit 1.0.0-dev.20250703020519 → 1.0.0-dev.20250703125152
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/dist/cli/information.js +1 -1
- package/dist/constants-Br1y2J-P.d.ts +19 -0
- package/dist/constants-DYSMm0U6.js +27 -0
- package/dist/constants-DYSMm0U6.js.map +1 -0
- package/dist/dotprops-C22abhGZ.js +36 -0
- package/dist/dotprops-C22abhGZ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/kv/constants.d.ts +2 -0
- package/dist/kv/constants.js +3 -0
- package/dist/kv/dotprops.d.ts +6 -0
- package/dist/kv/dotprops.js +4 -0
- package/dist/kv/kv.d.ts +77 -35
- package/dist/kv/kv.js +142 -59
- package/dist/kv/kv.js.map +1 -1
- package/dist/kv/serde.d.ts +3 -0
- package/dist/kv/serde.js +5 -0
- package/dist/serde-4EKSAKpL.d.ts +12 -0
- package/dist/serde-CXY4F7OD.js +97 -0
- package/dist/serde-CXY4F7OD.js.map +1 -0
- package/dist/{version-BCFBQoh8.js → version-BGji_hXj.js} +2 -2
- package/dist/{version-BCFBQoh8.js.map → version-BGji_hXj.js.map} +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/cli/information.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require('../chunk-nOFOJqeH.js');
|
|
2
|
-
const require_version = require('../version-
|
|
2
|
+
const require_version = require('../version-BGji_hXj.js');
|
|
3
3
|
const node_fs = require_chunk.__toESM(require("node:fs"));
|
|
4
4
|
const node_path = require_chunk.__toESM(require("node:path"));
|
|
5
5
|
const node_child_process = require_chunk.__toESM(require("node:child_process"));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/kv/constants.d.ts
|
|
2
|
+
declare enum SerializerType {
|
|
3
|
+
String = 0,
|
|
4
|
+
Number = 1,
|
|
5
|
+
Boolean = 2,
|
|
6
|
+
Object = 3,
|
|
7
|
+
Date = 4,
|
|
8
|
+
BigInt = 5,
|
|
9
|
+
Null = 6,
|
|
10
|
+
Undefined = 7,
|
|
11
|
+
Array = 8,
|
|
12
|
+
Map = 9,
|
|
13
|
+
Set = 10,
|
|
14
|
+
Buffer = 11,
|
|
15
|
+
RegExp = 12,
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { SerializerType };
|
|
19
|
+
//# sourceMappingURL=constants-Br1y2J-P.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/kv/constants.ts
|
|
3
|
+
let SerializerType = /* @__PURE__ */ function(SerializerType$1) {
|
|
4
|
+
SerializerType$1[SerializerType$1["String"] = 0] = "String";
|
|
5
|
+
SerializerType$1[SerializerType$1["Number"] = 1] = "Number";
|
|
6
|
+
SerializerType$1[SerializerType$1["Boolean"] = 2] = "Boolean";
|
|
7
|
+
SerializerType$1[SerializerType$1["Object"] = 3] = "Object";
|
|
8
|
+
SerializerType$1[SerializerType$1["Date"] = 4] = "Date";
|
|
9
|
+
SerializerType$1[SerializerType$1["BigInt"] = 5] = "BigInt";
|
|
10
|
+
SerializerType$1[SerializerType$1["Null"] = 6] = "Null";
|
|
11
|
+
SerializerType$1[SerializerType$1["Undefined"] = 7] = "Undefined";
|
|
12
|
+
SerializerType$1[SerializerType$1["Array"] = 8] = "Array";
|
|
13
|
+
SerializerType$1[SerializerType$1["Map"] = 9] = "Map";
|
|
14
|
+
SerializerType$1[SerializerType$1["Set"] = 10] = "Set";
|
|
15
|
+
SerializerType$1[SerializerType$1["Buffer"] = 11] = "Buffer";
|
|
16
|
+
SerializerType$1[SerializerType$1["RegExp"] = 12] = "RegExp";
|
|
17
|
+
return SerializerType$1;
|
|
18
|
+
}({});
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
Object.defineProperty(exports, 'SerializerType', {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return SerializerType;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=constants-DYSMm0U6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-DYSMm0U6.js","names":[],"sources":["../src/kv/constants.ts"],"sourcesContent":["export enum SerializerType {\n String,\n Number,\n Boolean,\n Object,\n Date,\n BigInt,\n Null,\n Undefined,\n Array,\n Map,\n Set,\n Buffer,\n RegExp,\n}\n"],"mappings":";;AAAA,IAAY,4DAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/kv/dotprops.ts
|
|
3
|
+
function getNestedValue(obj, path) {
|
|
4
|
+
const keys = path.split(".");
|
|
5
|
+
let current = obj;
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
if (current === null || current === void 0) return void 0;
|
|
8
|
+
current = current[key];
|
|
9
|
+
}
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
function setNestedValue(obj, path, value) {
|
|
13
|
+
const keys = path.split(".");
|
|
14
|
+
const lastKey = keys.pop();
|
|
15
|
+
let current = obj;
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
if (current[key] === null || current[key] === void 0) current[key] = {};
|
|
18
|
+
current = current[key];
|
|
19
|
+
}
|
|
20
|
+
current[lastKey] = value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, 'getNestedValue', {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return getNestedValue;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, 'setNestedValue', {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return setNestedValue;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=dotprops-C22abhGZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dotprops-C22abhGZ.js","names":[],"sources":["../src/kv/dotprops.ts"],"sourcesContent":["export function getNestedValue(obj: any, path: string): any {\n const keys = path.split('.');\n let current = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = current[key];\n }\n\n return current;\n}\n\nexport function setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n let current = obj;\n\n for (const key of keys) {\n if (current[key] === null || current[key] === undefined) {\n current[key] = {};\n }\n current = current[key];\n }\n\n current[lastKey] = value;\n}\n"],"mappings":";;AAAA,SAAgB,eAAe,KAAU,MAAmB;CAC1D,MAAM,OAAO,KAAK,MAAM,IAAI;CAC5B,IAAI,UAAU;AAEd,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,YAAY,QAAQ,mBACtB;AAEF,YAAU,QAAQ;CACpB;AAEA,QAAO;AACT;AAEA,SAAgB,eAAe,KAAU,MAAc,OAAkB;CACvE,MAAM,OAAO,KAAK,MAAM,IAAI;CAC5B,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,UAAU;AAEd,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,QAAQ,SAAS,QAAQ,QAAQ,gBACnC,SAAQ,OAAO,CAAE;AAEnB,YAAU,QAAQ;CACpB;AAEA,SAAQ,WAAW;AACrB"}
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ require('./store-CyzliDXj.js');
|
|
|
36
36
|
const require_helpers = require('./helpers-DfV6HlgI.js');
|
|
37
37
|
require('./app-gCenKq8k.js');
|
|
38
38
|
require('./ILogger-BMIMljYD.js');
|
|
39
|
-
const require_version = require('./version-
|
|
39
|
+
const require_version = require('./version-BGji_hXj.js');
|
|
40
40
|
const require_feature_flags = require('./feature-flags-DJcINI5E.js');
|
|
41
41
|
const require_init = require('./init-DeoDd5cK.js');
|
|
42
42
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/kv/dotprops.d.ts
|
|
2
|
+
declare function getNestedValue(obj: any, path: string): any;
|
|
3
|
+
declare function setNestedValue(obj: any, path: string, value: any): void;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { getNestedValue, setNestedValue };
|
|
6
|
+
//# sourceMappingURL=dotprops.d.ts.map
|
package/dist/kv/kv.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import "../constants-Br1y2J-P.js";
|
|
2
|
+
import { SerializedValue } from "../serde-4EKSAKpL.js";
|
|
1
3
|
import { DatabaseSync } from "node:sqlite";
|
|
2
4
|
|
|
3
5
|
//#region src/kv/kv.d.ts
|
|
4
|
-
|
|
5
6
|
/**
|
|
6
7
|
* Configuration options for the KV store
|
|
7
8
|
*/
|
|
@@ -15,17 +16,25 @@ interface KvOptions {
|
|
|
15
16
|
* A key-value store implementation using SQLite
|
|
16
17
|
*
|
|
17
18
|
* This class provides a simple, persistent key-value storage solution
|
|
18
|
-
* with support for namespaces, automatic cleanup, iteration, and
|
|
19
|
+
* with support for namespaces, automatic cleanup, iteration, expiration, and JSON serialization.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```typescript
|
|
22
23
|
* const kv = new KV('data.db');
|
|
23
|
-
* kv.set('user:123', JSON.stringify({ name: 'John', age: 30 }));
|
|
24
|
-
* const user = JSON.parse(kv.get('user:123') || '{}');
|
|
25
24
|
*
|
|
26
|
-
* //
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* // Store any JSON-serializable data
|
|
26
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
27
|
+
* kv.set('counter', 42);
|
|
28
|
+
* kv.set('active', true);
|
|
29
|
+
* kv.set('dates', [new Date(), new Date()]);
|
|
30
|
+
*
|
|
31
|
+
* // Use dot notation for nested properties
|
|
32
|
+
* kv.set('user:123.name', 'John');
|
|
33
|
+
* kv.set('user:123.settings.theme', 'dark');
|
|
34
|
+
*
|
|
35
|
+
* // Retrieve data
|
|
36
|
+
* const user = kv.get('user:123'); // { name: 'John', age: 30, settings: { theme: 'dark' } }
|
|
37
|
+
* const name = kv.get('user:123.name'); // 'John'
|
|
29
38
|
* ```
|
|
30
39
|
*/
|
|
31
40
|
declare class KV implements Disposable, AsyncDisposable {
|
|
@@ -70,48 +79,76 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
70
79
|
/**
|
|
71
80
|
* Retrieves a value by key
|
|
72
81
|
*
|
|
73
|
-
* @param key - The key to retrieve
|
|
82
|
+
* @param key - The key to retrieve (supports dot notation for nested properties)
|
|
74
83
|
* @returns The value associated with the key, or `undefined` if not found or expired
|
|
75
84
|
*
|
|
76
85
|
* @example
|
|
77
86
|
* ```typescript
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
87
|
+
* // Store an object
|
|
88
|
+
* kv.set('user:123', { name: 'John', age: 30, settings: { theme: 'dark' } });
|
|
89
|
+
*
|
|
90
|
+
* // Get the entire object
|
|
91
|
+
* const user = kv.get('user:123');
|
|
92
|
+
* // { name: 'John', age: 30, settings: { theme: 'dark' } }
|
|
93
|
+
*
|
|
94
|
+
* // Get nested properties using dot notation
|
|
95
|
+
* const name = kv.get('user:123.name'); // 'John'
|
|
96
|
+
* const theme = kv.get('user:123.settings.theme'); // 'dark'
|
|
82
97
|
* ```
|
|
83
98
|
*/
|
|
84
|
-
get(key: string):
|
|
99
|
+
get<T = any>(key: string): T | undefined;
|
|
85
100
|
/**
|
|
86
101
|
* Sets a key-value pair
|
|
87
102
|
*
|
|
88
|
-
* @param key - The key to set
|
|
89
|
-
* @param value - The value to associate with the key
|
|
103
|
+
* @param key - The key to set (supports dot notation for nested properties)
|
|
104
|
+
* @param value - The value to associate with the key (any JSON-serializable type)
|
|
90
105
|
*
|
|
91
106
|
* @example
|
|
92
107
|
* ```typescript
|
|
93
|
-
*
|
|
94
|
-
* kv.set('counter',
|
|
108
|
+
* // Store primitive values
|
|
109
|
+
* kv.set('counter', 42);
|
|
110
|
+
* kv.set('active', true);
|
|
111
|
+
* kv.set('name', 'John');
|
|
112
|
+
*
|
|
113
|
+
* // Store objects
|
|
114
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
115
|
+
*
|
|
116
|
+
* // Store arrays
|
|
117
|
+
* kv.set('tags', ['javascript', 'typescript', 'sqlite']);
|
|
118
|
+
*
|
|
119
|
+
* // Store dates
|
|
120
|
+
* kv.set('created', new Date());
|
|
121
|
+
*
|
|
122
|
+
* // Store maps and sets
|
|
123
|
+
* kv.set('permissions', new Map([['admin', true], ['user', false]]));
|
|
124
|
+
* kv.set('unique_ids', new Set([1, 2, 3, 4, 5]));
|
|
125
|
+
*
|
|
126
|
+
* // Use dot notation for nested properties
|
|
127
|
+
* kv.set('user:123.settings.theme', 'dark');
|
|
128
|
+
* kv.set('user:123.settings.notifications', true);
|
|
95
129
|
* ```
|
|
96
130
|
*/
|
|
97
|
-
set(key: string, value:
|
|
131
|
+
set(key: string, value: any): void;
|
|
98
132
|
/**
|
|
99
133
|
* Sets a key-value pair with expiration
|
|
100
134
|
*
|
|
101
|
-
* @param key - The key to set
|
|
102
|
-
* @param value - The value to associate with the key
|
|
135
|
+
* @param key - The key to set (supports dot notation for nested properties)
|
|
136
|
+
* @param value - The value to associate with the key (any JSON-serializable type)
|
|
103
137
|
* @param ttl - Time to live in milliseconds
|
|
104
138
|
*
|
|
105
139
|
* @example
|
|
106
140
|
* ```typescript
|
|
107
141
|
* // Set with 1 hour expiration
|
|
108
|
-
* kv.setex('session:123', '
|
|
142
|
+
* kv.setex('session:123', { userId: 123, token: 'abc123' }, 60 * 60 * 1000);
|
|
109
143
|
*
|
|
110
144
|
* // Set with 5 minutes expiration
|
|
111
|
-
* kv.setex('temp:data',
|
|
145
|
+
* kv.setex('temp:data', { cached: true, timestamp: Date.now() }, 5 * 60 * 1000);
|
|
146
|
+
*
|
|
147
|
+
* // Use dot notation with expiration
|
|
148
|
+
* kv.setex('user:123.temp_settings', { theme: 'light' }, 30 * 60 * 1000);
|
|
112
149
|
* ```
|
|
113
150
|
*/
|
|
114
|
-
setex(key: string, value:
|
|
151
|
+
setex(key: string, value: any, ttl: number): void;
|
|
115
152
|
/**
|
|
116
153
|
* Sets expiration for an existing key
|
|
117
154
|
*
|
|
@@ -121,7 +158,7 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
121
158
|
*
|
|
122
159
|
* @example
|
|
123
160
|
* ```typescript
|
|
124
|
-
* kv.set('user:123', '
|
|
161
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
125
162
|
*
|
|
126
163
|
* // Set 30 minute expiration
|
|
127
164
|
* if (kv.expire('user:123', 30 * 60 * 1000)) {
|
|
@@ -157,6 +194,7 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
157
194
|
* @example
|
|
158
195
|
* ```typescript
|
|
159
196
|
* kv.delete('user:123');
|
|
197
|
+
* kv.delete('user:123.settings.theme'); // Delete nested property
|
|
160
198
|
* ```
|
|
161
199
|
*/
|
|
162
200
|
delete(key: string): void;
|
|
@@ -171,6 +209,10 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
171
209
|
* if (kv.has('user:123')) {
|
|
172
210
|
* console.log('User exists and is not expired');
|
|
173
211
|
* }
|
|
212
|
+
*
|
|
213
|
+
* if (kv.has('user:123.settings.theme')) {
|
|
214
|
+
* console.log('Theme setting exists');
|
|
215
|
+
* }
|
|
174
216
|
* ```
|
|
175
217
|
*/
|
|
176
218
|
has(key: string): boolean;
|
|
@@ -197,7 +239,7 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
197
239
|
* console.log('All values:', values);
|
|
198
240
|
* ```
|
|
199
241
|
*/
|
|
200
|
-
values():
|
|
242
|
+
values(): any[];
|
|
201
243
|
/**
|
|
202
244
|
* Gets the total number of key-value pairs in the current namespace (excluding expired keys)
|
|
203
245
|
*
|
|
@@ -228,10 +270,10 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
228
270
|
* ```typescript
|
|
229
271
|
* const all = kv.all();
|
|
230
272
|
* console.log('All entries:', all);
|
|
231
|
-
* // Output: { 'key1':
|
|
273
|
+
* // Output: { 'key1': value1, 'key2': value2 }
|
|
232
274
|
* ```
|
|
233
275
|
*/
|
|
234
|
-
all(): Record<string,
|
|
276
|
+
all(): Record<string, any>;
|
|
235
277
|
/**
|
|
236
278
|
* Gets all available namespaces (tables) in the database
|
|
237
279
|
*
|
|
@@ -261,7 +303,7 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
261
303
|
* const userKv = kv.namespace('users');
|
|
262
304
|
* const configKv = kv.namespace('config');
|
|
263
305
|
*
|
|
264
|
-
* userKv.set('123', 'John
|
|
306
|
+
* userKv.set('123', { name: 'John', age: 30 });
|
|
265
307
|
* configKv.set('theme', 'dark');
|
|
266
308
|
* ```
|
|
267
309
|
*/
|
|
@@ -274,14 +316,14 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
274
316
|
* @example
|
|
275
317
|
* ```typescript
|
|
276
318
|
* for (const [key, value] of kv) {
|
|
277
|
-
* console.log(`${key}
|
|
319
|
+
* console.log(`${key}:`, value);
|
|
278
320
|
* }
|
|
279
321
|
*
|
|
280
322
|
* // Or using spread operator
|
|
281
323
|
* const entries = [...kv];
|
|
282
324
|
* ```
|
|
283
325
|
*/
|
|
284
|
-
[Symbol.iterator](): Iterator<[string,
|
|
326
|
+
[Symbol.iterator](): Iterator<[string, any]>;
|
|
285
327
|
/**
|
|
286
328
|
* Executes a function within a transaction
|
|
287
329
|
*
|
|
@@ -292,16 +334,16 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
292
334
|
* ```typescript
|
|
293
335
|
* // Synchronous transaction
|
|
294
336
|
* kv.transaction(() => {
|
|
295
|
-
* kv.set('user:123',
|
|
296
|
-
* kv.set('user:456',
|
|
337
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
338
|
+
* kv.set('user:456', { name: 'Jane', age: 25 });
|
|
297
339
|
* // If any operation fails, all changes are rolled back
|
|
298
340
|
* });
|
|
299
341
|
*
|
|
300
342
|
* // Async transaction
|
|
301
343
|
* await kv.transaction(async () => {
|
|
302
|
-
* kv.set('user:123',
|
|
344
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
303
345
|
* await someAsyncOperation();
|
|
304
|
-
* kv.set('user:456',
|
|
346
|
+
* kv.set('user:456', { name: 'Jane', age: 25 });
|
|
305
347
|
* // If any operation fails, all changes are rolled back
|
|
306
348
|
* });
|
|
307
349
|
* ```
|
|
@@ -317,5 +359,5 @@ declare class KV implements Disposable, AsyncDisposable {
|
|
|
317
359
|
*/
|
|
318
360
|
declare function openKV(path?: string | Buffer | URL | DatabaseSync, options?: KvOptions): KV;
|
|
319
361
|
//#endregion
|
|
320
|
-
export { KV, KvOptions, openKV };
|
|
362
|
+
export { KV, KvOptions, SerializedValue, openKV };
|
|
321
363
|
//# sourceMappingURL=kv.d.ts.map
|
package/dist/kv/kv.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const require_chunk = require('../chunk-nOFOJqeH.js');
|
|
2
|
+
require('../constants-DYSMm0U6.js');
|
|
3
|
+
const require_dotprops = require('../dotprops-C22abhGZ.js');
|
|
4
|
+
const require_serde = require('../serde-CXY4F7OD.js');
|
|
2
5
|
const node_sqlite = require_chunk.__toESM(require("node:sqlite"));
|
|
3
6
|
|
|
4
7
|
//#region src/kv/kv.ts
|
|
@@ -6,17 +9,25 @@ const node_sqlite = require_chunk.__toESM(require("node:sqlite"));
|
|
|
6
9
|
* A key-value store implementation using SQLite
|
|
7
10
|
*
|
|
8
11
|
* This class provides a simple, persistent key-value storage solution
|
|
9
|
-
* with support for namespaces, automatic cleanup, iteration, and
|
|
12
|
+
* with support for namespaces, automatic cleanup, iteration, expiration, and JSON serialization.
|
|
10
13
|
*
|
|
11
14
|
* @example
|
|
12
15
|
* ```typescript
|
|
13
16
|
* const kv = new KV('data.db');
|
|
14
|
-
* kv.set('user:123', JSON.stringify({ name: 'John', age: 30 }));
|
|
15
|
-
* const user = JSON.parse(kv.get('user:123') || '{}');
|
|
16
17
|
*
|
|
17
|
-
* //
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* // Store any JSON-serializable data
|
|
19
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
20
|
+
* kv.set('counter', 42);
|
|
21
|
+
* kv.set('active', true);
|
|
22
|
+
* kv.set('dates', [new Date(), new Date()]);
|
|
23
|
+
*
|
|
24
|
+
* // Use dot notation for nested properties
|
|
25
|
+
* kv.set('user:123.name', 'John');
|
|
26
|
+
* kv.set('user:123.settings.theme', 'dark');
|
|
27
|
+
*
|
|
28
|
+
* // Retrieve data
|
|
29
|
+
* const user = kv.get('user:123'); // { name: 'John', age: 30, settings: { theme: 'dark' } }
|
|
30
|
+
* const name = kv.get('user:123.name'); // 'John'
|
|
20
31
|
* ```
|
|
21
32
|
*/
|
|
22
33
|
var KV = class KV {
|
|
@@ -35,26 +46,27 @@ var KV = class KV {
|
|
|
35
46
|
this.options = options;
|
|
36
47
|
this.db = path instanceof node_sqlite.DatabaseSync ? path : new node_sqlite.DatabaseSync(path, { open: true });
|
|
37
48
|
if (options.enableWAL) this.db.exec(`PRAGMA journal_mode = WAL;`);
|
|
38
|
-
this.
|
|
39
|
-
|
|
49
|
+
const namespace = this.options.namespace ?? "commandkit_kv";
|
|
50
|
+
this.db.exec(`
|
|
51
|
+
CREATE TABLE IF NOT EXISTS ${namespace} (
|
|
40
52
|
key TEXT PRIMARY KEY,
|
|
41
53
|
value TEXT,
|
|
42
54
|
expires_at INTEGER
|
|
43
55
|
)
|
|
44
|
-
`)
|
|
56
|
+
`);
|
|
45
57
|
this.statements = {
|
|
46
|
-
get: this.db.prepare(`SELECT value, expires_at FROM
|
|
47
|
-
set: this.db.prepare(`INSERT OR REPLACE INTO
|
|
48
|
-
setex: this.db.prepare(`INSERT OR REPLACE INTO
|
|
49
|
-
delete: this.db.prepare(`DELETE FROM
|
|
50
|
-
has: this.db.prepare(`SELECT COUNT(*) FROM
|
|
51
|
-
keys: this.db.prepare(`SELECT key FROM
|
|
52
|
-
values: this.db.prepare(`SELECT value FROM
|
|
53
|
-
clear: this.db.prepare(`DELETE FROM
|
|
54
|
-
count: this.db.prepare(`SELECT COUNT(*) FROM
|
|
55
|
-
all: this.db.prepare(`SELECT key, value FROM
|
|
56
|
-
expire: this.db.prepare(`UPDATE
|
|
57
|
-
ttl: this.db.prepare(`SELECT expires_at FROM
|
|
58
|
+
get: this.db.prepare(`SELECT value, expires_at FROM ${namespace} WHERE key = ?`),
|
|
59
|
+
set: this.db.prepare(`INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`),
|
|
60
|
+
setex: this.db.prepare(`INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`),
|
|
61
|
+
delete: this.db.prepare(`DELETE FROM ${namespace} WHERE key = ?`),
|
|
62
|
+
has: this.db.prepare(`SELECT COUNT(*) FROM ${namespace} WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`),
|
|
63
|
+
keys: this.db.prepare(`SELECT key FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`),
|
|
64
|
+
values: this.db.prepare(`SELECT value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`),
|
|
65
|
+
clear: this.db.prepare(`DELETE FROM ${namespace}`),
|
|
66
|
+
count: this.db.prepare(`SELECT COUNT(*) FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`),
|
|
67
|
+
all: this.db.prepare(`SELECT key, value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`),
|
|
68
|
+
expire: this.db.prepare(`UPDATE ${namespace} SET expires_at = ? WHERE key = ?`),
|
|
69
|
+
ttl: this.db.prepare(`SELECT expires_at FROM ${namespace} WHERE key = ?`),
|
|
58
70
|
namespaces: this.db.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`),
|
|
59
71
|
begin: this.db.prepare(`BEGIN TRANSACTION`),
|
|
60
72
|
commit: this.db.prepare(`COMMIT`),
|
|
@@ -104,60 +116,117 @@ var KV = class KV {
|
|
|
104
116
|
/**
|
|
105
117
|
* Retrieves a value by key
|
|
106
118
|
*
|
|
107
|
-
* @param key - The key to retrieve
|
|
119
|
+
* @param key - The key to retrieve (supports dot notation for nested properties)
|
|
108
120
|
* @returns The value associated with the key, or `undefined` if not found or expired
|
|
109
121
|
*
|
|
110
122
|
* @example
|
|
111
123
|
* ```typescript
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
124
|
+
* // Store an object
|
|
125
|
+
* kv.set('user:123', { name: 'John', age: 30, settings: { theme: 'dark' } });
|
|
126
|
+
*
|
|
127
|
+
* // Get the entire object
|
|
128
|
+
* const user = kv.get('user:123');
|
|
129
|
+
* // { name: 'John', age: 30, settings: { theme: 'dark' } }
|
|
130
|
+
*
|
|
131
|
+
* // Get nested properties using dot notation
|
|
132
|
+
* const name = kv.get('user:123.name'); // 'John'
|
|
133
|
+
* const theme = kv.get('user:123.settings.theme'); // 'dark'
|
|
116
134
|
* ```
|
|
117
135
|
*/
|
|
118
136
|
get(key) {
|
|
119
|
-
const result = this.statements.get.get(
|
|
137
|
+
const result = this.statements.get.get(key);
|
|
120
138
|
if (!result) return void 0;
|
|
121
139
|
if (result.expires_at && Number(result.expires_at) <= this.getCurrentTime()) {
|
|
122
140
|
this.delete(key);
|
|
123
141
|
return void 0;
|
|
124
142
|
}
|
|
125
|
-
|
|
143
|
+
const serialized = JSON.parse(result.value);
|
|
144
|
+
const deserialized = require_serde.deserializer(serialized);
|
|
145
|
+
if (key.includes(".")) return require_dotprops.getNestedValue(deserialized, key.split(".").slice(1).join("."));
|
|
146
|
+
return deserialized;
|
|
126
147
|
}
|
|
127
148
|
/**
|
|
128
149
|
* Sets a key-value pair
|
|
129
150
|
*
|
|
130
|
-
* @param key - The key to set
|
|
131
|
-
* @param value - The value to associate with the key
|
|
151
|
+
* @param key - The key to set (supports dot notation for nested properties)
|
|
152
|
+
* @param value - The value to associate with the key (any JSON-serializable type)
|
|
132
153
|
*
|
|
133
154
|
* @example
|
|
134
155
|
* ```typescript
|
|
135
|
-
*
|
|
136
|
-
* kv.set('counter',
|
|
156
|
+
* // Store primitive values
|
|
157
|
+
* kv.set('counter', 42);
|
|
158
|
+
* kv.set('active', true);
|
|
159
|
+
* kv.set('name', 'John');
|
|
160
|
+
*
|
|
161
|
+
* // Store objects
|
|
162
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
163
|
+
*
|
|
164
|
+
* // Store arrays
|
|
165
|
+
* kv.set('tags', ['javascript', 'typescript', 'sqlite']);
|
|
166
|
+
*
|
|
167
|
+
* // Store dates
|
|
168
|
+
* kv.set('created', new Date());
|
|
169
|
+
*
|
|
170
|
+
* // Store maps and sets
|
|
171
|
+
* kv.set('permissions', new Map([['admin', true], ['user', false]]));
|
|
172
|
+
* kv.set('unique_ids', new Set([1, 2, 3, 4, 5]));
|
|
173
|
+
*
|
|
174
|
+
* // Use dot notation for nested properties
|
|
175
|
+
* kv.set('user:123.settings.theme', 'dark');
|
|
176
|
+
* kv.set('user:123.settings.notifications', true);
|
|
137
177
|
* ```
|
|
138
178
|
*/
|
|
139
179
|
set(key, value) {
|
|
140
|
-
|
|
180
|
+
let serializedValue;
|
|
181
|
+
if (key.includes(".")) {
|
|
182
|
+
const [baseKey, ...pathParts] = key.split(".");
|
|
183
|
+
const path = pathParts.join(".");
|
|
184
|
+
const existing = this.get(baseKey) || {};
|
|
185
|
+
require_dotprops.setNestedValue(existing, path, value);
|
|
186
|
+
const serialized = require_serde.serializer(existing);
|
|
187
|
+
serializedValue = JSON.stringify(serialized);
|
|
188
|
+
this.statements.set.run(baseKey, serializedValue, null);
|
|
189
|
+
} else {
|
|
190
|
+
const serialized = require_serde.serializer(value);
|
|
191
|
+
serializedValue = JSON.stringify(serialized);
|
|
192
|
+
this.statements.set.run(key, serializedValue, null);
|
|
193
|
+
}
|
|
141
194
|
}
|
|
142
195
|
/**
|
|
143
196
|
* Sets a key-value pair with expiration
|
|
144
197
|
*
|
|
145
|
-
* @param key - The key to set
|
|
146
|
-
* @param value - The value to associate with the key
|
|
198
|
+
* @param key - The key to set (supports dot notation for nested properties)
|
|
199
|
+
* @param value - The value to associate with the key (any JSON-serializable type)
|
|
147
200
|
* @param ttl - Time to live in milliseconds
|
|
148
201
|
*
|
|
149
202
|
* @example
|
|
150
203
|
* ```typescript
|
|
151
204
|
* // Set with 1 hour expiration
|
|
152
|
-
* kv.setex('session:123', '
|
|
205
|
+
* kv.setex('session:123', { userId: 123, token: 'abc123' }, 60 * 60 * 1000);
|
|
153
206
|
*
|
|
154
207
|
* // Set with 5 minutes expiration
|
|
155
|
-
* kv.setex('temp:data',
|
|
208
|
+
* kv.setex('temp:data', { cached: true, timestamp: Date.now() }, 5 * 60 * 1000);
|
|
209
|
+
*
|
|
210
|
+
* // Use dot notation with expiration
|
|
211
|
+
* kv.setex('user:123.temp_settings', { theme: 'light' }, 30 * 60 * 1000);
|
|
156
212
|
* ```
|
|
157
213
|
*/
|
|
158
214
|
setex(key, value, ttl) {
|
|
159
215
|
const expiresAt = this.getCurrentTime() + ttl;
|
|
160
|
-
|
|
216
|
+
let serializedValue;
|
|
217
|
+
if (key.includes(".")) {
|
|
218
|
+
const [baseKey, ...pathParts] = key.split(".");
|
|
219
|
+
const path = pathParts.join(".");
|
|
220
|
+
const existing = this.get(baseKey) || {};
|
|
221
|
+
require_dotprops.setNestedValue(existing, path, value);
|
|
222
|
+
const serialized = require_serde.serializer(existing);
|
|
223
|
+
serializedValue = JSON.stringify(serialized);
|
|
224
|
+
this.statements.setex.run(baseKey, serializedValue, expiresAt);
|
|
225
|
+
} else {
|
|
226
|
+
const serialized = require_serde.serializer(value);
|
|
227
|
+
serializedValue = JSON.stringify(serialized);
|
|
228
|
+
this.statements.setex.run(key, serializedValue, expiresAt);
|
|
229
|
+
}
|
|
161
230
|
}
|
|
162
231
|
/**
|
|
163
232
|
* Sets expiration for an existing key
|
|
@@ -168,7 +237,7 @@ var KV = class KV {
|
|
|
168
237
|
*
|
|
169
238
|
* @example
|
|
170
239
|
* ```typescript
|
|
171
|
-
* kv.set('user:123', '
|
|
240
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
172
241
|
*
|
|
173
242
|
* // Set 30 minute expiration
|
|
174
243
|
* if (kv.expire('user:123', 30 * 60 * 1000)) {
|
|
@@ -179,7 +248,7 @@ var KV = class KV {
|
|
|
179
248
|
expire(key, ttl) {
|
|
180
249
|
if (!this.has(key)) return false;
|
|
181
250
|
const expiresAt = this.getCurrentTime() + ttl;
|
|
182
|
-
this.statements.expire.run(
|
|
251
|
+
this.statements.expire.run(expiresAt, key);
|
|
183
252
|
return true;
|
|
184
253
|
}
|
|
185
254
|
/**
|
|
@@ -201,7 +270,7 @@ var KV = class KV {
|
|
|
201
270
|
* ```
|
|
202
271
|
*/
|
|
203
272
|
ttl(key) {
|
|
204
|
-
const result = this.statements.ttl.get(
|
|
273
|
+
const result = this.statements.ttl.get(key);
|
|
205
274
|
if (!result) return -1;
|
|
206
275
|
if (!result.expires_at) return -2;
|
|
207
276
|
const remaining = Number(result.expires_at) - this.getCurrentTime();
|
|
@@ -215,10 +284,11 @@ var KV = class KV {
|
|
|
215
284
|
* @example
|
|
216
285
|
* ```typescript
|
|
217
286
|
* kv.delete('user:123');
|
|
287
|
+
* kv.delete('user:123.settings.theme'); // Delete nested property
|
|
218
288
|
* ```
|
|
219
289
|
*/
|
|
220
290
|
delete(key) {
|
|
221
|
-
this.statements.delete.run(
|
|
291
|
+
this.statements.delete.run(key);
|
|
222
292
|
}
|
|
223
293
|
/**
|
|
224
294
|
* Checks if a key exists and is not expired
|
|
@@ -231,10 +301,14 @@ var KV = class KV {
|
|
|
231
301
|
* if (kv.has('user:123')) {
|
|
232
302
|
* console.log('User exists and is not expired');
|
|
233
303
|
* }
|
|
304
|
+
*
|
|
305
|
+
* if (kv.has('user:123.settings.theme')) {
|
|
306
|
+
* console.log('Theme setting exists');
|
|
307
|
+
* }
|
|
234
308
|
* ```
|
|
235
309
|
*/
|
|
236
310
|
has(key) {
|
|
237
|
-
const result = this.statements.has.get(
|
|
311
|
+
const result = this.statements.has.get(key, this.getCurrentTime());
|
|
238
312
|
return (result === null || result === void 0 ? void 0 : result.count) !== void 0 && result.count !== null && Number(result.count) > 0;
|
|
239
313
|
}
|
|
240
314
|
/**
|
|
@@ -249,7 +323,7 @@ var KV = class KV {
|
|
|
249
323
|
* ```
|
|
250
324
|
*/
|
|
251
325
|
keys() {
|
|
252
|
-
const result = this.statements.keys.all(this.
|
|
326
|
+
const result = this.statements.keys.all(this.getCurrentTime());
|
|
253
327
|
return result.map((row) => row.key);
|
|
254
328
|
}
|
|
255
329
|
/**
|
|
@@ -264,8 +338,11 @@ var KV = class KV {
|
|
|
264
338
|
* ```
|
|
265
339
|
*/
|
|
266
340
|
values() {
|
|
267
|
-
const result = this.statements.values.all(this.
|
|
268
|
-
return result.map((row) =>
|
|
341
|
+
const result = this.statements.values.all(this.getCurrentTime());
|
|
342
|
+
return result.map((row) => {
|
|
343
|
+
const serialized = JSON.parse(row.value);
|
|
344
|
+
return require_serde.deserializer(serialized);
|
|
345
|
+
});
|
|
269
346
|
}
|
|
270
347
|
/**
|
|
271
348
|
* Gets the total number of key-value pairs in the current namespace (excluding expired keys)
|
|
@@ -279,7 +356,7 @@ var KV = class KV {
|
|
|
279
356
|
* ```
|
|
280
357
|
*/
|
|
281
358
|
count() {
|
|
282
|
-
const result = this.statements.count.get(this.
|
|
359
|
+
const result = this.statements.count.get(this.getCurrentTime());
|
|
283
360
|
return Number((result === null || result === void 0 ? void 0 : result.count) ?? 0);
|
|
284
361
|
}
|
|
285
362
|
/**
|
|
@@ -291,7 +368,7 @@ var KV = class KV {
|
|
|
291
368
|
* ```
|
|
292
369
|
*/
|
|
293
370
|
clear() {
|
|
294
|
-
this.statements.clear.run(
|
|
371
|
+
this.statements.clear.run();
|
|
295
372
|
}
|
|
296
373
|
/**
|
|
297
374
|
* Gets all key-value pairs as an object (excluding expired keys)
|
|
@@ -302,12 +379,15 @@ var KV = class KV {
|
|
|
302
379
|
* ```typescript
|
|
303
380
|
* const all = kv.all();
|
|
304
381
|
* console.log('All entries:', all);
|
|
305
|
-
* // Output: { 'key1':
|
|
382
|
+
* // Output: { 'key1': value1, 'key2': value2 }
|
|
306
383
|
* ```
|
|
307
384
|
*/
|
|
308
385
|
all() {
|
|
309
|
-
const result = this.statements.all.all(this.
|
|
310
|
-
return Object.fromEntries(result.map((row) =>
|
|
386
|
+
const result = this.statements.all.all(this.getCurrentTime());
|
|
387
|
+
return Object.fromEntries(result.map((row) => {
|
|
388
|
+
const serialized = JSON.parse(row.value);
|
|
389
|
+
return [row.key, require_serde.deserializer(serialized)];
|
|
390
|
+
}));
|
|
311
391
|
}
|
|
312
392
|
/**
|
|
313
393
|
* Gets all available namespaces (tables) in the database
|
|
@@ -343,7 +423,7 @@ var KV = class KV {
|
|
|
343
423
|
* const userKv = kv.namespace('users');
|
|
344
424
|
* const configKv = kv.namespace('config');
|
|
345
425
|
*
|
|
346
|
-
* userKv.set('123', 'John
|
|
426
|
+
* userKv.set('123', { name: 'John', age: 30 });
|
|
347
427
|
* configKv.set('theme', 'dark');
|
|
348
428
|
* ```
|
|
349
429
|
*/
|
|
@@ -361,7 +441,7 @@ var KV = class KV {
|
|
|
361
441
|
* @example
|
|
362
442
|
* ```typescript
|
|
363
443
|
* for (const [key, value] of kv) {
|
|
364
|
-
* console.log(`${key}
|
|
444
|
+
* console.log(`${key}:`, value);
|
|
365
445
|
* }
|
|
366
446
|
*
|
|
367
447
|
* // Or using spread operator
|
|
@@ -369,8 +449,11 @@ var KV = class KV {
|
|
|
369
449
|
* ```
|
|
370
450
|
*/
|
|
371
451
|
*[Symbol.iterator]() {
|
|
372
|
-
const result = this.statements.all.iterate(this.
|
|
373
|
-
for (const row of result)
|
|
452
|
+
const result = this.statements.all.iterate(this.getCurrentTime());
|
|
453
|
+
for (const row of result) {
|
|
454
|
+
const serialized = JSON.parse(row.value);
|
|
455
|
+
yield [row.key, require_serde.deserializer(serialized)];
|
|
456
|
+
}
|
|
374
457
|
}
|
|
375
458
|
/**
|
|
376
459
|
* Executes a function within a transaction
|
|
@@ -382,16 +465,16 @@ var KV = class KV {
|
|
|
382
465
|
* ```typescript
|
|
383
466
|
* // Synchronous transaction
|
|
384
467
|
* kv.transaction(() => {
|
|
385
|
-
* kv.set('user:123',
|
|
386
|
-
* kv.set('user:456',
|
|
468
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
469
|
+
* kv.set('user:456', { name: 'Jane', age: 25 });
|
|
387
470
|
* // If any operation fails, all changes are rolled back
|
|
388
471
|
* });
|
|
389
472
|
*
|
|
390
473
|
* // Async transaction
|
|
391
474
|
* await kv.transaction(async () => {
|
|
392
|
-
* kv.set('user:123',
|
|
475
|
+
* kv.set('user:123', { name: 'John', age: 30 });
|
|
393
476
|
* await someAsyncOperation();
|
|
394
|
-
* kv.set('user:456',
|
|
477
|
+
* kv.set('user:456', { name: 'Jane', age: 25 });
|
|
395
478
|
* // If any operation fails, all changes are rolled back
|
|
396
479
|
* });
|
|
397
480
|
* ```
|
package/dist/kv/kv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kv.js","names":[],"sources":["../../src/kv/kv.ts"],"sourcesContent":["import { DatabaseSync, StatementSync } from 'node:sqlite';\n\n/**\n * Configuration options for the KV store\n */\nexport interface KvOptions {\n /** Enable Write-Ahead Logging for better performance and durability */\n enableWAL?: boolean;\n /** Namespace for the key-value store table */\n namespace?: string;\n}\n\n/**\n * A key-value store implementation using SQLite\n *\n * This class provides a simple, persistent key-value storage solution\n * with support for namespaces, automatic cleanup, iteration, and expiration.\n *\n * @example\n * ```typescript\n * const kv = new KV('data.db');\n * kv.set('user:123', JSON.stringify({ name: 'John', age: 30 }));\n * const user = JSON.parse(kv.get('user:123') || '{}');\n *\n * // Using namespaces\n * const userKv = kv.namespace('users');\n * userKv.set('123', JSON.stringify({ name: 'John' }));\n * ```\n */\nexport class KV implements Disposable, AsyncDisposable {\n private db: DatabaseSync;\n private statements: Record<string, StatementSync> = {};\n\n /**\n * Creates a new KV store instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n */\n public constructor(\n path: string | Buffer | URL | DatabaseSync,\n private options: KvOptions = {\n enableWAL: true,\n namespace: 'commandkit_kv',\n },\n ) {\n this.db =\n path instanceof DatabaseSync\n ? path\n : new DatabaseSync(path, { open: true });\n\n if (options.enableWAL) {\n this.db.exec(/* sql */ `PRAGMA journal_mode = WAL;`);\n }\n\n this.db\n .prepare(\n /* sql */ `\n CREATE TABLE IF NOT EXISTS ? (\n key TEXT PRIMARY KEY,\n value TEXT,\n expires_at INTEGER\n )\n `,\n )\n .run(options.namespace ?? 'commandkit_kv');\n\n this.statements = {\n get: this.db.prepare(\n /* sql */ `SELECT value, expires_at FROM ? WHERE key = ?`,\n ),\n set: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ? (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n setex: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ? (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n delete: this.db.prepare(/* sql */ `DELETE FROM ? WHERE key = ?`),\n has: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ? WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`,\n ),\n keys: this.db.prepare(\n /* sql */ `SELECT key FROM ? WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n values: this.db.prepare(\n /* sql */ `SELECT value FROM ? WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n clear: this.db.prepare(/* sql */ `DELETE FROM ?`),\n count: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ? WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n all: this.db.prepare(\n /* sql */ `SELECT key, value FROM ? WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n expire: this.db.prepare(\n /* sql */ `UPDATE ? SET expires_at = ? WHERE key = ?`,\n ),\n ttl: this.db.prepare(/* sql */ `SELECT expires_at FROM ? WHERE key = ?`),\n namespaces: this.db.prepare(\n /* sql */ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`,\n ),\n begin: this.db.prepare(/* sql */ `BEGIN TRANSACTION`),\n commit: this.db.prepare(/* sql */ `COMMIT`),\n rollback: this.db.prepare(/* sql */ `ROLLBACK`),\n };\n }\n\n /**\n * Gets the current timestamp in milliseconds\n */\n private getCurrentTime(): number {\n return Date.now();\n }\n\n /**\n * Checks if the database connection is open\n *\n * @returns `true` if the database is open, `false` otherwise\n */\n public isOpen(): boolean {\n return this.db.isOpen;\n }\n\n /**\n * Gets the underlying SQLite database instance\n *\n * @returns The DatabaseSync instance\n */\n public getDatabase(): DatabaseSync {\n return this.db;\n }\n\n /**\n * Closes the database connection\n */\n public close(): void {\n if (this.db.isOpen) this.db.close();\n }\n\n /**\n * Disposable implementation - closes the database when disposed\n */\n public [Symbol.dispose]() {\n this.close();\n }\n\n /**\n * AsyncDisposable implementation - closes the database when disposed\n */\n public async [Symbol.asyncDispose]() {\n this.close();\n }\n\n /**\n * Retrieves a value by key\n *\n * @param key - The key to retrieve\n * @returns The value associated with the key, or `undefined` if not found or expired\n *\n * @example\n * ```typescript\n * const value = kv.get('my-key');\n * if (value) {\n * console.log('Found:', value);\n * }\n * ```\n */\n public get(key: string): string | undefined {\n const result = this.statements.get.get(this.getCurrentNamespace(), key);\n\n if (!result) return undefined;\n\n // Check if the key has expired\n if (\n result.expires_at &&\n Number(result.expires_at) <= this.getCurrentTime()\n ) {\n this.delete(key);\n return undefined;\n }\n\n return result.value as string;\n }\n\n /**\n * Sets a key-value pair\n *\n * @param key - The key to set\n * @param value - The value to associate with the key\n *\n * @example\n * ```typescript\n * kv.set('user:123', JSON.stringify({ name: 'John' }));\n * kv.set('counter', '42');\n * ```\n */\n public set(key: string, value: string): void {\n this.statements.set.run(this.getCurrentNamespace(), key, value, null);\n }\n\n /**\n * Sets a key-value pair with expiration\n *\n * @param key - The key to set\n * @param value - The value to associate with the key\n * @param ttl - Time to live in milliseconds\n *\n * @example\n * ```typescript\n * // Set with 1 hour expiration\n * kv.setex('session:123', 'user_data', 60 * 60 * 1000);\n *\n * // Set with 5 minutes expiration\n * kv.setex('temp:data', 'cached_value', 5 * 60 * 1000);\n * ```\n */\n public setex(key: string, value: string, ttl: number): void {\n const expiresAt = this.getCurrentTime() + ttl;\n this.statements.setex.run(\n this.getCurrentNamespace(),\n key,\n value,\n expiresAt,\n );\n }\n\n /**\n * Sets expiration for an existing key\n *\n * @param key - The key to set expiration for\n * @param ttl - Time to live in milliseconds\n * @returns `true` if the key exists and expiration was set, `false` otherwise\n *\n * @example\n * ```typescript\n * kv.set('user:123', 'user_data');\n *\n * // Set 30 minute expiration\n * if (kv.expire('user:123', 30 * 60 * 1000)) {\n * console.log('Expiration set successfully');\n * }\n * ```\n */\n public expire(key: string, ttl: number): boolean {\n if (!this.has(key)) return false;\n\n const expiresAt = this.getCurrentTime() + ttl;\n this.statements.expire.run(this.getCurrentNamespace(), expiresAt, key);\n return true;\n }\n\n /**\n * Gets the time to live for a key\n *\n * @param key - The key to check\n * @returns Time to live in milliseconds, or `-1` if the key doesn't exist, or `-2` if the key has no expiration\n *\n * @example\n * ```typescript\n * const ttl = kv.ttl('user:123');\n * if (ttl > 0) {\n * console.log(`Key expires in ${ttl}ms`);\n * } else if (ttl === -2) {\n * console.log('Key has no expiration');\n * } else {\n * console.log('Key does not exist');\n * }\n * ```\n */\n public ttl(key: string): number {\n const result = this.statements.ttl.get(this.getCurrentNamespace(), key);\n\n if (!result) return -1; // Key doesn't exist\n\n if (!result.expires_at) return -2; // No expiration\n\n const remaining = Number(result.expires_at) - this.getCurrentTime();\n return remaining > 0 ? remaining : -1; // Expired or doesn't exist\n }\n\n /**\n * Deletes a key-value pair\n *\n * @param key - The key to delete\n *\n * @example\n * ```typescript\n * kv.delete('user:123');\n * ```\n */\n public delete(key: string): void {\n this.statements.delete.run(this.getCurrentNamespace(), key);\n }\n\n /**\n * Checks if a key exists and is not expired\n *\n * @param key - The key to check\n * @returns `true` if the key exists and is not expired, `false` otherwise\n *\n * @example\n * ```typescript\n * if (kv.has('user:123')) {\n * console.log('User exists and is not expired');\n * }\n * ```\n */\n public has(key: string): boolean {\n const result = this.statements.has.get(\n this.getCurrentNamespace(),\n key,\n this.getCurrentTime(),\n );\n\n return (\n result?.count !== undefined &&\n result.count !== null &&\n Number(result.count) > 0\n );\n }\n\n /**\n * Gets all keys in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired keys\n *\n * @example\n * ```typescript\n * const keys = kv.keys();\n * console.log('All keys:', keys);\n * ```\n */\n public keys(): string[] {\n const result = this.statements.keys.all(\n this.getCurrentNamespace(),\n this.getCurrentTime(),\n );\n\n return result.map((row) => row.key as string);\n }\n\n /**\n * Gets all values in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired values\n *\n * @example\n * ```typescript\n * const values = kv.values();\n * console.log('All values:', values);\n * ```\n */\n public values(): string[] {\n const result = this.statements.values.all(\n this.getCurrentNamespace(),\n this.getCurrentTime(),\n );\n\n return result.map((row) => row.value as string);\n }\n\n /**\n * Gets the total number of key-value pairs in the current namespace (excluding expired keys)\n *\n * @returns The count of non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const count = kv.count();\n * console.log(`Total entries: ${count}`);\n * ```\n */\n public count(): number {\n const result = this.statements.count.get(\n this.getCurrentNamespace(),\n this.getCurrentTime(),\n );\n\n return Number(result?.count ?? 0);\n }\n\n /**\n * Removes all key-value pairs from the current namespace\n *\n * @example\n * ```typescript\n * kv.clear(); // Removes all entries in current namespace\n * ```\n */\n public clear(): void {\n this.statements.clear.run(this.getCurrentNamespace());\n }\n\n /**\n * Gets all key-value pairs as an object (excluding expired keys)\n *\n * @returns Object with all non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const all = kv.all();\n * console.log('All entries:', all);\n * // Output: { 'key1': 'value1', 'key2': 'value2' }\n * ```\n */\n public all(): Record<string, string> {\n const result = this.statements.all.all(\n this.getCurrentNamespace(),\n this.getCurrentTime(),\n );\n\n return Object.fromEntries(\n result.map((row) => [row.key as string, row.value as string]),\n );\n }\n\n /**\n * Gets all available namespaces (tables) in the database\n *\n * @returns Array of namespace names\n *\n * @example\n * ```typescript\n * const namespaces = kv.namespaces();\n * console.log('Available namespaces:', namespaces);\n * ```\n */\n public namespaces(): string[] {\n const result = this.statements.namespaces.all();\n\n return result.map((row) => row.name as string);\n }\n\n /**\n * Gets the current namespace name\n *\n * @returns The current namespace string\n */\n public getCurrentNamespace(): string {\n return this.options.namespace ?? 'commandkit_kv';\n }\n\n /**\n * Creates a new KV instance with a different namespace\n *\n * @param namespace - The namespace to use for the new instance\n * @returns A new KV instance with the specified namespace\n *\n * @example\n * ```typescript\n * const userKv = kv.namespace('users');\n * const configKv = kv.namespace('config');\n *\n * userKv.set('123', 'John Doe');\n * configKv.set('theme', 'dark');\n * ```\n */\n public namespace(namespace: string): KV {\n return new KV(this.db, {\n enableWAL: this.options.enableWAL,\n namespace,\n });\n }\n\n /**\n * Iterator implementation for iterating over all non-expired key-value pairs\n *\n * @returns Iterator yielding [key, value] tuples\n *\n * @example\n * ```typescript\n * for (const [key, value] of kv) {\n * console.log(`${key}: ${value}`);\n * }\n *\n * // Or using spread operator\n * const entries = [...kv];\n * ```\n */\n public *[Symbol.iterator](): Iterator<[string, string]> {\n const result = this.statements.all.iterate(\n this.getCurrentNamespace(),\n this.getCurrentTime(),\n );\n\n for (const row of result) {\n yield [row.key as string, row.value as string];\n }\n }\n\n /**\n * Executes a function within a transaction\n *\n * @param fn - Function to execute within the transaction (can be async)\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * // Synchronous transaction\n * kv.transaction(() => {\n * kv.set('user:123', JSON.stringify({ name: 'John' }));\n * kv.set('user:456', JSON.stringify({ name: 'Jane' }));\n * // If any operation fails, all changes are rolled back\n * });\n *\n * // Async transaction\n * await kv.transaction(async () => {\n * kv.set('user:123', JSON.stringify({ name: 'John' }));\n * await someAsyncOperation();\n * kv.set('user:456', JSON.stringify({ name: 'Jane' }));\n * // If any operation fails, all changes are rolled back\n * });\n * ```\n */\n public async transaction<T>(fn: () => T | Promise<T>): Promise<T> {\n try {\n // Begin transaction\n this.statements.begin.run();\n\n // Execute the function\n const result = await fn();\n\n // Commit transaction\n this.statements.commit.run();\n\n return result;\n } catch (error) {\n // Rollback transaction on error\n this.statements.rollback.run();\n throw error;\n }\n }\n}\n\n/**\n * Opens a new KV instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n * @returns A new KV instance\n */\nexport function openKV(\n path: string | Buffer | URL | DatabaseSync = 'commandkit_kv.db',\n options: KvOptions = { enableWAL: true, namespace: 'commandkit_kv' },\n): KV {\n return new KV(path, options);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kv.js","names":[],"sources":["../../src/kv/kv.ts"],"sourcesContent":["import { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { deserializer, serializer } from './serde';\nimport { getNestedValue, setNestedValue } from './dotprops';\n\nexport type { SerializedValue } from './serde';\n\n/**\n * Configuration options for the KV store\n */\nexport interface KvOptions {\n /** Enable Write-Ahead Logging for better performance and durability */\n enableWAL?: boolean;\n /** Namespace for the key-value store table */\n namespace?: string;\n}\n\n/**\n * A key-value store implementation using SQLite\n *\n * This class provides a simple, persistent key-value storage solution\n * with support for namespaces, automatic cleanup, iteration, expiration, and JSON serialization.\n *\n * @example\n * ```typescript\n * const kv = new KV('data.db');\n *\n * // Store any JSON-serializable data\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('dates', [new Date(), new Date()]);\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.name', 'John');\n * kv.set('user:123.settings.theme', 'dark');\n *\n * // Retrieve data\n * const user = kv.get('user:123'); // { name: 'John', age: 30, settings: { theme: 'dark' } }\n * const name = kv.get('user:123.name'); // 'John'\n * ```\n */\nexport class KV implements Disposable, AsyncDisposable {\n private db: DatabaseSync;\n private statements: Record<string, StatementSync> = {};\n\n /**\n * Creates a new KV store instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n */\n public constructor(\n path: string | Buffer | URL | DatabaseSync,\n private options: KvOptions = {\n enableWAL: true,\n namespace: 'commandkit_kv',\n },\n ) {\n this.db =\n path instanceof DatabaseSync\n ? path\n : new DatabaseSync(path, { open: true });\n\n if (options.enableWAL) {\n this.db.exec(/* sql */ `PRAGMA journal_mode = WAL;`);\n }\n\n const namespace = this.options.namespace ?? 'commandkit_kv';\n\n this.db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS ${namespace} (\n key TEXT PRIMARY KEY,\n value TEXT,\n expires_at INTEGER\n )\n `);\n\n this.statements = {\n get: this.db.prepare(\n /* sql */ `SELECT value, expires_at FROM ${namespace} WHERE key = ?`,\n ),\n set: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n setex: this.db.prepare(\n /* sql */ `INSERT OR REPLACE INTO ${namespace} (key, value, expires_at) VALUES (?, ?, ?)`,\n ),\n delete: this.db.prepare(\n /* sql */ `DELETE FROM ${namespace} WHERE key = ?`,\n ),\n has: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE key = ? AND (expires_at IS NULL OR expires_at > ?)`,\n ),\n keys: this.db.prepare(\n /* sql */ `SELECT key FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n values: this.db.prepare(\n /* sql */ `SELECT value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n clear: this.db.prepare(/* sql */ `DELETE FROM ${namespace}`),\n count: this.db.prepare(\n /* sql */ `SELECT COUNT(*) FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n all: this.db.prepare(\n /* sql */ `SELECT key, value FROM ${namespace} WHERE expires_at IS NULL OR expires_at > ?`,\n ),\n expire: this.db.prepare(\n /* sql */ `UPDATE ${namespace} SET expires_at = ? WHERE key = ?`,\n ),\n ttl: this.db.prepare(\n /* sql */ `SELECT expires_at FROM ${namespace} WHERE key = ?`,\n ),\n namespaces: this.db.prepare(\n /* sql */ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`,\n ),\n begin: this.db.prepare(/* sql */ `BEGIN TRANSACTION`),\n commit: this.db.prepare(/* sql */ `COMMIT`),\n rollback: this.db.prepare(/* sql */ `ROLLBACK`),\n };\n }\n\n /**\n * Gets the current timestamp in milliseconds\n */\n private getCurrentTime(): number {\n return Date.now();\n }\n\n /**\n * Checks if the database connection is open\n *\n * @returns `true` if the database is open, `false` otherwise\n */\n public isOpen(): boolean {\n return this.db.isOpen;\n }\n\n /**\n * Gets the underlying SQLite database instance\n *\n * @returns The DatabaseSync instance\n */\n public getDatabase(): DatabaseSync {\n return this.db;\n }\n\n /**\n * Closes the database connection\n */\n public close(): void {\n if (this.db.isOpen) this.db.close();\n }\n\n /**\n * Disposable implementation - closes the database when disposed\n */\n public [Symbol.dispose]() {\n this.close();\n }\n\n /**\n * AsyncDisposable implementation - closes the database when disposed\n */\n public async [Symbol.asyncDispose]() {\n this.close();\n }\n\n /**\n * Retrieves a value by key\n *\n * @param key - The key to retrieve (supports dot notation for nested properties)\n * @returns The value associated with the key, or `undefined` if not found or expired\n *\n * @example\n * ```typescript\n * // Store an object\n * kv.set('user:123', { name: 'John', age: 30, settings: { theme: 'dark' } });\n *\n * // Get the entire object\n * const user = kv.get('user:123');\n * // { name: 'John', age: 30, settings: { theme: 'dark' } }\n *\n * // Get nested properties using dot notation\n * const name = kv.get('user:123.name'); // 'John'\n * const theme = kv.get('user:123.settings.theme'); // 'dark'\n * ```\n */\n public get<T = any>(key: string): T | undefined {\n const result = this.statements.get.get(key);\n\n if (!result) return undefined;\n\n // Check if the key has expired\n if (\n result.expires_at &&\n Number(result.expires_at) <= this.getCurrentTime()\n ) {\n this.delete(key);\n return undefined;\n }\n\n const serialized = JSON.parse(result.value as string);\n const deserialized = deserializer(serialized);\n\n // Handle dot notation for nested properties\n if (key.includes('.')) {\n return getNestedValue(deserialized, key.split('.').slice(1).join('.'));\n }\n\n return deserialized;\n }\n\n /**\n * Sets a key-value pair\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n *\n * @example\n * ```typescript\n * // Store primitive values\n * kv.set('counter', 42);\n * kv.set('active', true);\n * kv.set('name', 'John');\n *\n * // Store objects\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Store arrays\n * kv.set('tags', ['javascript', 'typescript', 'sqlite']);\n *\n * // Store dates\n * kv.set('created', new Date());\n *\n * // Store maps and sets\n * kv.set('permissions', new Map([['admin', true], ['user', false]]));\n * kv.set('unique_ids', new Set([1, 2, 3, 4, 5]));\n *\n * // Use dot notation for nested properties\n * kv.set('user:123.settings.theme', 'dark');\n * kv.set('user:123.settings.notifications', true);\n * ```\n */\n public set(key: string, value: any): void {\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(baseKey, serializedValue, null);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.set.run(key, serializedValue, null);\n }\n }\n\n /**\n * Sets a key-value pair with expiration\n *\n * @param key - The key to set (supports dot notation for nested properties)\n * @param value - The value to associate with the key (any JSON-serializable type)\n * @param ttl - Time to live in milliseconds\n *\n * @example\n * ```typescript\n * // Set with 1 hour expiration\n * kv.setex('session:123', { userId: 123, token: 'abc123' }, 60 * 60 * 1000);\n *\n * // Set with 5 minutes expiration\n * kv.setex('temp:data', { cached: true, timestamp: Date.now() }, 5 * 60 * 1000);\n *\n * // Use dot notation with expiration\n * kv.setex('user:123.temp_settings', { theme: 'light' }, 30 * 60 * 1000);\n * ```\n */\n public setex(key: string, value: any, ttl: number): void {\n const expiresAt = this.getCurrentTime() + ttl;\n let serializedValue: string;\n\n if (key.includes('.')) {\n // Handle dot notation for nested properties\n const [baseKey, ...pathParts] = key.split('.');\n const path = pathParts.join('.');\n\n // Get existing value or create new object\n const existing = this.get(baseKey) || {};\n setNestedValue(existing, path, value);\n\n const serialized = serializer(existing);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(baseKey, serializedValue, expiresAt);\n } else {\n const serialized = serializer(value);\n serializedValue = JSON.stringify(serialized);\n\n this.statements.setex.run(key, serializedValue, expiresAt);\n }\n }\n\n /**\n * Sets expiration for an existing key\n *\n * @param key - The key to set expiration for\n * @param ttl - Time to live in milliseconds\n * @returns `true` if the key exists and expiration was set, `false` otherwise\n *\n * @example\n * ```typescript\n * kv.set('user:123', { name: 'John', age: 30 });\n *\n * // Set 30 minute expiration\n * if (kv.expire('user:123', 30 * 60 * 1000)) {\n * console.log('Expiration set successfully');\n * }\n * ```\n */\n public expire(key: string, ttl: number): boolean {\n if (!this.has(key)) return false;\n\n const expiresAt = this.getCurrentTime() + ttl;\n this.statements.expire.run(expiresAt, key);\n return true;\n }\n\n /**\n * Gets the time to live for a key\n *\n * @param key - The key to check\n * @returns Time to live in milliseconds, or `-1` if the key doesn't exist, or `-2` if the key has no expiration\n *\n * @example\n * ```typescript\n * const ttl = kv.ttl('user:123');\n * if (ttl > 0) {\n * console.log(`Key expires in ${ttl}ms`);\n * } else if (ttl === -2) {\n * console.log('Key has no expiration');\n * } else {\n * console.log('Key does not exist');\n * }\n * ```\n */\n public ttl(key: string): number {\n const result = this.statements.ttl.get(key);\n\n if (!result) return -1; // Key doesn't exist\n\n if (!result.expires_at) return -2; // No expiration\n\n const remaining = Number(result.expires_at) - this.getCurrentTime();\n return remaining > 0 ? remaining : -1; // Expired or doesn't exist\n }\n\n /**\n * Deletes a key-value pair\n *\n * @param key - The key to delete\n *\n * @example\n * ```typescript\n * kv.delete('user:123');\n * kv.delete('user:123.settings.theme'); // Delete nested property\n * ```\n */\n public delete(key: string): void {\n this.statements.delete.run(key);\n }\n\n /**\n * Checks if a key exists and is not expired\n *\n * @param key - The key to check\n * @returns `true` if the key exists and is not expired, `false` otherwise\n *\n * @example\n * ```typescript\n * if (kv.has('user:123')) {\n * console.log('User exists and is not expired');\n * }\n *\n * if (kv.has('user:123.settings.theme')) {\n * console.log('Theme setting exists');\n * }\n * ```\n */\n public has(key: string): boolean {\n const result = this.statements.has.get(key, this.getCurrentTime());\n\n return (\n result?.count !== undefined &&\n result.count !== null &&\n Number(result.count) > 0\n );\n }\n\n /**\n * Gets all keys in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired keys\n *\n * @example\n * ```typescript\n * const keys = kv.keys();\n * console.log('All keys:', keys);\n * ```\n */\n public keys(): string[] {\n const result = this.statements.keys.all(this.getCurrentTime());\n\n return result.map((row) => row.key as string);\n }\n\n /**\n * Gets all values in the current namespace (excluding expired keys)\n *\n * @returns Array of all non-expired values\n *\n * @example\n * ```typescript\n * const values = kv.values();\n * console.log('All values:', values);\n * ```\n */\n public values(): any[] {\n const result = this.statements.values.all(this.getCurrentTime());\n\n return result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return deserializer(serialized);\n });\n }\n\n /**\n * Gets the total number of key-value pairs in the current namespace (excluding expired keys)\n *\n * @returns The count of non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const count = kv.count();\n * console.log(`Total entries: ${count}`);\n * ```\n */\n public count(): number {\n const result = this.statements.count.get(this.getCurrentTime());\n\n return Number(result?.count ?? 0);\n }\n\n /**\n * Removes all key-value pairs from the current namespace\n *\n * @example\n * ```typescript\n * kv.clear(); // Removes all entries in current namespace\n * ```\n */\n public clear(): void {\n this.statements.clear.run();\n }\n\n /**\n * Gets all key-value pairs as an object (excluding expired keys)\n *\n * @returns Object with all non-expired key-value pairs\n *\n * @example\n * ```typescript\n * const all = kv.all();\n * console.log('All entries:', all);\n * // Output: { 'key1': value1, 'key2': value2 }\n * ```\n */\n public all(): Record<string, any> {\n const result = this.statements.all.all(this.getCurrentTime());\n\n return Object.fromEntries(\n result.map((row) => {\n const serialized = JSON.parse(row.value as string);\n return [row.key as string, deserializer(serialized)];\n }),\n );\n }\n\n /**\n * Gets all available namespaces (tables) in the database\n *\n * @returns Array of namespace names\n *\n * @example\n * ```typescript\n * const namespaces = kv.namespaces();\n * console.log('Available namespaces:', namespaces);\n * ```\n */\n public namespaces(): string[] {\n const result = this.statements.namespaces.all();\n\n return result.map((row) => row.name as string);\n }\n\n /**\n * Gets the current namespace name\n *\n * @returns The current namespace string\n */\n public getCurrentNamespace(): string {\n return this.options.namespace ?? 'commandkit_kv';\n }\n\n /**\n * Creates a new KV instance with a different namespace\n *\n * @param namespace - The namespace to use for the new instance\n * @returns A new KV instance with the specified namespace\n *\n * @example\n * ```typescript\n * const userKv = kv.namespace('users');\n * const configKv = kv.namespace('config');\n *\n * userKv.set('123', { name: 'John', age: 30 });\n * configKv.set('theme', 'dark');\n * ```\n */\n public namespace(namespace: string): KV {\n return new KV(this.db, {\n enableWAL: this.options.enableWAL,\n namespace,\n });\n }\n\n /**\n * Iterator implementation for iterating over all non-expired key-value pairs\n *\n * @returns Iterator yielding [key, value] tuples\n *\n * @example\n * ```typescript\n * for (const [key, value] of kv) {\n * console.log(`${key}:`, value);\n * }\n *\n * // Or using spread operator\n * const entries = [...kv];\n * ```\n */\n public *[Symbol.iterator](): Iterator<[string, any]> {\n const result = this.statements.all.iterate(this.getCurrentTime());\n\n for (const row of result) {\n const serialized = JSON.parse(row.value as string);\n yield [row.key as string, deserializer(serialized)];\n }\n }\n\n /**\n * Executes a function within a transaction\n *\n * @param fn - Function to execute within the transaction (can be async)\n * @returns The result of the function\n *\n * @example\n * ```typescript\n * // Synchronous transaction\n * kv.transaction(() => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n *\n * // Async transaction\n * await kv.transaction(async () => {\n * kv.set('user:123', { name: 'John', age: 30 });\n * await someAsyncOperation();\n * kv.set('user:456', { name: 'Jane', age: 25 });\n * // If any operation fails, all changes are rolled back\n * });\n * ```\n */\n public async transaction<T>(fn: () => T | Promise<T>): Promise<T> {\n try {\n // Begin transaction\n this.statements.begin.run();\n\n // Execute the function\n const result = await fn();\n\n // Commit transaction\n this.statements.commit.run();\n\n return result;\n } catch (error) {\n // Rollback transaction on error\n this.statements.rollback.run();\n throw error;\n }\n }\n}\n\n/**\n * Opens a new KV instance\n *\n * @param path - Database file path, buffer, URL, or existing DatabaseSync instance\n * @param options - Configuration options for the KV store\n * @returns A new KV instance\n */\nexport function openKV(\n path: string | Buffer | URL | DatabaseSync = 'commandkit_kv.db',\n options: KvOptions = { enableWAL: true, namespace: 'commandkit_kv' },\n): KV {\n return new KV(path, options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa,KAAb,MAAa,GAA0C;CACrD,AAAQ;CACR,AAAQ,aAA4C,CAAE;;;;;;;CAQtD,AAAO,YACP,MACQ,UAAqB;EAC3B,WAAW;EACX,WAAW;CACZ,GACD;EAJQ;AAKN,OAAK,KACL,gBAAgB,2BAChB,OACA,IAAI,yBAAa,MAAM,EAAE,MAAM,KAAM;AAErC,MAAI,QAAQ,UACV,MAAK,GAAG,MAAe,4BAA4B;EAGrD,MAAM,YAAY,KAAK,QAAQ,aAAa;AAE5C,OAAK,GAAG,MAAe;mCACQ,UAAU;;;;;MAKvC;AAEF,OAAK,aAAa;GAChB,KAAK,KAAK,GAAG,SACD,gCAAgC,UAAU,gBACrD;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,4CAC9C;GACD,OAAO,KAAK,GAAG,SACH,yBAAyB,UAAU,4CAC9C;GACD,QAAQ,KAAK,GAAG,SACJ,cAAc,UAAU,gBACnC;GACD,KAAK,KAAK,GAAG,SACD,uBAAuB,UAAU,2DAC5C;GACD,MAAM,KAAK,GAAG,SACF,kBAAkB,UAAU,6CACvC;GACD,QAAQ,KAAK,GAAG,SACJ,oBAAoB,UAAU,6CACzC;GACD,OAAO,KAAK,GAAG,SAAkB,cAAc,UAAU,EAAE;GAC3D,OAAO,KAAK,GAAG,SACH,uBAAuB,UAAU,6CAC5C;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,6CAC9C;GACD,QAAQ,KAAK,GAAG,SACJ,SAAS,UAAU,mCAC9B;GACD,KAAK,KAAK,GAAG,SACD,yBAAyB,UAAU,gBAC9C;GACD,YAAY,KAAK,GAAG,SACR,kFACX;GACD,OAAO,KAAK,GAAG,SAAkB,mBAAmB;GACpD,QAAQ,KAAK,GAAG,SAAkB,QAAQ;GAC1C,UAAU,KAAK,GAAG,SAAkB,UAAU;EAC/C;CACH;;;;CAKA,AAAQ,iBAAyB;AAC/B,SAAO,KAAK,KAAK;CACnB;;;;;;CAOA,AAAO,SAAkB;AACvB,SAAO,KAAK,GAAG;CACjB;;;;;;CAOA,AAAO,cAA4B;AACjC,SAAO,KAAK;CACd;;;;CAKA,AAAO,QAAc;AACnB,MAAI,KAAK,GAAG,OAAQ,MAAK,GAAG,OAAO;CACrC;;;;CAKA,CAAQ,OAAO,WAAW;AACxB,OAAK,OAAO;CACd;;;;CAKA,OAAc,OAAO,gBAAgB;AACnC,OAAK,OAAO;CACd;;;;;;;;;;;;;;;;;;;;;CAsBA,AAAO,IAAa,KAA4B;EAC9C,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,IAAI;AAE3C,OAAK,OAAQ;AAGb,MACA,OAAO,cACP,OAAO,OAAO,WAAW,IAAI,KAAK,gBAAgB,EAClD;AACE,QAAK,OAAO,IAAI;AAChB;EACF;EAEA,MAAM,aAAa,KAAK,MAAM,OAAO,MAAgB;EACrD,MAAM,eAAe,2BAAa,WAAW;AAG7C,MAAI,IAAI,SAAS,IAAI,CACnB,QAAO,gCAAe,cAAc,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;AAGxE,SAAO;CACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCA,AAAO,IAAI,KAAa,OAAkB;EACxC,IAAI;AAEJ,MAAI,IAAI,SAAS,IAAI,EAAE;GAErB,MAAM,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,MAAM,IAAI;GAC9C,MAAM,OAAO,UAAU,KAAK,IAAI;GAGhC,MAAM,WAAW,KAAK,IAAI,QAAQ,IAAI,CAAE;AACxC,mCAAe,UAAU,MAAM,MAAM;GAErC,MAAM,aAAa,yBAAW,SAAS;AACvC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,IAAI,IAAI,SAAS,iBAAiB,KAAK;EACxD,OAAM;GACL,MAAM,aAAa,yBAAW,MAAM;AACpC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,IAAI,IAAI,KAAK,iBAAiB,KAAK;EACrD;CACF;;;;;;;;;;;;;;;;;;;;CAqBA,AAAO,MAAM,KAAa,OAAY,KAAmB;EACvD,MAAM,YAAY,KAAK,gBAAgB,GAAG;EAC1C,IAAI;AAEJ,MAAI,IAAI,SAAS,IAAI,EAAE;GAErB,MAAM,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,MAAM,IAAI;GAC9C,MAAM,OAAO,UAAU,KAAK,IAAI;GAGhC,MAAM,WAAW,KAAK,IAAI,QAAQ,IAAI,CAAE;AACxC,mCAAe,UAAU,MAAM,MAAM;GAErC,MAAM,aAAa,yBAAW,SAAS;AACvC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,MAAM,IAAI,SAAS,iBAAiB,UAAU;EAC/D,OAAM;GACL,MAAM,aAAa,yBAAW,MAAM;AACpC,qBAAkB,KAAK,UAAU,WAAW;AAE5C,QAAK,WAAW,MAAM,IAAI,KAAK,iBAAiB,UAAU;EAC5D;CACF;;;;;;;;;;;;;;;;;;CAmBA,AAAO,OAAO,KAAa,KAAsB;AAC/C,OAAK,KAAK,IAAI,IAAI,CAAE,QAAO;EAE3B,MAAM,YAAY,KAAK,gBAAgB,GAAG;AAC1C,OAAK,WAAW,OAAO,IAAI,WAAW,IAAI;AAC1C,SAAO;CACT;;;;;;;;;;;;;;;;;;;CAoBA,AAAO,IAAI,KAAqB;EAC9B,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,IAAI;AAE3C,OAAK,OAAQ,QAAO;AAEpB,OAAK,OAAO,WAAY,QAAO;EAE/B,MAAM,YAAY,OAAO,OAAO,WAAW,GAAG,KAAK,gBAAgB;AACnE,SAAO,YAAY,IAAI,YAAY;CACrC;;;;;;;;;;;;CAaA,AAAO,OAAO,KAAmB;AAC/B,OAAK,WAAW,OAAO,IAAI,IAAI;CACjC;;;;;;;;;;;;;;;;;;CAmBA,AAAO,IAAI,KAAsB;EAC/B,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,gBAAgB,CAAC;AAElE,0DACE,OAAQ,qBACR,OAAO,UAAU,QACjB,OAAO,OAAO,MAAM,GAAG;CAE3B;;;;;;;;;;;;CAaA,AAAO,OAAiB;EACtB,MAAM,SAAS,KAAK,WAAW,KAAK,IAAI,KAAK,gBAAgB,CAAC;AAE9D,SAAO,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAc;CAC/C;;;;;;;;;;;;CAaA,AAAO,SAAgB;EACrB,MAAM,SAAS,KAAK,WAAW,OAAO,IAAI,KAAK,gBAAgB,CAAC;AAEhE,SAAO,OAAO,IAAI,CAAC,QAAQ;GACzB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,UAAO,2BAAa,WAAW;EAChC,EAAC;CACJ;;;;;;;;;;;;CAaA,AAAO,QAAgB;EACrB,MAAM,SAAS,KAAK,WAAW,MAAM,IAAI,KAAK,gBAAgB,CAAC;AAE/D,SAAO,wDAAO,OAAQ,UAAS,EAAE;CACnC;;;;;;;;;CAUA,AAAO,QAAc;AACnB,OAAK,WAAW,MAAM,KAAK;CAC7B;;;;;;;;;;;;;CAcA,AAAO,MAA2B;EAChC,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,KAAK,gBAAgB,CAAC;AAE7D,SAAO,OAAO,YACZ,OAAO,IAAI,CAAC,QAAQ;GAClB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,UAAO,CAAC,IAAI,KAAe,2BAAa,WAAW,AAAC;EACrD,EAAC,CACH;CACH;;;;;;;;;;;;CAaA,AAAO,aAAuB;EAC5B,MAAM,SAAS,KAAK,WAAW,WAAW,KAAK;AAE/C,SAAO,OAAO,IAAI,CAAC,QAAQ,IAAI,KAAe;CAChD;;;;;;CAOA,AAAO,sBAA8B;AACnC,SAAO,KAAK,QAAQ,aAAa;CACnC;;;;;;;;;;;;;;;;CAiBA,AAAO,UAAU,WAAuB;AACtC,SAAO,IAAI,GAAG,KAAK,IAAI;GACrB,WAAW,KAAK,QAAQ;GACxB;EACD;CACH;;;;;;;;;;;;;;;;CAiBA,EAAS,OAAO,YAAqC;EACnD,MAAM,SAAS,KAAK,WAAW,IAAI,QAAQ,KAAK,gBAAgB,CAAC;AAEjE,OAAK,MAAM,OAAO,QAAQ;GACxB,MAAM,aAAa,KAAK,MAAM,IAAI,MAAgB;AAClD,SAAM,CAAC,IAAI,KAAe,2BAAa,WAAW,AAAC;EACrD;CACF;;;;;;;;;;;;;;;;;;;;;;;;;CA0BA,MAAa,YAAe,IAAsC;AAChE,MAAI;AAEF,QAAK,WAAW,MAAM,KAAK;GAG3B,MAAM,SAAS,MAAM,IAAI;AAGzB,QAAK,WAAW,OAAO,KAAK;AAE5B,UAAO;EACR,SAAQ,OAAO;AAEd,QAAK,WAAW,SAAS,KAAK;AAC9B,SAAM;EACR;CACF;AACF;;;;;;;;AASA,SAAgB,OAChB,OAA6C,oBAC7C,UAAqB;CAAE,WAAW;CAAM,WAAW;AAAiB,GAC/D;AACH,QAAO,IAAI,GAAG,MAAM;AACtB"}
|
package/dist/kv/serde.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SerializerType } from "./constants-Br1y2J-P.js";
|
|
2
|
+
|
|
3
|
+
//#region src/kv/serde.d.ts
|
|
4
|
+
interface SerializedValue {
|
|
5
|
+
t: SerializerType;
|
|
6
|
+
v: any;
|
|
7
|
+
}
|
|
8
|
+
declare function serializer(value: any): SerializedValue;
|
|
9
|
+
declare function deserializer(serialized: SerializedValue): any;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { SerializedValue, deserializer, serializer };
|
|
12
|
+
//# sourceMappingURL=serde-4EKSAKpL.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const require_constants = require('./constants-DYSMm0U6.js');
|
|
2
|
+
|
|
3
|
+
//#region src/kv/serde.ts
|
|
4
|
+
function serializer(value) {
|
|
5
|
+
if (value === null) return {
|
|
6
|
+
t: require_constants.SerializerType.Null,
|
|
7
|
+
v: null
|
|
8
|
+
};
|
|
9
|
+
if (value === void 0) return {
|
|
10
|
+
t: require_constants.SerializerType.Undefined,
|
|
11
|
+
v: void 0
|
|
12
|
+
};
|
|
13
|
+
if (typeof value === "string") return {
|
|
14
|
+
t: require_constants.SerializerType.String,
|
|
15
|
+
v: value
|
|
16
|
+
};
|
|
17
|
+
if (typeof value === "number") return {
|
|
18
|
+
t: require_constants.SerializerType.Number,
|
|
19
|
+
v: value
|
|
20
|
+
};
|
|
21
|
+
if (typeof value === "boolean") return {
|
|
22
|
+
t: require_constants.SerializerType.Boolean,
|
|
23
|
+
v: value
|
|
24
|
+
};
|
|
25
|
+
if (typeof value === "bigint") return {
|
|
26
|
+
t: require_constants.SerializerType.BigInt,
|
|
27
|
+
v: value.toString()
|
|
28
|
+
};
|
|
29
|
+
if (value instanceof Date) return {
|
|
30
|
+
t: require_constants.SerializerType.Date,
|
|
31
|
+
v: value.toISOString()
|
|
32
|
+
};
|
|
33
|
+
if (Array.isArray(value)) return {
|
|
34
|
+
t: require_constants.SerializerType.Array,
|
|
35
|
+
v: value
|
|
36
|
+
};
|
|
37
|
+
if (value instanceof Map) return {
|
|
38
|
+
t: require_constants.SerializerType.Map,
|
|
39
|
+
v: Array.from(value.entries())
|
|
40
|
+
};
|
|
41
|
+
if (value instanceof Set) return {
|
|
42
|
+
t: require_constants.SerializerType.Set,
|
|
43
|
+
v: Array.from(value)
|
|
44
|
+
};
|
|
45
|
+
if (Buffer.isBuffer(value)) return {
|
|
46
|
+
t: require_constants.SerializerType.Buffer,
|
|
47
|
+
v: value.toString("base64")
|
|
48
|
+
};
|
|
49
|
+
if (value instanceof RegExp) return {
|
|
50
|
+
t: require_constants.SerializerType.RegExp,
|
|
51
|
+
v: {
|
|
52
|
+
source: value.source,
|
|
53
|
+
flags: value.flags
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (typeof value === "object") return {
|
|
57
|
+
t: require_constants.SerializerType.Object,
|
|
58
|
+
v: value
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
t: require_constants.SerializerType.String,
|
|
62
|
+
v: String(value)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function deserializer(serialized) {
|
|
66
|
+
switch (serialized.t) {
|
|
67
|
+
case require_constants.SerializerType.Null: return null;
|
|
68
|
+
case require_constants.SerializerType.Undefined: return void 0;
|
|
69
|
+
case require_constants.SerializerType.String: return serialized.v;
|
|
70
|
+
case require_constants.SerializerType.Number: return serialized.v;
|
|
71
|
+
case require_constants.SerializerType.Boolean: return serialized.v;
|
|
72
|
+
case require_constants.SerializerType.BigInt: return BigInt(serialized.v);
|
|
73
|
+
case require_constants.SerializerType.Date: return new Date(serialized.v);
|
|
74
|
+
case require_constants.SerializerType.Array: return serialized.v;
|
|
75
|
+
case require_constants.SerializerType.Map: return new Map(serialized.v);
|
|
76
|
+
case require_constants.SerializerType.Set: return new Set(serialized.v);
|
|
77
|
+
case require_constants.SerializerType.Buffer: return Buffer.from(serialized.v, "base64");
|
|
78
|
+
case require_constants.SerializerType.RegExp: return new RegExp(serialized.v.source, serialized.v.flags);
|
|
79
|
+
case require_constants.SerializerType.Object: return serialized.v;
|
|
80
|
+
default: return serialized.v;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//#endregion
|
|
85
|
+
Object.defineProperty(exports, 'deserializer', {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function () {
|
|
88
|
+
return deserializer;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(exports, 'serializer', {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
get: function () {
|
|
94
|
+
return serializer;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=serde-CXY4F7OD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serde-CXY4F7OD.js","names":[],"sources":["../src/kv/serde.ts"],"sourcesContent":["import { SerializerType } from './constants';\n\nexport interface SerializedValue {\n t: SerializerType;\n v: any;\n}\n\nexport function serializer(value: any): SerializedValue {\n if (value === null) {\n return { t: SerializerType.Null, v: null };\n }\n\n if (value === undefined) {\n return { t: SerializerType.Undefined, v: undefined };\n }\n\n if (typeof value === 'string') {\n return { t: SerializerType.String, v: value };\n }\n\n if (typeof value === 'number') {\n return { t: SerializerType.Number, v: value };\n }\n\n if (typeof value === 'boolean') {\n return { t: SerializerType.Boolean, v: value };\n }\n\n if (typeof value === 'bigint') {\n return { t: SerializerType.BigInt, v: value.toString() };\n }\n\n if (value instanceof Date) {\n return { t: SerializerType.Date, v: value.toISOString() };\n }\n\n if (Array.isArray(value)) {\n return { t: SerializerType.Array, v: value };\n }\n\n if (value instanceof Map) {\n return { t: SerializerType.Map, v: Array.from(value.entries()) };\n }\n\n if (value instanceof Set) {\n return { t: SerializerType.Set, v: Array.from(value) };\n }\n\n if (Buffer.isBuffer(value)) {\n return { t: SerializerType.Buffer, v: value.toString('base64') };\n }\n\n if (value instanceof RegExp) {\n return {\n t: SerializerType.RegExp,\n v: { source: value.source, flags: value.flags },\n };\n }\n\n if (typeof value === 'object') {\n return { t: SerializerType.Object, v: value };\n }\n\n // Fallback to string\n return { t: SerializerType.String, v: String(value) };\n}\n\nexport function deserializer(serialized: SerializedValue): any {\n switch (serialized.t) {\n case SerializerType.Null:\n return null;\n case SerializerType.Undefined:\n return undefined;\n case SerializerType.String:\n return serialized.v;\n case SerializerType.Number:\n return serialized.v;\n case SerializerType.Boolean:\n return serialized.v;\n case SerializerType.BigInt:\n return BigInt(serialized.v);\n case SerializerType.Date:\n return new Date(serialized.v);\n case SerializerType.Array:\n return serialized.v;\n case SerializerType.Map:\n return new Map(serialized.v);\n case SerializerType.Set:\n return new Set(serialized.v);\n case SerializerType.Buffer:\n return Buffer.from(serialized.v, 'base64');\n case SerializerType.RegExp:\n return new RegExp(serialized.v.source, serialized.v.flags);\n case SerializerType.Object:\n return serialized.v;\n default:\n return serialized.v;\n }\n}\n"],"mappings":";;;AAOA,SAAgB,WAAW,OAA6B;AACtD,KAAI,UAAU,KACZ,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG;CAAM;AAG5C,KAAI,iBACF,QAAO;EAAE,GAAG,iCAAe;EAAW;CAAc;AAGtD,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAG/C,YAAW,UAAU,UACnB,QAAO;EAAE,GAAG,iCAAe;EAAS,GAAG;CAAO;AAGhD,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,UAAU;CAAE;AAG1D,KAAI,iBAAiB,KACnB,QAAO;EAAE,GAAG,iCAAe;EAAM,GAAG,MAAM,aAAa;CAAE;AAG3D,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO;EAAE,GAAG,iCAAe;EAAO,GAAG;CAAO;AAG9C,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM,SAAS,CAAC;CAAE;AAGlE,KAAI,iBAAiB,IACnB,QAAO;EAAE,GAAG,iCAAe;EAAK,GAAG,MAAM,KAAK,MAAM;CAAE;AAGxD,KAAI,OAAO,SAAS,MAAM,CACxB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,MAAM,SAAS,SAAS;CAAE;AAGlE,KAAI,iBAAiB,OACnB,QAAO;EACL,GAAG,iCAAe;EAClB,GAAG;GAAE,QAAQ,MAAM;GAAQ,OAAO,MAAM;EAAO;CAChD;AAGH,YAAW,UAAU,SACnB,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG;CAAO;AAI/C,QAAO;EAAE,GAAG,iCAAe;EAAQ,GAAG,OAAO,MAAM;CAAE;AACvD;AAEA,SAAgB,aAAa,YAAkC;AAC7D,SAAQ,WAAW,GAAnB;EACE,KAAK,iCAAe,KAClB,QAAO;EACT,KAAK,iCAAe,UAClB;EACF,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,QAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,OAClB,QAAO,OAAO,WAAW,EAAE;EAC7B,KAAK,iCAAe,KAClB,QAAO,IAAI,KAAK,WAAW;EAC7B,KAAK,iCAAe,MAClB,QAAO,WAAW;EACpB,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,IAClB,QAAO,IAAI,IAAI,WAAW;EAC5B,KAAK,iCAAe,OAClB,QAAO,OAAO,KAAK,WAAW,GAAG,SAAS;EAC5C,KAAK,iCAAe,OAClB,QAAO,IAAI,OAAO,WAAW,EAAE,QAAQ,WAAW,EAAE;EACtD,KAAK,iCAAe,OAClB,QAAO,WAAW;EACpB,QACE,QAAO,WAAW;CACtB;AACF"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* The current version of CommandKit.
|
|
8
8
|
*/
|
|
9
|
-
const version = "1.0.0-dev.
|
|
9
|
+
const version = "1.0.0-dev.20250703125152";
|
|
10
10
|
|
|
11
11
|
//#endregion
|
|
12
12
|
Object.defineProperty(exports, 'version', {
|
|
@@ -15,4 +15,4 @@ Object.defineProperty(exports, 'version', {
|
|
|
15
15
|
return version;
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
-
//# sourceMappingURL=version-
|
|
18
|
+
//# sourceMappingURL=version-BGji_hXj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-
|
|
1
|
+
{"version":3,"file":"version-BGji_hXj.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["/**\n * @private\n */\nfunction $version(): string {\n 'use macro';\n return require('../package.json').version;\n}\n\n/**\n * The current version of CommandKit.\n */\nexport const version: string = $version();\n"],"mappings":";;;;;;;;AAWA,MAAa,UAA4B"}
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "commandkit",
|
|
3
3
|
"description": "Beginner friendly command & event handler for Discord.js",
|
|
4
|
-
"version": "1.0.0-dev.
|
|
4
|
+
"version": "1.0.0-dev.20250703125152",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
"tsx": "^4.19.2",
|
|
179
179
|
"typescript": "^5.7.3",
|
|
180
180
|
"vitest": "^3.0.5",
|
|
181
|
-
"tsconfig": "0.0.0-dev.
|
|
181
|
+
"tsconfig": "0.0.0-dev.20250703125152"
|
|
182
182
|
},
|
|
183
183
|
"peerDependencies": {
|
|
184
184
|
"discord.js": "^14"
|